]> git.cworth.org Git - apitrace/commitdiff
Merge branch 'master' into dxva
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Mon, 5 Nov 2012 23:38:09 +0000 (23:38 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Mon, 5 Nov 2012 23:38:09 +0000 (23:38 +0000)
Conflicts:
common/trace_parser_flags.cpp

142 files changed:
.lvimrc [new file with mode: 0644]
CMakeLists.txt
INSTALL.markdown
LICENSE
README.markdown
cmake/FindQJSON.cmake [deleted file]
cmake/toolchain/android.toolchain.cmake
common/os_posix.cpp
common/os_thread.hpp
common/os_time.hpp
common/os_win32.cpp
common/pickle.hpp
common/trace_parser_flags.cpp
common/trace_profiler.cpp [new file with mode: 0644]
common/trace_profiler.hpp [new file with mode: 0644]
common/trace_writer_local.cpp
gui/CMakeLists.txt
gui/apitrace.cpp
gui/calldurationgraph.h [new file with mode: 0644]
gui/graphing/frameaxiswidget.cpp [new file with mode: 0644]
gui/graphing/frameaxiswidget.h [new file with mode: 0644]
gui/graphing/graphaxiswidget.cpp [new file with mode: 0644]
gui/graphing/graphaxiswidget.h [new file with mode: 0644]
gui/graphing/graphing.h [new file with mode: 0644]
gui/graphing/graphlabelwidget.h [new file with mode: 0644]
gui/graphing/graphview.cpp [new file with mode: 0644]
gui/graphing/graphview.h [new file with mode: 0644]
gui/graphing/graphwidget.cpp [new file with mode: 0644]
gui/graphing/graphwidget.h [new file with mode: 0644]
gui/graphing/heatmapverticalaxiswidget.cpp [new file with mode: 0644]
gui/graphing/heatmapverticalaxiswidget.h [new file with mode: 0644]
gui/graphing/heatmapview.cpp [new file with mode: 0644]
gui/graphing/heatmapview.h [new file with mode: 0644]
gui/graphing/histogramview.cpp [new file with mode: 0644]
gui/graphing/histogramview.h [new file with mode: 0644]
gui/graphing/timeaxiswidget.cpp [new file with mode: 0644]
gui/graphing/timeaxiswidget.h [new file with mode: 0644]
gui/main.cpp
gui/mainwindow.cpp
gui/mainwindow.h
gui/profiledialog.cpp [new file with mode: 0644]
gui/profiledialog.h [new file with mode: 0644]
gui/profileheatmap.h [new file with mode: 0644]
gui/profiletablemodel.cpp [new file with mode: 0644]
gui/profiletablemodel.h [new file with mode: 0644]
gui/profiling.h [new file with mode: 0644]
gui/retracer.cpp
gui/retracer.h
gui/ui/mainwindow.ui
gui/ui/profiledialog.ui [new file with mode: 0644]
gui/ui/profilereplaydialog.ui [new file with mode: 0644]
helpers/d3d10size.hpp [new file with mode: 0644]
helpers/d3d9size.hpp [new file with mode: 0644]
helpers/d3dsize.hpp [deleted file]
helpers/eglsize.cpp [new file with mode: 0644]
helpers/eglsize.hpp [new file with mode: 0644]
helpers/glsize.hpp
retrace/d3dretrace.hpp
retrace/d3dretrace.py
retrace/d3dretrace_main.cpp
retrace/d3dretrace_ws.cpp
retrace/d3dstate.cpp
retrace/glretrace.hpp
retrace/glretrace.py
retrace/glretrace_cgl.cpp
retrace/glretrace_egl.cpp
retrace/glretrace_glx.cpp
retrace/glretrace_main.cpp [changed mode: 0644->0755]
retrace/glretrace_wgl.cpp
retrace/glretrace_ws.cpp
retrace/glstate_images.cpp
retrace/glws.cpp
retrace/glws.hpp
retrace/glws_cocoa.mm
retrace/glws_egl_xlib.cpp
retrace/glws_glx.cpp
retrace/glws_wgl.cpp
retrace/json.hpp
retrace/retrace.cpp
retrace/retrace.hpp
retrace/retrace_main.cpp
retrace/retrace_swizzle.cpp
scripts/profileshader.py [new file with mode: 0755]
scripts/retracediff.py
scripts/tracediff.py
scripts/tracediff2.py
scripts/unpickle.py
specs/cglapi.py
specs/d3d10.py
specs/d3d10sdklayers.py
specs/dxgi.py
specs/eglapi.py
specs/glapi.py
specs/glesapi.py
specs/glparams.py
specs/gltypes.py
specs/glxapi.py
specs/scripts/glspec.py
specs/stdapi.py
specs/wglapi.py
specs/winapi.py
thirdparty/khronos/EGL/eglext.h
thirdparty/khronos/GL/glext.h
thirdparty/khronos/GLES/glext.h
thirdparty/khronos/GLES2/gl2ext.h
thirdparty/qjson/.gitignore [new file with mode: 0644]
thirdparty/qjson/CMakeLists.txt
thirdparty/qjson/COPYING [deleted file]
thirdparty/qjson/COPYING.lib [new file with mode: 0644]
thirdparty/qjson/README
thirdparty/qjson/json_parser.cc
thirdparty/qjson/json_parser.hh
thirdparty/qjson/json_parser.yy
thirdparty/qjson/json_scanner.cpp
thirdparty/qjson/json_scanner.h
thirdparty/qjson/parser.cpp
thirdparty/qjson/parser.h
thirdparty/qjson/parser_p.h
thirdparty/qjson/parserrunnable.cpp
thirdparty/qjson/parserrunnable.h
thirdparty/qjson/qjson_debug.h
thirdparty/qjson/qjson_export.h
thirdparty/qjson/qobjecthelper.cpp
thirdparty/qjson/qobjecthelper.h
thirdparty/qjson/serializer.cpp
thirdparty/qjson/serializer.h
thirdparty/qjson/serializerrunnable.cpp
thirdparty/qjson/serializerrunnable.h
wrappers/.gitignore
wrappers/CMakeLists.txt
wrappers/d3d10_1trace.py
wrappers/d3d10trace.py
wrappers/d3d9shader.cpp
wrappers/d3d9trace.py
wrappers/d3dcommontrace.py [new file with mode: 0644]
wrappers/egltrace.py
wrappers/gltrace.hpp
wrappers/gltrace.py
wrappers/gltrace_state.cpp
wrappers/glxtrace.py
wrappers/trace.py
wrappers/wgltrace.py

diff --git a/.lvimrc b/.lvimrc
new file mode 100644 (file)
index 0000000..815bdd0
--- /dev/null
+++ b/.lvimrc
@@ -0,0 +1 @@
+set sw=4 ts=4 et
index 3970f05c71d56edd3126165efc75119e23880c37..83490d56b3d7e17c2230a6ccd0c7d9c725e25acc 100644 (file)
@@ -1,5 +1,14 @@
 cmake_minimum_required (VERSION 2.8)
 
+
+# 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.
+if (APPLE)
+    set (CMAKE_C_COMPILER "clang")
+    set (CMAKE_CXX_COMPILER "clang++")
+endif ()
+
+
 project (apitrace)
 
 
@@ -25,6 +34,21 @@ set (ENABLE_EGL true CACHE BOOL "Enable EGL support.")
 ##############################################################################
 # Find dependencies
 
+# Ensure __thread is support
+if (NOT MSVC)
+    include (CheckCXXSourceCompiles)
+    check_cxx_source_compiles("__thread int i; int main() { return 0; }" HAVE_COMPILER_TLS)
+    if (NOT HAVE_COMPILER_TLS)
+        if (APPLE)
+            message (FATAL_ERROR "C++ compiler does not support __thread keyword. Please install XCode 4.5 or higher.")
+        else (MINGW32)
+            message (FATAL_ERROR "C++ compiler does not support __thread keyword. Please use MinGW g++ version 4.4 or higher")
+        else ()
+            message (FATAL_ERROR "C++ compiler does not support __thread keyword.")
+        endif ()
+    endif ()
+endif ()
+
 set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
 
 set (CMAKE_USE_PYTHON_VERSION 2.7 2.6)
@@ -45,7 +69,6 @@ if (ENABLE_GUI)
         set (REQUIRE_GUI REQUIRED)
     endif ()
     find_package (Qt4 4.7 COMPONENTS QtCore QtGui QtWebKit ${REQUIRE_GUI})
-    find_package (QJSON ${REQUIRE_GUI})
 endif ()
 
 if (WIN32)
@@ -59,6 +82,10 @@ else ()
     if (X11_FOUND)
         include_directories (${X11_INCLUDE_DIR})
         add_definitions (-DHAVE_X11)
+    else ()
+        # Print a clear message when X11 is not found
+        include (FindPackageMessage)
+        find_package_message (X11 "Could not find X11" "")
     endif ()
 endif ()
 
@@ -127,6 +154,9 @@ else ()
         set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb -O0")
         set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -ggdb")
     endif ()
+
+    # Be nice to Eclipse
+    add_definitions (-fmessage-length=0)
 endif ()
 
 if (MINGW)
@@ -189,16 +219,12 @@ if (WIN32)
     add_subdirectory (thirdparty/less)
 endif ()
 
-# The Qt website provides binaries for Windows and MacOSX, and they are
-# automatically found by cmake without any manual intervention.  The situation
-# for QJSON is substantially different: there are no binaries for QJSON
-# available, and there is no standard installation directory that is detected
-# by cmake.
-#
-# By bundling the QJSON source, we make it much more easier to build the GUI on
-# Windows and MacOSX.  But we only use the bundled sources when ENABLE_GUI is
-# AUTO.
-if (QT4_FOUND AND NOT QJSON_FOUND AND (ENABLE_GUI STREQUAL "AUTO"))
+# 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 EXCLUDE_FROM_ALL)
     set (QJSON_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty)
     set (QJSON_LIBRARY_DIRS)
@@ -295,6 +321,7 @@ add_library (common STATIC
     common/trace_loader.cpp
     common/trace_resource.cpp
     common/trace_tools_trace.cpp
+    common/trace_profiler.cpp
     common/image.cpp
     common/image_bmp.cpp
     common/image_pnm.cpp
index b4c99e8826c860c2fe651ac66b01dc88eb384e36..2228bdff860368cdf72203e97f0b62a54683b736 100644 (file)
@@ -16,12 +16,12 @@ Requirements common for all platforms:
 
 The GUI also dependends on:
 
-* Qt version 4.7
+* 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 `-DENABLED_GUI=FALSE` is passed instead.  The implicit default is
+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.
 
@@ -40,12 +40,23 @@ Build as:
     cmake -H. -Bbuild
     make -C build
 
-You can also build the 32bit GL wrapper on 64bit distro with a multilib gcc by
-doing:
 
-    cmake -H. -Bbuild32 -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DCMAKE_EXE_LINKER_FLAGS=-m32 -DENABLE_GUI=FALSE
+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
 -------
 
@@ -84,7 +95,7 @@ Additional requirements:
 
 To build with Visual Studio first invoke CMake GUI as:
 
-    cmake-gui -H. -B%cd%\build
+    cmake-gui -H%cd% -B%cd%\build
 
 and press the _Configure_ button.
 
@@ -93,14 +104,14 @@ not found automatically, you can manually specify the location of the
 dependencies from the CMake GUI.
 
 After you've successfully configured, you can start the build by opening the
-generated `build\apitrace.sln` solution file, or invoking `cmake` as:
+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
+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/LICENSE b/LICENSE
index 29598650db97a8aed201c678a1675643f0b19ab9..d0cf6d2cc800068817a5e5fb011281881cff9ae3 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,9 @@
-Copyright 2011 Jose Fonseca, Zack Rusin
-Copyright 2008-2010 VMware, Inc.
+Copyright 2007-2012 VMware, Inc.
+Copyright 2011 Intel Corporation
+Copyright 2011 LunarG, Inc.
+Copyright 2011 Zack Rusin
+Copyright 2011-2012 Jose Fonseca
+
 All Rights Reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -20,4 +24,3 @@ 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.
 
-
index 9702ba0739294d14c41c8c7eb1264c3491d1391a..ab1453059d6f97b325197a14ce07b1e961889a39 100644 (file)
@@ -11,6 +11,8 @@ About **apitrace**
 
 * visualize and edit trace files.
 
+See the [apitrace homepage](http://apitrace.github.com/) for more details.
+
 
 Obtaining **apitrace**
 ======================
@@ -50,7 +52,9 @@ Replay an OpenGL trace with
     glretrace application.trace
 
 Pass the `-sb` option to use a single buffered visual.  Pass `--help` to
-glretrace for more options.
+`glretrace` for more options.
+
+EGL traces must be replayed with `eglretrace` instead of `glretrace`.
 
 
 Basic GUI usage
@@ -110,22 +114,25 @@ or 32 bits.  This can be done by doing
 But beware of wrapper shell scripts -- what matters is the architecture of the
 main process.
 
-Run the application you want to trace as
+Run the GLX application you want to trace as
 
-     LD_PRELOAD=/path/to/apitrace/wrappers/glxtrace.so /path/to/application
+    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.
 
-The `LD_PRELOAD` mechanism should work with most applications.  There are some
-applications, e.g., Unigine Heaven, which global function pointers with the
-same name as GL entrypoints, living in a shared object that wasn't linked with
-`-Bsymbolic` flag, so relocations to those globals 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 into
-`LD_LIBRARY_PATH`:
+For EGL applications you will need to use `egltrace.so` instead of
+`glxtrace.so`.
+
+The `LD_PRELOAD` mechanism should work with the majority applications.  There
+are some applications (e.g., Unigine Heaven, Android GPU emulator, etc.), that
+have global function pointers with the same name as GL entrypoints, living in a
+shared object that wasn't linked with `-Bsymbolic` flag, so relocations to
+those globals 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
@@ -134,6 +141,9 @@ to trace by using `glxtrace.so` as an ordinary `libGL.so` and injecting into
     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.
 
@@ -148,49 +158,45 @@ Sandwitch:
 
 For standalone applications the instructions above for Linux should
 work. To trace applications started from within the Android VM process
-(app_process aka zygote) you'll have to wrap this process and enable
+(`app_process` aka zygote) you'll have to wrap this process and enable
 tracing dynamically for the application to be traced.
 
 - Wrapping the android main VM process:
 
-  In the Android root /init.rc add the LD_PRELOAD setting to zygote's
+  In the Android root /init.rc add the `LD_PRELOAD` setting to zygote's
   environment in the 'service zygote' section:
 
-  """
-  service zygote ...
-     setenv LD_PRELOAD /data/egltrace.so
-     ...
-  """
+        service zygote ...
+           setenv LD_PRELOAD /data/egltrace.so
+           ...
 
   Note that ICS will overwrite the /init.rc during each boot with the
   version in the recovery image. So you'll have to change the file in
   your ICS source tree, rebuild and reflash the device.
   Rebuilding/reflashing only the recovery image should be sufficient.
 
-
 - Copy egltrace.so to /data
 
   On the host:
-  $ adb push /path/to/apitrace/build/wrappers/egltrace.so /data
 
+        adb push /path/to/apitrace/build/wrappers/egltrace.so /data
 
 - Adjust file permissions to store the trace file:
 
   By default egltrace.so will store the trace in
-  /data/app_process.trace. For this to work for applications running
-  with a uid other than 0, you have to allow writes to the /data
+  `/data/app_process.trace`. For this to work for applications running
+  with a uid other than 0, you have to allow writes to the `/data`
   directory on the device:
 
-  # chmod 0777 /data
-
+        chmod 0777 /data
 
 - Enable tracing for a specific process name:
 
   To trace for example the Settings application:
-  # setprop debug.apitrace.procname com.android.settings
 
-  In general this name will match what 'ps' reports.
+        setprop debug.apitrace.procname com.android.settings
 
+  In general this name will match what `ps` reports.
 
 - Start the application:
 
@@ -198,7 +204,7 @@ tracing dynamically for the application to be traced.
   of pre-starting the apps, you might have to kill the application
   first:
 
-  # kill <pid of app>
+        kill <pid of app>
 
   Launch the application for example from the application menu.
 
@@ -276,8 +282,14 @@ From OpenGL ES applications you can embed annotations in the trace file through
 extension.
 
 
-For Direct3D applications you can follow the same procedure used for 
-[instrumenting an application for PIX](http://technet.microsoft.com/en-us/query/ee417250)
+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 GL state at a particular call
@@ -312,8 +324,8 @@ You can make a video of the output by doing
     | ffmpeg -r 30 -f image2pipe -vcodec ppm -i pipe: -vcodec mpeg4 -y output.mp4
 
 
-Triming a trace
----------------
+Trimming a trace
+----------------
 
 You can make a smaller trace by doing:
 
@@ -324,6 +336,27 @@ individual call numbers a plaintext file, as described in the 'Call sets'
 section above.
 
 
+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 this can then be read by hand or analysed 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:
+
+    ./glretrace -pgpu -pcpu -ppd foo.trace | ./scripts/profileshader.py
+
+
 Advanced usage for OpenGL implementors
 ======================================
 
@@ -435,60 +468,4 @@ Or on Windows:
     python scripts\retracediff.py --retrace \path\to\glretrace.exe --ref-env TRACE_LIBGL=\path\to\reference\opengl32.dll application.trace
 
 
-Links
-=====
-
-About **apitrace**:
-
-* [Official mailing list](http://lists.freedesktop.org/mailman/listinfo/apitrace)
-
-* [Zack Rusin's blog introducing the GUI](http://zrusin.blogspot.com/2011/04/apitrace.html)
-
-* [Jose's Fonseca blog introducing the tool](http://jrfonseca.blogspot.com/2008/07/tracing-d3d-applications.html)
-
-
-Direct3D
---------
-
-Open-source:
-
-* [Proxy DLL](http://www.mikoweb.eu/index.php?node=21)
-
-  * [Intercept Calls to DirectX with a Proxy DLL](http://www.codeguru.com/cpp/g-m/directx/directx8/article.php/c11453/)
-
-* [Direct3D 9 API Interceptor](http://graphics.stanford.edu/~mdfisher/D3D9Interceptor.html)
-
-Closed-source:
-
-* [Microsoft PIX](http://msdn.microsoft.com/en-us/library/ee417062.aspx)
-
-  * [D3DSpy](http://doc.51windows.net/Directx9_SDK/?url=/directx9_sdk/graphics/programmingguide/TutorialsAndSamplesAndToolsAndTips/Tools/D3DSpy.htm): the predecessor of PIX
-
-* [NVIDIA PerfKit](http://developer.nvidia.com/nvidia-perfkit)
-
-* [AMD GPU PerfStudio](http://developer.amd.com/gpu/PerfStudio/pages/APITraceWindow.aspx)
-
-* [Intel Graphics Performance Analyzers](http://www.intel.com/software/gpa/)
-
-
-OpenGL
-------
-
-Open-source:
-
-* [BuGLe](http://www.opengl.org/sdk/tools/BuGLe/)
-
-* [GLIntercept](http://code.google.com/p/glintercept/)
-
-* [tracy](https://gitorious.org/tracy): OpenGL ES and OpenVG trace, retrace, and state inspection
-
-* [WebGL-Inspector](http://benvanik.github.com/WebGL-Inspector/)
-
-Closed-source:
-
-* [gDEBugger](http://www.gremedy.com/products.php) and [AMD gDEBugger](http://developer.amd.com/tools/gDEBugger/Pages/default.aspx)
-
-* [glslDevil](http://cumbia.informatik.uni-stuttgart.de/glsldevil/index.html)
-
-* [AMD GPU PerfStudio](http://developer.amd.com/gpu/PerfStudio/pages/APITraceWindow.aspx)
-
+[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/c1062ad633aa7a458e9d7520021307e4 "githalytics.com")](http://githalytics.com/apitrace/apitrace)
diff --git a/cmake/FindQJSON.cmake b/cmake/FindQJSON.cmake
deleted file mode 100644 (file)
index cd007e1..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# Find QJSON - JSON handling library for Qt
-#
-# This module defines
-#  QJSON_FOUND - whether the qsjon library was found
-#  QJSON_LIBRARIES - the qjson library
-#  QJSON_INCLUDE_DIR - the include path of the qjson library
-#
-
-if (QJSON_INCLUDE_DIR AND QJSON_LIBRARIES)
-
-  # Already in cache
-  set (QJSON_FOUND TRUE)
-
-else (QJSON_INCLUDE_DIR AND QJSON_LIBRARIES)
-
-  if (NOT WIN32)
-    # use pkg-config to get the values of QJSON_INCLUDE_DIRS
-    # and QJSON_LIBRARY_DIRS to add as hints to the find commands.
-    include (FindPkgConfig)
-    pkg_check_modules (PC_QJSON QJson>=0.5)
-  endif (NOT WIN32)
-
-  find_library (QJSON_LIBRARIES
-    NAMES
-    qjson
-    PATHS
-    ${PC_QJSON_LIBRARY_DIRS}
-    ${LIB_INSTALL_DIR}
-    ${KDE4_LIB_DIR}
-  )
-
-  find_path (QJSON_INCLUDE_DIR
-    NAMES
-    qjson/parser.h
-    PATHS
-    ${PC_QJSON_INCLUDE_DIRS}
-    ${INCLUDE_INSTALL_DIR}
-    ${KDE4_INCLUDE_DIR}
-  )
-
-  include(FindPackageHandleStandardArgs)
-  find_package_handle_standard_args(QJSON DEFAULT_MSG QJSON_LIBRARIES QJSON_INCLUDE_DIR)
-
-endif (QJSON_INCLUDE_DIR AND QJSON_LIBRARIES)
index 2f5341646e24f8f0d0100042792e563e9d9bc5d1..56c7fd2fc4574c041ed3ec16bbe056a79f22e9cb 100644 (file)
@@ -1,10 +1,10 @@
 # ------------------------------------------------------------------------------
-#  Android CMake toolchain file, for use with the Android NDK r5-r7
-#  Requires cmake 2.6.3 or newer (2.8.3 or newer is recommended).
+#  Android CMake toolchain file, for use with the Android NDK r5-r8
+#  Requires cmake 2.6.3 or newer (2.8.5 or newer is recommended).
 #  See home page: http://code.google.com/p/android-cmake/
 #
 #  The file is mantained by the OpenCV project. And also can be found at
-#  http://code.opencv.org/svn/opencv/trunk/opencv/android/android.toolchain.cmake
+#  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
@@ -20,7 +20,7 @@
 #
 #  Usage Windows:
 #     You need native port of make to build your project.
-#     Android NDK r7 already has make.exe on board.
+#     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
 #
 #    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 
+#    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 
+#      Interface (ABI). This option nearly matches to the APP_ABI variable
 #      used by ndk-build tool from Android NDK.
-#      Possible values are:
+#
+#      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.
@@ -55,7 +56,9 @@
 #            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.
+#            See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation.
+#        "mips" - matches to the NDK ABI with the same name
+#            (not testes on real devices)
 #
 #    ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for.
 #      Option is read-only when standalone toolchain used.
 #      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 
+#
+#    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 will be set true, mutually exclusive.
 #    NEON option will be set true if VFP is set to NEON.
 #
 #    under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}
 #    (depending on the target ABI). This is convenient for Android packaging.
 #
+#  Authors:
+#    Ethan Rublee ethan.ruble@gmail.com
+#    Andrey Kamaev andrey.kamaev@itseez.com
 #
 #  Change Log:
-#   - initial version December 2010 Ethan Rublee ethan.ruble@gmail.com
-#   - modified April 2011 Andrey Kamaev andrey.kamaev@itseez.com
+#   - initial version December 2010
+#   - modified 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
 #     [+] 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
-#   - modified May 2011 Andrey Kamaev andrey.kamaev@itseez.com
+#   - modified 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
-#   - modified June 2011 Andrey Kamaev andrey.kamaev@itseez.com
-#     [~] default NDK path is updated for version r5c 
+#   - modified 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
-#   - modified July 2011 Andrey Kamaev andrey.kamaev@itseez.com
+#   - modified July 2011
 #     [~] fixed options caching
 #     [~] search for all supported NDK versions
 #     [~] allowed spaces in NDK path
-#   - modified September 2011 Andrey Kamaev andrey.kamaev@itseez.com
+#   - modified September 2011
 #     [~] updated for NDK r6b
-#   - modified November 2011 Andrey Kamaev andrey.kamaev@itseez.com
+#   - modified November 2011
 #     [*] rewritten for NDK r7
 #     [+] x86 toolchain support (experimental)
 #     [+] added "armeabi-v6 with VFP" ABI for ARMv6 processors.
 #     [~] 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
-#   - modified January 2012 Andrey Kamaev andrey.kamaev@itseez.com
+#   - modified 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
-#   - modified February 2012 Andrey Kamaev andrey.kamaev@itseez.com
+#   - modified February 2012
 #     [+] updated for NDK r7b
 #     [~] fixed cmake try_compile() command
 #     [~] Fix for missing install_name_tool on OS X
+#   - modified 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
+#   - modified April 2012
+#     [+] updated for NDK r7c
+#     [~] fixed most of problems with compiler/linker flags and caching
+#     [+] added option ANDROID_FUNCTION_LEVEL_LINKING
+#   - modified May 2012
+#     [+] updated for NDK r8
+#     [+] added mips architecture support
+#   - modified August 2012
+#     [+] updated for NDK r8b
+#     [~] all intermediate files generated by toolchain are moved into CMakeFiles
+#     [~] libstdc++ and libsupc are removed from explicit link libraries
 # ------------------------------------------------------------------------------
 
 cmake_minimum_required( VERSION 2.6.3 )
 
-if( PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
+if( DEFINED CMAKE_CROSSCOMPILING )
+ # subsequent toolchain loading is not really needed
+ return()
+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
+# this one not so much
 set( CMAKE_SYSTEM_VERSION 1 )
 
-set( ANDROID_SUPPORTED_NDK_VERSIONS -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
-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()
- set( ANDROID_NDK_SEARCH_PATHS /opt/android-ndk "$ENV{HOME}/NVPACK/android-ndk" )
+set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -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()
-set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain )
+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 )
@@ -298,11 +335,11 @@ macro( __COPY_IF_DIFFERENT _source _destination )
 endmacro()
 
 
-#stl version: by default gnustl_static will be used
+# stl version: by default gnustl_static will be used
 set( ANDROID_USE_STLPORT FALSE CACHE BOOL "Experimental: use stlport_static instead of gnustl_static")
 mark_as_advanced( ANDROID_USE_STLPORT )
 
-#fight against cygwin
+# 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 )
@@ -311,7 +348,7 @@ if( ANDROID_FORBID_SYGWIN )
  endif()
 
  if( CMAKE_HOST_WIN32 )
-  #remove cygwin from PATH
+  # remove cygwin from PATH
   set( __new_path "$ENV{PATH}")
   __LIST_FILTER( __new_path "cygwin" )
   set(ENV{PATH} "${__new_path}")
@@ -319,7 +356,7 @@ if( ANDROID_FORBID_SYGWIN )
  endif()
 endif()
 
-#detect current host platform
+# detect current host platform
 set( TOOL_OS_SUFFIX "" )
 if( CMAKE_HOST_APPLE )
  set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86" )
@@ -332,10 +369,10 @@ else()
  message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
 endif()
 
-#see if we have path to Android NDK
+# 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
+ # 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 )
@@ -364,10 +401,10 @@ if( NOT ANDROID_NDK )
  endif( NOT ANDROID_STANDALONE_TOOLCHAIN )
 endif( NOT ANDROID_NDK )
 
-#remember found paths
+# remember found paths
 if( ANDROID_NDK )
  get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE )
- #try to detect change
+ # try to detect change
  if( CMAKE_AR )
   string( LENGTH "${ANDROID_NDK}" __length )
   string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath )
@@ -381,7 +418,7 @@ if( ANDROID_NDK )
  set( BUILD_WITH_ANDROID_NDK True )
 elseif( ANDROID_STANDALONE_TOOLCHAIN )
  get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE )
- #try to detect change
+ # try to detect change
  if( CMAKE_AR )
   string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length )
   string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath )
@@ -405,9 +442,10 @@ else()
       sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
 endif()
 
-#get all the details about standalone toolchain
+# 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 )
@@ -417,9 +455,11 @@ if( BUILD_WITH_STANDALONE_TOOLCHAIN )
   set( __availableToolchainArchs "x86" )
  elseif( __availableToolchainMachines MATCHES arm )
   set( __availableToolchainArchs "arm" )
+ elseif( __availableToolchainMachines MATCHES mipsel )
+  set( __availableToolchainArchs "mipsel" )
  endif()
  if( ANDROID_COMPILER_VERSION )
-  #do not run gcc every time because it is relatevely expencive
+  # do not run gcc every time because it is relatevely expencive
   set( __availableToolchainCompilerVersions "${ANDROID_COMPILER_VERSION}" )
  else()
   execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" --version
@@ -428,7 +468,7 @@ if( BUILD_WITH_STANDALONE_TOOLCHAIN )
  endif()
 endif()
 
-#get all the details about NDK
+# 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}" )
@@ -440,11 +480,11 @@ if( BUILD_WITH_ANDROID_NDK )
  foreach( __toolchain ${__availableToolchains} )
   __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK}/toolchains/${__toolchain}/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
   if( __machine )
-   string( REGEX MATCH "[0-9]+.[0-9]+.[0-9]+$" __version "${__toolchain}" )
+   string( REGEX MATCH "[0-9]+[.][0-9]+[.]*[0-9]*$" __version "${__toolchain}" )
    string( REGEX MATCH "^[^-]+" __arch "${__toolchain}" )
-   list( APPEND __availableToolchainMachines ${__machine} )
-   list( APPEND __availableToolchainArchs ${__arch} )
-   list( APPEND __availableToolchainCompilerVersions ${__version} )
+   list( APPEND __availableToolchainMachines "${__machine}" )
+   list( APPEND __availableToolchainArchs "${__arch}" )
+   list( APPEND __availableToolchainCompilerVersions "${__version}" )
   else()
    list( REMOVE_ITEM __availableToolchains "${__toolchain}" )
   endif()
@@ -454,7 +494,7 @@ if( BUILD_WITH_ANDROID_NDK )
  endif()
 endif()
 
-#build list of available ABIs
+# build list of available ABIs
 if( NOT ANDROID_SUPPORTED_ABIS )
  set( ANDROID_SUPPORTED_ABIS "" )
  set( __uniqToolchainArchNames ${__availableToolchainArchs} )
@@ -469,9 +509,9 @@ if( NOT ANDROID_SUPPORTED_ABIS )
  endif()
 endif()
 
-#choose target ABI
+# choose target ABI
 __INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${ANDROID_SUPPORTED_ABIS} )
-#verify that target ABI is supported
+# 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}" )
@@ -481,42 +521,54 @@ if( __androidAbiIdx EQUAL -1 )
 endif()
 unset( __androidAbiIdx )
 
-#remember target ABI
+# 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 )
 
-#set target ABI options
+# 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( 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( 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( 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( CMAKE_SYSTEM_PROCESSOR "armv6" )
- #need always fallback to older platform
+ # 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( 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( 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( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
  set( VFPV3 true )
  set( NEON true )
@@ -524,10 +576,16 @@ else()
  message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." )
 endif()
 
-set( ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} CACHE INTERNAL "ANDROID_ABI can be changed only to one of these ABIs. Changing to any other ABI requires to reset cmake cache." )
+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()
+
+set( ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} CACHE INTERNAL "ANDROID_ABI can be changed only to one of these ABIs. Changing to any other ABI requires to reset cmake cache." )
 if( CMAKE_VERSION VERSION_GREATER "2.8" )
- list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} )
- set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} )
+ list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME} )
+ set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} )
 endif()
 
 if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 )
@@ -538,14 +596,14 @@ else()
  unset( ANDROID_FORCE_ARM_BUILD CACHE )
 endif()
 
-#choose toolchain
+# choose toolchain
 if( ANDROID_TOOLCHAIN_NAME )
  list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx )
  if( __toolchainIdx EQUAL -1 )
   message( FATAL_ERROR "Previously selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing. You need to remove CMakeCache.txt and rerun cmake manually to change the toolchain" )
  endif()
  list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch )
- if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME )
+ if( NOT __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME )
   message( SEND_ERROR "Previously selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." )
  endif()
 else()
@@ -556,7 +614,7 @@ else()
  math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" )
  foreach( __idx RANGE ${__availableToolchainsCount} )
   list( GET __availableToolchainArchs ${__idx} __toolchainArch )
-  if( __toolchainArch STREQUAL ANDROID_ARCH_NAME )
+  if( __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME )
    list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion )
    if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion )
     set( __toolchainMaxVersion "${__toolchainVersion}" )
@@ -583,10 +641,10 @@ 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_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL )
+# 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}" )
-#validate
+# 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_NATIVE_API_LEVEL}) is not supported by your NDK/toolchain." )
@@ -605,7 +663,7 @@ if( CMAKE_VERSION VERSION_GREATER "2.8" )
  set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
 endif()
 
-#setup paths
+# setup paths
 if( BUILD_WITH_STANDALONE_TOOLCHAIN )
  set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
  set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" )
@@ -618,22 +676,32 @@ if( BUILD_WITH_ANDROID_NDK )
   set( __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" )
   set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}" )
  else()
-  set( __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/include" )
-  set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}" )
+  if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
+   set( __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/include" )
+   set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}" )
+  else()
+   set( __stlIncludePath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/include" )
+   set( __stlLibPath "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}" )
+  endif()
  endif()
 endif()
 
 # specify the cross compiler
 set( CMAKE_C_COMPILER   "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}"     CACHE PATH "gcc" )
 set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}"     CACHE PATH "g++" )
+set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}"     CACHE PATH "Assembler" )
+if( CMAKE_VERSION VERSION_LESS 2.8.5 )
+ set( CMAKE_ASM_COMPILER_ARG1 "-c" )
+endif()
+# there may be a way to make cmake deduce these TODO deduce the rest of the tools
 set( CMAKE_STRIP        "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}"   CACHE PATH "strip" )
-#there may be a way to make cmake deduce these TODO deduce the rest of the tools
 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" )
+set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" )
 if( APPLE )
  find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
  if( NOT CMAKE_INSTALL_NAME_TOOL )
@@ -641,32 +709,32 @@ if( APPLE )
  endif()
  mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
 endif()
-#export directories
+
+# export directories
 set( ANDROID_SYSTEM_INCLUDE_DIRS "" )
 set( ANDROID_SYSTEM_LIB_DIRS "" )
 
-#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" )
-
-set( DO_NOT_CHANGE_OUTPUT_PATHS_ON_FIRST_PASS OFF CACHE BOOL "" )
-if( DO_NOT_CHANGE_OUTPUT_PATHS_ON_FIRST_PASS )
- 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()
-set( DO_NOT_CHANGE_OUTPUT_PATHS_ON_FIRST_PASS ON CACHE INTERNAL "" FORCE )
-
-#includes
+# XXX: commented for apitrace
+## 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()
+
+# includes
 list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_SYSROOT}/usr/include" )
 if( __stlIncludePath AND EXISTS "${__stlIncludePath}" )
  list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${__stlIncludePath}" )
 endif()
 
-#STL bits includes
+# c++ bits includes
 if( __stlLibPath AND EXISTS "${__stlLibPath}/include" )
  list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${__stlLibPath}/include" )
 endif()
@@ -680,7 +748,7 @@ elseif( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/incl
  list( APPEND ANDROID_SYSTEM_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" )
 endif()
 
-#flags and definitions
+# flags and definitions
 if(ANDROID_SYSROOT MATCHES "[ ;\"]")
  set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" )
  # quotes will break try_compile and compiler identification
@@ -695,72 +763,86 @@ add_definitions( -DANDROID )
 # Force set compilers because standard identification works badly for us
 include( CMakeForceCompiler )
 CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU )
-CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU )
-set( CMAKE_SIZEOF_VOID_P 4 )
+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 )
+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 )
+# 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)
 
 # NDK flags
 if( ARMEABI OR ARMEABI_V7A )
  # NDK also defines -ffunction-sections -funwind-tables but they result in worse OpenCV performance
- set( CMAKE_CXX_FLAGS "-fPIC -Wno-psabi" )
- set( CMAKE_C_FLAGS "-fPIC -Wno-psabi" )
- if( ANDROID_USE_STLPORT )
-  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions" )
-  set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions" )
- else()
-  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti -fexceptions" )
-  set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions" )
- endif()
+ set( _CMAKE_CXX_FLAGS "-fPIC -Wno-psabi" )
+ set( _CMAKE_C_FLAGS "-fPIC -Wno-psabi" )
  remove_definitions( -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ )
  add_definitions( -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ )
  # extra arm-specific flags
  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" )
 elseif( X86 )
- set( CMAKE_CXX_FLAGS "-ffunction-sections -funwind-tables" )
- set( CMAKE_C_FLAGS "-ffunction-sections -funwind-tables" )
- if( ANDROID_USE_STLPORT )
-  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions" )
-  set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions" )
- else()
-  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti -fexceptions" )
-  set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions" )
- endif()
+ set( _CMAKE_CXX_FLAGS "-funwind-tables" )
+ set( _CMAKE_C_FLAGS "-funwind-tables" )
+elseif( MIPS )
+ set( _CMAKE_CXX_FLAGS "-fpic -Wno-psabi -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" )
+ set( _CMAKE_CXX_FLAGS "-fpic -Wno-psabi -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" )
+else()
+ set( _CMAKE_CXX_FLAGS "" )
+ set( _CMAKE_C_FLAGS "" )
+endif()
+
+if( ANDROID_USE_STLPORT )
+ set( _CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions" )
+ set( _CMAKE_C_FLAGS "${_CMAKE_C_FLAGS} -fno-exceptions" )
 else()
- set( CMAKE_CXX_FLAGS "" )
- set( CMAKE_C_FLAGS "" )
+ set( _CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS} -frtti -fexceptions" )
+ set( _CMAKE_C_FLAGS "${_CMAKE_C_FLAGS} -fexceptions" )
 endif()
 
-#release and debug flags
+# release and debug flags
 if( ARMEABI OR ARMEABI_V7A )
  if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 )
-  #It is recommended to use the -mthumb compiler flag to force the generation
-  #of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones).
+  # It is recommended to use the -mthumb compiler flag to force the generation
+  # of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones).
   # O3 instead of O2/Os in release mode - like cmake sets for desktop gcc
-  set( CMAKE_CXX_FLAGS_RELEASE "-mthumb -O3" )
-  set( CMAKE_C_FLAGS_RELEASE   "-mthumb -O3" )
-  set( CMAKE_CXX_FLAGS_DEBUG "-marm -Os -finline-limit=64" )
-  set( CMAKE_C_FLAGS_DEBUG   "-marm -Os -finline-limit=64" )
+  set( _CMAKE_CXX_FLAGS_RELEASE "-mthumb -O3" )
+  set( _CMAKE_C_FLAGS_RELEASE   "-mthumb -O3" )
+  set( _CMAKE_CXX_FLAGS_DEBUG "-marm -Os -finline-limit=64" )
+  set( _CMAKE_C_FLAGS_DEBUG   "-marm -Os -finline-limit=64" )
  else()
   # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI
   # O3 instead of O2/Os in release mode - like cmake sets for desktop gcc
-  set( CMAKE_CXX_FLAGS_RELEASE "-marm -O3 -fstrict-aliasing" )
-  set( CMAKE_C_FLAGS_RELEASE   "-marm -O3 -fstrict-aliasing" )
-  set( CMAKE_CXX_FLAGS_DEBUG "-marm -O0 -finline-limit=300" )
-  set( CMAKE_C_FLAGS_DEBUG   "-marm -O0 -finline-limit=300" )
+  set( _CMAKE_CXX_FLAGS_RELEASE "-marm -O3 -fstrict-aliasing" )
+  set( _CMAKE_C_FLAGS_RELEASE   "-marm -O3 -fstrict-aliasing" )
+  set( _CMAKE_CXX_FLAGS_DEBUG "-marm -O0 -finline-limit=300" )
+  set( _CMAKE_C_FLAGS_DEBUG   "-marm -O0 -finline-limit=300" )
  endif()
 elseif( X86 )
- set( CMAKE_CXX_FLAGS_RELEASE "-O3 -fstrict-aliasing" )
- set( CMAKE_C_FLAGS_RELEASE   "-O3 -fstrict-aliasing" )
- set( CMAKE_CXX_FLAGS_DEBUG "-O0 -finline-limit=300" )
- set( CMAKE_C_FLAGS_DEBUG   "-O0 -finline-limit=300" )
+ set( _CMAKE_CXX_FLAGS_RELEASE "-O3 -fstrict-aliasing" )
+ set( _CMAKE_C_FLAGS_RELEASE   "-O3 -fstrict-aliasing" )
+ set( _CMAKE_CXX_FLAGS_DEBUG "-O0 -finline-limit=300" )
+ set( _CMAKE_C_FLAGS_DEBUG   "-O0 -finline-limit=300" )
+elseif( MIPS )
+ set( _CMAKE_CXX_FLAGS_RELEASE "-O3 -funswitch-loops -finline-limit=300" )
+ set( _CMAKE_C_FLAGS_RELEASE   "-O3 -funswitch-loops -finline-limit=300" )
+ set( _CMAKE_CXX_FLAGS_DEBUG "-O0 -g" )
+ set( _CMAKE_C_FLAGS_DEBUG   "-O0 -g" )
 endif()
-set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -DNDEBUG" )
-set( CMAKE_C_FLAGS_RELEASE   "${CMAKE_C_FLAGS_RELEASE}   -fomit-frame-pointer -DNDEBUG" )
-set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-strict-aliasing -fno-omit-frame-pointer -DDEBUG -D_DEBUG" )
-set( CMAKE_C_FLAGS_DEBUG   "${CMAKE_C_FLAGS_DEBUG}   -fno-strict-aliasing -fno-omit-frame-pointer -DDEBUG -D_DEBUG" )
+set( _CMAKE_CXX_FLAGS_RELEASE "${_CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer -DNDEBUG" )
+set( _CMAKE_C_FLAGS_RELEASE   "${_CMAKE_C_FLAGS_RELEASE}   -fomit-frame-pointer -DNDEBUG" )
+set( _CMAKE_CXX_FLAGS_DEBUG "${_CMAKE_CXX_FLAGS_DEBUG} -fno-strict-aliasing -fno-omit-frame-pointer -DDEBUG -D_DEBUG" )
+set( _CMAKE_C_FLAGS_DEBUG   "${_CMAKE_C_FLAGS_DEBUG}   -fno-strict-aliasing -fno-omit-frame-pointer -DDEBUG -D_DEBUG" )
 
-#ABI-specific flags
+# ABI-specific flags
 if( ARMEABI_V7A )
  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" )
  if( NEON )
@@ -778,104 +860,118 @@ elseif( X86 )
  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" )#sse?
 endif()
 
-#linker flags
-list( APPEND ANDROID_SYSTEM_LIB_DIRS "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}" "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" )
-set( LINKER_FLAGS "" )
-#STL
+# linker flags
+if( NOT DEFINED __ndklibspath )
+ set( __ndklibspath "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/ndklibs/${ANDROID_NDK_ABI_NAME}" )
+endif()
+list( APPEND ANDROID_SYSTEM_LIB_DIRS "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" )
+set( ANDROID_LINKER_FLAGS "" )
+
+# STL
 if( ANDROID_USE_STLPORT )
  if( EXISTS "${__stlLibPath}/libstlport_static.a" )
-  __COPY_IF_DIFFERENT( "${__stlLibPath}/libstlport_static.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" )
- endif()
- if( EXISTS "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" )
-  set( LINKER_FLAGS "${LINKER_FLAGS} -Wl,--start-group -lstlport_static" )
+  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> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES> \"${__stlLibPath}/libstlport_static.a\"")
+  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> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES> \"${__stlLibPath}/libstlport_static.a\"")
  endif()
 else( ANDROID_USE_STLPORT )
  if( EXISTS "${__stlLibPath}/libgnustl_static.a" )
-  __COPY_IF_DIFFERENT( "${__stlLibPath}/libgnustl_static.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
+  __COPY_IF_DIFFERENT( "${__stlLibPath}/libgnustl_static.a" "${__ndklibspath}/libstdc++.a" )
  elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" )
-  __COPY_IF_DIFFERENT( "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
+  __COPY_IF_DIFFERENT( "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" "${__ndklibspath}/libstdc++.a" )
  elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" )
-  __COPY_IF_DIFFERENT( "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
+  __COPY_IF_DIFFERENT( "${__stlLibPath}/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" "${__ndklibspath}/libstdc++.a" )
  elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${__stlLibPath}/thumb/libstdc++.a" )
-  __COPY_IF_DIFFERENT( "${__stlLibPath}/thumb/libstdc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
+  __COPY_IF_DIFFERENT( "${__stlLibPath}/thumb/libstdc++.a" "${__ndklibspath}/libstdc++.a" )
  elseif( EXISTS "${__stlLibPath}/libstdc++.a" )
-  __COPY_IF_DIFFERENT( "${__stlLibPath}/libstdc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
- endif()
- if( EXISTS "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
-  set( LINKER_FLAGS "${LINKER_FLAGS} -lstdc++" )
+  __COPY_IF_DIFFERENT( "${__stlLibPath}/libstdc++.a" "${__ndklibspath}/libstdc++.a" )
  endif()
-
- #gcc exception & rtti support
  if( EXISTS "${__stlLibPath}/libsupc++.a" )
-  __COPY_IF_DIFFERENT( "${__stlLibPath}/libsupc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" )
+  __COPY_IF_DIFFERENT( "${__stlLibPath}/libsupc++.a" "${__ndklibspath}/libsupc++.a" )
  elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" )
-  __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" )
+  __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" "${__ndklibspath}/libsupc++.a" )
  elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" )
-  __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" )
+  __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" "${__ndklibspath}/libsupc++.a" )
  elseif( ANDROID_ARCH_NAME STREQUAL "arm" AND EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" )
-  __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" )
+  __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" "${__ndklibspath}/libsupc++.a" )
  elseif( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" )
-  __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" )
- endif()
- if( EXISTS "${CMAKE_BINARY_DIR}/systemlibs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" )
-  set( LINKER_FLAGS "${LINKER_FLAGS} -lsupc++" )
+  __COPY_IF_DIFFERENT( "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" "${__ndklibspath}/libsupc++.a" )
  endif()
+ list( APPEND ANDROID_SYSTEM_LIB_DIRS "${__ndklibspath}" )
 endif( ANDROID_USE_STLPORT )
 
-#cleanup for STL search
+# cleanup for STL search
 unset( __stlIncludePath )
 unset( __stlLibPath )
 
-#other linker flags
+# other linker flags
 __INIT_VARIABLE( ANDROID_NO_UNDEFINED OBSOLETE_NO_UNDEFINED VALUES ON )
 set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" FORCE )
 mark_as_advanced( ANDROID_NO_UNDEFINED )
 if( ANDROID_NO_UNDEFINED )
- set( LINKER_FLAGS "-Wl,--no-undefined ${LINKER_FLAGS}" )
+ set( ANDROID_LINKER_FLAGS "-Wl,--no-undefined ${ANDROID_LINKER_FLAGS}" )
 endif()
 
 if (ANDROID_NDK MATCHES "-r[56].?$")
- #libGLESv2.so in NDK's prior to r7 refers to exteranal symbols. So this flag option is required for all projects using OpenGL from native.
+ # libGLESv2.so in NDK's prior to r7 refers to exteranal 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()
+
 set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" FORCE )
 mark_as_advanced( ANDROID_SO_UNDEFINED )
 if( ANDROID_SO_UNDEFINED )
- set( LINKER_FLAGS "${LINKER_FLAGS} -Wl,-allow-shlib-undefined" )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" )
+endif()
+
+__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON )
+set( ANDROID_FUNCTION_LEVEL_LINKING ON CACHE BOOL "Allows or disallows undefined symbols in shared libraries" FORCE )
+mark_as_advanced( ANDROID_FUNCTION_LEVEL_LINKING )
+if( ANDROID_FUNCTION_LEVEL_LINKING )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" )
+ set( ANDROID_LINKER_FLAGS "-Wl,--gc-sections ${ANDROID_LINKER_FLAGS}" )
 endif()
 
 if( ARMEABI_V7A )
  # this is *required* to use the following linker flags that routes around
  # a CPU bug in some Cortex-A8 implementations:
- set( LINKER_FLAGS "-Wl,--fix-cortex-a8 ${LINKER_FLAGS}" )
+ set( ANDROID_LINKER_FLAGS "-Wl,--fix-cortex-a8 ${ANDROID_LINKER_FLAGS}" )
 endif()
 
-#cache flags
-set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags" )
-set( CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c flags" )
-set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "c++ Release flags" )
-set( CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "c Release flags" )
-set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "c++ Debug flags" )
-set( CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "c Debug flags" )
-set( CMAKE_SHARED_LINKER_FLAGS "${LINKER_FLAGS}" CACHE STRING "linker flags" )
-set( CMAKE_MODULE_LINKER_FLAGS "${LINKER_FLAGS}" CACHE STRING "linker flags" )
-set( CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections -Wl,-z,nocopyreloc ${LINKER_FLAGS}" CACHE STRING "linker flags" )
+# cache flags
+set( CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags" )
+set( CMAKE_C_FLAGS "${_CMAKE_C_FLAGS}" CACHE STRING "c flags" )
+set( CMAKE_CXX_FLAGS_RELEASE "${_CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "c++ Release flags" )
+set( CMAKE_C_FLAGS_RELEASE "${_CMAKE_C_FLAGS_RELEASE}" CACHE STRING "c Release flags" )
+set( CMAKE_CXX_FLAGS_DEBUG "${_CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "c++ Debug flags" )
+set( CMAKE_C_FLAGS_DEBUG "${_CMAKE_C_FLAGS_DEBUG}" CACHE STRING "c Debug flags" )
+set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "linker flags" )
+set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "linker flags" )
+set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "linker flags" )
 
 include_directories( SYSTEM ${ANDROID_SYSTEM_INCLUDE_DIRS} )
 link_directories( ${ANDROID_SYSTEM_LIB_DIRS} )
 
-#finish flags
-set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Extra Android falgs")
-set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
-set( CMAKE_C_FLAGS   "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
+# finish flags
+set( ANDROID_CXX_FLAGS    "${ANDROID_CXX_FLAGS}"    CACHE INTERNAL "Extra Android compiler flags")
+set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Extra Android linker flags")
+set( CMAKE_CXX_FLAGS           "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
+set( CMAKE_C_FLAGS             "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
+if( MIPS AND BUILD_WITH_ANDROID_NDK )
+ set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/mipself.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" )
+ set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/mipself.xsc ${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" )
+ set( CMAKE_EXE_LINKER_FLAGS    "-Wl,-T,${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}/mipself.x ${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" )
+else()
+ 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}" )
+endif()
 
-#set these global flags for cmake client scripts to change behavior
+# set these global flags for cmake client scripts to change behavior
 set( ANDROID True )
 set( BUILD_ANDROID True )
 
-# where is the target environment 
+# 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
@@ -884,7 +980,7 @@ 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 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 )
@@ -906,7 +1002,7 @@ macro( find_host_package )
 endmacro()
 
 
-#macro to find programs on the host OS
+# 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 )
@@ -944,13 +1040,18 @@ endmacro()
 # export toolchain settings for the try_compile() command
 if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
  set( __toolchain_config "")
- foreach( __var ANDROID_ABI ANDROID_FORCE_ARM_BUILD ANDROID_NATIVE_API_LEVEL ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_SET_OBSOLETE_VARIABLES LIBRARY_OUTPUT_PATH_ROOT ANDROID_USE_STLPORT ANDROID_FORBID_SYGWIN ANDROID_NDK ANDROID_STANDALONE_TOOLCHAIN )
+ foreach( __var ANDROID_ABI ANDROID_FORCE_ARM_BUILD ANDROID_NATIVE_API_LEVEL ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_SET_OBSOLETE_VARIABLES LIBRARY_OUTPUT_PATH_ROOT ANDROID_USE_STLPORT ANDROID_FORBID_SYGWIN ANDROID_NDK ANDROID_STANDALONE_TOOLCHAIN ANDROID_FUNCTION_LEVEL_LINKING __ndklibspath )
   if( DEFINED ${__var} )
-   set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" )\n" )
+   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_CURRENT_BINARY_DIR}/CMakeFiles/android.toolchain.config.cmake" "${__toolchain_config}" )
+ file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" )
  unset( __toolchain_config )
+ unset( __ndklibspath )
 endif()
 
 
@@ -963,19 +1064,23 @@ if( ANDROID_SET_OBSOLETE_VARIABLES )
  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"
-#   ANDROID_FORCE_ARM_BUILD : ON/OFF
+#   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_SET_OBSOLETE_VARIABLES : ON/OFF
+#   ANDROID_USE_STLPORT : OFF/ON - EXPERIMENTAL!!!
+#   ANDROID_FORBID_SYGWIN : ON/OFF
 #   ANDROID_NO_UNDEFINED : ON/OFF
 #   ANDROID_SO_UNDEFINED : OFF/ON  (default depends on NDK version)
-#   ANDROID_SET_OBSOLETE_VARIABLES : ON/OFF
+#   ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF
+# Variables that takes effect only at first run:
+#   ANDROID_FORCE_ARM_BUILD : ON/OFF
 #   LIBRARY_OUTPUT_PATH_ROOT : <any valid path>
-#   ANDROID_USE_STLPORT : OFF/ON - EXPERIMENTAL!!! 
-#   ANDROID_FORBID_SYGWIN : ON/OFF
 # Can be set only at the first run:
 #   ANDROID_NDK
 #   ANDROID_STANDALONE_TOOLCHAIN
+#   ANDROID_TOOLCHAIN_NAME : "arm-linux-androideabi-4.4.3" or "arm-linux-androideabi-4.6" or "mipsel-linux-android-4.4.3" or "mipsel-linux-android-4.6" or "x86-4.4.3" or "x86-4.6"
 # Obsolete:
 #   ANDROID_API_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL
 #   ARM_TARGET : superseded by ANDROID_ABI
@@ -996,8 +1101,9 @@ endif()
 #   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" or "x86" depending on ANDROID_ABI
-#   ANDROID_ARCH_NAME : "arm" or "x86" depending on ANDROID_ABI
+#   ANDROID_ARCH_NAME : "arm" or "x86" or "mips" depending on ANDROID_ABI
 #   TOOL_OS_SUFFIX : "" or ".exe" depending on host platform
+#   ANDROID_SYSROOT : path to the compiler sysroot
 #   ANDROID_SYSTEM_INCLUDE_DIRS
 #   ANDROID_SYSTEM_LIB_DIRS
 # Obsolete:
@@ -1007,8 +1113,6 @@ endif()
 #   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_SYSROOT : path to the compiler sysroot
-#   ANDROID_TOOLCHAIN_NAME : "standalone", "arm-linux-androideabi-4.4.3" or "x86-4.4.3" or something similar.
 #   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_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK
index 7d39d8ada5e0ffafc0f730bcdd3e913744f734d2..0d93b31bcafa6e56604fa639a7656d20128835ca 100644 (file)
@@ -134,7 +134,11 @@ int execute(char * const * args)
     if (pid == 0) {
         // child
         execvp(args[0], args);
-        fprintf(stderr, "error: failed to execute %s\n", args[0]);
+        fprintf(stderr, "error: failed to execute:");
+        for (unsigned i = 0; args[i]; ++i) {
+            fprintf(stderr, " %s", args[i]);
+        }
+        fprintf(stderr, "\n");
         exit(-1);
     } else {
         // parent
index fe7faaa004ae98fc318a07da9ea3aa174ee9fbec..5e9577b56a29924b816abfc10fb16baf70a9bb14 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright 2011 Jose Fonseca
+ * Copyright 2011-2012 Jose Fonseca
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,9 +24,9 @@
  **************************************************************************/
 
 /*
- * Simple OS abstraction.
+ * OS native thread abstraction.
  *
- * Mimics C++11 / boost threads.
+ * Mimics C++11 threads.
  */
 
 #ifndef _OS_THREAD_HPP_
 #include <pthread.h>
 #endif
 
+
+#define USE_WIN32_CONDITION_VARIABLES 0
+
+
+/**
+ * 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(_MSC_VER)
+#  define thread_specific __declspec(thread)
+#elif defined(__GNUC__)
+#  define thread_specific __thread
+#else
+#  define thread_specific
+#  error "Unsupported compiler"
+#endif
+
+
 namespace os {
 
 
-    class recursive_mutex
+    /**
+     * Base class for mutex and recursive_mutex.
+     */
+    class _base_mutex
     {
     public:
 #ifdef _WIN32
@@ -51,7 +75,7 @@ namespace os {
         typedef pthread_mutex_t native_handle_type;
 #endif
 
-        recursive_mutex(void) {
+        _base_mutex(void) {
 #ifdef _WIN32
             InitializeCriticalSection(&_native_handle);
 #else
@@ -63,7 +87,7 @@ namespace os {
 #endif
         }
 
-        ~recursive_mutex() {
+        ~_base_mutex() {
 #ifdef _WIN32
             DeleteCriticalSection(&_native_handle);
 #else
@@ -89,73 +113,235 @@ namespace os {
 #endif
         }
 
-    private:
+        native_handle_type & native_handle() {
+            return _native_handle;
+        }
+
+    protected:
         native_handle_type _native_handle;
     };
 
 
-    template <typename T>
-    class thread_specific_ptr
+    /**
+     * Same interface as std::mutex.
+     */
+    class mutex : public _base_mutex
     {
-    private:
+    public:
+        inline
+        mutex(void) {
 #ifdef _WIN32
-        DWORD dwTlsIndex;
+            InitializeCriticalSection(&_native_handle);
 #else
-        pthread_key_t key;
+            pthread_mutex_init(&_native_handle, NULL);
+#endif
+        }
+    };
+
+
+    /**
+     * Same interface as std::recursive_mutex.
+     */
+    class recursive_mutex : public _base_mutex
+    {
+    public:
+        inline
+        recursive_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
+        }
+    };
+
+
+    /**
+     * Same interface as std::unique_lock;
+     */
+    template< class Mutex >
+    class unique_lock
+    {
+    public:
+        typedef Mutex mutex_type;
+
+        inline explicit
+        unique_lock(mutex_type & mutex) :
+            _mutex(&mutex)
+        {
+            _mutex->lock();
+        }
+
+        inline
+        ~unique_lock() {
+            _mutex->unlock();
+        }
+
+        inline void
+        lock() {
+            _mutex->lock();
+        }
 
-        static void destructor(void *ptr) {
-            delete static_cast<T *>(ptr);
+        inline void
+        unlock() {
+            _mutex->unlock();
+        }
+
+        mutex_type *
+        mutex() const {
+            return _mutex;
         }
+
+    protected:
+        mutex_type *_mutex;
+    };
+
+
+    /**
+     * Same interface as std::condition_variable
+     */
+    class condition_variable
+    {
+    private:
+#ifdef _WIN32
+#  if USE_WIN32_CONDITION_VARIABLES
+        // XXX: Only supported on Vista an higher. Not yet supported by WINE.
+        typedef CONDITION_VARIABLE native_handle_type;
+        native_handle_type _native_handle;
+#else
+        // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+        LONG cWaiters;
+        HANDLE hEvent;
+#endif
+#else
+        typedef pthread_cond_t native_handle_type;
+        native_handle_type _native_handle;
 #endif
 
     public:
-        thread_specific_ptr(void) {
+        condition_variable() {
+#ifdef _WIN32
+#  if USE_WIN32_CONDITION_VARIABLES
+            InitializeConditionVariable(&_native_handle);
+#  else
+            cWaiters = 0;
+            hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+#  endif
+#else
+            pthread_cond_init(&_native_handle, NULL);
+#endif
+        }
+
+        ~condition_variable() {
 #ifdef _WIN32
-            dwTlsIndex = TlsAlloc();
+#  if USE_WIN32_CONDITION_VARIABLES
+            /* No-op */
+#  else
+            CloseHandle(hEvent);
+#  endif
 #else
-            pthread_key_create(&key, &destructor);
+            pthread_cond_destroy(&_native_handle);
 #endif
         }
 
-        ~thread_specific_ptr() {
+        inline void
+        signal(void) {
 #ifdef _WIN32
-            TlsFree(dwTlsIndex);
+#  if USE_WIN32_CONDITION_VARIABLES
+            WakeConditionVariable(&_native_handle);
+#  else
+            if (cWaiters) {
+                SetEvent(hEvent);
+            }
+#  endif
 #else
-            pthread_key_delete(key);
+            pthread_cond_signal(&_native_handle);
 #endif
         }
 
-        T* get(void) const {
-            void *ptr;
+        inline void
+        wait(unique_lock<mutex> & lock) {
+            mutex::native_handle_type & mutex_native_handle = lock.mutex()->native_handle();
 #ifdef _WIN32
-            ptr = TlsGetValue(dwTlsIndex);
+#  if USE_WIN32_CONDITION_VARIABLES
+            SleepConditionVariableCS(&_native_handle, &mutex_native_handle, INFINITE);
+#  else
+            InterlockedIncrement(&cWaiters);
+            LeaveCriticalSection(&mutex_native_handle);
+            WaitForSingleObject(hEvent, INFINITE);
+            EnterCriticalSection(&mutex_native_handle);
+            InterlockedDecrement(&cWaiters);
+#  endif
 #else
-            ptr = pthread_getspecific(key);
+            pthread_cond_wait(&_native_handle, &mutex_native_handle);
 #endif
-            return static_cast<T*>(ptr);
         }
+    };
 
-        T* operator -> (void) const
+
+    /**
+     * Same interface as std::thread
+     */
+    class thread {
+    public:
+#ifdef _WIN32
+        typedef HANDLE native_handle_type;
+#else
+        typedef pthread_t native_handle_type;
+#endif
+
+        inline
+        thread() :
+            _native_handle(0)
         {
-            return get();
         }
 
-        T& operator * (void) const
+        inline
+        thread(thread &other) :
+            _native_handle(other._native_handle)
         {
-            return *get();
         }
 
-        void reset(T* new_value=0) {
-            T * old_value = get();
+        template< class Function, class Arg >
+        explicit thread( Function& f, Arg arg ) {
 #ifdef _WIN32
-            TlsSetValue(dwTlsIndex, new_value);
+            DWORD id = 0;
+            _native_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)f, (LPVOID)arg, 0, &id);
 #else
-            pthread_setspecific(key, new_value);
+            pthread_create(&_native_handle, NULL, ( void *(*) (void *))f, arg);
 #endif
-            if (old_value) {
-                delete old_value;
-            }
         }
+
+        inline bool
+        joinable(void) const {
+            return _native_handle != 0;
+        }
+
+        inline void
+        join() {
+#ifdef _WIN32
+            WaitForSingleObject(_native_handle, INFINITE);
+#else
+            pthread_join(_native_handle, NULL);
+#endif
+        }
+
+    private:
+        native_handle_type _native_handle;
+
+#if 0
+#ifdef _WIN32
+        template< class Function, class Arg >
+        static DWORD WINAPI
+        ThreadProc(LPVOID lpParameter) {
+
+        );
+#endif
+#endif
     };
 
 } /* namespace os */
index 75175d85f6ecb15d8fc69622e10526b23ab5bb3d..13cc733ae05488312b4fb5554d08fcb8fd49bc2d 100644 (file)
 
 
 #if defined(_WIN32)
-#include <windows.h>
-#elif defined(__linux__)
-#include <time.h>
-#elif defined(__APPLE__)
-#include <mach/mach_time.h>
+#  include <windows.h>
 #else
-#include <sys/time.h>
+#  if defined(__linux__)
+#    include <time.h>
+#  elif defined(__APPLE__)
+#    include <mach/mach_time.h>
+#  else
+#    include <sys/time.h>
+#  endif
+#  include <unistd.h>
 #endif
 
 
@@ -88,6 +91,15 @@ namespace os {
 #endif
     }
 
+    // Suspend execution
+    inline void
+    sleep(unsigned long usecs) {
+#if defined(_WIN32)
+        Sleep((usecs + 999) / 1000);
+#else
+        usleep(usecs);
+#endif
+    }
 
 } /* namespace os */
 
index 617928cc080292c0055a4827c8dfd8f5af2293cd..e9306cdc6dfa0168b3bca328d5511b66bb551932 100644 (file)
@@ -275,6 +275,15 @@ unhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
         return EXCEPTION_CONTINUE_SEARCH;
     }
 
+    /*
+     * Ignore .NET exception.
+     *
+     * http://ig2600.blogspot.co.uk/2011/01/why-do-i-keep-getting-exception-code.html
+     */
+    if (pExceptionRecord->ExceptionCode == 0xe0434352) {
+        return EXCEPTION_CONTINUE_SEARCH;
+    }
+
     // Clear direction flag
 #ifdef _MSC_VER
 #ifndef _WIN64
index 60694fa83d92d8da1e9891e6865574d13d7e0ea2..41667e653783be3bf934ceba9a11afaaba373615 100644 (file)
@@ -300,12 +300,15 @@ protected:
             return;
         }
 
-        unsigned c = 1;
         // Same as l >> (8 * sizeof l), but without the warnings
         T sign = l < 0 ? ~0 : 0;
-        while ((l >> (8 * c)) != sign) {
+
+        T sl = l;
+        unsigned c = 0;
+        do {
             ++c;
-        }
+        } while (sl >>= 8 != sign);
+
         // Add an extra byte if sign bit doesn't match
         if (((l >> (8 * c - 1)) & 1) != ((l >> (8 * sizeof l - 1)) & 1)) {
             ++c;
index dcc846be36735d307f21fe75c8e9e8cd00abc541..78a095523c5095d6a42a5f4450a3f574e244766f 100644 (file)
@@ -56,6 +56,7 @@ defaultCallFlags = 0;
 const Entry<CallFlags>
 callFlagTable[] = {
     { "CGLFlushDrawable",                              CALL_FLAG_END_FRAME },
+    { "CGLGetCurrentContext",                          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 },
@@ -74,6 +75,7 @@ callFlagTable[] = {
     { "IDirect3DDevice9::GetDeviceCaps",               CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
     { "IDirect3DDevice9::GetRenderTargetData",         CALL_FLAG_END_FRAME },
     { "IDirect3DDevice9::Present",                     CALL_FLAG_END_FRAME },
+    { "IDirect3DDevice9::SetRenderTarget",             CALL_FLAG_SWAP_RENDERTARGET },
     { "IDirect3DDevice9Ex::Clear",                     CALL_FLAG_RENDER },
     { "IDirect3DDevice9Ex::DrawIndexedPrimitive",      CALL_FLAG_RENDER },
     { "IDirect3DDevice9Ex::DrawIndexedPrimitiveUP",    CALL_FLAG_RENDER },
@@ -84,6 +86,7 @@ callFlagTable[] = {
     { "IDirect3DDevice9Ex::GetDeviceCaps",             CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
     { "IDirect3DDevice9Ex::GetRenderTargetData",       CALL_FLAG_END_FRAME },
     { "IDirect3DDevice9Ex::Present",                   CALL_FLAG_END_FRAME },
+    { "IDirect3DDevice9Ex::SetRenderTarget",           CALL_FLAG_SWAP_RENDERTARGET },
     { "IDirect3DSwapChain9::Present",                  CALL_FLAG_END_FRAME },
     { "IDirect3DSwapChain9Ex::Present",                CALL_FLAG_END_FRAME },
     { "eglGetProcAddress",                             CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
@@ -170,6 +173,8 @@ callFlagTable[] = {
     { "glXGetCurrentContext",                          CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
     { "glXGetCurrentDisplay",                          CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
     { "glXGetCurrentDrawable",                         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 },
diff --git a/common/trace_profiler.cpp b/common/trace_profiler.cpp
new file mode 100644 (file)
index 0000000..0f90ee2
--- /dev/null
@@ -0,0 +1,200 @@
+/**************************************************************************
+ *
+ * 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 "trace_profiler.hpp"
+#include "os_time.hpp"
+#include <iostream>
+#include <string.h>
+#include <sstream>
+
+namespace trace {
+Profiler::Profiler()
+    : baseGpuTime(0),
+      baseCpuTime(0),
+      minCpuTime(1000),
+      cpuTimes(false),
+      gpuTimes(true),
+      pixelsDrawn(false)
+{
+}
+
+Profiler::~Profiler()
+{
+}
+
+void Profiler::setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_)
+{
+    cpuTimes = cpuTimes_;
+    gpuTimes = gpuTimes_;
+    pixelsDrawn = pixelsDrawn_;
+
+    std::cout << "# call no gpu_start gpu_dura cpu_start cpu_dura pixels program name" << std::endl;
+}
+
+int64_t Profiler::getBaseCpuTime()
+{
+    return baseCpuTime;
+}
+
+int64_t Profiler::getBaseGpuTime()
+{
+    return baseGpuTime;
+}
+
+void Profiler::setBaseCpuTime(int64_t cpuStart)
+{
+    baseCpuTime = cpuStart;
+}
+
+void Profiler::setBaseGpuTime(int64_t gpuStart)
+{
+    baseGpuTime = gpuStart;
+}
+
+bool Profiler::hasBaseTimes()
+{
+    return baseCpuTime != 0 || baseGpuTime != 0;
+}
+
+void Profiler::addCall(unsigned no,
+                       const char *name,
+                       unsigned program,
+                       int64_t pixels,
+                       int64_t gpuStart, int64_t gpuDuration,
+                       int64_t cpuStart, int64_t cpuDuration)
+{
+    if (gpuTimes && gpuStart) {
+        gpuStart -= baseGpuTime;
+    } else {
+        gpuStart = 0;
+        gpuDuration = 0;
+    }
+
+    if (cpuTimes && cpuStart) {
+        double cpuTimeScale = 1.0E9 / os::timeFrequency;
+        cpuStart = (cpuStart - baseCpuTime) * cpuTimeScale;
+        cpuDuration = cpuDuration * cpuTimeScale;
+
+        if (cpuDuration < minCpuTime) {
+            return;
+        }
+    } else {
+        cpuStart = 0;
+        cpuDuration = 0;
+    }
+
+    if (!pixelsDrawn) {
+        pixels = 0;
+    }
+
+    std::cout << "call"
+              << " " << no
+              << " " << gpuStart
+              << " " << gpuDuration
+              << " " << cpuStart
+              << " " << cpuDuration
+              << " " << pixels
+              << " " << program
+              << " " << name
+              << std::endl;
+}
+
+void Profiler::addFrameEnd()
+{
+    std::cout << "frame_end" << std::endl;
+}
+
+void Profiler::parseLine(const char* in, Profile* profile)
+{
+    std::stringstream line(in, std::ios_base::in);
+    std::string type;
+    static int64_t lastGpuTime;
+    static int64_t lastCpuTime;
+
+    if (in[0] == '#' || strlen(in) < 4)
+        return;
+
+    if (profile->programs.size() == 0 && profile->calls.size() == 0 && profile->frames.size() == 0) {
+        lastGpuTime = 0;
+        lastCpuTime = 0;
+    }
+
+    line >> type;
+
+    if (type.compare("call") == 0) {
+        Profile::Call call;
+
+        line >> call.no
+             >> call.gpuStart
+             >> call.gpuDuration
+             >> call.cpuStart
+             >> call.cpuDuration
+             >> call.pixels
+             >> call.program
+             >> call.name;
+
+        if (lastGpuTime < call.gpuStart + call.gpuDuration) {
+            lastGpuTime = call.gpuStart + call.gpuDuration;
+        }
+
+        if (lastCpuTime < call.cpuStart + call.cpuDuration) {
+            lastCpuTime = call.cpuStart + call.cpuDuration;
+        }
+
+        profile->calls.push_back(call);
+
+        if (call.pixels >= 0) {
+            if (profile->programs.size() <= call.program) {
+                profile->programs.resize(call.program + 1);
+            }
+
+            Profile::Program& program = profile->programs[call.program];
+            program.cpuTotal += call.cpuDuration;
+            program.gpuTotal += call.gpuDuration;
+            program.pixelTotal += call.pixels;
+            program.calls.push_back(profile->calls.size() - 1);
+        }
+    } else if (type.compare("frame_end") == 0) {
+        Profile::Frame frame;
+        frame.no = profile->frames.size();
+
+        if (frame.no == 0) {
+            frame.gpuStart = 0;
+            frame.cpuStart = 0;
+            frame.calls.begin = 0;
+        } else {
+            frame.gpuStart = profile->frames.back().gpuStart + profile->frames.back().gpuDuration;
+            frame.cpuStart = profile->frames.back().cpuStart + profile->frames.back().cpuDuration;
+            frame.calls.begin = profile->frames.back().calls.end + 1;
+        }
+
+        frame.gpuDuration = lastGpuTime - frame.gpuStart;
+        frame.cpuDuration = lastCpuTime - frame.cpuStart;
+        frame.calls.end = profile->calls.size() - 1;
+
+        profile->frames.push_back(frame);
+    }
+}
+}
diff --git a/common/trace_profiler.hpp b/common/trace_profiler.hpp
new file mode 100644 (file)
index 0000000..d833242
--- /dev/null
@@ -0,0 +1,123 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef TRACE_PROFILER_H
+#define TRACE_PROFILER_H
+
+#include <string>
+#include <vector>
+#include <stdint.h>
+
+namespace trace
+{
+
+struct Profile {
+    struct Call {
+        unsigned no;
+
+        unsigned program;
+
+        int64_t gpuStart;
+        int64_t gpuDuration;
+
+        int64_t cpuStart;
+        int64_t cpuDuration;
+
+        int64_t pixels;
+
+        std::string name;
+    };
+
+    struct Frame {
+        unsigned no;
+
+        int64_t gpuStart;
+        int64_t gpuDuration;
+
+        int64_t cpuStart;
+        int64_t cpuDuration;
+
+        /* Indices to profile->calls array */
+        struct {
+            unsigned begin;
+            unsigned end;
+        } calls;
+    };
+
+    struct Program {
+        Program() : gpuTotal(0), cpuTotal(0), pixelTotal(0) {}
+
+        uint64_t gpuTotal;
+        uint64_t cpuTotal;
+        uint64_t pixelTotal;
+
+        /* Indices to profile->calls array */
+        std::vector<unsigned> calls;
+    };
+
+    std::vector<Call> calls;
+    std::vector<Frame> frames;
+    std::vector<Program> programs;
+};
+
+class Profiler
+{
+public:
+    Profiler();
+    ~Profiler();
+
+    void setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_);
+
+    void addCall(unsigned no,
+                 const char* name,
+                 unsigned program,
+                 int64_t pixels,
+                 int64_t gpuStart, int64_t gpuDuration,
+                 int64_t cpuStart, int64_t cpuDuration);
+
+    void addFrameEnd();
+
+    bool hasBaseTimes();
+
+    void setBaseCpuTime(int64_t cpuStart);
+    void setBaseGpuTime(int64_t gpuStart);
+
+    int64_t getBaseCpuTime();
+    int64_t getBaseGpuTime();
+
+    static void parseLine(const char* line, Profile* profile);
+
+private:
+    int64_t baseGpuTime;
+    int64_t baseCpuTime;
+    int64_t minCpuTime;
+
+    bool cpuTimes;
+    bool gpuTimes;
+    bool pixelsDrawn;
+};
+}
+
+#endif // TRACE_PROFILER_H
index 5aeedac520febb823ad08e86aa10bd30a05a24ca..feb5c912dfd06b2a61f2a003f9f9759bc23255e0 100644 (file)
@@ -128,8 +128,8 @@ LocalWriter::open(void) {
 #endif
 }
 
-static unsigned next_thread_id = 0;
-static os::thread_specific_ptr<unsigned> thread_id_specific_ptr;
+static unsigned next_thread_num = 1;
+static thread_specific unsigned thread_num = 0;
 
 unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
     mutex.lock();
@@ -139,17 +139,13 @@ unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
         open();
     }
 
-    unsigned *thread_id_ptr = thread_id_specific_ptr.get();
-    unsigned thread_id;
-    if (thread_id_ptr) {
-        thread_id = *thread_id_ptr;
-    } else {
-        thread_id = next_thread_id++;
-        thread_id_ptr = new unsigned;
-        *thread_id_ptr = thread_id;
-        thread_id_specific_ptr.reset(thread_id_ptr);
+    unsigned this_thread_num = thread_num;
+    if (!this_thread_num) {
+        this_thread_num = thread_num = next_thread_num++;
     }
 
+    assert(thread_num > 0);
+    unsigned thread_id = thread_num - 1;
     return Writer::beginEnter(sig, thread_id);
 }
 
index 070aca70faaac02b58a1f9195506a8cd3a4ccbbd..8968cb4852f2c52eff7e328f7f822b59941864fa 100644 (file)
@@ -14,6 +14,8 @@ set(qapitrace_SRCS
    jumpwidget.cpp
    mainwindow.cpp
    main.cpp
+   profiledialog.cpp
+   profiletablemodel.cpp
    retracer.cpp
    saverthread.cpp
    searchwidget.cpp
@@ -24,6 +26,14 @@ set(qapitrace_SRCS
    traceprocess.cpp
    trimprocess.cpp
    vertexdatainterpreter.cpp
+   graphing/frameaxiswidget.cpp
+   graphing/graphwidget.cpp
+   graphing/graphaxiswidget.cpp
+   graphing/graphview.cpp
+   graphing/heatmapview.cpp
+   graphing/heatmapverticalaxiswidget.cpp
+   graphing/histogramview.cpp
+   graphing/timeaxiswidget.cpp
  )
 
 qt4_automoc(${qapitrace_SRCS})
@@ -35,6 +45,8 @@ set(qapitrace_UIS
    ui/imageviewer.ui
    ui/jumpwidget.ui
    ui/mainwindow.ui
+   ui/profiledialog.ui
+   ui/profilereplaydialog.ui
    ui/retracerdialog.ui
    ui/settings.ui
    ui/tracedialog.ui
@@ -59,6 +71,11 @@ target_link_libraries (qapitrace
     ${QT_LIBRARIES}
 )
 
+# Recent builds of Qt no longer support i386 architecture
+if (APPLE)
+    set_target_properties (qapitrace PROPERTIES OSX_ARCHITECTURES x86_64)
+endif ()
+
 ########### install files ###############
 
 install (TARGETS qapitrace RUNTIME DESTINATION bin)
index b11c17c6740e33520dd366b50fed219ce3283cd4..6a8ebe2cd043a4608191db584f2b78274ba09143 100644 (file)
@@ -230,7 +230,7 @@ bool ApiTrace::isSaving() const
 
 bool ApiTrace::hasErrors() const
 {
-    return !m_errors.isEmpty();
+    return !m_errors.isEmpty() || !m_queuedErrors.isEmpty();
 }
 
 void ApiTrace::loadFrame(ApiTraceFrame *frame)
diff --git a/gui/calldurationgraph.h b/gui/calldurationgraph.h
new file mode 100644 (file)
index 0000000..0c7e8c9
--- /dev/null
@@ -0,0 +1,173 @@
+#ifndef CALLDURATIONGRAPH_H
+#define CALLDURATIONGRAPH_H
+
+#include "graphing/graphwidget.h"
+#include "trace_profiler.hpp"
+#include "profiling.h"
+
+/**
+ * Wrapper for call duration graphs.
+ *
+ * This implements the transformSelectionIn and transformSelectionOut to
+ * allow sharing the selection between the graphs and the heatmap as they
+ * are using different scales. The duration graphs have call.no on the X-axis
+ * whereas the heatmap has time on the X axis.
+ */
+class CallDurationGraph : public GraphWidget {
+public:
+    CallDurationGraph(QWidget* parent = 0) :
+        GraphWidget(parent),
+        m_profile(NULL)
+    {
+    }
+
+    void setProfile(const trace::Profile* profile)
+    {
+        m_profile = profile;
+    }
+
+protected:
+    /* Transform from time-based horizontal selection to call no based. */
+    virtual SelectionState transformSelectionIn(SelectionState state)
+    {
+        if (!m_profile || state.type != SelectionState::Horizontal) {
+            return state;
+        }
+
+        qint64 timeStart = state.start;
+        qint64 timeEnd = state.end;
+
+        std::vector<trace::Profile::Call>::const_iterator itr;
+
+        itr =
+            Profiling::binarySearchTimespan<
+                trace::Profile::Call,
+                &trace::Profile::Call::cpuStart,
+                &trace::Profile::Call::cpuDuration>
+            (m_profile->calls.begin(), m_profile->calls.end(), timeStart, true);
+
+        state.start = itr - m_profile->calls.begin();
+
+        itr =
+            Profiling::binarySearchTimespan<
+                trace::Profile::Call,
+                &trace::Profile::Call::cpuStart,
+                &trace::Profile::Call::cpuDuration>
+            (m_profile->calls.begin(), m_profile->calls.end(), timeEnd, true);
+
+        state.end = itr - m_profile->calls.begin();
+
+        return state;
+    }
+
+    virtual SelectionState transformSelectionOut(SelectionState state)
+    {
+        if (!m_profile || state.type != SelectionState::Horizontal) {
+            return state;
+        }
+
+        qint64 start = qMax<qint64>(0, state.start);
+        qint64 end = qMin<qint64>(state.end, m_profile->calls.size());
+
+        /* Call based -> time based */
+        state.start = m_profile->calls[start].cpuStart;
+        state.end = m_profile->calls[end].cpuStart + m_profile->calls[end].cpuDuration;
+
+        return state;
+    }
+
+private:
+    const trace::Profile* m_profile;
+};
+
+/* Data provider for call duration graphs */
+class CallDurationDataProvider : public GraphDataProvider {
+public:
+    CallDurationDataProvider(const trace::Profile* profile, bool gpu) :
+        m_gpu(gpu),
+        m_profile(profile),
+        m_selectionState(NULL)
+    {
+    }
+
+    virtual qint64 size() const
+    {
+        return m_profile ? m_profile->calls.size() : 0;
+    }
+
+    virtual bool selected(qint64 index) const
+    {
+        if (m_selectionState) {
+            if (m_selectionState->type == SelectionState::Horizontal) {
+                if (m_selectionState->start <= index && index < m_selectionState->end) {
+                    return true;
+                }
+            } else if (m_selectionState->type == SelectionState::Vertical) {
+                return m_profile->calls[index].program == m_selectionState->start;
+            }
+        }
+
+        return false;
+    }
+
+    virtual void setSelectionState(SelectionState* state)
+    {
+        m_selectionState = state;
+    }
+
+    virtual qint64 value(qint64 index) const
+    {
+        if (m_gpu) {
+            return m_profile->calls[index].gpuDuration;
+        } else {
+            return m_profile->calls[index].cpuDuration;
+        }
+    }
+
+    virtual void itemDoubleClicked(qint64 index) const
+    {
+        if (!m_profile) {
+            return;
+        }
+
+        if (index < 0 || index >= m_profile->calls.size()) {
+            return;
+        }
+
+        const trace::Profile::Call& call = m_profile->calls[index];
+        Profiling::jumpToCall(call.no);
+    }
+
+    virtual QString itemTooltip(qint64 index) const
+    {
+        if (!m_profile) {
+            return QString();
+        }
+
+        if (index < 0 || index >= m_profile->calls.size()) {
+            return QString();
+        }
+
+        const trace::Profile::Call& call = m_profile->calls[index];
+
+        QString text;
+        text  = QString::fromStdString(call.name);
+        text += QString("\nCall: %1").arg(call.no);
+        text += QString("\nCPU Duration: %1").arg(Profiling::getTimeString(call.cpuDuration));
+
+        if (call.pixels >= 0) {
+            text += QString("\nGPU Duration: %1").arg(Profiling::getTimeString(call.gpuDuration));
+            text += QString("\nPixels Drawn: %1").arg(QLocale::system().toString((qlonglong)call.pixels));
+            text += QString("\nProgram: %1").arg(call.program);
+        }
+
+        return text;
+    }
+
+private:
+    bool m_gpu;
+    const trace::Profile* m_profile;
+    SelectionState* m_selectionState;
+};
+
+#endif
diff --git a/gui/graphing/frameaxiswidget.cpp b/gui/graphing/frameaxiswidget.cpp
new file mode 100644 (file)
index 0000000..ad5d868
--- /dev/null
@@ -0,0 +1,99 @@
+#include "frameaxiswidget.h"
+
+#include <QPainter>
+
+FrameAxisWidget::FrameAxisWidget(QWidget* parent) :
+    GraphAxisWidget(parent),
+    m_data(NULL)
+{
+    setSelectable(GraphAxisWidget::Range);
+}
+
+void FrameAxisWidget::setDataProvider(FrameDataProvider* data)
+{
+    delete m_data;
+    m_data = data;
+}
+
+void FrameAxisWidget::paintEvent(QPaintEvent *)
+{
+    if (!m_data || m_orientation != GraphAxisWidget::Horizontal) {
+        /* TODO: Vertical axis support */
+        return;
+    }
+
+    QPainter painter(this);
+    painter.setPen(Qt::black);
+    painter.setBrush(Qt::lightGray);
+    painter.drawRect(0, 0, width() - 1, height() - 1);
+
+    qint64 range = m_valueEnd - m_valueBegin;
+    double dxdv = width() / (double)range;
+    double scroll = dxdv * m_valueBegin;
+    int lastLabel = -9999;
+
+    /* Iterate over frames, drawing a label when there is space to do so */
+    for (unsigned i = 0; i < m_data->size(); ++i) {
+        static const int padding = 4;
+        qint64 start = m_data->frameStart(i);
+        qint64 end = m_data->frameEnd(i);
+        bool visible = false;
+
+        if (start > m_valueEnd) {
+            break;
+        }
+
+        if (end < m_valueBegin) {
+            visible = false;
+        }
+
+        double left = dxdv * start;
+        double right = dxdv * end;
+        QString text = QString("%1").arg(i);
+
+        int width = painter.fontMetrics().width(text) + padding * 2;
+
+        if (right > scroll) {
+            visible = true;
+        }
+
+        if (left - lastLabel > width) {
+            lastLabel = left + width;
+
+            if (visible) {
+                int textX;
+
+                if (left < scroll && right - left > width) {
+                    if (right - scroll > width) {
+                        textX = 0;
+                    } else {
+                        textX = right - scroll - width;
+                    }
+                } else {
+                    textX = left - scroll;
+                }
+
+                painter.drawText(textX + padding, 0, width - padding, height() - 5, Qt::AlignLeft | Qt::AlignVCenter, text);
+                painter.drawLine(left - scroll, height() / 2, left - scroll, height() - 1);
+            }
+        } else if (visible) {
+            painter.drawLine(left - scroll, height() * 3/4.0, left - scroll, height() - 1);
+        }
+    }
+
+    /* Draw selection */
+    if (hasSelection()) {
+        double left = (dxdv * m_selectionState->start) - scroll;
+        double right = (dxdv * m_selectionState->end) - scroll;
+
+        painter.setPen(Qt::green);
+
+        if (left >= 0 && left <= width()) {
+            painter.drawLine(left, 0, left, height());
+        }
+
+        if (right >= 0 && right <= width()) {
+            painter.drawLine(right, 0, right, height());
+        }
+    }
+}
diff --git a/gui/graphing/frameaxiswidget.h b/gui/graphing/frameaxiswidget.h
new file mode 100644 (file)
index 0000000..db091d9
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef FRAMEAXISWIDGET_H
+#define FRAMEAXISWIDGET_H
+
+#include "graphaxiswidget.h"
+
+class FrameDataProvider {
+public:
+    /* Number of frames */
+    virtual unsigned size() const = 0;
+
+    /* Start and end values of frame */
+    virtual qint64 frameStart(unsigned frame) const = 0;
+    virtual qint64 frameEnd(unsigned frame) const = 0;
+};
+
+/**
+ * A generic axis which will draw frame numbers over a period of values.
+ * Frames designated by start / end values.
+ */
+class FrameAxisWidget : public GraphAxisWidget {
+public:
+    FrameAxisWidget(QWidget* parent = 0);
+
+    void setDataProvider(FrameDataProvider* data);
+
+    virtual void paintEvent(QPaintEvent *e);
+
+protected:
+    FrameDataProvider* m_data;
+};
+
+#endif
diff --git a/gui/graphing/graphaxiswidget.cpp b/gui/graphing/graphaxiswidget.cpp
new file mode 100644 (file)
index 0000000..0adeadd
--- /dev/null
@@ -0,0 +1,141 @@
+#include "graphaxiswidget.h"
+
+#include <QMouseEvent>
+
+GraphAxisWidget::GraphAxisWidget(QWidget* parent) :
+    QWidget(parent),
+    m_selectable(None),
+    m_selectionState(NULL)
+{
+}
+
+
+bool GraphAxisWidget::hasSelection()
+{
+    if (!m_selectionState) {
+        return false;
+    }
+
+    if (m_selectionState->type == SelectionState::Horizontal && m_orientation == GraphAxisWidget::Horizontal) {
+        return true;
+    }
+
+    if (m_selectionState->type == SelectionState::Vertical && m_orientation == GraphAxisWidget::Vertical) {
+        return true;
+    }
+
+    return false;
+}
+
+
+void GraphAxisWidget::setSelectable(SelectionStyle selectable)
+{
+    m_selectable = selectable;
+}
+
+
+void GraphAxisWidget::setSelectionState(SelectionState* state)
+{
+    m_selectionState = state;
+}
+
+
+void GraphAxisWidget::setOrientation(Orientation v)
+{
+    m_orientation = v;
+
+    if (m_orientation == Horizontal) {
+        setMinimumWidth(60);
+    } else {
+        setMinimumHeight(60);
+    }
+}
+
+
+void GraphAxisWidget::mouseMoveEvent(QMouseEvent *e)
+{
+    if (m_selectable == None) {
+        return;
+    }
+
+    int pos, max;
+
+    if (m_orientation == Horizontal) {
+        pos = e->x();
+        max = width();
+    } else {
+        pos = e->y();
+        max = height();
+    }
+
+    double value = m_valueEnd - m_valueBegin;
+    value *= pos / (double)max;
+    value += m_valueBegin;
+
+    if (e->buttons().testFlag(Qt::LeftButton)) {
+        m_selectionState->start = qMin<qint64>(m_mousePressValue, value);
+        m_selectionState->end = qMax<qint64>(m_mousePressValue, value);
+        m_selectionState->type = m_orientation == Horizontal ? SelectionState::Horizontal : SelectionState::Vertical;
+        emit selectionChanged();
+        update();
+    }
+}
+
+
+void GraphAxisWidget::mousePressEvent(QMouseEvent *e)
+{
+    if (m_selectable == None) {
+        return;
+    }
+
+    int pos, max;
+
+    if (m_orientation == Horizontal) {
+        pos = e->x();
+        max = width();
+    } else {
+        pos = e->y();
+        max = height();
+    }
+
+    double value = m_valueEnd - m_valueBegin;
+    value *= pos / (double)max;
+    value += m_valueBegin;
+
+    m_mousePressPosition = e->pos();
+    m_mousePressValue = value;
+}
+
+
+void GraphAxisWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+    if (m_selectable == None) {
+        return;
+    }
+
+    int dx = qAbs(m_mousePressPosition.x() - e->x());
+    int dy = qAbs(m_mousePressPosition.y() - e->y());
+
+    if (dx + dy < 2) {
+        m_selectionState->type = SelectionState::None;
+        emit selectionChanged();
+    }
+}
+
+
+void GraphAxisWidget::setRange(qint64 min, qint64 max)
+{
+    m_valueMin = min;
+    m_valueMax = max;
+    update();
+}
+
+
+void GraphAxisWidget::setView(qint64 start, qint64 end)
+{
+    m_valueBegin = start;
+    m_valueEnd = end;
+    update();
+}
+
+#include "graphaxiswidget.moc"
diff --git a/gui/graphing/graphaxiswidget.h b/gui/graphing/graphaxiswidget.h
new file mode 100644 (file)
index 0000000..6ae0080
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef GRAPHAXISWIDGET_H
+#define GRAPHAXISWIDGET_H
+
+#include "graphing.h"
+
+#include <QWidget>
+
+/**
+ * The generic base class of all graph axes.
+ *
+ * Handles orientation, simple selections, and view area.
+ */
+class GraphAxisWidget : public QWidget {
+    Q_OBJECT
+public:
+    enum Orientation {
+        Horizontal,
+        Vertical
+    };
+
+    enum SelectionStyle {
+        None,
+        Single,
+        Range
+    };
+
+public:
+    GraphAxisWidget(QWidget* parent = 0);
+    virtual ~GraphAxisWidget(){}
+
+    /* Is this axis part of the active selection */
+    bool hasSelection();
+
+    void setSelectable(SelectionStyle selectable);
+    void setSelectionState(SelectionState* state);
+
+    void setOrientation(Orientation v);
+
+    virtual void mouseMoveEvent(QMouseEvent *e);
+    virtual void mousePressEvent(QMouseEvent *e);
+    virtual void mouseReleaseEvent(QMouseEvent *e);
+
+public slots:
+    /* The minimum and maximum values of this axis */
+    void setRange(qint64 min, qint64 max);
+
+    /* The currently visible range of values */
+    void setView(qint64 start, qint64 end);
+
+signals:
+    void selectionChanged();
+
+protected:
+    Orientation m_orientation;
+
+    /* The min/max value of this axis */
+    qint64 m_valueMin;
+    qint64 m_valueMax;
+
+    /* The highest and lowest currently visible value */
+    qint64 m_valueBegin;
+    qint64 m_valueEnd;
+
+    /* Selection */
+    SelectionStyle m_selectable;
+    SelectionState* m_selectionState;
+
+    /* Mouse tracking */
+    QPoint m_mousePressPosition;
+    qint64 m_mousePressValue;
+};
+
+#endif
diff --git a/gui/graphing/graphing.h b/gui/graphing/graphing.h
new file mode 100644 (file)
index 0000000..35b4a91
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef GRAPHING_H
+#define GRAPHING_H
+
+#include <QString>
+
+/**
+ * A simple struct to hold a horizontal or vertical selection
+ */
+struct SelectionState {
+    enum SelectionType {
+        None,
+        Horizontal,
+        Vertical
+    };
+
+    SelectionType type;
+    qint64 start;
+    qint64 end;
+};
+
+
+/**
+ * Fairly generic data provider for graphs
+ */
+class GraphDataProvider {
+public:
+    virtual ~GraphDataProvider(){}
+
+    /* Number of elements in graph */
+    virtual qint64 size() const = 0;
+
+    /* Returns value for index */
+    virtual qint64 value(qint64 index) const = 0;
+
+    /* Is the item at index selected */
+    virtual bool selected(qint64 index) const = 0;
+
+    /* Get mouse hover tooltip for item */
+    virtual QString itemTooltip(qint64 index) const = 0;
+
+    /* Called on item double click */
+    virtual void itemDoubleClicked(qint64 index) const = 0;
+
+    /* Set pointer to selection state */
+    virtual void setSelectionState(SelectionState* state) = 0;
+};
+
+#endif
diff --git a/gui/graphing/graphlabelwidget.h b/gui/graphing/graphlabelwidget.h
new file mode 100644 (file)
index 0000000..49c0cd4
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef GRAPHLABELWIDGET_H
+#define GRAPHLABELWIDGET_H
+
+#include <QWidget>
+#include <QPainter>
+
+/**
+ * A very simple label widget, basically a box with text in.
+ */
+class GraphLabelWidget : public QWidget {
+public:
+    GraphLabelWidget(QString text = QString(), QWidget* parent = 0) :
+        QWidget(parent),
+        m_flags(Qt::AlignHCenter | Qt::AlignVCenter),
+        m_text(text)
+    {
+    }
+
+    void setText(const QString& text)
+    {
+        m_text = text;
+    }
+
+    void setFlags(int flags)
+    {
+        m_flags = flags;
+    }
+
+    virtual void paintEvent(QPaintEvent *)
+    {
+        QPainter painter(this);
+        painter.setPen(Qt::black);
+        painter.fillRect(rect(), Qt::lightGray);
+        painter.drawText(rect(), m_flags, m_text);
+    }
+
+protected:
+    int m_flags;
+    QString m_text;
+};
+
+#endif
diff --git a/gui/graphing/graphview.cpp b/gui/graphing/graphview.cpp
new file mode 100644 (file)
index 0000000..9b42c4b
--- /dev/null
@@ -0,0 +1,187 @@
+#include "graphview.h"
+
+#include <QMouseEvent>
+#include <QApplication>
+
+GraphView::GraphView(QWidget* parent) :
+    QWidget(parent),
+    m_viewLeft(0),
+    m_viewRight(0),
+    m_viewBottom(0),
+    m_viewTop(0),
+    m_graphLeft(0),
+    m_graphRight(0),
+    m_graphBottom(0),
+    m_graphTop(0),
+    m_viewWidth(0),
+    m_viewWidthMin(0),
+    m_viewWidthMax(0),
+    m_viewHeight(0),
+    m_viewHeightMin(0),
+    m_viewHeightMax(0),
+    m_selectionState(NULL)
+{
+    memset(&m_previous, -1, sizeof(m_previous));
+}
+
+void GraphView::update()
+{
+    if (m_graphLeft != m_previous.m_graphLeft || m_graphRight != m_previous.m_graphRight) {
+        m_previous.m_graphLeft = m_graphLeft;
+        m_previous.m_graphRight = m_graphRight;
+
+        emit horizontalRangeChanged(m_graphLeft, m_graphRight);
+    }
+
+    if (m_viewLeft != m_previous.m_viewLeft || m_viewRight != m_previous.m_viewRight) {
+        m_previous.m_viewLeft = m_viewLeft;
+        m_previous.m_viewRight = m_viewRight;
+
+        emit horizontalViewChanged(m_viewLeft, m_viewRight);
+    }
+
+    if (m_graphBottom != m_previous.m_graphBottom || m_graphTop != m_previous.m_graphTop) {
+        m_previous.m_graphBottom = m_graphBottom;
+        m_previous.m_graphTop = m_graphTop;
+
+        emit verticalRangeChanged(m_graphBottom, m_graphTop);
+    }
+
+    if (m_viewBottom != m_previous.m_viewBottom || m_viewTop != m_previous.m_viewTop) {
+        m_previous.m_viewBottom = m_viewBottom;
+        m_previous.m_viewTop = m_viewTop;
+
+        emit verticalViewChanged(m_viewBottom, m_viewTop);
+    }
+
+    QWidget::update();
+}
+
+void GraphView::resizeEvent(QResizeEvent *)
+{
+    m_viewHeight = height();
+    m_viewHeightMin = m_viewHeight;
+    m_viewHeightMax = m_viewHeight;
+
+    m_viewTop = m_viewBottom + m_viewHeight;
+
+    update();
+}
+
+void GraphView::wheelEvent(QWheelEvent *e)
+{
+    int zoomPercent = 10;
+
+    /* If holding Ctrl key then zoom 2x faster */
+    if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
+        zoomPercent = 20;
+    }
+
+    /* Zoom view by adjusting width */
+    double dt = m_viewWidth;
+    double size = dt;
+    size *= -e->delta();
+
+    /* Zoom deltas normally come in increments of 120 */
+    size /= 120 * (100 / zoomPercent);
+
+    m_viewWidth += size;
+    m_viewWidth = qBound(m_viewWidthMin, m_viewWidth, m_viewWidthMax);
+
+    /* Scroll view to zoom around mouse */
+    dt -= m_viewWidth;
+    dt *= e->x();
+    dt /= width();
+
+    m_viewLeft = dt + m_viewLeft;
+    m_viewLeft = qBound(m_graphLeft, m_viewLeft, m_graphRight - m_viewWidth);
+    m_viewRight = m_viewLeft + m_viewWidth;
+
+    update();
+}
+
+void GraphView::mouseMoveEvent(QMouseEvent *e)
+{
+    if (e->buttons().testFlag(Qt::LeftButton)) {
+        /* Horizontal scroll */
+        double dvdx = m_viewWidth / (double)width();
+        dvdx *= m_mousePressPosition.x() - e->pos().x();
+
+        m_viewLeft = m_mousePressViewLeft + dvdx;
+        m_viewLeft = qBound(m_graphLeft, m_viewLeft, m_graphRight - m_viewWidth);
+        m_viewRight = m_viewLeft + m_viewWidth;
+
+        /* Vertical scroll */
+        double dvdy = m_viewHeight / (double)height();
+        dvdy *= m_mousePressPosition.y() - e->pos().y();
+
+        m_viewBottom = m_mousePressViewBottom + dvdy;
+        m_viewBottom = qBound(m_graphBottom, m_viewBottom, m_graphTop - m_viewHeight);
+        m_viewTop = m_viewBottom + m_viewHeight;
+
+        update();
+    }
+}
+
+void GraphView::mousePressEvent(QMouseEvent *e)
+{
+    m_mousePressPosition = e->pos();
+    m_mousePressViewLeft = m_viewLeft;
+    m_mousePressViewBottom = m_viewBottom;
+}
+
+void GraphView::mouseDoubleClickEvent(QMouseEvent *e)
+{
+    if (m_selectionState) {
+        m_selectionState->type = SelectionState::None;
+        emit selectionChanged();
+    }
+}
+
+void GraphView::setSelectionState(SelectionState* state)
+{
+    m_selectionState = state;
+}
+
+void GraphView::setHorizontalView(qint64 start, qint64 end)
+{
+    m_viewLeft = qBound(m_graphLeft, start, m_graphRight - (end - start));
+    m_viewRight = qBound(m_graphLeft, end, m_graphRight);
+    m_viewWidth = m_viewRight - m_viewLeft;
+    update();
+}
+
+void GraphView::setVerticalView(qint64 start, qint64 end)
+{
+    m_viewBottom = qBound(m_graphBottom, start, m_graphTop - (end - start));
+    m_viewTop = qBound(m_graphBottom, end, m_graphTop);
+    m_viewHeight = m_viewTop - m_viewBottom;
+    update();
+}
+
+void GraphView::setDefaultView(qint64 min, qint64 max)
+{
+    m_graphLeft = min;
+    m_graphRight = max;
+    m_viewWidth = max - min;
+
+    m_viewWidthMin = 1;
+    m_viewWidthMax = m_viewWidth;
+
+    m_viewLeft = min;
+    m_viewRight = max;
+
+    m_viewHeight = height();
+    m_viewHeightMin = m_viewHeight;
+    m_viewHeightMax = m_viewHeight;
+
+    m_viewBottom = 0;
+    m_viewTop = m_viewHeight;
+
+    m_graphBottom = 0;
+    m_graphTop = m_viewHeight;
+
+    update();
+}
+
+#include "graphview.moc"
diff --git a/gui/graphing/graphview.h b/gui/graphing/graphview.h
new file mode 100644 (file)
index 0000000..6b881d4
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef GRAPHVIEW_H
+#define GRAPHVIEW_H
+
+#include "graphing.h"
+
+#include <QWidget>
+
+/**
+ * The generic base class for a graph's view, this is the component that
+ * displays the actual data for the graph.
+ *
+ * - Stores the view area within the graph
+ * - Simple user interaction such as translating and zooming with mouse
+ * - Selection tracking synchronised with axis
+ */
+class GraphView : public QWidget {
+    Q_OBJECT
+public:
+    GraphView(QWidget* parent = 0);
+    virtual ~GraphView(){}
+
+    virtual void update();
+
+    virtual void resizeEvent(QResizeEvent *);
+
+    virtual void wheelEvent(QWheelEvent *e);
+    virtual void mouseMoveEvent(QMouseEvent *e);
+    virtual void mousePressEvent(QMouseEvent *e);
+    virtual void mouseDoubleClickEvent(QMouseEvent *e);
+
+    virtual void setSelectionState(SelectionState* state);
+
+    void setHorizontalView(qint64 start, qint64 end);
+    void setVerticalView(qint64 start, qint64 end);
+
+protected:
+    void setDefaultView(qint64 min, qint64 max);
+
+signals:
+    void selectionChanged();
+
+    void verticalViewChanged(qint64 start, qint64 end);
+    void verticalRangeChanged(qint64 min, qint64 max);
+
+    void horizontalRangeChanged(qint64 min, qint64 max);
+    void horizontalViewChanged(qint64 start, qint64 end);
+
+protected:
+    /* Viewport area */
+    qint64 m_viewLeft;
+    qint64 m_viewRight;
+    qint64 m_viewBottom;
+    qint64 m_viewTop;
+
+    /* Graph limits */
+    qint64 m_graphLeft;
+    qint64 m_graphRight;
+    qint64 m_graphBottom;
+    qint64 m_graphTop;
+
+    /* Viewport width (m_viewRight - m_viewLeft), used for zoom */
+    qint64 m_viewWidth;
+    qint64 m_viewWidthMin;
+    qint64 m_viewWidthMax;
+
+    /* Viewport height (m_viewTop - m_viewBottom), used for zoom */
+    qint64 m_viewHeight;
+    qint64 m_viewHeightMin;
+    qint64 m_viewHeightMax;
+
+    /* Mouse tracking */
+    QPoint m_mousePressPosition;
+    qint64 m_mousePressViewLeft;
+    qint64 m_mousePressViewBottom;
+
+    /* Selection */
+    SelectionState* m_selectionState;
+
+    /* State from the last update() call */
+    struct PreviousUpdate {
+        qint64 m_viewLeft;
+        qint64 m_viewRight;
+        qint64 m_viewBottom;
+        qint64 m_viewTop;
+
+        qint64 m_graphLeft;
+        qint64 m_graphRight;
+        qint64 m_graphBottom;
+        qint64 m_graphTop;
+    } m_previous;
+};
+
+#endif
diff --git a/gui/graphing/graphwidget.cpp b/gui/graphing/graphwidget.cpp
new file mode 100644 (file)
index 0000000..88a86cc
--- /dev/null
@@ -0,0 +1,583 @@
+#include "graphwidget.h"
+
+#include <QScrollBar>
+
+GraphWidget::GraphWidget(QWidget* parent) :
+    QWidget(parent),
+    m_view(NULL),
+    m_label(NULL),
+    m_axisTop(NULL),
+    m_axisLeft(NULL),
+    m_axisRight(NULL),
+    m_axisBottom(NULL),
+    m_horizontalScrollbar(NULL),
+    m_horizontalMin(0),
+    m_horizontalMax(0),
+    m_horizontalStart(0),
+    m_horizontalEnd(0),
+    m_horizontalScrollbarPolicy(Qt::ScrollBarAlwaysOff),
+    m_verticalScrollbar(NULL),
+    m_verticalMin(0),
+    m_verticalMax(0),
+    m_verticalStart(0),
+    m_verticalEnd(0),
+    m_verticalScrollbarPolicy(Qt::ScrollBarAlwaysOff)
+{
+    m_selection.type = SelectionState::None;
+
+    m_verticalScrollbar = new QScrollBar(this);
+    m_verticalScrollbar->setOrientation(Qt::Vertical);
+    m_verticalScrollbar->hide();
+    m_verticalScrollbar->resize(m_verticalScrollbar->sizeHint());
+
+    m_horizontalScrollbar = new QScrollBar(this);
+    m_horizontalScrollbar->setOrientation(Qt::Horizontal);
+    m_horizontalScrollbar->hide();
+    m_horizontalScrollbar->resize(m_horizontalScrollbar->sizeHint());
+
+    updateLayout();
+    setAutoFillBackground(true);
+}
+
+
+GraphView* GraphWidget::view()
+{
+    return m_view;
+}
+
+
+GraphLabelWidget* GraphWidget::label()
+{
+    return m_label;
+}
+
+
+GraphAxisWidget* GraphWidget::axis(AxisPosition pos)
+{
+    switch(pos) {
+        case AxisTop:
+            return m_axisTop;
+
+        case AxisLeft:
+            return m_axisLeft;
+
+        case AxisRight:
+            return m_axisRight;
+
+        case AxisBottom:
+            return m_axisBottom;
+
+        default:
+            return NULL;
+    }
+}
+
+
+void GraphWidget::setView(GraphView* view)
+{
+    delete m_view;
+    m_view = view;
+
+    updateConnections();
+
+    m_view->setSelectionState(&m_selection);
+    m_view->show();
+    m_view->update();
+}
+
+
+void GraphWidget::setLabel(GraphLabelWidget* label)
+{
+    delete m_label;
+    m_label = label;
+}
+
+
+void GraphWidget::setAxis(AxisPosition pos, GraphAxisWidget* axis)
+{
+    switch(pos) {
+        case AxisTop:
+            delete m_axisTop;
+            m_axisTop = axis;
+            m_axisTop->setOrientation(GraphAxisWidget::Horizontal);
+            m_axisTop->setSelectionState(&m_selection);
+            break;
+
+        case AxisLeft:
+            delete m_axisLeft;
+            m_axisLeft = axis;
+            m_axisLeft->setOrientation(GraphAxisWidget::Vertical);
+            m_axisLeft->setSelectionState(&m_selection);
+            break;
+
+        case AxisRight:
+            delete m_axisRight;
+            m_axisRight = axis;
+            m_axisRight->setOrientation(GraphAxisWidget::Vertical);
+            m_axisRight->setSelectionState(&m_selection);
+            break;
+
+        case AxisBottom:
+            delete m_axisBottom;
+            m_axisBottom = axis;
+            m_axisBottom->setOrientation(GraphAxisWidget::Horizontal);
+            m_axisBottom->setSelectionState(&m_selection);
+            break;
+    }
+
+    updateConnections();
+    updateSelection();
+    axis->show();
+}
+
+
+void GraphWidget::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy)
+{
+    m_horizontalScrollbarPolicy = policy;
+    updateScrollbars();
+}
+
+
+void GraphWidget::setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy)
+{
+    m_verticalScrollbarPolicy = policy;
+    updateScrollbars();
+}
+
+
+void GraphWidget::resizeEvent(QResizeEvent *e)
+{
+    updateLayout();
+    update();
+}
+
+
+/* Used if a selection would be shared between graphs with different axis */
+SelectionState GraphWidget::transformSelectionIn(SelectionState state)
+{
+    return state;
+}
+
+
+/* Used if a selection would be shared between graphs with different axis */
+SelectionState GraphWidget::transformSelectionOut(SelectionState state)
+{
+    return state;
+}
+
+
+/* Update the scrollbars based on current view */
+void GraphWidget::updateScrollbars()
+{
+    /* Vertical scroll bar */
+    qint64 size = (m_verticalMax - m_verticalMin) - (m_verticalEnd - m_verticalStart);
+
+    if (size <= INT_MAX) {
+        m_verticalScrollbar->setValue(m_verticalStart - m_verticalMin);
+        m_verticalScrollbar->setPageStep(m_verticalEnd - m_verticalStart);
+        m_verticalScrollbar->setRange(0, size);
+    } else {
+        /* QScrollBar only supports up to INT_MAX values,
+         * here we must scale our values to match this */
+        double curSize = m_verticalEnd - m_verticalStart;
+        double pages = (m_verticalMax - m_verticalMin) / curSize;
+        double value = (m_verticalStart - m_verticalMin) / curSize;
+
+        m_verticalScrollbar->setValue(value);
+        m_verticalScrollbar->setPageStep(1);
+        m_verticalScrollbar->setRange(0, pages);
+    }
+
+    /* Adhere to scrollbar policy */
+    bool visible = false;
+
+    if (m_verticalScrollbarPolicy == Qt::ScrollBarAlwaysOn) {
+        visible = true;
+    } else if (m_verticalScrollbarPolicy == Qt::ScrollBarAlwaysOff) {
+        visible = false;
+    } else if (m_verticalScrollbarPolicy == Qt::ScrollBarAsNeeded) {
+        visible = m_verticalMin != m_verticalStart || m_verticalMax != m_verticalEnd;
+    }
+
+    if (visible != m_verticalScrollbar->isVisible()) {
+        m_verticalScrollbar->setVisible(visible);
+        updateLayout();
+    }
+
+    /* Horizontal scroll bar */
+    size = (m_horizontalMax - m_horizontalMin) - (m_horizontalEnd - m_horizontalStart);
+
+    if (size <= INT_MAX) {
+        m_horizontalScrollbar->setValue(m_horizontalStart - m_horizontalMin);
+        m_horizontalScrollbar->setPageStep(m_horizontalEnd - m_horizontalStart);
+        m_horizontalScrollbar->setRange(0, size);
+    } else {
+        /* QScrollBar only supports up to INT_MAX values,
+         * here we must scale our values to match this */
+        double dxdv = INT_MAX / (double)size;
+        double value = (m_horizontalStart - m_horizontalMin) * dxdv;
+        double pageStep = (m_horizontalEnd - m_horizontalStart) * dxdv;
+
+        m_horizontalScrollbar->setValue((int)value);
+        m_horizontalScrollbar->setPageStep((int)pageStep);
+        m_horizontalScrollbar->setRange(0, INT_MAX);
+    }
+
+    /* Adhere to scrollbar policy */
+    visible = false;
+
+    if (m_horizontalScrollbarPolicy == Qt::ScrollBarAlwaysOn) {
+        visible = true;
+    } else if (m_horizontalScrollbarPolicy == Qt::ScrollBarAlwaysOff) {
+        visible = false;
+    } else if (m_horizontalScrollbarPolicy == Qt::ScrollBarAsNeeded) {
+        visible =  m_horizontalMin != m_horizontalStart || m_horizontalMax != m_horizontalEnd;
+    }
+
+    if (visible != m_horizontalScrollbar->isVisible()) {
+        m_horizontalScrollbar->setVisible(visible);
+        updateLayout();
+    }
+}
+
+
+/* Update all signal / slot connections */
+void GraphWidget::updateConnections()
+{
+    if (m_view) {
+        connect(m_view, SIGNAL(selectionChanged()), this, SLOT(updateSelection()), Qt::UniqueConnection);
+
+        connect(m_view, SIGNAL(horizontalViewChanged(qint64,qint64)), this, SLOT(horizontalViewChange(qint64,qint64)), Qt::UniqueConnection);
+        connect(m_view, SIGNAL(horizontalRangeChanged(qint64,qint64)), this, SLOT(horizontalRangeChange(qint64,qint64)), Qt::UniqueConnection);
+
+        connect(m_view, SIGNAL(verticalViewChanged(qint64,qint64)), this, SLOT(verticalViewChange(qint64,qint64)), Qt::UniqueConnection);
+        connect(m_view, SIGNAL(verticalRangeChanged(qint64,qint64)), this, SLOT(verticalRangeChange(qint64,qint64)), Qt::UniqueConnection);
+    }
+
+    if (m_axisTop) {
+        if (m_view) {
+            connect(m_view, SIGNAL(horizontalViewChanged(qint64,qint64)), m_axisTop, SLOT(setView(qint64,qint64)), Qt::UniqueConnection);
+            connect(m_view, SIGNAL(horizontalRangeChanged(qint64,qint64)), m_axisTop, SLOT(setRange(qint64,qint64)), Qt::UniqueConnection);
+        }
+
+        connect(m_axisTop, SIGNAL(selectionChanged()), this, SLOT(updateSelection()), Qt::UniqueConnection);
+    }
+
+    if (m_axisLeft) {
+        if (m_view) {
+            connect(m_view, SIGNAL(verticalViewChanged(qint64,qint64)), m_axisLeft, SLOT(setView(qint64,qint64)), Qt::UniqueConnection);
+            connect(m_view, SIGNAL(verticalRangeChanged(qint64,qint64)), m_axisLeft, SLOT(setRange(qint64,qint64)), Qt::UniqueConnection);
+        }
+
+        connect(m_axisLeft, SIGNAL(selectionChanged()), this, SLOT(updateSelection()), Qt::UniqueConnection);
+    }
+
+    if (m_axisRight) {
+        if (m_view) {
+            connect(m_view, SIGNAL(verticalViewChanged(qint64,qint64)), m_axisRight, SLOT(setView(qint64,qint64)), Qt::UniqueConnection);
+            connect(m_view, SIGNAL(verticalRangeChanged(qint64,qint64)), m_axisRight, SLOT(setRange(qint64,qint64)), Qt::UniqueConnection);
+        }
+
+        connect(m_axisRight, SIGNAL(selectionChanged()), this, SLOT(updateSelection()), Qt::UniqueConnection);
+    }
+
+    if (m_axisBottom) {
+        if (m_view) {
+            connect(m_view, SIGNAL(horizontalViewChanged(qint64,qint64)), m_axisBottom, SLOT(setView(qint64,qint64)), Qt::UniqueConnection);
+            connect(m_view, SIGNAL(horizontalRangeChanged(qint64,qint64)), m_axisBottom, SLOT(setRange(qint64,qint64)), Qt::UniqueConnection);
+        }
+
+        connect(m_axisBottom, SIGNAL(selectionChanged()), this, SLOT(updateSelection()), Qt::UniqueConnection);
+    }
+
+    if (m_horizontalScrollbar) {
+        connect(m_horizontalScrollbar, SIGNAL(actionTriggered(int)), this, SLOT(horizontalScrollAction(int)));
+    }
+
+    if (m_verticalScrollbar) {
+        connect(m_verticalScrollbar, SIGNAL(actionTriggered(int)), this, SLOT(verticalScrollAction(int)));
+    }
+}
+
+
+/* Recalculate the layout */
+void GraphWidget::updateLayout()
+{
+    int x, y;
+    int padX = 0, padY = 0;
+
+    if (m_axisTop) {
+        padY += m_axisTop->height();
+    }
+
+    if (m_axisBottom) {
+        padY += m_axisBottom->height();
+    }
+
+    if (m_axisLeft) {
+        padX += m_axisLeft->width();
+    }
+
+    if (m_axisRight) {
+        padX += m_axisRight->width();
+    }
+
+    if (m_horizontalScrollbar->isVisible()) {
+        padY += m_horizontalScrollbar->height();
+    }
+
+    if (m_verticalScrollbar->isVisible()) {
+        padX += m_verticalScrollbar->width();
+    }
+
+    if (m_axisTop) {
+        x = m_axisLeft ? m_axisLeft->width() : 0;
+        y = 0;
+
+        m_axisTop->move(x, y);
+        m_axisTop->resize(width() - padX, m_axisTop->height());
+    }
+
+    if (m_axisBottom) {
+        x = m_axisLeft ? m_axisLeft->width() : 0;
+        y = height() - m_axisBottom->height();
+
+        if (m_horizontalScrollbar->isVisible())  {
+            y -= m_horizontalScrollbar->height();
+        }
+
+        m_axisBottom->move(x, y);
+        m_axisBottom->resize(width() - padX, m_axisBottom->height());
+    }
+
+    if (m_axisLeft) {
+        x = 0;
+        y = m_axisTop ? m_axisTop->height() : 0;
+
+        m_axisLeft->move(x, y);
+        m_axisLeft->resize(m_axisLeft->width(), height() - padY);
+    }
+
+    if (m_axisRight) {
+        x = width() - m_axisRight->width();
+        y = m_axisTop ? m_axisTop->height() : 0;
+
+        if (m_verticalScrollbar->isVisible())  {
+            x -= m_verticalScrollbar->width();
+        }
+
+        m_axisRight->move(x, y);
+        m_axisRight->resize(m_axisRight->width(), height() - padY);
+    }
+
+    if (m_view) {
+        x = m_axisLeft ? m_axisLeft->width() : 0;
+        y = m_axisTop ? m_axisTop->height() : 0;
+
+        m_view->move(x, y);
+        m_view->resize(width() - padX, height() - padY);
+    }
+
+    if (m_label) {
+        if (m_axisTop && m_axisLeft) {
+            m_label->move(0, 0);
+            m_label->resize(m_axisLeft->width(), m_axisTop->height());
+        }
+    }
+
+    if (m_verticalScrollbar) {
+        m_verticalScrollbar->move(width() - m_verticalScrollbar->width(), 0);
+
+        if (m_horizontalScrollbar) {
+            m_verticalScrollbar->resize(m_verticalScrollbar->width(), height() - m_horizontalScrollbar->height());
+        } else {
+            m_verticalScrollbar->resize(m_verticalScrollbar->width(), height());
+        }
+    }
+
+    if (m_horizontalScrollbar) {
+        m_horizontalScrollbar->move(0, height() - m_horizontalScrollbar->height());
+
+        if (m_verticalScrollbar) {
+            m_horizontalScrollbar->resize(width() - m_verticalScrollbar->width(), m_horizontalScrollbar->height());
+        } else {
+            m_horizontalScrollbar->resize(width(), m_horizontalScrollbar->height());
+        }
+    }
+}
+
+
+void GraphWidget::setSelection(SelectionState state)
+{
+    m_selection = transformSelectionIn(state);
+    updateSelection(false);
+}
+
+
+void GraphWidget::setHorizontalView(qint64 start, qint64 end)
+{
+    if (m_view) {
+        m_view->setHorizontalView(start, end);
+    }
+}
+
+
+void GraphWidget::setVerticalView(qint64 start, qint64 end)
+{
+    if (m_view) {
+        m_view->setVerticalView(start, end);
+    }
+}
+
+
+/* Called when the view is translated / zoomed */
+void GraphWidget::verticalViewChange(qint64 start, qint64 end)
+{
+    m_verticalStart = start;
+    m_verticalEnd = end;
+    updateScrollbars();
+
+    emit verticalViewChanged(start, end);
+}
+
+
+void GraphWidget::verticalRangeChange(qint64 start, qint64 end)
+{
+    m_verticalMin = start;
+    m_verticalMax = end;
+    updateScrollbars();
+
+    emit verticalRangeChanged(start, end);
+}
+
+
+void GraphWidget::horizontalViewChange(qint64 start, qint64 end)
+{
+    m_horizontalStart = start;
+    m_horizontalEnd = end;
+    updateScrollbars();
+
+    emit horizontalViewChanged(start, end);
+}
+
+
+void GraphWidget::horizontalRangeChange(qint64 start, qint64 end)
+{
+    m_horizontalMin = start;
+    m_horizontalMax = end;
+    updateScrollbars();
+
+    emit horizontalRangeChanged(start, end);
+}
+
+
+/* User interaction with horizontal scroll bar */
+void GraphWidget::horizontalScrollAction(int /*action*/)
+{
+    int value = m_horizontalScrollbar->sliderPosition();
+    qint64 size = (m_horizontalMax - m_horizontalMin) - (m_horizontalEnd - m_horizontalStart);
+
+    /* Calculate the new scroll values */
+    if (size <= INT_MAX) {
+        m_horizontalEnd -= m_horizontalStart;
+        m_horizontalStart = value + m_horizontalMin;
+        m_horizontalEnd += value;
+    } else {
+        /* QScrollBar only supports up to INT_MAX values, here we must scale
+         * our values to match this */
+        double dxdv = INT_MAX / (double)size;
+
+        size = m_horizontalEnd - m_horizontalStart;
+        m_horizontalStart = value / dxdv + m_horizontalMin;
+        m_horizontalEnd = m_horizontalStart + size;
+    }
+
+    /* Update view */
+    if (m_view) {
+        m_view->setHorizontalView(m_horizontalStart, m_horizontalEnd);
+    }
+
+    /* Update horizontal axes */
+    if (m_axisTop) {
+        m_axisTop->setView(m_horizontalStart, m_horizontalEnd);
+    }
+
+    if (m_axisBottom) {
+        m_axisBottom->setView(m_horizontalStart, m_horizontalEnd);
+    }
+
+    /* Inform the world of our changes! */
+    emit horizontalViewChanged(m_horizontalStart, m_horizontalEnd);
+}
+
+
+/* User interaction with vertical scroll bar */
+void GraphWidget::verticalScrollAction(int /*action*/)
+{
+    int value = m_verticalScrollbar->sliderPosition();
+    qint64 size = (m_verticalMax - m_verticalMin) - (m_verticalEnd - m_verticalStart);
+
+    /* Calculate the new scroll values */
+    if (size <= INT_MAX) {
+        m_verticalEnd -= m_verticalStart;
+        m_verticalStart = value + m_verticalMin;
+        m_verticalEnd += value;
+    } else {
+        /* QScrollBar only supports up to INT_MAX values, here we must scale
+         * our values to match this */
+        double dxdv = INT_MAX / (double)size;
+
+        size = m_verticalEnd - m_verticalStart;
+        m_verticalStart = value / dxdv + m_verticalMin;
+        m_verticalEnd = m_verticalStart + size;
+    }
+
+    /* Update view */
+    if (m_view) {
+        m_view->setVerticalView(m_verticalStart, m_verticalEnd);
+    }
+
+    /* Update vertical axes */
+    if (m_axisLeft) {
+        m_axisLeft->setView(m_verticalStart, m_verticalEnd);
+    }
+
+    if (m_axisRight) {
+        m_axisRight->setView(m_verticalStart, m_verticalEnd);
+    }
+
+    /* Inform the world of our changes! */
+    emit verticalViewChanged(m_verticalStart, m_verticalEnd);
+}
+
+
+/* Update child elements when selection changes */
+void GraphWidget::updateSelection(bool emitSignal)
+{
+    if (m_view) {
+        m_view->update();
+    }
+
+    if (m_axisTop) {
+        m_axisTop->update();
+    }
+
+    if (m_axisLeft) {
+        m_axisLeft->update();
+    }
+
+    if (m_axisRight) {
+        m_axisRight->update();
+    }
+
+    if (m_axisBottom) {
+        m_axisBottom->update();
+    }
+
+    if (emitSignal) {
+        emit selectionChanged(transformSelectionOut(m_selection));
+    }
+}
+
+
+#include "graphwidget.moc"
diff --git a/gui/graphing/graphwidget.h b/gui/graphing/graphwidget.h
new file mode 100644 (file)
index 0000000..16b7786
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef GRAPHWIDGET_H
+#define GRAPHWIDGET_H
+
+#include "graphview.h"
+#include "graphaxiswidget.h"
+#include "graphlabelwidget.h"
+
+class QScrollBar;
+
+/**
+ * The generic GraphWidget class which combines the elements of a graph,
+ * the axis, view, scrollbars and label.
+ */
+class GraphWidget : public QWidget {
+    Q_OBJECT
+public:
+    enum AxisPosition {
+        AxisTop,
+        AxisLeft,
+        AxisRight,
+        AxisBottom
+    };
+
+public:
+    GraphWidget(QWidget* parent = 0);
+    virtual ~GraphWidget(){}
+
+    GraphView* view();
+    GraphLabelWidget* label();
+    GraphAxisWidget* axis(AxisPosition pos);
+
+    void setView(GraphView* view);
+    void setLabel(GraphLabelWidget* label);
+    void setAxis(AxisPosition pos, GraphAxisWidget* axis);
+
+    void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy);
+    void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy);
+
+    virtual void resizeEvent(QResizeEvent *e);
+
+protected:
+    /* Used if a selection would be shared between graphs with different axis */
+    virtual SelectionState transformSelectionIn(SelectionState state);
+    virtual SelectionState transformSelectionOut(SelectionState state);
+
+    /* Update the scrollbars based on current view */
+    void updateScrollbars();
+
+    /* Update all signal / slot connections */
+    void updateConnections();
+
+    /* Recalculate child widget layout */
+    void updateLayout();
+
+public slots:
+    void setSelection(SelectionState state);
+
+    /* Set view areas */
+    void setHorizontalView(qint64 start, qint64 end);
+    void setVerticalView(qint64 start, qint64 end);
+
+protected slots:
+    /* View changed by translation / zooming */
+    void verticalViewChange(qint64 start, qint64 end);
+    void verticalRangeChange(qint64 start, qint64 end);
+    void horizontalViewChange(qint64 start, qint64 end);
+    void horizontalRangeChange(qint64 start, qint64 end);
+
+    /* User interaction with scroll bars */
+    void horizontalScrollAction(int action);
+    void verticalScrollAction(int action);
+
+    /* Update child elements when selection changes */
+    void updateSelection(bool emitSignal = true);
+
+signals:
+    void selectionChanged(SelectionState state);
+
+    void verticalViewChanged(qint64 start, qint64 end);
+    void verticalRangeChanged(qint64 start, qint64 end);
+
+    void horizontalViewChanged(qint64 start, qint64 end);
+    void horizontalRangeChanged(qint64 start, qint64 end);
+
+protected:
+    SelectionState m_selection;
+
+    GraphView* m_view;
+
+    GraphLabelWidget* m_label;
+
+    GraphAxisWidget* m_axisTop;
+    GraphAxisWidget* m_axisLeft;
+    GraphAxisWidget* m_axisRight;
+    GraphAxisWidget* m_axisBottom;
+
+    QScrollBar* m_horizontalScrollbar;
+    qint64 m_horizontalMin;
+    qint64 m_horizontalMax;
+    qint64 m_horizontalStart;
+    qint64 m_horizontalEnd;
+    Qt::ScrollBarPolicy m_horizontalScrollbarPolicy;
+
+    QScrollBar* m_verticalScrollbar;
+    qint64 m_verticalMin;
+    qint64 m_verticalMax;
+    qint64 m_verticalStart;
+    qint64 m_verticalEnd;
+    Qt::ScrollBarPolicy m_verticalScrollbarPolicy;
+};
+
+#endif
diff --git a/gui/graphing/heatmapverticalaxiswidget.cpp b/gui/graphing/heatmapverticalaxiswidget.cpp
new file mode 100644 (file)
index 0000000..ae127c0
--- /dev/null
@@ -0,0 +1,82 @@
+#include "heatmapverticalaxiswidget.h"
+
+#include <qmath.h>
+#include <QPainter>
+#include <QMouseEvent>
+
+HeatmapVerticalAxisWidget::HeatmapVerticalAxisWidget(QWidget* parent) :
+    GraphAxisWidget(parent),
+    m_data(NULL)
+{
+    m_rowHeight = 20;
+}
+
+void HeatmapVerticalAxisWidget::setDataProvider(HeatmapDataProvider* data)
+{
+    delete m_data;
+    m_data = data;
+
+    m_valueMin = 0;
+    m_valueMax = (data->dataRows() + data->headerRows()) * m_rowHeight;
+
+    m_valueBegin = m_valueMin;
+    m_valueEnd = m_valueMax;
+
+    update();
+}
+
+void HeatmapVerticalAxisWidget::mouseDoubleClickEvent(QMouseEvent *e)
+{
+    if (e->pos().y() < m_data->headerRows() * m_rowHeight) {
+        m_selectionState->type = SelectionState::None;
+        emit selectionChanged();
+    } else {
+        int row = e->pos().y();
+        row -= m_data->headerRows() * m_rowHeight;
+        row += m_valueBegin;
+        row /= m_rowHeight;
+
+        if (row >= m_data->dataRows()) {
+            m_selectionState->type = SelectionState::None;
+            emit selectionChanged();
+        } else {
+            m_selectionState->type = SelectionState::Vertical;
+            m_selectionState->start = m_data->dataRowAt(row);
+            m_selectionState->end = m_selectionState->start;
+            emit selectionChanged();
+        }
+    }
+}
+
+void HeatmapVerticalAxisWidget::paintEvent(QPaintEvent *)
+{
+    if (!m_data) {
+        return;
+    }
+
+    QPainter painter(this);
+    painter.setPen(Qt::black);
+    painter.setBrush(Qt::lightGray);
+    painter.drawRect(0, 0, width() - 1, height() - 1);
+
+    /* Draw scrollable rows */
+    painter.translate(0, m_data->headerRows() * m_rowHeight - m_valueBegin % m_rowHeight);
+    int rowStart = m_valueBegin / m_rowHeight;
+    int rowEnd = qMin<int>(qCeil(m_valueEnd / (double)m_rowHeight), m_data->dataRows());
+
+    for (unsigned i = rowStart; i < rowEnd; ++i) {
+        painter.drawText(0, 0, width(), m_rowHeight, Qt::AlignHCenter | Qt::AlignVCenter, m_data->dataLabel(i));
+        painter.drawLine(0, m_rowHeight, width(), m_rowHeight);
+        painter.translate(0, m_rowHeight);
+    }
+
+    /* Draw fixed position headers */
+    painter.resetTransform();
+    painter.drawRect(0, 0, width() - 1, m_data->headerRows() * m_rowHeight);
+
+    for (unsigned i = 0; i < m_data->headerRows(); ++i) {
+        painter.drawText(0, 0, width(), m_rowHeight, Qt::AlignHCenter | Qt::AlignVCenter, m_data->headerLabel(i));
+        painter.drawLine(0, m_rowHeight, width(), m_rowHeight);
+        painter.translate(0, m_rowHeight);
+    }
+}
diff --git a/gui/graphing/heatmapverticalaxiswidget.h b/gui/graphing/heatmapverticalaxiswidget.h
new file mode 100644 (file)
index 0000000..ca64adb
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef HEATMAPVERTICALAXISWIDGET_H
+#define HEATMAPVERTICALAXISWIDGET_H
+
+#include "heatmapview.h"
+#include "graphaxiswidget.h"
+
+/**
+ * Vertical axis specifically for heatmap displaying header and data rows
+ */
+class HeatmapVerticalAxisWidget : public GraphAxisWidget {
+public:
+    HeatmapVerticalAxisWidget(QWidget* parent);
+
+    void setDataProvider(HeatmapDataProvider* data);
+
+    virtual void mouseDoubleClickEvent(QMouseEvent *e);
+    virtual void paintEvent(QPaintEvent *);
+
+protected:
+    int m_rowHeight;
+    HeatmapDataProvider* m_data;
+};
+
+#endif
diff --git a/gui/graphing/heatmapview.cpp b/gui/graphing/heatmapview.cpp
new file mode 100644 (file)
index 0000000..9bb485c
--- /dev/null
@@ -0,0 +1,276 @@
+#include "heatmapview.h"
+
+#include <qmath.h>
+#include <QToolTip>
+#include <QPainter>
+#include <QMouseEvent>
+
+HeatmapView::HeatmapView(QWidget* parent) :
+    GraphView(parent),
+    m_data(NULL)
+{
+    m_rowHeight = 20;
+    setMouseTracking(true);
+}
+
+
+void HeatmapView::setDataProvider(HeatmapDataProvider* data)
+{
+    delete m_data;
+    m_data = data;
+
+    if (m_data) {
+        m_data->setSelectionState(m_selectionState);
+
+        setDefaultView(m_data->start(), m_data->end());
+
+        m_viewWidthMin = 1000;
+
+        m_graphBottom = 0;
+        m_graphTop = (m_data->headerRows() + m_data->dataRows()) * m_rowHeight;
+    } else {
+        setDefaultView(0, 0);
+        m_graphBottom = m_graphTop = 0;
+    }
+
+    update();
+}
+
+
+void HeatmapView::setSelectionState(SelectionState* state)
+{
+    if (m_data) {
+        m_data->setSelectionState(state);
+    }
+
+    GraphView::setSelectionState(state);
+}
+
+
+void HeatmapView::mouseMoveEvent(QMouseEvent *e)
+{
+    GraphView::mouseMoveEvent(e);
+
+    if (e->buttons() || !m_data) {
+        QToolTip::hideText();
+        return;
+    }
+
+    qint64 index = itemAtPosition(e->pos());
+
+    if (index >= 0) {
+        QToolTip::showText(e->globalPos(), m_data->itemTooltip(index));
+    } else {
+        QToolTip::hideText();
+    }
+}
+
+
+void HeatmapView::mouseDoubleClickEvent(QMouseEvent *e)
+{
+    if (m_data && e->button() == Qt::LeftButton) {
+        qint64 index = itemAtPosition(e->pos());
+
+        if (index >= 0) {
+            m_data->itemDoubleClicked(index);
+            return;
+        }
+    }
+
+    GraphView::mouseDoubleClickEvent(e);
+}
+
+
+void HeatmapView::paintEvent(QPaintEvent *)
+{
+    if (!m_data) {
+        return;
+    }
+
+    QPainter painter(this);
+    painter.fillRect(0, m_data->headerRows() * m_rowHeight, width(), height(), Qt::white);
+
+    /* Draw data rows */
+    painter.translate(0, m_data->headerRows() * m_rowHeight - m_viewBottom % m_rowHeight);
+    int rowStart = m_viewBottom / m_rowHeight;
+    int rowEnd = qMin<int>(qCeil(m_viewTop / (double)m_rowHeight), m_data->dataRows());
+
+    for (unsigned i = rowStart; i < rowEnd; ++i) {
+        HeatmapRowIterator* itr = m_data->dataRowIterator(i, m_viewLeft, m_viewRight, width());
+        paintRow(painter, itr);
+        painter.translate(0, m_rowHeight);
+        delete itr;
+    }
+
+    /* Draw Header */
+    painter.resetTransform();
+    painter.fillRect(0, 0, width(), m_data->headerRows() * m_rowHeight, Qt::white);
+
+    for (unsigned i = 0; i < m_data->headerRows(); ++i) {
+        HeatmapRowIterator* itr = m_data->headerRowIterator(i, m_viewLeft, m_viewRight, width());
+        paintRow(painter, itr);
+        painter.translate(0, m_rowHeight);
+        delete itr;
+    }
+
+    /* Draw Axis Lines */
+    painter.resetTransform();
+    painter.setPen(Qt::black);
+    painter.drawLine(0, m_rowHeight, width(), m_rowHeight);
+    painter.drawLine(0, m_rowHeight * 2, width(), m_rowHeight * 2);
+
+    painter.setPen(QColor(240, 240, 240));
+    painter.translate(0, m_data->headerRows() * m_rowHeight - m_viewBottom % m_rowHeight);
+
+    for (unsigned i = rowStart; i < rowEnd; ++i) {
+        painter.drawLine(0, m_rowHeight, width(), m_rowHeight);
+        painter.translate(0, m_rowHeight);
+    }
+
+    /* Draw selection borders */
+    painter.resetTransform();
+    painter.setPen(Qt::green);
+
+    if (m_selectionState->type == SelectionState::Horizontal) {
+        double dxdt = width() / (double)m_viewWidth;
+        double scroll = m_viewLeft * dxdt;
+        double left = (m_selectionState->start * dxdt) - scroll;
+        double right = (m_selectionState->end * dxdt) - scroll;
+
+        /* Highlight time */
+        if (left >= 0 && left <= width()) {
+            painter.drawLine(left, 0, left, height());
+        }
+
+        if (right >= 0 && right <= width()) {
+            painter.drawLine(right, 0, right, height());
+        }
+    } else if (m_selectionState->type == SelectionState::Vertical) {
+        /* Highlight row */
+        int row = m_selectionState->start;
+
+        for (unsigned i = rowStart; i < rowEnd; ++i) {
+            if (m_data->dataRowAt(i) == row) {
+                row = i - rowStart;
+
+                painter.translate(0, m_data->headerRows() * m_rowHeight - m_viewBottom % m_rowHeight);
+                painter.drawLine(0, (row + 1) * m_rowHeight, width(), (row + 1) * m_rowHeight);
+
+                if (row > 0) {
+                    painter.drawLine(0, row * m_rowHeight, width(), row * m_rowHeight);
+                }
+
+                break;
+            }
+        }
+    }
+}
+
+
+void HeatmapView::paintRow(QPainter& painter, HeatmapRowIterator* itr)
+{
+    bool selection = m_selectionState ? m_selectionState->type != SelectionState::None : false;
+
+    while (itr->next())
+    {
+        double heat = itr->heat();
+        int width = itr->width();
+        int x = itr->step();
+
+        /* Gamma correction */
+        heat = qPow(heat, 1.0 / 2.0);
+
+        if (width == 1) {
+            /* Draw single line */
+            if (selection) {
+                double selectedHeat = itr->selectedHeat();
+
+                if (selectedHeat >= 0.999) {
+                    heat = 255.0 - qBound(0.0, heat * 255.0, 255.0);
+
+                    if (itr->isGpu()) {
+                        painter.setPen(QColor(255, heat, heat));
+                    } else {
+                        painter.setPen(QColor(heat, heat, 255));
+                    }
+
+                    painter.drawLine(x, 0, x, m_rowHeight - 1);
+                } else {
+                    heat = 255.0 - qBound(0.0, heat * 100.0, 100.0);
+                    painter.setPen(QColor(heat, heat, heat));
+                    painter.drawLine(x, 0, x, m_rowHeight - 1);
+
+                    if (selectedHeat > 0.001) {
+                        selectedHeat = qPow(selectedHeat, 1.0 / 2.0);
+                        selectedHeat = qBound(0.0, selectedHeat * 255.0, 255.0);
+
+                        if (itr->isGpu()) {
+                            painter.setPen(QColor(255, 0, 0, selectedHeat));
+                        } else {
+                            painter.setPen(QColor(0, 0, 255, selectedHeat));
+                        }
+
+                        painter.drawLine(x, 0, x, m_rowHeight - 1);
+                    }
+                }
+            } else {
+                heat = qBound(0.0, heat * 255.0, 255.0);
+
+                if (itr->isGpu()) {
+                    painter.setPen(QColor(255, 255 - heat, 255 - heat));
+                } else {
+                    painter.setPen(QColor(255 - heat, 255 - heat, 255));
+                }
+
+                painter.drawLine(x, 0, x, m_rowHeight - 1);
+            }
+        } else {
+            double selectedHeat = itr->selectedHeat();
+
+            if (selection && selectedHeat < 0.9) {
+                painter.fillRect(x, 0, width, m_rowHeight, QColor(255 - 100, 255 - 100, 255 - 100));
+            } else if (itr->isGpu()) {
+                painter.fillRect(x, 0, width, m_rowHeight, QColor(255, 0, 0));
+            } else {
+                painter.fillRect(x, 0, width, m_rowHeight, QColor(0, 0, 255));
+            }
+
+            if (width > 6) {
+                painter.setPen(Qt::white);
+                QString elided = painter.fontMetrics().elidedText(itr->label(), Qt::ElideRight, width - 1);
+
+                painter.drawText(x + 1, 0, width - 1, m_rowHeight - 1,
+                                 Qt::AlignLeft | Qt::AlignVCenter,
+                                 elided);
+            }
+        }
+    }
+}
+
+
+qint64 HeatmapView::itemAtPosition(QPoint pos)
+{
+    if (!m_data) {
+        return -1;
+    }
+
+    double t = m_viewWidth / (double)width();
+    t *= pos.x();
+    t += m_viewLeft;
+
+    qint64 time = (qint64)t;
+    qint64 index;
+
+    if (pos.y() < m_data->headerRows() * m_rowHeight) {
+        int row = pos.y() / m_rowHeight;
+        index = m_data->headerItemAt(row, time);
+    } else {
+        int row = pos.y();
+        row -= m_data->headerRows() * m_rowHeight;
+        row += m_viewBottom;
+        row /= m_rowHeight;
+        index = m_data->dataItemAt(row, time);
+    }
+
+    return index;
+}
diff --git a/gui/graphing/heatmapview.h b/gui/graphing/heatmapview.h
new file mode 100644 (file)
index 0000000..781c9a7
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef HEATMAPVIEW_H
+#define HEATMAPVIEW_H
+
+#include "graphview.h"
+
+/**
+ * The heatmap iterator will only return data when there is something to draw,
+ * this allows much faster access to the data in the case where the view is
+ * zoomed out to the point of where there is multiple calls in one pixel,
+ * it automagically calculates the heat for that pixel.
+ */
+class HeatmapRowIterator {
+public:
+    virtual ~HeatmapRowIterator(){}
+
+    /* Go to the next visible heat map */
+    virtual bool next() = 0;
+
+    /* Is the current value GPU or CPU heat */
+    virtual bool isGpu() const = 0;
+
+    /* Current step (normally x coordinate) */
+    virtual int step() const = 0;
+
+    /* Current width (in steps) */
+    virtual int width() const = 0;
+
+    /* Current heat */
+    virtual float heat() const = 0;
+
+    /* Heat value for selected calls */
+    virtual float selectedHeat() const = 0;
+
+    /* Label only used when there is a single call in this heat */
+    virtual QString label() const = 0;
+};
+
+
+/**
+ * Data provider for the whole heatmap
+ */
+class HeatmapDataProvider {
+public:
+    virtual ~HeatmapDataProvider(){}
+
+    /* The start and end values (time on x-axis) for the heatmap */
+    virtual qint64 start() const = 0;
+    virtual qint64 end() const = 0;
+
+    /*
+     * Header rows (fixed at top of heatmap view)
+     */
+
+    /* Header row count */
+    virtual unsigned headerRows() const = 0;
+
+    /* Label to be used in the vertical axis */
+    virtual QString headerLabel(unsigned row) const = 0;
+
+    /* Get identifier (program no) for row */
+    virtual qint64 headerRowAt(unsigned row) const = 0;
+
+    /* Get item at row and time */
+    virtual qint64 headerItemAt(unsigned row, qint64 time) const = 0;
+
+    /* Get iterator for a row between start and end time for steps */
+    virtual HeatmapRowIterator* headerRowIterator(int row, qint64 start, qint64 end, int steps) const = 0;
+
+    /*
+     * Data rows (scrollable in heatmap view)
+     */
+
+    /* Data row count */
+    virtual unsigned dataRows() const = 0;
+
+    /* Label to be used in the vertical axis */
+    virtual QString dataLabel(unsigned row) const = 0;
+
+    /* Get identifier (program no) for row */
+    virtual qint64 dataRowAt(unsigned row) const = 0;
+
+    /* Get item at row and time */
+    virtual qint64 dataItemAt(unsigned row, qint64 time) const = 0;
+
+    /* Get iterator for a row between start and end time for steps */
+    virtual HeatmapRowIterator* dataRowIterator(int row, qint64 start, qint64 end, int steps) const = 0;
+
+    /* Handle double click on item */
+    virtual void itemDoubleClicked(qint64 index) const = 0;
+
+    /* Get mouse over tooltip for item */
+    virtual QString itemTooltip(qint64 index) const = 0;
+
+    /* Set the selection */
+    virtual void setSelectionState(SelectionState* state) = 0;
+};
+
+
+/**
+ * A not very generic heatmap for row based data
+ */
+class HeatmapView : public GraphView {
+public:
+    HeatmapView(QWidget* parent);
+
+    void setDataProvider(HeatmapDataProvider* data);
+    void setSelectionState(SelectionState* state);
+
+    virtual void mouseMoveEvent(QMouseEvent *e);
+    virtual void mouseDoubleClickEvent(QMouseEvent *e);
+
+    virtual void paintEvent(QPaintEvent *e);
+    virtual void paintRow(QPainter& painter, HeatmapRowIterator* itr);
+
+
+protected:
+    qint64 itemAtPosition(QPoint pos);
+
+protected:
+    int m_rowHeight;
+    HeatmapDataProvider* m_data;
+};
+
+#endif
diff --git a/gui/graphing/histogramview.cpp b/gui/graphing/histogramview.cpp
new file mode 100644 (file)
index 0000000..0b94577
--- /dev/null
@@ -0,0 +1,258 @@
+#include "histogramview.h"
+
+#include <QPen>
+#include <QBrush>
+#include <qmath.h>
+#include <QPainter>
+#include <QToolTip>
+#include <QMouseEvent>
+
+HistogramView::HistogramView(QWidget* parent) :
+    GraphView(parent),
+    m_data(NULL)
+{
+    setMouseTracking(true);
+
+    m_gradientUnselected.setColorAt(0.9, QColor(200, 200, 200));
+    m_gradientUnselected.setColorAt(0.0, QColor(220, 220, 220));
+
+    m_gradientSelected.setColorAt(0.9, QColor(0, 0, 210));
+    m_gradientSelected.setColorAt(0.0, QColor(130, 130, 255));
+}
+
+
+void HistogramView::setDataProvider(GraphDataProvider* data)
+{
+    delete m_data;
+    m_data = data;
+
+    if (m_data) {
+        m_data->setSelectionState(m_selectionState);
+        setDefaultView(0, m_data->size());
+        m_viewWidthMin = 10;
+    } else {
+        setDefaultView(0, 0);
+    }
+}
+
+
+void HistogramView::setSelectionState(SelectionState* state)
+{
+    if (m_data) {
+        m_data->setSelectionState(state);
+    }
+
+    GraphView::setSelectionState(state);
+}
+
+
+void HistogramView::setSelectedGradient(const QLinearGradient& gradient)
+{
+    m_gradientSelected = gradient;
+}
+
+
+void HistogramView::setUnelectedGradient(const QLinearGradient& gradient)
+{
+    m_gradientUnselected = gradient;
+}
+
+
+void HistogramView::mouseMoveEvent(QMouseEvent *e)
+{
+    GraphView::mouseMoveEvent(e);
+
+    if (e->buttons() || !m_data) {
+        QToolTip::hideText();
+        return;
+    }
+
+    qint64 index = itemAtPosition(e->pos());
+    qint64 time = valueAtPosition(e->pos());
+
+    if (m_data->value(index) >= time) {
+        QToolTip::showText(e->globalPos(), m_data->itemTooltip(index));
+    } else {
+        QToolTip::hideText();
+    }
+}
+
+
+void HistogramView::mouseDoubleClickEvent(QMouseEvent *e)
+{
+    if (e->button() == Qt::LeftButton) {
+        qint64 index = itemAtPosition(e->pos());
+        qint64 time = valueAtPosition(e->pos());
+
+        if (m_data->value(index) >= time) {
+            m_data->itemDoubleClicked(index);
+            return;
+        }
+    }
+
+    GraphView::mouseDoubleClickEvent(e);
+}
+
+
+void HistogramView::update()
+{
+    m_graphBottom = 0;
+    m_graphTop = 0;
+
+    if (m_data) {
+        for (qint64 i = m_viewLeft; i < m_viewRight; ++i) {
+            qint64 value = m_data->value(i);
+
+            if (value > m_graphTop) {
+                m_graphTop = value;
+            }
+        }
+    }
+
+    GraphView::update();
+}
+
+
+void HistogramView::resizeEvent(QResizeEvent *)
+{
+    m_gradientSelected.setStart(0, height());
+    m_gradientUnselected.setStart(0, height());
+}
+
+
+/* Draw the histogram
+ *
+ * When the view is zoomed such that there is more than one item occupying a single pixel
+ * the one with the highest value will be displayed.
+ */
+void HistogramView::paintEvent(QPaintEvent *)
+{
+    if (!m_data) {
+        return;
+    }
+
+    QBrush selectedBrush = QBrush(m_gradientSelected);
+    QPen selectedPen = QPen(selectedBrush, 1);
+
+    QBrush unselectedBrush = QBrush(m_gradientUnselected);
+    QPen unselectedPen = QPen(unselectedBrush, 1);
+
+    QPainter painter(this);
+    painter.fillRect(0, 0, width(), height(), Qt::white);
+
+    double dydv = height() / (double)m_graphTop;
+    double dxdv = width() / (double)(m_viewRight - m_viewLeft);
+    bool selection = m_selectionState && m_selectionState->type != SelectionState::None;
+
+    if (dxdv < 1.0) {
+        /* Less than one pixel per item */
+        qint64 longestValue = m_graphBottom;
+        qint64 longestSelected = m_graphBottom;
+        int lastX = 0;
+        double x = 0;
+
+        if (selection) {
+            painter.setPen(unselectedPen);
+        } else {
+            painter.setPen(selectedPen);
+        }
+
+        for (qint64 i = m_viewLeft; i < m_viewRight; ++i) {
+            qint64 value = m_data->value(i);
+            int ix;
+
+            if (value > longestValue) {
+                longestValue = value;
+            }
+
+            if (selection && m_data->selected(i) && value > longestSelected) {
+                longestSelected = value;
+            }
+
+            x += dxdv;
+            ix = (int)x;
+
+            if (lastX != ix) {
+                painter.drawLine(lastX, height(), lastX, height() - (longestValue * dydv));
+
+                if (selection && longestSelected > m_graphBottom) {
+                    painter.setPen(selectedPen);
+                    painter.drawLine(lastX, height(), lastX, height() - (longestSelected * dydv));
+                    painter.setPen(unselectedPen);
+                    longestSelected = m_graphBottom;
+                }
+
+                longestValue = m_graphBottom;
+                lastX = ix;
+            }
+        }
+    } else {
+        /* Draw rectangles for graph */
+        double x = 0;
+
+        for (qint64 i = m_viewLeft; i < m_viewRight; ++i, x += dxdv) {
+            qint64 value = m_data->value(i);
+            int y = qMax<int>(1, value * dydv);
+
+            if (!selection || m_data->selected(i)) {
+                painter.fillRect(x, height() - y, dxdv, y, selectedBrush);
+            } else {
+                painter.fillRect(x, height() - y, dxdv, y, unselectedBrush);
+            }
+        }
+    }
+
+    /* Draw the borders for the selection */
+    if (m_selectionState && m_selectionState->type == SelectionState::Horizontal) {
+        double dxdt = width() / (double)m_viewWidth;
+        double scroll = m_viewLeft * dxdt;
+        double left = (m_selectionState->start * dxdt) - scroll;
+        double right = (m_selectionState->end * dxdt) - scroll;
+
+        painter.setPen(Qt::green);
+
+        if (left >= 0 && left <= width()) {
+            painter.drawLine(left, 0, left, height());
+        }
+
+        if (right >= 0 && right <= width()) {
+            painter.drawLine(right, 0, right, height());
+        }
+    }
+}
+
+
+/* Find the item with the highest value at pos.x() +/- 1,
+ * the mouse must be within the bar height-wise.
+ */
+qint64 HistogramView::itemAtPosition(QPoint pos) {
+    double dvdx = m_viewWidth / (double)width();
+
+    qint64 left = qFloor(dvdx) * (pos.x() - 1) + m_viewLeft;
+    qint64 right = qCeil(dvdx) * (pos.x() + 1) + m_viewLeft;
+
+    qint64 longestIndex = 0;
+    qint64 longestValue = 0;
+
+    left = qBound<qint64>(0, left, m_data->size() - 1);
+    right = qBound<qint64>(0, right, m_data->size() - 1);
+
+    for (qint64 i = left; i <= right; ++i) {
+        if (m_data->value(i) > longestValue) {
+            longestValue = m_data->value(i);
+            longestIndex = i;
+        }
+    }
+
+    return longestIndex;
+}
+
+
+/* Return the value at position */
+qint64 HistogramView::valueAtPosition(QPoint pos) {
+    double value = m_graphTop / (double)height();
+    value *= height() - pos.y();
+    value += m_graphBottom;
+    return (qint64)value;
+}
+
diff --git a/gui/graphing/histogramview.h b/gui/graphing/histogramview.h
new file mode 100644 (file)
index 0000000..563d664
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef HISTOGRAMVIEW_H
+#define HISTOGRAMVIEW_H
+
+#include "graphview.h"
+
+/**
+ * Histogram graph view.
+ *
+ * When the view is zoomed such that there is more than one item occupying
+ * a single pixel the one with the highest value will be displayed.
+ */
+class HistogramView : public GraphView {
+public:
+    HistogramView(QWidget* parent);
+
+    void setDataProvider(GraphDataProvider* data);
+    void setSelectionState(SelectionState* state);
+
+    /* Gradient colours for selected and unselected items */
+    void setSelectedGradient(const QLinearGradient& gradient);
+    void setUnelectedGradient(const QLinearGradient& gradient);
+
+    virtual void mouseMoveEvent(QMouseEvent *e);
+    virtual void mouseDoubleClickEvent(QMouseEvent *e);
+
+    virtual void update();
+    virtual void resizeEvent(QResizeEvent *e);
+    virtual void paintEvent(QPaintEvent *e);
+
+protected:
+    qint64 itemAtPosition(QPoint pos);
+    qint64 valueAtPosition(QPoint pos);
+
+protected:
+    QLinearGradient m_gradientSelected;
+    QLinearGradient m_gradientUnselected;
+
+    GraphDataProvider* m_data;
+};
+
+#endif
diff --git a/gui/graphing/timeaxiswidget.cpp b/gui/graphing/timeaxiswidget.cpp
new file mode 100644 (file)
index 0000000..cebabf7
--- /dev/null
@@ -0,0 +1,80 @@
+#include "timeaxiswidget.h"
+#include "profiling.h"
+
+#include <qmath.h>
+#include <QPainter>
+
+TimeAxisWidget::TimeAxisWidget(QWidget* parent) :
+    GraphAxisWidget(parent)
+{
+}
+
+void TimeAxisWidget::paintEvent(QPaintEvent *)
+{
+    /* TODO: Support selections? */
+    /* TODO: Vertical scrolling? */
+
+    QPainter painter(this);
+    painter.setPen(Qt::black);
+    painter.setBrush(Qt::lightGray);
+    painter.drawRect(0, 0, width() - 1, height() - 1);
+
+    if (m_orientation == GraphAxisWidget::Vertical) {
+        int axisHeight = height() - 1;
+        int fontHeight = painter.fontMetrics().height();
+        int ticks     = axisHeight / (fontHeight * 2);
+
+        double range  = m_valueMax - m_valueMin;
+        double step   = range / (double)ticks;
+        double step10 = qPow(10.0, qFloor(qLn(step) / qLn(10.0)));
+        step = qFloor((step / step10) * 2) * (step10 / 2);
+
+        if (step <= 0) {
+            return;
+        }
+
+        painter.resetTransform();
+
+        for (double tick = 0; tick <= range; tick += step) {
+            int y = axisHeight - ((tick / range) * axisHeight);
+
+            painter.drawLine(width() - 8, y, width(), y);
+
+            painter.drawText(0,
+                             qBound(0, y - fontHeight / 2, axisHeight - fontHeight),
+                             width() - 10,
+                             fontHeight,
+                             Qt::AlignRight | Qt::AlignVCenter,
+                             Profiling::getTimeString(tick, m_valueMax));
+        }
+    } else {
+        int axisWidth = width() - 1;
+        int fontWidth = painter.fontMetrics().width("0.000 ns");
+        int fontHeight= painter.fontMetrics().height();
+        int ticks     = axisWidth / (fontWidth * 2);
+
+        double range  = m_valueMax - m_valueMin;
+        double step   = range / (double)ticks;
+        double step10 = qPow(10.0, qFloor(qLn(step) / qLn(10.0)));
+        step = qFloor((step / step10) * 2) * (step10 / 2);
+
+        if (step <= 0) {
+            return;
+        }
+
+        painter.resetTransform();
+
+        for (double tick = 0; tick <= range; tick += step) {
+            int x = (tick / range) * axisWidth;
+
+            painter.drawLine(x, 0, x, 8);
+
+            painter.drawText(qBound(0, x - fontWidth / 2, axisWidth - fontWidth),
+                             8,
+                             fontWidth,
+                             fontHeight,
+                             Qt::AlignHCenter | Qt::AlignTop,
+                             Profiling::getTimeString(tick, m_valueMax));
+        }
+    }
+}
diff --git a/gui/graphing/timeaxiswidget.h b/gui/graphing/timeaxiswidget.h
new file mode 100644 (file)
index 0000000..836651c
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef TIMEAXISWIDGET_H
+#define TIMEAXISWIDGET_H
+
+#include "graphaxiswidget.h"
+
+/**
+ * A simple axis that draws text using getTimeString to nicely format time values
+ */
+class TimeAxisWidget : public GraphAxisWidget {
+public:
+    TimeAxisWidget(QWidget* parent = 0);
+
+    virtual void paintEvent(QPaintEvent *e);
+};
+
+#endif
index 18e07f1ffcb87275aaa777184a22fb839c31f2fd..0ed50ed8f2b33506f931f570d9662430d59712ec 100644 (file)
@@ -22,6 +22,7 @@ static void usage(void)
 
 int main(int argc, char **argv)
 {
+    QApplication::setGraphicsSystem("raster");
     QApplication app(argc, argv);
 
     qRegisterMetaType<QList<ApiTraceFrame*> >();
index 50f7d9124a9f4dac6184c4cf42ea14f38e89d35a..caf9e370236ebed41d8aa29409cc3e253b1457a4 100644 (file)
@@ -8,6 +8,7 @@
 #include "argumentseditor.h"
 #include "imageviewer.h"
 #include "jumpwidget.h"
+#include "profiledialog.h"
 #include "retracer.h"
 #include "searchwidget.h"
 #include "settingsdialog.h"
@@ -17,7 +18,9 @@
 #include "trimprocess.h"
 #include "thumbnail.h"
 #include "ui_retracerdialog.h"
+#include "ui_profilereplaydialog.h"
 #include "vertexdatainterpreter.h"
+#include "trace_profiler.hpp"
 
 #include <QAction>
 #include <QApplication>
@@ -49,6 +52,15 @@ MainWindow::MainWindow()
     initConnections();
 }
 
+MainWindow::~MainWindow()
+{
+    delete m_trace;
+    m_trace = 0;
+
+    delete m_proxyModel;
+    delete m_model;
+}
+
 void MainWindow::createTrace()
 {
     if (!m_traceProcess->canTrace()) {
@@ -164,21 +176,52 @@ void MainWindow::replayStart()
                "Please wait until it finishes and try again."));
         return;
     }
+
     QDialog dlg;
     Ui_RetracerDialog dlgUi;
     dlgUi.setupUi(&dlg);
 
     dlgUi.doubleBufferingCB->setChecked(
         m_retracer->isDoubleBuffered());
+
     dlgUi.errorCheckCB->setChecked(
         !m_retracer->isBenchmarking());
 
     if (dlg.exec() == QDialog::Accepted) {
         m_retracer->setDoubleBuffered(
             dlgUi.doubleBufferingCB->isChecked());
+
         m_retracer->setBenchmarking(
             !dlgUi.errorCheckCB->isChecked());
-        replayTrace(false, true);
+
+        m_retracer->setProfiling(false, false, false);
+
+        replayTrace(false, false);
+    }
+}
+
+void MainWindow::replayProfile()
+{
+    if (m_trace->isSaving()) {
+        QMessageBox::warning(
+            this,
+            tr("Trace Saving"),
+            tr("QApiTrace is currently saving the edited trace file. "
+               "Please wait until it finishes and try again."));
+        return;
+    }
+
+    QDialog dlg;
+    Ui_ProfileReplayDialog dlgUi;
+    dlgUi.setupUi(&dlg);
+
+    if (dlg.exec() == QDialog::Accepted) {
+        m_retracer->setProfiling(
+            dlgUi.gpuTimesCB->isChecked(),
+            dlgUi.cpuTimesCB->isChecked(),
+            dlgUi.pixelsDrawnCB->isChecked());
+
+        replayTrace(false, false);
     }
 }
 
@@ -187,6 +230,7 @@ void MainWindow::replayStop()
     m_retracer->quit();
     m_ui.actionStop->setEnabled(false);
     m_ui.actionReplay->setEnabled(true);
+    m_ui.actionProfile->setEnabled(true);
     m_ui.actionLookupState->setEnabled(true);
     m_ui.actionShowThumbnails->setEnabled(true);
 }
@@ -200,12 +244,14 @@ void MainWindow::newTraceFile(const QString &fileName)
 
     if (fileName.isEmpty()) {
         m_ui.actionReplay->setEnabled(false);
+        m_ui.actionProfile->setEnabled(false);
         m_ui.actionLookupState->setEnabled(false);
         m_ui.actionShowThumbnails->setEnabled(false);
         setWindowTitle(tr("QApiTrace"));
     } else {
         QFileInfo info(fileName);
         m_ui.actionReplay->setEnabled(true);
+        m_ui.actionProfile->setEnabled(true);
         m_ui.actionLookupState->setEnabled(true);
         m_ui.actionShowThumbnails->setEnabled(true);
         m_ui.actionTrim->setEnabled(true);
@@ -218,6 +264,7 @@ void MainWindow::replayFinished(const QString &message)
 {
     m_ui.actionStop->setEnabled(false);
     m_ui.actionReplay->setEnabled(true);
+    m_ui.actionProfile->setEnabled(true);
     m_ui.actionLookupState->setEnabled(true);
     m_ui.actionShowThumbnails->setEnabled(true);
 
@@ -235,6 +282,7 @@ void MainWindow::replayError(const QString &message)
 {
     m_ui.actionStop->setEnabled(false);
     m_ui.actionReplay->setEnabled(true);
+    m_ui.actionProfile->setEnabled(true);
     m_ui.actionLookupState->setEnabled(true);
     m_ui.actionShowThumbnails->setEnabled(true);
     m_stateEvent = 0;
@@ -316,6 +364,9 @@ void MainWindow::replayTrace(bool dumpState, bool dumpThumbnails)
             statusBar()->showMessage(
                 tr("Capturing thumbnails..."));
         }
+    } else if (m_retracer->isProfiling()) {
+        statusBar()->showMessage(
+                    tr("Profiling draw calls in trace file..."));
     } else {
         statusBar()->showMessage(
             tr("Replaying the trace file..."));
@@ -378,15 +429,6 @@ void MainWindow::trim()
     trimEvent();
 }
 
-MainWindow::~MainWindow()
-{
-    delete m_trace;
-    m_trace = 0;
-
-    delete m_proxyModel;
-    delete m_model;
-}
-
 static void
 variantToString(const QVariant &var, QString &str)
 {
@@ -757,6 +799,8 @@ void MainWindow::initObjects()
 
     m_traceProcess = new TraceProcess(this);
     m_trimProcess = new TrimProcess(this);
+
+    m_profileDialog = new ProfileDialog();
 }
 
 void MainWindow::initConnections()
@@ -788,6 +832,8 @@ void MainWindow::initConnections()
             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>&)),
@@ -823,6 +869,8 @@ void MainWindow::initConnections()
 
     connect(m_ui.actionReplay, SIGNAL(triggered()),
             this, SLOT(replayStart()));
+    connect(m_ui.actionProfile, SIGNAL(triggered()),
+            this, SLOT(replayProfile()));
     connect(m_ui.actionStop, SIGNAL(triggered()),
             this, SLOT(replayStop()));
     connect(m_ui.actionLookupState, SIGNAL(triggered()),
@@ -881,6 +929,26 @@ void MainWindow::initConnections()
     connect(m_ui.errorsTreeWidget,
             SIGNAL(itemActivated(QTreeWidgetItem*, int)),
             this, SLOT(slotErrorSelected(QTreeWidgetItem*)));
+
+    connect(m_ui.actionShowProfileDialog, SIGNAL(triggered(bool)),
+            m_profileDialog, SLOT(show()));
+    connect(m_profileDialog, SIGNAL(jumpToCall(int)),
+            this, SLOT(slotJumpTo(int)));
+}
+
+void MainWindow::closeEvent(QCloseEvent * event)
+{
+    m_profileDialog->close();
+    QMainWindow::closeEvent(event);
+}
+
+void MainWindow::replayProfileFound(trace::Profile *profile)
+{
+    m_ui.actionShowProfileDialog->setEnabled(true);
+    m_profileDialog->setProfile(profile);
+    m_profileDialog->show();
+    m_profileDialog->activateWindow();
+    m_profileDialog->setFocus();
 }
 
 void MainWindow::replayStateFound(ApiTraceState *state)
@@ -1308,6 +1376,7 @@ void MainWindow::slotFoundFrameStart(ApiTraceFrame *frame)
         QModelIndex idx = m_proxyModel->indexForCall(call);
         if (idx.isValid()) {
             m_ui.callView->setCurrentIndex(idx);
+            m_ui.callView->scrollTo(idx, QAbstractItemView::PositionAtTop);
             break;
         }
         ++itr;
@@ -1330,6 +1399,7 @@ void MainWindow::slotFoundFrameEnd(ApiTraceFrame *frame)
         QModelIndex idx = m_proxyModel->indexForCall(call);
         if (idx.isValid()) {
             m_ui.callView->setCurrentIndex(idx);
+            m_ui.callView->scrollTo(idx, QAbstractItemView::PositionAtBottom);
             break;
         }
     } while (itr != calls.constBegin());
@@ -1337,9 +1407,12 @@ void MainWindow::slotFoundFrameEnd(ApiTraceFrame *frame)
 
 void MainWindow::slotJumpToResult(ApiTraceCall *call)
 {
-    QModelIndex index = m_proxyModel->indexForCall(call);
-    if (index.isValid()) {
-        m_ui.callView->setCurrentIndex(index);
+    QModelIndex idx = m_proxyModel->indexForCall(call);
+    if (idx.isValid()) {
+        activateWindow();
+        m_ui.callView->setFocus();
+        m_ui.callView->setCurrentIndex(idx);
+        m_ui.callView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
     } else {
         statusBar()->showMessage(tr("Call has been filtered out."));
     }
index 1346b86377415ba5e16a1c625a0480683fcd59eb..2248127f76aae57b8acd4728c7b090ad628564da 100644 (file)
@@ -30,8 +30,11 @@ class SearchWidget;
 class ShadersSourceWidget;
 class TraceProcess;
 class TrimProcess;
+class ProfileDialog;
 class VertexDataInterpreter;
 
+namespace trace { struct Profile; }
+
 class MainWindow : public QMainWindow
 {
     Q_OBJECT
@@ -48,9 +51,11 @@ private slots:
     void createTrace();
     void openTrace();
     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 replayError(const QString &msg);
     void startedLoadingTrace();
@@ -107,6 +112,8 @@ private:
     ApiTraceFrame *currentFrame() const;
     ApiTraceCall *currentCall() const;
 
+protected:
+    virtual void closeEvent(QCloseEvent * event);
 
 private:
     Ui_MainWindow m_ui;
@@ -141,6 +148,8 @@ private:
     ArgumentsEditor *m_argsEditor;
 
     ApiTraceEvent *m_nonDefaultsLookupEvent;
+
+    ProfileDialog* m_profileDialog;
 };
 
 
diff --git a/gui/profiledialog.cpp b/gui/profiledialog.cpp
new file mode 100644 (file)
index 0000000..a9892cf
--- /dev/null
@@ -0,0 +1,265 @@
+#include "profiledialog.h"
+#include "profiletablemodel.h"
+#include <QSortFilterProxyModel>
+
+#include "graphing/histogramview.h"
+#include "graphing/timeaxiswidget.h"
+#include "graphing/frameaxiswidget.h"
+#include "graphing/heatmapverticalaxiswidget.h"
+#include "profileheatmap.h"
+
+/* Handy function to allow selection of a call in main window */
+ProfileDialog* g_profileDialog = 0;
+
+void Profiling::jumpToCall(int index)
+{
+    if (g_profileDialog) {
+        g_profileDialog->showCall(index);
+    }
+}
+
+/* Provides frame numbers based off call index */
+class FrameCallDataProvider : public FrameDataProvider {
+public:
+    FrameCallDataProvider(const trace::Profile* profile)
+    {
+        m_profile = profile;
+    }
+
+    unsigned size() const {
+        return m_profile->frames.size();
+    }
+
+    qint64 frameStart(unsigned index) const {
+        return m_profile->frames[index].calls.begin;
+    }
+
+    qint64 frameEnd(unsigned index) const {
+        return m_profile->frames[index].calls.end;
+    }
+
+private:
+    const trace::Profile* m_profile;
+};
+
+/* Provides frame numbers based off time */
+class FrameTimeDataProvider : public FrameDataProvider {
+public:
+    FrameTimeDataProvider(const trace::Profile* profile)
+    {
+        m_profile = profile;
+    }
+
+    unsigned size() const {
+        return m_profile->frames.size();
+    }
+
+    qint64 frameStart(unsigned index) const {
+        return m_profile->frames[index].cpuStart;
+    }
+
+    qint64 frameEnd(unsigned index) const {
+        return m_profile->frames[index].cpuStart + m_profile->frames[index].cpuDuration;
+    }
+
+private:
+    const trace::Profile* m_profile;
+};
+
+ProfileDialog::ProfileDialog(QWidget *parent)
+    : QDialog(parent),
+      m_profile(0)
+{
+    setupUi(this);
+    g_profileDialog = this;
+
+    /* Gradients for call duration histograms */
+    QLinearGradient cpuGradient;
+    cpuGradient.setColorAt(0.9, QColor(0, 0, 210));
+    cpuGradient.setColorAt(0.0, QColor(130, 130, 255));
+
+    QLinearGradient gpuGradient;
+    gpuGradient.setColorAt(0.9, QColor(210, 0, 0));
+    gpuGradient.setColorAt(0.0, QColor(255, 130, 130));
+
+
+    /* Setup heatmap timeline */
+    m_timeline->setLabel(new GraphLabelWidget("Frames ", m_timeline));
+    m_timeline->label()->setFlags(Qt::AlignVCenter | Qt::AlignRight);
+
+    m_timeline->setView(new HeatmapView(m_timeline));
+
+    m_timeline->setAxis(GraphWidget::AxisTop, new FrameAxisWidget(m_timeline));
+    m_timeline->setAxis(GraphWidget::AxisLeft, new HeatmapVerticalAxisWidget(m_timeline));
+    m_timeline->axis(GraphWidget::AxisLeft)->resize(80, 0);
+
+    m_timeline->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    m_timeline->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+
+
+    /* Setup Cpu call duration histogram */
+    m_cpuGraph->setLabel(new GraphLabelWidget("CPU", m_cpuGraph));
+
+    m_cpuGraph->setAxis(GraphWidget::AxisTop, new FrameAxisWidget(m_cpuGraph));
+    m_cpuGraph->setAxis(GraphWidget::AxisLeft, new TimeAxisWidget(m_cpuGraph));
+    m_cpuGraph->axis(GraphWidget::AxisLeft)->resize(80, 0);
+
+    HistogramView* cpuView = new HistogramView(m_cpuGraph);
+    cpuView->setSelectedGradient(cpuGradient);
+    m_cpuGraph->setView(cpuView);
+
+
+    /* Setup Gpu call duration histogram */
+    m_gpuGraph->setLabel(new GraphLabelWidget("GPU", m_gpuGraph));
+
+    m_gpuGraph->setAxis(GraphWidget::AxisTop, new FrameAxisWidget(m_gpuGraph));
+    m_gpuGraph->setAxis(GraphWidget::AxisLeft, new TimeAxisWidget(m_gpuGraph));
+    m_gpuGraph->axis(GraphWidget::AxisLeft)->resize(80, 0);
+
+    HistogramView* gpuView = new HistogramView(m_gpuGraph);
+    gpuView->setSelectedGradient(gpuGradient);
+    m_gpuGraph->setView(gpuView);
+
+
+    /* Synchronise selections */
+    connect(m_timeline, SIGNAL(selectionChanged(SelectionState)), m_cpuGraph, SLOT(setSelection(SelectionState)));
+    connect(m_timeline, SIGNAL(selectionChanged(SelectionState)), m_gpuGraph, SLOT(setSelection(SelectionState)));
+
+    connect(m_cpuGraph, SIGNAL(selectionChanged(SelectionState)), m_timeline, SLOT(setSelection(SelectionState)));
+    connect(m_cpuGraph, SIGNAL(selectionChanged(SelectionState)), m_gpuGraph, SLOT(setSelection(SelectionState)));
+
+    connect(m_gpuGraph, SIGNAL(selectionChanged(SelectionState)), m_timeline, SLOT(setSelection(SelectionState)));
+    connect(m_gpuGraph, SIGNAL(selectionChanged(SelectionState)), m_cpuGraph, SLOT(setSelection(SelectionState)));
+
+    connect(m_timeline, SIGNAL(selectionChanged(SelectionState)), this, SLOT(graphSelectionChanged(SelectionState)));
+    connect(m_cpuGraph, SIGNAL(selectionChanged(SelectionState)), this, SLOT(graphSelectionChanged(SelectionState)));
+    connect(m_gpuGraph, SIGNAL(selectionChanged(SelectionState)), this, SLOT(graphSelectionChanged(SelectionState)));
+
+
+    /* Synchronise views between cpuGraph and gpuGraph */
+    connect(m_cpuGraph, SIGNAL(horizontalViewChanged(qint64,qint64)), m_gpuGraph, SLOT(setHorizontalView(qint64,qint64)));
+    connect(m_gpuGraph, SIGNAL(horizontalViewChanged(qint64,qint64)), m_cpuGraph, SLOT(setHorizontalView(qint64,qint64)));
+}
+
+
+ProfileDialog::~ProfileDialog()
+{
+    delete m_profile;
+}
+
+
+void ProfileDialog::showCall(int call)
+{
+    emit jumpToCall(call);
+}
+
+
+void ProfileDialog::tableDoubleClicked(const QModelIndex& index)
+{
+    ProfileTableModel* model = (ProfileTableModel*)m_table->model();
+
+    if (!model) {
+        return;
+    }
+
+    const trace::Profile::Call* call = model->getJumpCall(index);
+
+    if (call) {
+        emit jumpToCall(call->no);
+    } else {
+        unsigned program = model->getProgram(index);
+
+        SelectionState state;
+        state.type = SelectionState::Vertical;
+        state.end = state.start = program;
+
+        m_timeline->setSelection(state);
+        m_cpuGraph->setSelection(state);
+        m_gpuGraph->setSelection(state);
+    }
+}
+
+
+void ProfileDialog::setProfile(trace::Profile* profile)
+{
+
+    if (profile && profile->frames.size()) {
+        HeatmapVerticalAxisWidget* programAxis;
+        FrameAxisWidget* frameAxis;
+        HistogramView* histogram;
+        HeatmapView* heatmap;
+
+
+        /* Setup data providers for Cpu graph */
+        m_cpuGraph->setProfile(profile);
+        histogram = (HistogramView*)m_cpuGraph->view();
+        frameAxis = (FrameAxisWidget*)m_cpuGraph->axis(GraphWidget::AxisTop);
+
+        histogram->setDataProvider(new CallDurationDataProvider(profile, false));
+        frameAxis->setDataProvider(new FrameCallDataProvider(profile));
+
+        /* Setup data provider for Gpu graph */
+        m_gpuGraph->setProfile(profile);
+        histogram = (HistogramView*)m_gpuGraph->view();
+        frameAxis = (FrameAxisWidget*)m_gpuGraph->axis(GraphWidget::AxisTop);
+
+        histogram->setDataProvider(new CallDurationDataProvider(profile, true));
+        frameAxis->setDataProvider(new FrameCallDataProvider(profile));
+
+        /* Setup data provider for heatmap timeline */
+        heatmap = (HeatmapView*)m_timeline->view();
+        frameAxis = (FrameAxisWidget*)m_timeline->axis(GraphWidget::AxisTop);
+        programAxis = (HeatmapVerticalAxisWidget*)m_timeline->axis(GraphWidget::AxisLeft);
+
+        heatmap->setDataProvider(new ProfileHeatmapDataProvider(profile));
+        frameAxis->setDataProvider(new FrameTimeDataProvider(profile));
+        programAxis->setDataProvider(new ProfileHeatmapDataProvider(profile));
+
+        /* Setup data model for table view */
+        ProfileTableModel* model = new ProfileTableModel(m_table);
+        model->setProfile(profile);
+
+        delete m_table->model();
+        m_table->setModel(model);
+        m_table->update(QModelIndex());
+        m_table->sortByColumn(2, Qt::DescendingOrder);
+        m_table->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+        m_table->resizeColumnsToContents();
+
+        /* Reset selection */
+        SelectionState emptySelection;
+        emptySelection.type = SelectionState::None;
+        m_cpuGraph->setSelection(emptySelection);
+        m_gpuGraph->setSelection(emptySelection);
+        m_timeline->setSelection(emptySelection);
+    }
+
+    delete m_profile;
+    m_profile = profile;
+}
+
+
+void ProfileDialog::graphSelectionChanged(SelectionState state)
+{
+    ProfileTableModel* model = (ProfileTableModel*)m_table->model();
+
+    if (!model) {
+        return;
+    }
+
+    if (state.type == SelectionState::None) {
+        model->selectNone();
+    } else if (state.type == SelectionState::Horizontal) {
+        model->selectTime(state.start, state.end);
+    } else if (state.type == SelectionState::Vertical) {
+        model->selectProgram(state.start);
+    }
+
+    m_table->reset();
+
+    if (state.type == SelectionState::Vertical) {
+        m_table->selectRow(model->getRowIndex(state.start));
+    }
+}
+
+#include "profiledialog.moc"
diff --git a/gui/profiledialog.h b/gui/profiledialog.h
new file mode 100644 (file)
index 0000000..862d068
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef PROFILEDIALOG_H
+#define PROFILEDIALOG_H
+
+#include "ui_profiledialog.h"
+#include <QDialog>
+
+namespace trace { struct Profile; }
+
+class ProfileDialog : public QDialog, public Ui_ProfileDialog
+{
+    Q_OBJECT
+
+public:
+    ProfileDialog(QWidget *parent = 0);
+    ~ProfileDialog();
+    
+    void setProfile(trace::Profile* profile);
+    void showCall(int call);
+
+public slots:
+    void tableDoubleClicked(const QModelIndex& index);
+    void graphSelectionChanged(SelectionState state);
+
+signals:
+    void jumpToCall(int call);
+
+private:
+    trace::Profile *m_profile;
+};
+
+#endif
diff --git a/gui/profileheatmap.h b/gui/profileheatmap.h
new file mode 100644 (file)
index 0000000..e50ea26
--- /dev/null
@@ -0,0 +1,470 @@
+#ifndef PROFILEHEATMAP_H
+#define PROFILEHEATMAP_H
+
+#include "graphing/heatmapview.h"
+#include "profiling.h"
+
+/**
+ * Data providers for a heatmap based off the trace::Profile call data
+ */
+
+class ProfileHeatmapRowIterator : public HeatmapRowIterator {
+public:
+    ProfileHeatmapRowIterator(const trace::Profile* profile, qint64 start, qint64 end, int steps, bool gpu, int program = -1) :
+        m_profile(profile),
+        m_step(-1),
+        m_stepWidth(1),
+        m_stepCount(steps),
+        m_index(0),
+        m_timeStart(start),
+        m_timeEnd(end),
+        m_useGpu(gpu),
+        m_program(program),
+        m_selected(false),
+        m_timeSelection(false),
+        m_programSelection(false)
+    {
+        m_timeWidth = m_timeEnd - m_timeStart;
+    }
+
+    virtual bool next()
+    {
+        unsigned maxIndex = m_program == -1 ? m_profile->calls.size() : m_profile->programs[m_program].calls.size();
+
+        if (m_index >= maxIndex) {
+            return false;
+        }
+
+        double dtds = m_timeWidth / (double)m_stepCount;
+
+        qint64 heatDuration = 0;
+        qint64 programHeatDuration = 0;
+        m_heat = 0.0f;
+        m_step += m_stepWidth;
+        m_stepWidth = 1;
+
+        m_selected = false;
+
+        /* Iterator through calls until step != lastStep */
+        for (; m_index < maxIndex; ++m_index)
+        {
+            const trace::Profile::Call* call;
+
+            if (m_program == -1) {
+                call = &m_profile->calls[m_index];
+            } else {
+                call = &m_profile->calls[ m_profile->programs[m_program].calls[m_index] ];
+            }
+
+            qint64 start, duration, end;
+
+            if (m_useGpu) {
+                start = call->gpuStart;
+                duration = call->gpuDuration;
+
+                if (call->pixels < 0) {
+                    continue;
+                }
+            } else {
+                start = call->cpuStart;
+                duration = call->cpuDuration;
+            }
+
+            end = start + duration;
+
+            if (end < m_timeStart) {
+                continue;
+            }
+
+            if (start > m_timeEnd) {
+                m_index = m_profile->calls.size();
+                break;
+            }
+
+            double left  = timeToStep(start);
+            double right = timeToStep(end);
+
+            int leftStep = left;
+            int rightStep = right;
+
+            if (leftStep > m_step) {
+                break;
+            }
+
+            if (m_programSelection && call->program == m_programSel) {
+                m_selected = true;
+            }
+
+            if (rightStep - leftStep > 1) {
+                m_label = QString::fromStdString(call->name);
+                m_step = left;
+                m_stepWidth = rightStep - leftStep;
+                heatDuration = dtds;
+                ++m_index;
+                break;
+            }
+
+            if (leftStep < m_step) {
+                qint64 rightTime = stepToTime(rightStep);
+                heatDuration += end - rightTime;
+
+                if (m_programSelection && call->program == m_programSel) {
+                    programHeatDuration += end - rightTime;
+                }
+            } else if (leftStep == rightStep) {
+                heatDuration += duration;
+
+                if (m_programSelection && call->program == m_programSel) {
+                    programHeatDuration += duration;
+                }
+            } else if (rightStep - leftStep == 1) {
+                qint64 rightTime = stepToTime(rightStep);
+                heatDuration += rightTime - start;
+
+                if (m_programSelection && call->program == m_programSel) {
+                    programHeatDuration += rightTime - start;
+                }
+
+                break;
+            }
+        }
+
+        m_heat = heatDuration / dtds;
+        m_programHeat = programHeatDuration / dtds;
+
+        if (m_timeSelection) {
+            qint64 time = stepToTime(m_step);
+
+            if (time >= m_timeSelStart && time <= m_timeSelEnd) {
+                m_programHeat = 1.0;
+            }
+        }
+
+        if (m_programSelection && (m_program == m_programSel || (m_selected && m_stepWidth > 1))) {
+            m_programHeat = 1.0;
+        }
+
+        if (m_programHeat > 0) {
+            m_selected = true;
+        }
+
+        return true;
+    }
+
+    virtual bool isGpu() const
+    {
+        return m_useGpu;
+    }
+
+    virtual float heat() const
+    {
+        return m_heat;
+    }
+
+    virtual float selectedHeat() const
+    {
+        return m_programHeat;
+    }
+
+    virtual int step() const
+    {
+        return m_step;
+    }
+
+    virtual int width() const
+    {
+        return m_stepWidth;
+    }
+
+    virtual QString label() const
+    {
+        return m_label;
+    }
+
+    void setProgramSelection(int program)
+    {
+        m_programSelection = true;
+        m_programSel = program;
+    }
+
+    void setTimeSelection(qint64 start, qint64 end)
+    {
+        m_timeSelection = true;
+        m_timeSelStart = start;
+        m_timeSelEnd = end;
+    }
+
+private:
+    double timeToStep(qint64 time) const
+    {
+        double pos = time;
+        pos -= m_timeStart;
+        pos /= m_timeWidth;
+        pos *= m_stepCount;
+        return pos;
+    }
+
+    qint64 stepToTime(int pos) const
+    {
+        double time = pos;
+        time /= m_stepCount;
+        time *= m_timeWidth;
+        time += m_timeStart;
+        return (qint64)time;
+    }
+
+private:
+    const trace::Profile* m_profile;
+
+    int m_step;
+    int m_stepWidth;
+    int m_stepCount;
+
+    unsigned m_index;
+
+    float m_heat;
+
+    qint64 m_timeStart;
+    qint64 m_timeEnd;
+    qint64 m_timeWidth;
+
+    bool m_useGpu;
+    int m_program;
+
+    QString m_label;
+
+    bool m_selected;
+
+    bool m_timeSelection;
+    qint64 m_timeSelStart;
+    qint64 m_timeSelEnd;
+
+    bool m_programSelection;
+    int m_programSel;
+
+    float m_programHeat;
+};
+
+class ProfileHeatmapDataProvider : public HeatmapDataProvider {
+protected:
+    enum SelectionType {
+        None,
+        Time,
+        Program
+    };
+
+public:
+    ProfileHeatmapDataProvider(trace::Profile* profile) :
+        m_profile(profile),
+        m_selectionState(NULL)
+    {
+        sortRows();
+    }
+
+    virtual qint64 start() const
+    {
+        return m_profile->frames.front().cpuStart;
+    }
+
+    virtual qint64 end() const
+    {
+        return m_profile->frames.back().cpuStart + m_profile->frames.back().cpuDuration;
+    }
+
+    virtual unsigned dataRows() const
+    {
+        return m_rowPrograms.size();
+    }
+
+    virtual QString dataLabel(unsigned row) const
+    {
+        if (row >= m_rowPrograms.size()) {
+            return QString();
+        } else {
+            return QString("%1").arg(m_rowPrograms[row]);
+        }
+    }
+
+    virtual qint64 dataRowAt(unsigned row) const
+    {
+        if (row >= m_rowPrograms.size()) {
+            return 0;
+        } else {
+            return m_rowPrograms[row];
+        }
+    }
+
+    virtual HeatmapRowIterator* dataRowIterator(int row, qint64 start, qint64 end, int steps) const
+    {
+        ProfileHeatmapRowIterator* itr = new ProfileHeatmapRowIterator(m_profile, start, end, steps, true, m_rowPrograms[row]);
+
+        if (m_selectionState) {
+            if (m_selectionState->type == SelectionState::Horizontal) {
+                itr->setTimeSelection(m_selectionState->start, m_selectionState->end);
+            } else if (m_selectionState->type == SelectionState::Vertical) {
+                itr->setProgramSelection(m_selectionState->start);
+            }
+        }
+
+        return itr;
+    }
+
+    virtual unsigned headerRows() const
+    {
+        return 2;
+    }
+
+    virtual qint64 headerRowAt(unsigned row) const
+    {
+        return row;
+    }
+
+    virtual QString headerLabel(unsigned row) const
+    {
+        if (row == 0) {
+            return "CPU";
+        } else if (row == 1) {
+            return "GPU";
+        } else {
+            return QString();
+        }
+    }
+
+    virtual HeatmapRowIterator* headerRowIterator(int row, qint64 start, qint64 end, int steps) const
+    {
+        ProfileHeatmapRowIterator* itr = new ProfileHeatmapRowIterator(m_profile, start, end, steps, row != 0);
+
+        if (m_selectionState) {
+            if (m_selectionState->type == SelectionState::Horizontal) {
+                itr->setTimeSelection(m_selectionState->start, m_selectionState->end);
+            } else if (m_selectionState->type == SelectionState::Vertical) {
+                itr->setProgramSelection(m_selectionState->start);
+            }
+        }
+
+        return itr;
+    }
+
+    virtual qint64 dataItemAt(unsigned row, qint64 time) const
+    {
+        if (row >= m_rowPrograms.size()) {
+            return -1;
+        }
+
+        unsigned program = m_rowPrograms[row];
+
+        std::vector<unsigned>::const_iterator item =
+                Profiling::binarySearchTimespanIndexed
+                    (m_profile->calls, m_profile->programs[program].calls.begin(), m_profile->programs[program].calls.end(), time);
+
+        if (item == m_profile->programs[program].calls.end()) {
+            return -1;
+        }
+
+        return *item;
+    }
+
+    virtual qint64 headerItemAt(unsigned row, qint64 time) const
+    {
+        if (row >= m_rowPrograms.size()) {
+            return -1;
+        }
+
+        if (row == 0) {
+            /* CPU */
+            std::vector<trace::Profile::Call>::const_iterator item =
+                    Profiling::binarySearchTimespan<trace::Profile::Call,
+                                        &trace::Profile::Call::cpuStart,
+                                        &trace::Profile::Call::cpuDuration>
+                    (m_profile->calls.begin(), m_profile->calls.end(), time);
+
+            if (item != m_profile->calls.end()) {
+                return item - m_profile->calls.begin();
+            }
+        } else if (row == 1) {
+            /* GPU */
+            for (unsigned i = 0; i < m_rowPrograms.size(); ++i) {
+                qint64 index = dataItemAt(i, time);
+
+                if (index != -1) {
+                    return index;
+                }
+            }
+        }
+
+        return -1;
+    }
+
+    virtual void itemDoubleClicked(qint64 index) const
+    {
+        if (index < 0 || index >= m_profile->calls.size()) {
+            return;
+        }
+
+        const trace::Profile::Call& call = m_profile->calls[index];
+        Profiling::jumpToCall(call.no);
+    }
+
+    virtual QString itemTooltip(qint64 index) const
+    {
+        if (index >= m_profile->calls.size()) {
+            return QString();
+        }
+
+        const trace::Profile::Call& call = m_profile->calls[index];
+
+        QString text;
+        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));
+
+        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("\nPixels Drawn: %1").arg(QLocale::system().toString((qlonglong)call.pixels));
+        }
+
+        return text;
+    }
+
+    virtual void setSelectionState(SelectionState* state)
+    {
+        m_selectionState = state;
+    }
+
+private:
+    void sortRows()
+    {
+        typedef QPair<quint64, unsigned> Pair;
+        std::vector<Pair> gpu;
+
+        /* Map shader to visible row */
+        for (std::vector<trace::Profile::Program>::const_iterator itr = m_profile->programs.begin(); itr != m_profile->programs.end(); ++itr) {
+            const trace::Profile::Program& program = *itr;
+            unsigned no = itr -  m_profile->programs.begin();
+
+            if (program.gpuTotal > 0) {
+                gpu.push_back(Pair(program.gpuTotal, no));
+            }
+        }
+
+        /* Sort the shaders by most used gpu */
+        qSort(gpu);
+
+        /* Create row order */
+        m_rowPrograms.clear();
+
+        for (std::vector<Pair>::const_reverse_iterator itr = gpu.rbegin(); itr != gpu.rend(); ++itr) {
+            m_rowPrograms.push_back(itr->second);
+        }
+    }
+
+protected:
+    trace::Profile* m_profile;
+    std::vector<int> m_rowPrograms;
+    SelectionState* m_selectionState;
+};
+
+#endif
diff --git a/gui/profiletablemodel.cpp b/gui/profiletablemodel.cpp
new file mode 100644 (file)
index 0000000..11a0d0c
--- /dev/null
@@ -0,0 +1,331 @@
+#include "profiletablemodel.h"
+#include "profiledialog.h"
+#include "profiling.h"
+
+#include <QLocale>
+
+typedef trace::Profile::Call Call;
+typedef trace::Profile::Frame Frame;
+typedef trace::Profile::Program Program;
+
+enum {
+    COLUMN_PROGRAM,
+    COLUMN_USAGES,
+    COLUMN_GPU_TIME,
+    COLUMN_CPU_TIME,
+    COLUMN_PIXELS_DRAWN,
+    COLUMN_GPU_AVERAGE,
+    COLUMN_CPU_AVERAGE,
+    COLUMN_PIXELS_AVERAGE,
+    MAX_COLUMN
+};
+
+static QString columnNames[] = {
+    QString("Program"),
+    QString("Calls"),
+    QString("Total GPU Time"),
+    QString("Total CPU Time"),
+    QString("Total Pixels Drawn"),
+    QString("Avg GPU Time"),
+    QString("Avg CPU Time"),
+    QString("Avg Pixels Drawn")
+};
+
+ProfileTableModel::ProfileTableModel(QObject *parent)
+    : QAbstractTableModel(parent),
+      m_profile(0),
+      m_sortColumn(COLUMN_GPU_TIME),
+      m_sortOrder(Qt::DescendingOrder)
+{
+}
+
+
+void ProfileTableModel::setProfile(trace::Profile* profile)
+{
+    m_profile = profile;
+    m_timeMin = m_profile->frames.front().cpuStart;
+    m_timeMax = m_profile->frames.back().cpuStart + m_profile->frames.back().cpuDuration;
+    updateModel();
+}
+
+
+/**
+ * Set selection to nothing
+ */
+void ProfileTableModel::selectNone()
+{
+    m_timeMin = m_timeMax = 0;
+    updateModel();
+    sort(m_sortColumn, m_sortOrder);
+}
+
+
+/**
+ * Set selection to program
+ */
+void ProfileTableModel::selectProgram(unsigned /*program*/)
+{
+    /* We have no program based selection for table */
+    selectNone();
+}
+
+
+/**
+ * Set selection to a period of time
+ */
+void ProfileTableModel::selectTime(int64_t start, int64_t end)
+{
+    m_timeMin = start;
+    m_timeMax = end;
+
+    updateModel();
+    sort(m_sortColumn, m_sortOrder);
+}
+
+
+/**
+ * Creates the row data from trace profile
+ */
+void ProfileTableModel::updateModel()
+{
+    if (m_timeMin == m_timeMax) {
+        m_timeMin = m_profile->frames.front().cpuStart;
+        m_timeMax = m_profile->frames.back().cpuStart + m_profile->frames.back().cpuDuration;
+    }
+
+    for (QList<ProfileTableRow>::iterator itr = m_rowData.begin(); itr != m_rowData.end(); ++itr) {
+        ProfileTableRow& row = *itr;
+
+        row.uses = 0;
+        row.pixels = 0;
+        row.gpuTime = 0;
+        row.cpuTime = 0;
+        row.longestCpu = NULL;
+        row.longestGpu = NULL;
+        row.longestPixel = NULL;
+    }
+
+    for (std::vector<Program>::const_iterator itr = m_profile->programs.begin(); itr != m_profile->programs.end(); ++itr) {
+        ProfileTableRow* row = NULL;
+        const Program& program = *itr;
+
+        for (std::vector<unsigned>::const_iterator jtr = program.calls.begin(); jtr != program.calls.end(); ++jtr) {
+            const Call& call = m_profile->calls[*jtr];
+
+            if (call.cpuStart > m_timeMax) {
+                break;
+            }
+
+            if (call.cpuStart + call.cpuDuration < m_timeMin) {
+                continue;
+            }
+
+            if (!row) {
+                row = getRow(itr - m_profile->programs.begin());
+            }
+
+            row->uses++;
+            row->pixels  += call.pixels;
+            row->gpuTime += call.gpuDuration;
+            row->cpuTime += call.cpuDuration;
+
+            if (!row->longestGpu || row->longestGpu->gpuDuration < call.gpuDuration) {
+                row->longestGpu = &call;
+            }
+
+            if (!row->longestCpu || row->longestCpu->cpuDuration < call.cpuDuration) {
+                row->longestCpu = &call;
+            }
+
+            if (!row->longestPixel || row->longestPixel->pixels < call.pixels) {
+                row->longestPixel = &call;
+            }
+        }
+    }
+}
+
+
+/**
+ * Get the appropriate call associated with an item in the table
+ */
+const trace::Profile::Call *ProfileTableModel::getJumpCall(const QModelIndex & index) const {
+    const ProfileTableRow& row = m_rowData[index.row()];
+
+    switch(index.column()) {
+    case COLUMN_GPU_TIME:
+    case COLUMN_GPU_AVERAGE:
+        return row.longestGpu;
+    case COLUMN_CPU_TIME:
+    case COLUMN_CPU_AVERAGE:
+        return row.longestCpu;
+    case COLUMN_PIXELS_DRAWN:
+    case COLUMN_PIXELS_AVERAGE:
+        return row.longestPixel;
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Get the shader program associated with an item in the table
+ */
+unsigned ProfileTableModel::getProgram(const QModelIndex & index) const
+{
+    const ProfileTableRow& row = m_rowData[index.row()];
+    return row.program;
+}
+
+
+/**
+ * Get the row index for a shader program
+ */
+int ProfileTableModel::getRowIndex(unsigned program) const
+{
+    for (int i = 0; i < m_rowData.size(); ++i) {
+        if (m_rowData[i].program == program)
+            return i;
+    }
+
+    return -1;
+}
+
+
+/**
+ * Get the row data for a shader program
+ */
+ProfileTableRow* ProfileTableModel::getRow(unsigned program) {
+    for (QList<ProfileTableRow>::iterator itr = m_rowData.begin(); itr != m_rowData.end(); ++itr) {
+        if (itr->program == program)
+            return &*itr;
+    }
+
+    m_rowData.append(ProfileTableRow(program));
+    return &m_rowData.back();
+}
+
+
+int ProfileTableModel::rowCount(const QModelIndex & parent) const
+{
+    if (!parent.isValid()) {
+        return m_rowData.size();
+    } else {
+        return 0;
+    }
+}
+
+
+int ProfileTableModel::columnCount(const QModelIndex & /*parent*/) const
+{
+    return MAX_COLUMN;
+}
+
+
+QVariant ProfileTableModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid()) {
+        return QVariant();
+    }
+
+    if (role == Qt::DisplayRole) {
+        const ProfileTableRow& row = m_rowData[index.row()];
+
+        switch(index.column()) {
+        case COLUMN_PROGRAM:
+            return row.program;
+        case COLUMN_USAGES:
+            return QLocale::system().toString(row.uses);
+        case COLUMN_GPU_TIME:
+            return Profiling::getTimeString(row.gpuTime);
+        case COLUMN_CPU_TIME:
+            return Profiling::getTimeString(row.cpuTime);
+        case COLUMN_PIXELS_DRAWN:
+            return QLocale::system().toString((qlonglong)row.pixels);
+        case COLUMN_GPU_AVERAGE:
+            return Profiling::getTimeString((row.uses <= 0) ? 0 : (row.gpuTime / row.uses));
+        case COLUMN_CPU_AVERAGE:
+            return Profiling::getTimeString((row.uses <= 0) ? 0 : (row.cpuTime / row.uses));
+        case COLUMN_PIXELS_AVERAGE:
+            return QLocale::system().toString((row.uses <= 0) ? 0 : (row.pixels / row.uses));
+        }
+    } else if (role == Qt::TextAlignmentRole) {
+        return Qt::AlignRight;
+    }
+
+    return QVariant();
+}
+
+
+QVariant ProfileTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+    if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
+        if (section >= 0 && section < MAX_COLUMN) {
+            return columnNames[section];
+        }
+    }
+
+    return QVariant();
+}
+
+
+class ProgramSorter {
+public:
+    ProgramSorter(int column, Qt::SortOrder order)
+        : mSortColumn(column),
+          mSortOrder(order)
+    {
+    }
+
+    bool operator()(const ProfileTableRow &p1, const ProfileTableRow &p2) const
+    {
+        bool result = true;
+
+        switch(mSortColumn) {
+        case COLUMN_PROGRAM:
+            result = p1.program < p2.program;
+            break;
+        case COLUMN_USAGES:
+            result = p1.uses < p2.uses;
+            break;
+        case COLUMN_GPU_TIME:
+            result = p1.gpuTime < p2.gpuTime;
+            break;
+        case COLUMN_CPU_TIME:
+            result = p1.cpuTime < p2.cpuTime;
+            break;
+        case COLUMN_PIXELS_DRAWN:
+            result = p1.pixels < p2.pixels;
+            break;
+        case COLUMN_GPU_AVERAGE:
+            result = ((p1.uses <= 0) ? 0 : (p1.gpuTime / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.gpuTime / p2.uses));
+            break;
+        case COLUMN_CPU_AVERAGE:
+            result = ((p1.uses <= 0) ? 0 : (p1.cpuTime / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.cpuTime / p2.uses));
+            break;
+        case COLUMN_PIXELS_AVERAGE:
+            result = ((p1.uses <= 0) ? 0 : (p1.pixels / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.pixels / p2.uses));
+            break;
+        }
+
+        if (mSortOrder == Qt::DescendingOrder) {
+            return !result;
+        } else {
+            return result;
+        }
+    }
+
+private:
+    int mSortColumn;
+    Qt::SortOrder mSortOrder;
+};
+
+
+void ProfileTableModel::sort(int column, Qt::SortOrder order) {
+    m_sortColumn = column;
+    m_sortOrder = order;
+    qSort(m_rowData.begin(), m_rowData.end(), ProgramSorter(column, order));
+    emit dataChanged(createIndex(0, 0), createIndex(m_rowData.size(), MAX_COLUMN));
+}
+
+
+#include "profiletablemodel.moc"
diff --git a/gui/profiletablemodel.h b/gui/profiletablemodel.h
new file mode 100644 (file)
index 0000000..da17550
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef PROFILETABLEMODEL_H
+#define PROFILETABLEMODEL_H
+
+#include <QAbstractTableModel>
+#include "trace_profiler.hpp"
+
+struct ProfileTableRow
+{
+    ProfileTableRow(unsigned no)
+        : program(no),
+          uses(0),
+          gpuTime(0),
+          cpuTime(0),
+          pixels(0),
+          longestGpu(0),
+          longestCpu(0),
+          longestPixel(0)
+    {
+    }
+
+    unsigned program;
+    qulonglong uses;
+    qulonglong gpuTime;
+    qulonglong cpuTime;
+    qulonglong pixels;
+
+    const trace::Profile::Call* longestGpu;
+    const trace::Profile::Call* longestCpu;
+    const trace::Profile::Call* longestPixel;
+};
+
+class ProfileTableModel : public QAbstractTableModel
+{
+    Q_OBJECT
+
+public:
+    ProfileTableModel(QObject *parent = NULL);
+
+    void setProfile(trace::Profile* profile);
+
+    void selectNone();
+    void selectProgram(unsigned program);
+    void selectTime(int64_t start, int64_t end);
+
+    int getRowIndex(unsigned program) const;
+    unsigned getProgram(const QModelIndex & index) const;
+    const trace::Profile::Call* getJumpCall(const QModelIndex & index) const;
+
+    virtual int rowCount(const QModelIndex & parent) const;
+    virtual int columnCount(const QModelIndex & parent) const;
+
+    virtual QVariant data(const QModelIndex &index, int role) const;
+    virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+
+    virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
+
+private:
+    void updateModel();
+    ProfileTableRow* getRow(unsigned program);
+
+private:
+    QList<ProfileTableRow> m_rowData;
+    trace::Profile *m_profile;
+    int64_t m_timeMin;
+    int64_t m_timeMax;
+    int m_sortColumn;
+    Qt::SortOrder m_sortOrder;
+};
+
+#endif // PROFILEMODEL_H
diff --git a/gui/profiling.h b/gui/profiling.h
new file mode 100644 (file)
index 0000000..a5b1266
--- /dev/null
@@ -0,0 +1,128 @@
+#ifndef PROFILING_H
+#define PROFILING_H
+
+#include <QString>
+#include <QLocale>
+#include "trace_profiler.hpp"
+
+class Profiling {
+public:
+    /**
+     * Select and show the call in main window.
+     */
+    static void jumpToCall(int index);
+
+    /**
+     * Convert a CPU / GPU time to a textual representation.
+     * This includes automatic unit selection.
+     */
+    static QString getTimeString(int64_t time, int64_t unitTime = 0)
+    {
+        QString text;
+        QString unit = " ns";
+        double unitScale = 1;
+
+        if (unitTime == 0) {
+            unitTime = time;
+        }
+
+        if (unitTime >= 60e9) {
+            int64_t mins = time / 60e9;
+            text += QString("%1 m ").arg(mins);
+
+            time -= mins * 60e9;
+            unit = " s";
+            unitScale = 1e9;
+        } else if (unitTime >= 1e9) {
+            unit = " s";
+            unitScale = 1e9;
+        } else if (unitTime >= 1e6) {
+            unit = " ms";
+            unitScale = 1e6;
+        } else if (unitTime >= 1e3) {
+            unit = QString::fromUtf8(" µs");
+            unitScale = 1e3;
+        }
+
+        /* 3 decimal places */
+        text += QString("%1").arg(time / unitScale, 0, 'f', 3);
+
+        /* Remove trailing 0 */
+        while(text.endsWith('0'))
+            text.truncate(text.length() - 1);
+
+        /* Remove trailing decimal point */
+        if (text.endsWith(QLocale::system().decimalPoint()))
+            text.truncate(text.length() - 1);
+
+        return text + unit;
+    }
+
+    template<typename val_ty, int64_t val_ty::* mem_ptr_start, int64_t val_ty::* mem_ptr_dura>
+    static typename std::vector<val_ty>::const_iterator binarySearchTimespan(
+            typename std::vector<val_ty>::const_iterator begin,
+            typename std::vector<val_ty>::const_iterator end,
+            int64_t time,
+            bool nearest = false)
+    {
+        int lower = 0;
+        int upper = end - begin;
+        int pos = (lower + upper) / 2;
+        typename std::vector<val_ty>::const_iterator itr = begin + pos;
+
+        while (!((*itr).*mem_ptr_start <= time && (*itr).*mem_ptr_start + (*itr).*mem_ptr_dura > time) && (lower <= upper)) {
+            if ((*itr).*mem_ptr_start > time) {
+                upper = pos - 1;
+            } else {
+                lower = pos + 1;
+            }
+
+            pos = (lower + upper) / 2;
+            itr = begin + pos;
+        }
+
+        if (nearest || lower <= upper) {
+            return itr;
+        } else {
+            return end;
+        }
+    }
+
+    static std::vector<unsigned>::const_iterator binarySearchTimespanIndexed(
+            const std::vector<trace::Profile::Call>& calls,
+            std::vector<unsigned>::const_iterator begin,
+            std::vector<unsigned>::const_iterator end,
+            int64_t time,
+            bool nearest = false)
+    {
+        int lower = 0;
+        int upper = end - begin - 1;
+        int pos = (lower + upper) / 2;
+        std::vector<unsigned>::const_iterator itr = begin + pos;
+
+        while (lower <= upper) {
+            const trace::Profile::Call& call = calls[*itr];
+
+            if (call.gpuStart <= time && call.gpuStart + call.gpuDuration > time) {
+                break;
+            }
+
+            if (call.gpuStart > time) {
+                upper = pos - 1;
+            } else {
+                lower = pos + 1;
+            }
+
+            pos = (lower + upper) / 2;
+            itr = begin + pos;
+        }
+
+        if (nearest || lower <= upper) {
+            return itr;
+        } else {
+            return end;
+        }
+    }
+};
+
+#endif
index bbe638ca0fc0635f41e10ff9ffdbcf225f0bd0a5..6d743f70e72d04aab4cb7e181603e5597ea52f96 100644 (file)
@@ -5,6 +5,8 @@
 
 #include "image.hpp"
 
+#include "trace_profiler.hpp"
+
 #include <QDebug>
 #include <QVariant>
 #include <QList>
@@ -129,7 +131,10 @@ Retracer::Retracer(QObject *parent)
       m_benchmarking(false),
       m_doubleBuffered(true),
       m_captureState(false),
-      m_captureCall(0)
+      m_captureCall(0),
+      m_profileGpu(false),
+      m_profileCpu(false),
+      m_profilePixels(false)
 {
     qRegisterMetaType<QList<ApiTraceError> >();
 
@@ -182,6 +187,33 @@ void Retracer::setDoubleBuffered(bool db)
     m_doubleBuffered = db;
 }
 
+bool Retracer::isProfilingGpu() const
+{
+    return m_profileGpu;
+}
+
+bool Retracer::isProfilingCpu() const
+{
+    return m_profileCpu;
+}
+
+bool Retracer::isProfilingPixels() const
+{
+    return m_profilePixels;
+}
+
+bool Retracer::isProfiling() const
+{
+    return m_profileGpu || m_profileCpu || m_profilePixels;
+}
+
+void Retracer::setProfiling(bool gpu, bool cpu, bool pixels)
+{
+    m_profileGpu = gpu;
+    m_profileCpu = cpu;
+    m_profilePixels = pixels;
+}
+
 void Retracer::setCaptureAtCallNumber(qlonglong num)
 {
     m_captureCall = num;
@@ -212,7 +244,6 @@ void Retracer::setCaptureThumbnails(bool enable)
     m_captureThumbnails = enable;
 }
 
-
 /**
  * Starting point for the retracing thread.
  *
@@ -255,20 +286,34 @@ void Retracer::run()
         return;
     }
 
-    if (m_doubleBuffered) {
-        arguments << QLatin1String("-db");
-    } else {
-        arguments << QLatin1String("-sb");
-    }
-
     if (m_captureState) {
         arguments << QLatin1String("-D");
         arguments << QString::number(m_captureCall);
     } else if (m_captureThumbnails) {
         arguments << QLatin1String("-s"); // emit snapshots
         arguments << QLatin1String("-"); // emit to stdout
-    } else if (m_benchmarking) {
-        arguments << QLatin1String("-b");
+    } else if (isProfiling()) {
+        if (m_profileGpu) {
+            arguments << QLatin1String("-pgpu");
+        }
+
+        if (m_profileCpu) {
+            arguments << QLatin1String("-pcpu");
+        }
+
+        if (m_profilePixels) {
+            arguments << QLatin1String("-ppd");
+        }
+    } else {
+        if (m_doubleBuffered) {
+            arguments << QLatin1String("-db");
+        } else {
+            arguments << QLatin1String("-sb");
+        }
+
+        if (m_benchmarking) {
+            arguments << QLatin1String("-b");
+        }
     }
 
     arguments << m_fileName;
@@ -291,6 +336,7 @@ void Retracer::run()
 
     QList<QImage> thumbnails;
     QVariantMap parsedJson;
+    trace::Profile* profile = NULL;
 
     process.setReadChannel(QProcess::StandardOutput);
     if (process.waitForReadyRead(-1)) {
@@ -307,6 +353,9 @@ void Retracer::run()
 
             bool ok = false;
             QJson::Parser jsonParser;
+
+            // Allow Nan/Infinity
+            jsonParser.allowSpecialNumbers(true);
 #if 0
             parsedJson = jsonParser.parse(&io, &ok).toMap();
 #else
@@ -369,7 +418,20 @@ void Retracer::run()
             }
 
             Q_ASSERT(process.state() != QProcess::Running);
+        } else if (isProfiling()) {
+            profile = new trace::Profile();
+
+            while (!io.atEnd()) {
+                char line[256];
+                qint64 lineLength;
 
+                lineLength = io.readLine(line, 256);
+
+                if (lineLength == -1)
+                    break;
+
+                trace::Profiler::parseLine(line, profile);
+            }
         } else {
             QByteArray output;
             output = process.readAllStandardOutput();
@@ -431,6 +493,10 @@ void Retracer::run()
         emit foundThumbnails(thumbnails);
     }
 
+    if (isProfiling() && profile) {
+        emit foundProfile(profile);
+    }
+
     if (!errors.isEmpty()) {
         emit retraceErrors(errors);
     }
index d6da7ac5fd5e385cfca96bcab85553122a958b86..e889d8887cf3753ce609d86daefa6233d7134ddf 100644 (file)
@@ -9,6 +9,8 @@
 
 class ApiTraceState;
 
+namespace trace { struct Profile; }
+
 class Retracer : public QThread
 {
     Q_OBJECT
@@ -26,6 +28,12 @@ public:
     bool isDoubleBuffered() const;
     void setDoubleBuffered(bool db);
 
+    bool isProfilingGpu() const;
+    bool isProfilingCpu() const;
+    bool isProfilingPixels() const;
+    bool isProfiling() const;
+    void setProfiling(bool gpu, bool cpu, bool pixels);
+
     void setCaptureAtCallNumber(qlonglong num);
     qlonglong captureAtCallNumber() const;
 
@@ -38,6 +46,7 @@ public:
 signals:
     void finished(const QString &output);
     void foundState(ApiTraceState *state);
+    void foundProfile(trace::Profile *profile);
     void foundThumbnails(const QList<QImage> &thumbnails);
     void error(const QString &msg);
     void retraceErrors(const QList<ApiTraceError> &errors);
@@ -53,6 +62,9 @@ private:
     bool m_captureState;
     bool m_captureThumbnails;
     qlonglong m_captureCall;
+    bool m_profileGpu;
+    bool m_profileCpu;
+    bool m_profilePixels;
 
     QProcessEnvironment m_processEnvironment;
 };
index cb60ad9f3b36214d6f3cf02cbe847cb54d42d286..7cbb3d1e3bea979532b80bd7bdbf620b80822d9a 100644 (file)
     <addaction name="actionGo"/>
     <addaction name="actionGoFrameStart"/>
     <addaction name="actionGoFrameEnd"/>
-    <addaction name="separator"/>
-    <addaction name="actionShowErrorsDock"/>
    </widget>
    <widget class="QMenu" name="menu_Trace">
     <property name="title">
      <string>&amp;Trace</string>
     </property>
     <addaction name="actionReplay"/>
+    <addaction name="actionProfile"/>
     <addaction name="actionStop"/>
     <addaction name="actionLookupState"/>
     <addaction name="actionShowThumbnails"/>
     <addaction name="separator"/>
     <addaction name="actionOptions"/>
    </widget>
+   <widget class="QMenu" name="menuView">
+    <property name="title">
+     <string>&amp;View</string>
+    </property>
+    <addaction name="actionShowErrorsDock"/>
+    <addaction name="actionShowProfileDialog"/>
+   </widget>
    <addaction name="menuFile"/>
    <addaction name="menuEdit"/>
+   <addaction name="menuView"/>
    <addaction name="menu_Trace"/>
   </widget>
   <widget class="QStatusBar" name="statusbar"/>
     <bool>false</bool>
    </property>
    <property name="text">
-    <string>Show Errors Dock</string>
+    <string>Show &amp;Errors Dock</string>
+   </property>
+  </action>
+  <action name="actionShowProfileDialog">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Show &amp;Profile Results</string>
+   </property>
+  </action>
+  <action name="actionProfile">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>&amp;Profile</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+P</string>
    </property>
   </action>
   <zorder>stateDock</zorder>
diff --git a/gui/ui/profiledialog.ui b/gui/ui/profiledialog.ui
new file mode 100644 (file)
index 0000000..bbcfbe9
--- /dev/null
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProfileDialog</class>
+ <widget class="QDialog" name="ProfileDialog">
+  <property name="windowModality">
+   <enum>Qt::NonModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1105</width>
+    <height>804</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Profile Results</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true"/>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QSplitter" name="splitter">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="opaqueResize">
+      <bool>false</bool>
+     </property>
+     <widget class="GraphWidget" name="m_timeline" native="true">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>1</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="focusPolicy">
+       <enum>Qt::WheelFocus</enum>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="graphContainer" native="true">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="minimumSize">
+       <size>
+        <width>0</width>
+        <height>200</height>
+       </size>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="CallDurationGraph" name="m_gpuGraph" native="true">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="focusPolicy">
+          <enum>Qt::WheelFocus</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="CallDurationGraph" name="m_cpuGraph" native="true">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QTableView" name="m_table">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <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="verticalScrollMode">
+       <enum>QAbstractItemView::ScrollPerPixel</enum>
+      </property>
+      <property name="horizontalScrollMode">
+       <enum>QAbstractItemView::ScrollPerPixel</enum>
+      </property>
+      <property name="sortingEnabled">
+       <bool>true</bool>
+      </property>
+      <property name="wordWrap">
+       <bool>false</bool>
+      </property>
+      <attribute name="verticalHeaderVisible">
+       <bool>false</bool>
+      </attribute>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>GraphWidget</class>
+   <extends>QWidget</extends>
+   <header>graphing/graphwidget.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>CallDurationGraph</class>
+   <extends>QWidget</extends>
+   <header>calldurationgraph.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>m_table</sender>
+   <signal>doubleClicked(QModelIndex)</signal>
+   <receiver>ProfileDialog</receiver>
+   <slot>tableDoubleClicked(QModelIndex)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>895</x>
+     <y>220</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>511</x>
+     <y>383</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <slots>
+  <signal>jumpToCall(int)</signal>
+  <slot>setVerticalScrollMax(int)</slot>
+  <slot>setHorizontalScrollMax(int)</slot>
+  <slot>tableDoubleClicked(QModelIndex)</slot>
+  <slot>selectTime(int64_t,int64_t)</slot>
+  <slot>selectProgram(unsigned)</slot>
+  <slot>selectNone()</slot>
+ </slots>
+</ui>
diff --git a/gui/ui/profilereplaydialog.ui b/gui/ui/profilereplaydialog.ui
new file mode 100644 (file)
index 0000000..f5991ae
--- /dev/null
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProfileReplayDialog</class>
+ <widget class="QDialog" name="ProfileReplayDialog">
+  <property name="windowModality">
+   <enum>Qt::ApplicationModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>353</width>
+    <height>165</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Profile Configuration</string>
+  </property>
+  <property name="whatsThis">
+   <string>Allows setting options on the profiling process.</string>
+  </property>
+  <property name="modal">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="profileGroup">
+     <property name="title">
+      <string>Profiling</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <widget class="QCheckBox" name="gpuTimesCB">
+        <property name="text">
+         <string>GPU times</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="cpuTimesCB">
+        <property name="text">
+         <string>CPU times</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="pixelsDrawnCB">
+        <property name="text">
+         <string>Pixels drawn per call</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </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>accepted()</signal>
+   <receiver>ProfileReplayDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>176</x>
+     <y>142</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>176</x>
+     <y>82</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>ProfileReplayDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>176</x>
+     <y>142</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>176</x>
+     <y>82</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/helpers/d3d10size.hpp b/helpers/d3d10size.hpp
new file mode 100644 (file)
index 0000000..dbcab6a
--- /dev/null
@@ -0,0 +1,447 @@
+/**************************************************************************
+ *
+ * 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, 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.
+ */
+
+#ifndef _D3D10SIZE_HPP_
+#define _D3D10SIZE_HPP_
+
+
+/* We purposedly don't include any D3D header, so that this header can be used
+ * with all D3D versions. */
+
+#include <assert.h>
+
+#include <algorithm>
+
+
+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) {
+        return 0;
+    }
+
+    size_t BlockSize = 0;
+    UINT BlockWidth = 1;
+    UINT BlockHeight = 1;
+    switch (Format) {
+    case DXGI_FORMAT_UNKNOWN:
+        return 0;
+    case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+    case DXGI_FORMAT_R32G32B32A32_FLOAT:
+    case DXGI_FORMAT_R32G32B32A32_UINT:
+    case DXGI_FORMAT_R32G32B32A32_SINT:
+        BlockSize = 128;
+        break;
+    case DXGI_FORMAT_R32G32B32_TYPELESS:
+    case DXGI_FORMAT_R32G32B32_FLOAT:
+    case DXGI_FORMAT_R32G32B32_UINT:
+    case DXGI_FORMAT_R32G32B32_SINT:
+        BlockSize = 96;
+        break;
+    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_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:
+        BlockSize = 64;
+        break;
+    case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+    case DXGI_FORMAT_R10G10B10A2_UNORM:
+    case DXGI_FORMAT_R10G10B10A2_UINT:
+    case DXGI_FORMAT_R11G11B10_FLOAT:
+    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_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_R32_TYPELESS:
+    case DXGI_FORMAT_D32_FLOAT:
+    case DXGI_FORMAT_R32_FLOAT:
+    case DXGI_FORMAT_R32_UINT:
+    case DXGI_FORMAT_R32_SINT:
+    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:
+    case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+    case DXGI_FORMAT_B8G8R8A8_UNORM:
+    case DXGI_FORMAT_B8G8R8X8_UNORM:
+    case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+    case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+    case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+        BlockSize = 32;
+        break;
+    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_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_B5G6R5_UNORM:
+    case DXGI_FORMAT_B5G5R5A1_UNORM:
+        BlockSize = 16;
+        break;
+    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:
+        BlockSize = 8;
+        break;
+    case DXGI_FORMAT_R1_UNORM:
+        BlockSize = 1;
+        break;
+    case DXGI_FORMAT_R8G8_B8G8_UNORM:
+    case DXGI_FORMAT_G8R8_G8B8_UNORM:
+        BlockSize = 32;
+        BlockWidth = 2;
+        break;
+    case DXGI_FORMAT_BC1_TYPELESS:
+    case DXGI_FORMAT_BC1_UNORM:
+    case DXGI_FORMAT_BC1_UNORM_SRGB:
+    case DXGI_FORMAT_BC4_TYPELESS:
+    case DXGI_FORMAT_BC4_UNORM:
+    case DXGI_FORMAT_BC4_SNORM:
+        BlockSize = 64;
+        BlockWidth = 4;
+        BlockHeight = 4;
+        break;
+    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_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_BC7_TYPELESS:
+    case DXGI_FORMAT_BC7_UNORM:
+    case DXGI_FORMAT_BC7_UNORM_SRGB:
+        BlockSize = 128;
+        BlockWidth = 4;
+        BlockHeight = 4;
+        break;
+    default:
+        os::log("apitrace: warning: %s: unknown format 0x%04X\n", __FUNCTION__, Format);
+        return 0;
+    }
+
+    Width  = (Width  + BlockWidth - 1) / BlockWidth;
+    Height = (Height + BlockHeight - 1) / BlockHeight;
+
+    size_t size = (Width * BlockSize + 7)/ 8;
+
+    if (Height > 1) {
+        size += (Height - 1) * RowPitch;
+    }
+
+    if (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) {
+        return 0;
+    }
+
+    Width  = std::max(Width  >> MipLevel, UINT(1));
+    Height = std::max(Height >> MipLevel, UINT(1));
+    Depth  = std::max(Depth  >> MipLevel, UINT(1));
+
+    return _calcDataSize(Format, Width, Height, RowPitch, Depth, DepthPitch);
+}
+
+
+inline UINT
+_getNumMipLevels(UINT Width, UINT Height = 1, UINT Depth = 1) {
+    UINT MipLevels = 0;
+    do {
+        ++MipLevels;
+        Width  >>= 1;
+        Height >>= 1;
+        Depth  >>= 1;
+    } while (Width || Height || Depth);
+    return MipLevels;
+}
+
+inline UINT
+_getNumMipLevels(const D3D10_BUFFER_DESC *pDesc) {
+    return 1;
+}
+
+inline UINT
+_getNumMipLevels(const D3D10_TEXTURE1D_DESC *pDesc) {
+    return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width);
+}
+
+inline UINT
+_getNumMipLevels(const D3D10_TEXTURE2D_DESC *pDesc) {
+    return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width, pDesc->Height);
+}
+
+inline UINT
+_getNumMipLevels(const D3D10_TEXTURE3D_DESC *pDesc) {
+    return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width, pDesc->Height, pDesc->Depth);
+}
+
+inline UINT
+_getNumSubResources(const D3D10_BUFFER_DESC *pDesc) {
+    return 1;
+}
+
+inline UINT
+_getNumSubResources(const D3D10_TEXTURE1D_DESC *pDesc) {
+    return _getNumMipLevels(pDesc) * pDesc->ArraySize;
+}
+
+inline UINT
+_getNumSubResources(const D3D10_TEXTURE2D_DESC *pDesc) {
+    return _getNumMipLevels(pDesc) * pDesc->ArraySize;
+}
+
+inline UINT
+_getNumSubResources(const D3D10_TEXTURE3D_DESC *pDesc) {
+    return _getNumMipLevels(pDesc);
+}
+
+static inline size_t
+_calcSubresourceSize(const D3D10_BUFFER_DESC *pDesc, UINT Subresource, UINT RowPitch = 0, UINT SlicePitch = 0) {
+    return pDesc->ByteWidth;
+}
+
+static inline size_t
+_calcSubresourceSize(const D3D10_TEXTURE1D_DESC *pDesc, UINT Subresource, UINT RowPitch = 0, UINT SlicePitch = 0) {
+    UINT MipLevel = Subresource % _getNumMipLevels(pDesc);
+    return _calcMipDataSize(MipLevel, pDesc->Format, pDesc->Width, 1, RowPitch, 1, SlicePitch);
+}
+
+static inline size_t
+_calcSubresourceSize(const D3D10_TEXTURE2D_DESC *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 D3D10_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 void
+_getMapInfo(ID3D10Buffer *pResource, D3D10_MAP MapType, UINT MapFlags, void * * ppData,
+            void * & pMappedData, size_t & MappedSize) {
+    pMappedData = 0;
+    MappedSize = 0;
+
+    if (MapType == D3D10_MAP_READ) {
+        return;
+    }
+
+    D3D10_BUFFER_DESC Desc;
+    pResource->GetDesc(&Desc);
+
+    pMappedData = *ppData;
+    MappedSize = Desc.ByteWidth;
+}
+
+static inline void
+_getMapInfo(ID3D10Texture1D *pResource, UINT Subresource, D3D10_MAP MapType, UINT MapFlags, void * * ppData,
+            void * & pMappedData, size_t & MappedSize) {
+    pMappedData = 0;
+    MappedSize = 0;
+
+    if (MapType == D3D10_MAP_READ) {
+        return;
+    }
+
+    D3D10_TEXTURE1D_DESC Desc;
+    pResource->GetDesc(&Desc);
+
+    pMappedData = *ppData;
+    MappedSize = _calcSubresourceSize(&Desc, Subresource);
+}
+
+static inline void
+_getMapInfo(ID3D10Texture2D *pResource, UINT Subresource, D3D10_MAP MapType, UINT MapFlags, D3D10_MAPPED_TEXTURE2D * pMappedTex2D,
+            void * & pMappedData, size_t & MappedSize) {
+    pMappedData = 0;
+    MappedSize = 0;
+
+    if (MapType == D3D10_MAP_READ) {
+        return;
+    }
+
+    D3D10_TEXTURE2D_DESC Desc;
+    pResource->GetDesc(&Desc);
+
+    pMappedData = pMappedTex2D->pData;
+    MappedSize = _calcSubresourceSize(&Desc, Subresource, pMappedTex2D->RowPitch);
+}
+
+static inline void
+_getMapInfo(ID3D10Texture3D *pResource, UINT Subresource, D3D10_MAP MapType, UINT MapFlags, D3D10_MAPPED_TEXTURE3D * pMappedTex3D,
+            void * & pMappedData, size_t & MappedSize) {
+    pMappedData = 0;
+    MappedSize = 0;
+
+    if (MapType == D3D10_MAP_READ) {
+        return;
+    }
+
+    D3D10_TEXTURE3D_DESC Desc;
+    pResource->GetDesc(&Desc);
+
+    pMappedData = pMappedTex3D->pData;
+    MappedSize = _calcSubresourceSize(&Desc, Subresource, pMappedTex3D->RowPitch, pMappedTex3D->DepthPitch);
+}
+
+
+static inline void
+_getMapInfo(IDXGISurface *pResource, DXGI_MAPPED_RECT * pLockedRect, UINT MapFlags,
+            void * & pMappedData, size_t & MappedSize) {
+    pMappedData = 0;
+    MappedSize = 0;
+
+    if (!(MapFlags & DXGI_MAP_WRITE)) {
+        return;
+    }
+
+    DXGI_SURFACE_DESC Desc;
+    HRESULT hr = pResource->GetDesc(&Desc);
+    if (FAILED(hr)) {
+        return;
+    }
+
+    pMappedData = pLockedRect->pBits;
+    MappedSize = _calcDataSize(Desc.Format, Desc.Width, Desc.Height, pLockedRect->Pitch);
+}
+
+
+static inline size_t
+_calcSubresourceSize(ID3D10Resource *pDstResource, UINT DstSubresource, const D3D10_BOX *pDstBox, UINT SrcRowPitch, UINT SrcDepthPitch) {
+    if (pDstBox &&
+        (pDstBox->left  >= pDstBox->right ||
+         pDstBox->top   >= pDstBox->bottom ||
+         pDstBox->front >= pDstBox->back)) {
+        return 0;
+    }
+
+    D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
+    pDstResource->GetType(&Type);
+
+    DXGI_FORMAT Format;
+    UINT Width;
+    UINT Height = 1;
+    UINT Depth = 1;
+    UINT MipLevel = 0;
+
+    switch (Type) {
+    case D3D10_RESOURCE_DIMENSION_BUFFER:
+        if (pDstBox) {
+            return pDstBox->right - pDstBox->left;
+        } else {
+            D3D10_BUFFER_DESC Desc;
+            static_cast<ID3D10Buffer *>(pDstResource)->GetDesc(&Desc);
+            return Desc.ByteWidth;
+        }
+    case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
+        {
+            D3D10_TEXTURE1D_DESC Desc;
+            static_cast<ID3D10Texture1D *>(pDstResource)->GetDesc(&Desc);
+            Format = Desc.Format;
+            Width = Desc.Width;
+            MipLevel = DstSubresource % Desc.MipLevels;
+        }
+        break;
+    case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
+        {
+            D3D10_TEXTURE2D_DESC Desc;
+            static_cast<ID3D10Texture2D *>(pDstResource)->GetDesc(&Desc);
+            Format = Desc.Format;
+            Width = Desc.Width;
+            Height = Desc.Height;
+            MipLevel = DstSubresource % Desc.MipLevels;
+        }
+        break;
+    case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
+        {
+            D3D10_TEXTURE3D_DESC Desc;
+            static_cast<ID3D10Texture3D *>(pDstResource)->GetDesc(&Desc);
+            Format = Desc.Format;
+            Width = Desc.Width;
+            Height = Desc.Height;
+            Depth = Desc.Depth;
+        }
+        break;
+    case D3D10_RESOURCE_DIMENSION_UNKNOWN:
+    default:
+        assert(0);
+        return 0;
+    }
+
+    return _calcMipDataSize(MipLevel, Format, Width, Height, SrcRowPitch, Depth, SrcDepthPitch);
+}
+
+
+#endif /* _D3D10SIZE_HPP_ */
diff --git a/helpers/d3d9size.hpp b/helpers/d3d9size.hpp
new file mode 100644 (file)
index 0000000..0041e25
--- /dev/null
@@ -0,0 +1,379 @@
+/**************************************************************************
+ *
+ * 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, 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.
+ */
+
+#ifndef _D3D9SIZE_HPP_
+#define _D3D9SIZE_HPP_
+
+
+/* We purposedly don't include any D3D header, so that this header can be used
+ * with all D3D versions. */
+
+#include <assert.h>
+
+#include "os.hpp"
+
+
+static inline size_t
+_vertexCount(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount)
+{
+    switch (PrimitiveType) {
+    case D3DPT_POINTLIST:
+        return PrimitiveCount;
+    case D3DPT_LINELIST:
+        return PrimitiveCount*2;
+    case D3DPT_LINESTRIP:
+        return PrimitiveCount + 1;
+    case D3DPT_TRIANGLELIST:
+        return PrimitiveCount * 3;
+    case D3DPT_TRIANGLESTRIP:
+        return PrimitiveCount + 2;
+    case D3DPT_TRIANGLEFAN:
+        return PrimitiveCount + 1;
+    default:
+        os::log("apitrace: warning: %s: unknown D3DPRIMITIVETYPE %u\n", __FUNCTION__, PrimitiveType);
+        return 0;
+    }
+}
+
+
+static inline size_t
+_vertexDataSize(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, UINT VertexStride) {
+    return _vertexCount(PrimitiveType, PrimitiveCount) * VertexStride;
+}
+
+
+static inline size_t
+_indexDataSize(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, D3DFORMAT IndexDataFormat) {
+    UINT IndexStride;
+    switch (IndexDataFormat) {
+    case D3DFMT_INDEX16:
+        IndexStride = 2;
+        break;
+    case D3DFMT_INDEX32:
+        IndexStride = 4;
+        break;
+    default:
+        os::log("apitrace: warning: %s: unexpected index D3DFORMAT %u\n", __FUNCTION__, IndexDataFormat);
+        return 0;
+    }
+    return _vertexCount(PrimitiveType, PrimitiveCount) * IndexStride;
+}
+
+
+#if DIRECT3D_VERSION >= 0x0800
+
+/*
+ * Return the number of tokens for a given shader.
+ */
+static inline size_t
+_shaderSize(const DWORD *pFunction)
+{
+    DWORD dwLength = 0;
+
+    while (true) {
+        DWORD dwToken = pFunction[dwLength++];
+
+        switch (dwToken & D3DSI_OPCODE_MASK) {
+        case D3DSIO_COMMENT:
+            dwLength += (dwToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
+            break;
+
+        case D3DSIO_END:
+            if (dwToken != D3DSIO_END) {
+                os::log("apitrace: warning: %s: malformed END token\n", __FUNCTION__);
+            }
+            return dwLength * sizeof *pFunction;
+        }
+    }
+}
+
+
+static size_t
+_getLockSize(D3DFORMAT Format, UINT Width, UINT Height, INT RowPitch, UINT Depth = 1, INT SlicePitch = 0) {
+    if (Width == 0 || Height == 0 || Depth == 0) {
+        return 0;
+    }
+
+    if (RowPitch < 0) {
+        os::log("apitrace: warning: %s: negative row pitch %i\n", __FUNCTION__, RowPitch);
+        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;
+
+    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;
+
+    case D3DFMT_UYVY:
+    case D3DFMT_R8G8_B8G8:
+    case D3DFMT_YUY2:
+    case D3DFMT_G8R8_G8B8:
+        Width = (Width + 1) / 2;
+        break;
+
+    case D3DFMT_NV12:
+        return (Height + ((Height + 1) / 2)) * RowPitch;
+
+    case D3DFMT_NULL:
+        return 0;
+
+    default:
+        break;
+    }
+
+    (void)Width;
+
+    size_t size = Height * RowPitch;
+
+    if (Depth > 1) {
+        size += (Depth - 1) * SlicePitch;
+    }
+
+    return size;
+}
+
+
+#endif /* DIRECT3D_VERSION >= 0x0800 */
+
+
+#if DIRECT3D_VERSION >= 0x0900
+
+
+static inline void
+_getLockInfo(IDirect3DVertexBuffer9 *pBuffer, UINT OffsetToLock, UINT SizeToLock, void ** ppbData,
+             void * & pLockedData, size_t & LockedSize) {
+    pLockedData = *ppbData;
+    LockedSize = 0;
+
+    if (SizeToLock == 0) {
+        D3DVERTEXBUFFER_DESC Desc;
+        HRESULT hr = pBuffer->GetDesc(&Desc);
+        if (FAILED(hr)) {
+            return;
+        }
+        LockedSize = Desc.Size;
+    } else {
+        LockedSize = SizeToLock;
+    }
+}
+
+
+static inline void
+_getLockInfo(IDirect3DIndexBuffer9 *pBuffer, UINT OffsetToLock, UINT SizeToLock, void ** ppbData,
+             void * & pLockedData, size_t & LockedSize) {
+    pLockedData = *ppbData;
+    LockedSize = 0;
+
+    if (SizeToLock == 0) {
+        D3DINDEXBUFFER_DESC Desc;
+        HRESULT hr = pBuffer->GetDesc(&Desc);
+        if (FAILED(hr)) {
+            return;
+        }
+        LockedSize = Desc.Size;
+    } else {
+        LockedSize = SizeToLock;
+    }
+}
+
+
+static inline void
+_getLockInfo(IDirect3DSurface9 *pSurface, const D3DLOCKED_RECT *pLockedRect, const RECT *pRect,
+             void * & pLockedData, size_t & LockedSize) {
+    pLockedData = pLockedRect->pBits;
+    LockedSize = 0;
+
+    HRESULT hr;
+
+    D3DSURFACE_DESC Desc;
+    hr = pSurface->GetDesc(&Desc);
+    if (FAILED(hr)) {
+        return;
+    }
+
+    UINT Width;
+    UINT Height;
+    if (pRect) {
+        Width  = pRect->right  - pRect->left;
+        Height = pRect->bottom - pRect->top;
+    } else {
+        Width  = Desc.Width;
+        Height = Desc.Height;
+    }
+
+    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+}
+
+
+static inline void
+_getLockInfo(IDirect3DTexture9 *pTexture, UINT Level, const D3DLOCKED_RECT *pLockedRect, const RECT *pRect,
+             void * & pLockedData, size_t & LockedSize) {
+    pLockedData = pLockedRect->pBits;
+    LockedSize = 0;
+
+    HRESULT hr;
+
+    D3DSURFACE_DESC Desc;
+    hr = pTexture->GetLevelDesc(Level, &Desc);
+    if (FAILED(hr)) {
+        return;
+    }
+
+    UINT Width;
+    UINT Height;
+    if (pRect) {
+        Width  = pRect->right  - pRect->left;
+        Height = pRect->bottom - pRect->top;
+    } else {
+        Width  = Desc.Width;
+        Height = Desc.Height;
+    }
+
+    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+}
+
+
+static inline void
+_getLockInfo(IDirect3DCubeTexture9 *pTexture, D3DCUBEMAP_FACES FaceType, UINT Level, const D3DLOCKED_RECT *pLockedRect, const RECT *pRect,
+             void * & pLockedData, size_t & LockedSize) {
+    pLockedData = pLockedRect->pBits;
+    LockedSize = 0;
+
+    HRESULT hr;
+
+    (void)FaceType;
+
+    D3DSURFACE_DESC Desc;
+    hr = pTexture->GetLevelDesc(Level, &Desc);
+    if (FAILED(hr)) {
+        return;
+    }
+
+    UINT Width;
+    UINT Height;
+    if (pRect) {
+        Width  = pRect->right  - pRect->left;
+        Height = pRect->bottom - pRect->top;
+    } else {
+        Width  = Desc.Width;
+        Height = Desc.Height;
+    }
+
+    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
+}
+
+
+static inline void
+_getLockInfo(IDirect3DVolume9 *pVolume, const D3DLOCKED_BOX *pLockedVolume, const D3DBOX *pBox,
+             void * & pLockedData, size_t & LockedSize) {
+    pLockedData = pLockedVolume->pBits;
+    LockedSize = 0;
+
+    HRESULT hr;
+
+    D3DVOLUME_DESC Desc;
+    hr = pVolume->GetDesc(&Desc);
+    if (FAILED(hr)) {
+        return;
+    }
+
+    UINT Width;
+    UINT Height;
+    UINT Depth;
+    if (pBox) {
+        Width  = pBox->Right  - pBox->Left;
+        Height = pBox->Bottom - pBox->Top;
+        Depth  = pBox->Back   - pBox->Front;
+    } else {
+        Width  = Desc.Width;
+        Height = Desc.Height;
+        Depth  = Desc.Depth;
+    }
+
+    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
+}
+
+
+static inline void
+_getLockInfo(IDirect3DVolumeTexture9 *pTexture, UINT Level, const D3DLOCKED_BOX *pLockedVolume, const D3DBOX *pBox,
+             void * & pLockedData, size_t & LockedSize) {
+    pLockedData = pLockedVolume->pBits;
+    LockedSize = 0;
+
+    HRESULT hr;
+
+    D3DVOLUME_DESC Desc;
+    hr = pTexture->GetLevelDesc(Level, &Desc);
+    if (FAILED(hr)) {
+        return;
+    }
+
+    UINT Width;
+    UINT Height;
+    UINT Depth;
+    if (pBox) {
+        Width  = pBox->Right  - pBox->Left;
+        Height = pBox->Bottom - pBox->Top;
+        Depth  = pBox->Back   - pBox->Front;
+    } else {
+        Width  = Desc.Width;
+        Height = Desc.Height;
+        Depth  = Desc.Depth;
+    }
+
+    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
+}
+
+
+#endif /* DIRECT3D_VERSION >= 0x0900 */
+
+
+#endif /* _D3D9SIZE_HPP_ */
diff --git a/helpers/d3dsize.hpp b/helpers/d3dsize.hpp
deleted file mode 100644 (file)
index 156fdd2..0000000
+++ /dev/null
@@ -1,379 +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, 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.
- */
-
-#ifndef _D3D_SIZE_HPP_
-#define _D3D_SIZE_HPP_
-
-
-/* We purposedly don't include any D3D header, so that this header can be used
- * with all D3D versions. */
-
-#include <assert.h>
-
-#include "os.hpp"
-
-
-static inline size_t
-_vertexCount(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount)
-{
-    switch (PrimitiveType) {
-    case D3DPT_POINTLIST:
-        return PrimitiveCount;
-    case D3DPT_LINELIST:
-        return PrimitiveCount*2;
-    case D3DPT_LINESTRIP:
-        return PrimitiveCount + 1;
-    case D3DPT_TRIANGLELIST:
-        return PrimitiveCount * 3;
-    case D3DPT_TRIANGLESTRIP:
-        return PrimitiveCount + 2;
-    case D3DPT_TRIANGLEFAN:
-        return PrimitiveCount + 1;
-    default:
-        os::log("apitrace: warning: %s: unknown D3DPRIMITIVETYPE %u\n", __FUNCTION__, PrimitiveType);
-        return 0;
-    }
-}
-
-
-static inline size_t
-_vertexDataSize(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, UINT VertexStride) {
-    return _vertexCount(PrimitiveType, PrimitiveCount) * VertexStride;
-}
-
-
-static inline size_t
-_indexDataSize(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, D3DFORMAT IndexDataFormat) {
-    UINT IndexStride;
-    switch (IndexDataFormat) {
-    case D3DFMT_INDEX16:
-        IndexStride = 2;
-        break;
-    case D3DFMT_INDEX32:
-        IndexStride = 4;
-        break;
-    default:
-        os::log("apitrace: warning: %s: unexpected index D3DFORMAT %u\n", __FUNCTION__, IndexDataFormat);
-        return 0;
-    }
-    return _vertexCount(PrimitiveType, PrimitiveCount) * IndexStride;
-}
-
-
-#if DIRECT3D_VERSION >= 0x0800
-
-/*
- * Return the number of tokens for a given shader.
- */
-static inline size_t
-_shaderSize(const DWORD *pFunction)
-{
-    DWORD dwLength = 0;
-
-    while (true) {
-        DWORD dwToken = pFunction[dwLength++];
-
-        switch (dwToken & D3DSI_OPCODE_MASK) {
-        case D3DSIO_COMMENT:
-            dwLength += (dwToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
-            break;
-
-        case D3DSIO_END:
-            if (dwToken != D3DSIO_END) {
-                os::log("apitrace: warning: %s: malformed END token\n", __FUNCTION__);
-            }
-            return dwLength * sizeof *pFunction;
-        }
-    }
-}
-
-
-static size_t
-_getLockSize(D3DFORMAT Format, UINT Width, UINT Height, INT RowPitch, UINT Depth = 1, INT SlicePitch = 0) {
-    if (Width == 0 || Height == 0 || Depth == 0) {
-        return 0;
-    }
-
-    if (RowPitch < 0) {
-        os::log("apitrace: warning: %s: negative row pitch %i\n", __FUNCTION__, RowPitch);
-        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;
-
-    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;
-
-    case D3DFMT_UYVY:
-    case D3DFMT_R8G8_B8G8:
-    case D3DFMT_YUY2:
-    case D3DFMT_G8R8_G8B8:
-        Width = (Width + 1) / 2;
-        break;
-
-    case D3DFMT_NV12:
-        return (Height + ((Height + 1) / 2)) * RowPitch;
-
-    case D3DFMT_NULL:
-        return 0;
-
-    default:
-        break;
-    }
-
-    (void)Width;
-
-    size_t size = Height * RowPitch;
-
-    if (Depth > 1) {
-        size += (Depth - 1) * SlicePitch;
-    }
-
-    return size;
-}
-
-
-#endif /* DIRECT3D_VERSION >= 0x0800 */
-
-
-#if DIRECT3D_VERSION >= 0x0900
-
-
-static inline void
-_getLockInfo(IDirect3DVertexBuffer9 *pBuffer, UINT OffsetToLock, UINT SizeToLock, void ** ppbData,
-             void * & pLockedData, size_t & LockedSize) {
-    pLockedData = *ppbData;
-    LockedSize = 0;
-
-    if (SizeToLock == 0) {
-        D3DVERTEXBUFFER_DESC Desc;
-        HRESULT hr = pBuffer->GetDesc(&Desc);
-        if (FAILED(hr)) {
-            return;
-        }
-        LockedSize = Desc.Size;
-    } else {
-        LockedSize = SizeToLock;
-    }
-}
-
-
-static inline void
-_getLockInfo(IDirect3DIndexBuffer9 *pBuffer, UINT OffsetToLock, UINT SizeToLock, void ** ppbData,
-             void * & pLockedData, size_t & LockedSize) {
-    pLockedData = *ppbData;
-    LockedSize = 0;
-
-    if (SizeToLock == 0) {
-        D3DINDEXBUFFER_DESC Desc;
-        HRESULT hr = pBuffer->GetDesc(&Desc);
-        if (FAILED(hr)) {
-            return;
-        }
-        LockedSize = Desc.Size;
-    } else {
-        LockedSize = SizeToLock;
-    }
-}
-
-
-static inline void
-_getLockInfo(IDirect3DSurface9 *pSurface, const D3DLOCKED_RECT *pLockedRect, const RECT *pRect,
-             void * & pLockedData, size_t & LockedSize) {
-    pLockedData = pLockedRect->pBits;
-    LockedSize = 0;
-
-    HRESULT hr;
-
-    D3DSURFACE_DESC Desc;
-    hr = pSurface->GetDesc(&Desc);
-    if (FAILED(hr)) {
-        return;
-    }
-
-    UINT Width;
-    UINT Height;
-    if (pRect) {
-        Width  = pRect->right  - pRect->left;
-        Height = pRect->bottom - pRect->top;
-    } else {
-        Width  = Desc.Width;
-        Height = Desc.Height;
-    }
-
-    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
-}
-
-
-static inline void
-_getLockInfo(IDirect3DTexture9 *pTexture, UINT Level, const D3DLOCKED_RECT *pLockedRect, const RECT *pRect,
-             void * & pLockedData, size_t & LockedSize) {
-    pLockedData = pLockedRect->pBits;
-    LockedSize = 0;
-
-    HRESULT hr;
-
-    D3DSURFACE_DESC Desc;
-    hr = pTexture->GetLevelDesc(Level, &Desc);
-    if (FAILED(hr)) {
-        return;
-    }
-
-    UINT Width;
-    UINT Height;
-    if (pRect) {
-        Width  = pRect->right  - pRect->left;
-        Height = pRect->bottom - pRect->top;
-    } else {
-        Width  = Desc.Width;
-        Height = Desc.Height;
-    }
-
-    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
-}
-
-
-static inline void
-_getLockInfo(IDirect3DCubeTexture9 *pTexture, D3DCUBEMAP_FACES FaceType, UINT Level, const D3DLOCKED_RECT *pLockedRect, const RECT *pRect,
-             void * & pLockedData, size_t & LockedSize) {
-    pLockedData = pLockedRect->pBits;
-    LockedSize = 0;
-
-    HRESULT hr;
-
-    (void)FaceType;
-
-    D3DSURFACE_DESC Desc;
-    hr = pTexture->GetLevelDesc(Level, &Desc);
-    if (FAILED(hr)) {
-        return;
-    }
-
-    UINT Width;
-    UINT Height;
-    if (pRect) {
-        Width  = pRect->right  - pRect->left;
-        Height = pRect->bottom - pRect->top;
-    } else {
-        Width  = Desc.Width;
-        Height = Desc.Height;
-    }
-
-    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedRect->Pitch);
-}
-
-
-static inline void
-_getLockInfo(IDirect3DVolume9 *pVolume, const D3DLOCKED_BOX *pLockedVolume, const D3DBOX *pBox,
-             void * & pLockedData, size_t & LockedSize) {
-    pLockedData = pLockedVolume->pBits;
-    LockedSize = 0;
-
-    HRESULT hr;
-
-    D3DVOLUME_DESC Desc;
-    hr = pVolume->GetDesc(&Desc);
-    if (FAILED(hr)) {
-        return;
-    }
-
-    UINT Width;
-    UINT Height;
-    UINT Depth;
-    if (pBox) {
-        Width  = pBox->Right  - pBox->Left;
-        Height = pBox->Bottom - pBox->Top;
-        Depth  = pBox->Back   - pBox->Front;
-    } else {
-        Width  = Desc.Width;
-        Height = Desc.Height;
-        Depth  = Desc.Depth;
-    }
-
-    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
-}
-
-
-static inline void
-_getLockInfo(IDirect3DVolumeTexture9 *pTexture, UINT Level, const D3DLOCKED_BOX *pLockedVolume, const D3DBOX *pBox,
-             void * & pLockedData, size_t & LockedSize) {
-    pLockedData = pLockedVolume->pBits;
-    LockedSize = 0;
-
-    HRESULT hr;
-
-    D3DVOLUME_DESC Desc;
-    hr = pTexture->GetLevelDesc(Level, &Desc);
-    if (FAILED(hr)) {
-        return;
-    }
-
-    UINT Width;
-    UINT Height;
-    UINT Depth;
-    if (pBox) {
-        Width  = pBox->Right  - pBox->Left;
-        Height = pBox->Bottom - pBox->Top;
-        Depth  = pBox->Back   - pBox->Front;
-    } else {
-        Width  = Desc.Width;
-        Height = Desc.Height;
-        Depth  = Desc.Depth;
-    }
-
-    LockedSize = _getLockSize(Desc.Format, Width, Height, pLockedVolume->RowPitch, Depth, pLockedVolume->SlicePitch);
-}
-
-
-#endif /* DIRECT3D_VERSION >= 0x0900 */
-
-
-#endif /* _D3D_SIZE_HPP_ */
diff --git a/helpers/eglsize.cpp b/helpers/eglsize.cpp
new file mode 100644 (file)
index 0000000..4f2dfdc
--- /dev/null
@@ -0,0 +1,217 @@
+/*********************************************************************
+ *
+ * Copyright 2012 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.
+ *
+ *********************************************************************/
+
+/*
+ * Auxiliary functions to compute the size of array/blob arguments.
+ */
+
+#include <string.h>
+
+#include "os_thread.hpp"
+#include "glimports.hpp"
+#include "glproc.hpp"
+#include "glsize.hpp"
+#include "eglsize.hpp"
+#include "assert.h"
+
+
+static int
+bisect_val(int min, int max, bool is_valid_val(int val))
+{
+    bool valid;
+
+    while (1) {
+        int try_val = min + (max - min + 1) / 2;
+
+        valid = is_valid_val(try_val);
+        if (min == max)
+            break;
+
+        if (valid)
+            min = try_val;
+        else
+            max = try_val - 1;
+    }
+
+    return valid ? min : -1;
+}
+
+static bool
+is_valid_width(int val)
+{
+    _glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, val, 1);
+    return _glGetError() == GL_NO_ERROR;
+}
+
+static bool
+is_valid_height(int val)
+{
+    _glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, val);
+    return _glGetError() == GL_NO_ERROR;
+}
+
+static int
+detect_size(int *width_ret, int *height_ret)
+{
+    GLint max_tex_size;
+    int width;
+    int height;
+
+    max_tex_size = 0;
+    _glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
+
+    width = bisect_val(1, max_tex_size, is_valid_width);
+    if (width < 0)
+        return -1;
+
+    height = bisect_val(1, max_tex_size, is_valid_height);
+    if (height < 0)
+        return -1;
+
+    *width_ret = width;
+    *height_ret = height;
+
+    return 0;
+}
+
+/* XXX */
+static inline bool
+can_unpack_subimage(void) {
+    return false;
+}
+
+static void
+_eglCreateImageKHR_get_image_size(EGLImageKHR image, image_info *info)
+{
+    GLuint fbo = 0;
+    GLuint orig_fbo = 0;
+    GLuint texture = 0;
+    GLuint orig_texture;
+    GLenum status;
+
+    _glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&orig_fbo);
+    _glGenFramebuffers(1, &fbo);
+    _glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&orig_texture);
+    _glGenTextures(1, &texture);
+    _glBindTexture(GL_TEXTURE_2D, texture);
+
+    _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+
+    info->width = 0;
+    info->height = 0;
+
+    _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                            GL_TEXTURE_2D, texture, 0);
+    status = _glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if (status == GL_FRAMEBUFFER_COMPLETE) {
+        if (detect_size(&info->width, &info->height) != 0)
+            os::log("%s: can't detect image size\n", __func__);
+    } else {
+        os::log("%s: error: %x\n", __func__, status);
+    }
+
+    /* Don't leak errors to the traced application. */
+    (void)_glGetError();
+
+    _glBindTexture(GL_TEXTURE_2D, orig_texture);
+    _glDeleteTextures(1, &texture);
+
+    _glBindFramebuffer(GL_FRAMEBUFFER, orig_fbo);
+    _glDeleteFramebuffers(1, &fbo);
+}
+
+static void
+get_texture_2d_image(image_info *info)
+{
+    GLuint fbo = 0;
+    GLint prev_fbo = 0;
+    GLint texture;
+    GLenum status;
+
+    _glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
+    if (!texture)
+        return;
+
+    _glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
+    _glGenFramebuffers(1, &fbo);
+    _glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                            texture, 0);
+    status = _glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if (status != GL_FRAMEBUFFER_COMPLETE)
+        os::log("%s: error: %d\n", __func__, status);
+    _glReadPixels(0, 0, info->width, info->height, info->format, info->type, info->pixels);
+    /* Don't leak errors to the traced application. */
+    (void)_glGetError();
+
+    _glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo);
+    _glDeleteFramebuffers(1, &fbo);
+}
+
+struct image_info *
+_EGLImageKHR_get_image_info(GLenum target, EGLImageKHR image)
+{
+    GLuint tex;
+    GLuint bound_tex;
+    struct image_info *info;
+
+    info = new image_info;
+
+    memset(info, 0, sizeof *info);
+
+    info->internalformat = GL_RGBA;
+    info->format = GL_RGBA;
+    info->type = GL_UNSIGNED_BYTE;
+
+    _eglCreateImageKHR_get_image_size(image, info);
+
+    _glGenTextures(1, &tex);
+    _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&bound_tex);
+    _glBindTexture(GL_TEXTURE_2D, tex);
+    _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+
+    info->size = _glTexImage2D_size(info->format, info->type, info->width, info->height);
+    info->pixels = malloc(info->size);
+
+    get_texture_2d_image(info);
+    _glBindTexture(GL_TEXTURE_2D, bound_tex);
+    _glDeleteBuffers(1, &tex);
+
+    return info;
+}
+
+void
+_EGLImageKHR_free_image_info(struct image_info *info)
+{
+    free(info->pixels);
+    delete info;
+}
+
+
diff --git a/helpers/eglsize.hpp b/helpers/eglsize.hpp
new file mode 100644 (file)
index 0000000..a2014f6
--- /dev/null
@@ -0,0 +1,57 @@
+
+/*********************************************************************
+ *
+ * Copyright 2012 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.
+ *
+ *********************************************************************/
+
+/*
+ * Auxiliary functions to compute the size of array/blob arguments.
+ */
+#ifndef _EGLSIZE_HPP_
+#define _EGLSIZE_HPP_
+
+
+#include "glimports.hpp"
+
+
+struct image_info
+{
+    GLint internalformat;
+    GLsizei width;
+    GLsizei height;
+    GLenum format;
+    GLenum type;
+    GLsizei size;
+    GLvoid * pixels;
+};
+
+struct image_info *
+_EGLImageKHR_get_image_info(GLenum target, EGLImageKHR image);
+
+void
+_EGLImageKHR_free_image_info(struct image_info *info);
+
+
+#endif
index 5c646fdf10d510da8ff8b23571dc4d365972c249..9d39a3b717f6f812aee787d58a3be5a73623ad6d 100644 (file)
@@ -37,6 +37,8 @@
 
 #include <string.h>
 
+#include <algorithm>
+
 #include "os.hpp"
 #include "glimports.hpp"
 
@@ -299,6 +301,14 @@ _glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei count)
         return 0;
     }
 
+    if (size == GL_BGRA) {
+        size = 4; 
+    }
+
+    if (size > 4) {
+        os::log("apitrace: warning: %s: unexpected size 0x%04X\n", __FUNCTION__, size);
+    }
+
     size_t elementSize = size*_gl_type_size(type);
     if (!stride) {
         stride = (GLsizei)elementSize;
@@ -330,6 +340,11 @@ _glDrawArrays_count(GLint first, GLsizei count)
 
 #define _glDrawArraysEXT_count _glDrawArrays_count
 
+/* Forward declaration for definition in gltrace.py */
+void
+_shadow_glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
+                              GLvoid *data);
+
 static inline GLuint
 _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex)
 {
@@ -350,7 +365,7 @@ _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indice
             return 0;
         }
         memset(temp, 0, size);
-        _glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp);
+        _shadow_glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp);
         indices = temp;
     } else {
         if (!indices) {
@@ -429,31 +444,31 @@ _glDrawElementsIndirect_count(GLenum type, const GLvoid *indirect) {
 }
 
 static inline GLuint
-_glMultiDrawArrays_count(const GLint *first, const GLsizei *count, GLsizei primcount) {
+_glMultiDrawArrays_count(const GLint *first, const GLsizei *count, GLsizei drawcount) {
     GLuint _count = 0;
-    for (GLsizei prim = 0; prim < primcount; ++prim) {
-        GLuint _count_prim = _glDrawArrays_count(first[prim], count[prim]);
-        _count = std::max(_count, _count_prim);
+    for (GLsizei draw = 0; draw < drawcount; ++draw) {
+        GLuint _count_draw = _glDrawArrays_count(first[draw], count[draw]);
+        _count = std::max(_count, _count_draw);
     }
     return _count;
 }
 
 static inline GLuint
-_glMultiDrawElements_count(const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) {
+_glMultiDrawElements_count(const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount) {
     GLuint _count = 0;
-    for (GLsizei prim = 0; prim < primcount; ++prim) {
-        GLuint _count_prim = _glDrawElements_count(count[prim], type, indices[prim]);
-        _count = std::max(_count, _count_prim);
+    for (GLsizei draw = 0; draw < drawcount; ++draw) {
+        GLuint _count_draw = _glDrawElements_count(count[draw], type, indices[draw]);
+        _count = std::max(_count, _count_draw);
     }
     return _count;
 }
 
 static inline GLuint
-_glMultiDrawElementsBaseVertex_count(const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint * basevertex) {
+_glMultiDrawElementsBaseVertex_count(const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount, const GLint * basevertex) {
     GLuint _count = 0;
-    for (GLsizei prim = 0; prim < primcount; ++prim) {
-        GLuint _count_prim = _glDrawElementsBaseVertex_count(count[prim], type, indices[prim], basevertex[prim]);
-        _count = std::max(_count, _count_prim);
+    for (GLsizei draw = 0; draw < drawcount; ++draw) {
+        GLuint _count_draw = _glDrawElementsBaseVertex_count(count[draw], type, indices[draw], basevertex[draw]);
+        _count = std::max(_count, _count_draw);
     }
     return _count;
 }
@@ -461,8 +476,8 @@ _glMultiDrawElementsBaseVertex_count(const GLsizei *count, GLenum type, const GL
 #define _glMultiDrawArraysEXT_count _glMultiDrawArrays_count
 #define _glMultiDrawElementsEXT_count _glMultiDrawElements_count
 
-#define _glMultiModeDrawArraysIBM_count(first, count, primcount, modestride) _glMultiDrawArrays_count(first, count, primcount)
-#define _glMultiModeDrawElementsIBM_count(count, type, indices, primcount, modestride) _glMultiDrawElements_count(count, type, (const GLvoid **)indices, primcount)
+#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)
 
 
 static inline size_t
@@ -606,28 +621,32 @@ static inline size_t
 _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) {
     unsigned num_channels = _gl_format_channels(format);
 
+    unsigned bits_per_element;
     unsigned bits_per_pixel;
     switch (type) {
     case GL_BITMAP:
-        bits_per_pixel = 1;
+        bits_per_pixel = bits_per_element = 1;
         break;
     case GL_BYTE:
     case GL_UNSIGNED_BYTE:
-        bits_per_pixel = 8 * num_channels;
+        bits_per_element = 8;
+        bits_per_pixel = bits_per_element * num_channels;
         break;
     case GL_SHORT:
     case GL_UNSIGNED_SHORT:
     case GL_HALF_FLOAT:
-        bits_per_pixel = 16 * num_channels;
+        bits_per_element = 16;
+        bits_per_pixel = bits_per_element * num_channels;
         break;
     case GL_INT:
     case GL_UNSIGNED_INT:
     case GL_FLOAT:
-        bits_per_pixel = 32 * num_channels;
+        bits_per_element = 32;
+        bits_per_pixel = bits_per_element * num_channels;
         break;
     case GL_UNSIGNED_BYTE_3_3_2:
     case GL_UNSIGNED_BYTE_2_3_3_REV:
-        bits_per_pixel = 8;
+        bits_per_pixel = bits_per_element = 8;
         break;
     case GL_UNSIGNED_SHORT_4_4_4_4:
     case GL_UNSIGNED_SHORT_4_4_4_4_REV:
@@ -637,7 +656,7 @@ _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsize
     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 = 16;
+        bits_per_pixel = bits_per_element = 16;
         break;
     case GL_UNSIGNED_INT_8_8_8_8:
     case GL_UNSIGNED_INT_8_8_8_8_REV:
@@ -648,14 +667,14 @@ _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsize
     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 = 32;
+        bits_per_pixel = bits_per_element = 32;
         break;
     case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
-        bits_per_pixel = 64;
+        bits_per_pixel = bits_per_element = 64;
         break;
     default:
         os::log("apitrace: warning: %s: unexpected type GLenum 0x%04X\n", __FUNCTION__, type);
-        bits_per_pixel = 0;
+        bits_per_pixel = bits_per_element = 0;
         break;
     }
 
@@ -681,9 +700,11 @@ _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsize
 
     size_t row_stride = (row_length*bits_per_pixel + 7)/8;
 
-    if ((GLint)bits_per_pixel < alignment*8 &&
-        (bits_per_pixel & 7) == 0 &&
-        _is_pot(bits_per_pixel)) {
+    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) {
         row_stride = _align(row_stride, alignment);
     }
 
index 91f235766284474c0cf412ba7fcf2d8099cc714a..b552c0bf3935a609d06fe9be07f34bf4095897ec 100644 (file)
@@ -50,6 +50,12 @@ extern const retrace::Entry d3d9_callbacks[];
 HWND
 createWindow(int width, int height);
 
+void
+resizeWindow(HWND hWnd, int width, int height);
+
+bool
+processEvents(void);
+
 
 } /* namespace d3dretrace */
 
index a43289cc64ea6ef9b855ddc4c851d1c4ee4f4009..14b92ab4fe7503f50945412b4f34453273388865 100644 (file)
@@ -35,7 +35,8 @@ from specs.d3d9 import *
 class D3DRetracer(Retracer):
 
     def retraceApi(self, api):
-        print 'static const GUID GUID_D3DRETRACE = {0x7D71CAC9,0x7F58,0x432C,{0xA9,0x75,0xA1,0x9F,0xCF,0xCE,0xFD,0x14}};'
+        print '// Swizzling mapping for lock addresses'
+        print 'static std::map<void *, void *> _locks;'
         print
 
         self.table_name = 'd3dretrace::%s_callbacks' % api.name.lower()
@@ -54,6 +55,11 @@ class D3DRetracer(Retracer):
             if 'hFocusWindow' in method.argNames():
                 print r'    hFocusWindow = hWnd;'
 
+        if method.name in ('Reset', 'ResetEx'):
+            print r'    if (pPresentationParameters->Windowed) {'
+            print r'        d3dretrace::resizeWindow(pPresentationParameters->hDeviceWindow, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);'
+            print r'    }'
+
         # notify frame has been completed
         if method.name == 'Present':
             print r'    retrace::frameComplete(call);'
@@ -67,6 +73,10 @@ class D3DRetracer(Retracer):
 
         Retracer.invokeInterfaceMethod(self, interface, method)
 
+        # process events after presents
+        if method.name == 'Present':
+            print r'    d3dretrace::processEvents();'
+
         # check errors
         if str(method.type) == 'HRESULT':
             print r'    if (FAILED(_result)) {'
@@ -77,12 +87,11 @@ class D3DRetracer(Retracer):
             print '    VOID *_pbData = NULL;'
             print '    size_t _LockedSize = 0;'
             print '    _getLockInfo(_this, %s, _pbData, _LockedSize);' % ', '.join(method.argNames()[:-1])
-            print '    _this->SetPrivateData(GUID_D3DRETRACE, &_pbData, sizeof _pbData, 0);'
+            print '    _locks[_this] = _pbData;'
         
         if method.name in ('Unlock', 'UnlockRect', 'UnlockBox'):
             print '    VOID *_pbData = 0;'
-            print '    DWORD dwSizeOfData = sizeof _pbData;'
-            print '    _this->GetPrivateData(GUID_D3DRETRACE, &_pbData, &dwSizeOfData);'
+            print '    _pbData = _locks[_this];'
             print '    if (_pbData) {'
             print '        retrace::delRegionByPointer(_pbData);'
             print '    }'
@@ -95,7 +104,7 @@ if __name__ == '__main__':
 #include <iostream>
 
 #include "d3d9imports.hpp"
-#include "d3dsize.hpp"
+#include "d3d9size.hpp"
 #include "d3dretrace.hpp"
 
 '''
index 40d53eafb1b946201a076cb996b8dddb5d12202e..9878fe3c87b059690527f6c6e44f523d72f4880d 100644 (file)
@@ -87,6 +87,7 @@ retrace::flushRendering(void) {
 
 void
 retrace::waitForInput(void) {
+    /* TODO */
 }
 
 void
index 8626a764597e49507aa9cb6e6eb2ae654720eb71..42bd0abef159cd068a00d7cacbbee42050060b65 100644 (file)
@@ -37,6 +37,13 @@ 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;
@@ -45,6 +52,9 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         pMMI->ptMaxTrackSize.x = 60000;
         pMMI->ptMaxTrackSize.y = 60000;
         break;
+    case WM_CLOSE:
+        exit(0);
+        break;
     default:
         break;
     }
@@ -104,7 +114,38 @@ createWindow(int width, int height) {
 }
 
 
+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(hWnd, NULL, rWindow.left, rWindow.top, width, height, SWP_NOMOVE);
+}
 
 
+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 d3dretrace */
index 4fa89c2dde21f4a2b042f8f6a5d25be1d5b00e07..73746e7d14c9543ec4e2f91bcd0ad3b78579e876 100644 (file)
@@ -24,6 +24,8 @@
  **************************************************************************/
 
 
+#include <stdio.h>
+
 #include <iostream>
 
 #include "d3d9imports.hpp"
 namespace d3dstate {
 
 
+typedef HRESULT
+(WINAPI *PD3DXDISASSEMBLESHADER)(
+    CONST DWORD *pShader,
+    BOOL EnableColorCode,
+    LPCSTR pComments,
+    LPD3DXBUFFER *ppDisassembly
+);
+
+
+HRESULT
+disassembleShader(const DWORD *tokens, LPD3DXBUFFER *ppDisassembly)
+{
+    static BOOL firsttime = TRUE;
+
+    /*
+     * TODO: Consider using d3dcompile_xx.dll per
+     * http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx
+     */
+
+    static HMODULE hD3DXModule = NULL;
+    static PD3DXDISASSEMBLESHADER pfnD3DXDisassembleShader = NULL;
+
+    if (firsttime) {
+        if (!hD3DXModule) {
+            unsigned release;
+            int version;
+            for (release = 0; release <= 1; ++release) {
+                /* Version 41 corresponds to Mar 2009 version of DirectX Runtime / SDK */
+                for (version = 41; version >= 0; --version) {
+                    char filename[256];
+                    _snprintf(filename, sizeof(filename),
+                              "d3dx9%s%s%u.dll", release ? "" : "d", version ? "_" : "", version);
+                    hD3DXModule = LoadLibraryA(filename);
+                    if (hD3DXModule)
+                        goto found;
+                }
+            }
+found:
+            ;
+        }
+
+        if (hD3DXModule) {
+            if (!pfnD3DXDisassembleShader) {
+                pfnD3DXDisassembleShader = (PD3DXDISASSEMBLESHADER)GetProcAddress(hD3DXModule, "D3DXDisassembleShader");
+            }
+        }
+
+        firsttime = FALSE;
+    }
+
+    if (!pfnD3DXDisassembleShader) {
+        return E_FAIL;
+    }
+
+    return pfnD3DXDisassembleShader(tokens, FALSE, NULL, ppDisassembly);
+}
+
+
+template< class T >
+inline void
+dumpShader(JSONWriter &json, const char *name, T *pShader) {
+    if (!pShader) {
+        return;
+    }
+
+    HRESULT hr;
+
+    UINT SizeOfData = 0;
+
+    hr = pShader->GetFunction(NULL, &SizeOfData);
+    if (SUCCEEDED(hr)) {
+        void *pData;
+        pData = malloc(SizeOfData);
+        if (pData) {
+            hr = pShader->GetFunction(pData, &SizeOfData);
+            if (SUCCEEDED(hr)) {
+                LPD3DXBUFFER 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();
+                }
+
+            }
+            free(pData);
+        }
+    }
+}
+
+static void
+dumpShaders(JSONWriter &json, IDirect3DDevice9 *pDevice)
+{
+    json.beginMember("shaders");
+
+    HRESULT hr;
+    json.beginObject();
+
+    IDirect3DVertexShader9 *pVertexShader = NULL;
+    hr = pDevice->GetVertexShader(&pVertexShader);
+    if (SUCCEEDED(hr)) {
+        dumpShader(json, "vertex", pVertexShader);
+    }
+
+    IDirect3DPixelShader9 *pPixelShader = NULL;
+    hr = pDevice->GetPixelShader(&pPixelShader);
+    if (SUCCEEDED(hr)) {
+        dumpShader(json, "pixel", pPixelShader);
+    }
+
+    json.endObject();
+    json.endMember(); // shaders
+}
+
 void
 dumpDevice(std::ostream &os, IDirect3DDevice9 *pDevice)
 {
     JSONWriter json(os);
 
+    dumpShaders(json, pDevice);
+
     /* TODO */
 }
 
index fea187cf05ed19b474d255bb828000d255a71464..95a6d7596df230e8dd059194c493bbf58055cad3 100644 (file)
 
 namespace glretrace {
 
-
+struct Context {
+    Context(glws::Context* context)
+        : wsContext(context),
+          drawable(0),
+          activeProgram(0),
+          used(false)
+    {
+    }
+
+    ~Context();
+
+    glws::Context* wsContext;
+
+    // Bound drawable
+    glws::Drawable *drawable;
+
+    GLuint activeProgram;
+    bool used;
+    
+    // Context must be current
+    inline bool
+    hasExtension(const char *extension) const {
+        return wsContext->hasExtension(extension);
+    }
+};
+
+extern bool insideList;
 extern bool insideGlBeginEnd;
 
 
-extern glws::Drawable *currentDrawable;
-extern glws::Context *currentContext;
+Context *
+getCurrentContext(void);
+
+
+int
+parseAttrib(const trace::Value *attribs, int param, int default_);
+
 
 glws::Drawable *
 createDrawable(glws::Profile profile);
@@ -45,14 +76,17 @@ createDrawable(glws::Profile profile);
 glws::Drawable *
 createDrawable(void);
 
-glws::Context *
-createContext(glws::Context *shareContext, glws::Profile profile);
+glws::Drawable *
+createPbuffer(int width, int height);
+
+Context *
+createContext(Context *shareContext, glws::Profile profile);
 
-glws::Context *
-createContext(glws::Context *shareContext = 0);
+Context *
+createContext(Context *shareContext = 0);
 
 bool
-makeCurrent(trace::Call &call, glws::Drawable *drawable, glws::Context *context);
+makeCurrent(trace::Call &call, glws::Drawable *drawable, Context *context);
 
 
 void
@@ -65,9 +99,15 @@ extern const retrace::Entry wgl_callbacks[];
 extern const retrace::Entry egl_callbacks[];
 
 void frame_complete(trace::Call &call);
+void initContext();
+
 
 void updateDrawable(int width, int height);
 
+void flushQueries();
+void beginProfile(trace::Call &call, bool isDraw);
+void endProfile(trace::Call &call, bool isDraw);
+
 } /* namespace glretrace */
 
 
index 08fc6a054da8bb3bd43ffa7648f30030cb731c8b..e2ea3201bf183bd63597a964b11f95bcc101424f 100644 (file)
@@ -250,7 +250,7 @@ class GlRetracer(Retracer):
             print '    glretrace::insideGlBeginEnd = false;'
 
         if function.name.startswith('gl') and not function.name.startswith('glX'):
-            print r'    if (retrace::debug && !glretrace::currentContext) {'
+            print r'    if (retrace::debug && !glretrace::getCurrentContext()) {'
             print r'        retrace::warning(call) << "no current context\n";'
             print r'    }'
 
@@ -289,7 +289,36 @@ class GlRetracer(Retracer):
             print r'    if (pipeline) {'
             print r'        _pipelineHasBeenBound = true;'
             print r'    }'
-        
+
+        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
+            function.name == 'glBegin'
+        )
+
+        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;'
+
+        if function.name == 'glEndList':
+            print r'    glretrace::insideList = false;'
+
+        if function.name != 'glEnd':
+            print r'    if (!glretrace::insideList && !glretrace::insideGlBeginEnd && 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
             # shader source can be recovered.
@@ -321,12 +350,20 @@ class GlRetracer(Retracer):
         else:
             Retracer.invokeFunction(self, function)
 
-        # Error checking
         if function.name == "glBegin":
             print '    glretrace::insideGlBeginEnd = true;'
-        elif function.name.startswith('gl'):
+
+        print r'    if (!glretrace::insideList && !glretrace::insideGlBeginEnd && retrace::profiling) {'
+        if profileDraw:
+            print r'        glretrace::endProfile(call, true);'
+        else:
+            print r'        glretrace::endProfile(call, false);'
+        print r'    }'
+
+        # Error checking
+        if function.name.startswith('gl'):
             # glGetError is not allowed inside glBegin/glEnd
-            print '    if (retrace::debug && !glretrace::insideGlBeginEnd) {'
+            print '    if (retrace::debug && !glretrace::insideGlBeginEnd && glretrace::getCurrentContext()) {'
             print '        glretrace::checkGlError(call);'
             if function.name in ('glProgramStringARB', 'glProgramStringNV'):
                 print r'        GLint error_position = -1;'
@@ -441,14 +478,20 @@ class GlRetracer(Retracer):
            and 'program' not in function.argNames():
             # Determine the active program for uniforms swizzling
             print '    GLint program = -1;'
-            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 '    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 '        glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
+            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
 
index 0c91ba27fccb7a46d5e1a19e78e4c6295cb64e2e..a0755953b3a52059e35f9d4e0ff9447cba878305 100644 (file)
 #include "glretrace.hpp"
 
 
+#define kCGLPFAAllRenderers            1
+#define kCGLPFADoubleBuffer            5
+#define kCGLPFAStereo                  6
+#define kCGLPFAAuxBuffers              7
+#define kCGLPFAColorSize               8
+#define kCGLPFAAlphaSize              11
+#define kCGLPFADepthSize              12
+#define kCGLPFAStencilSize            13
+#define kCGLPFAAccumSize              14
+#define kCGLPFAMinimumPolicy          51
+#define kCGLPFAMaximumPolicy          52
+#define kCGLPFAOffScreen              53
+#define kCGLPFAFullScreen             54
+#define kCGLPFASampleBuffers          55
+#define kCGLPFASamples                56
+#define kCGLPFAAuxDepthStencil        57
+#define kCGLPFAColorFloat             58
+#define kCGLPFAMultisample            59
+#define kCGLPFASupersample            60
+#define kCGLPFASampleAlpha            61
+#define kCGLPFARendererID             70
+#define kCGLPFASingleRenderer         71
+#define kCGLPFANoRecovery             72
+#define kCGLPFAAccelerated            73
+#define kCGLPFAClosestPolicy          74
+#define kCGLPFARobust                 75
+#define kCGLPFABackingStore           76
+#define kCGLPFAMPSafe                 78
+#define kCGLPFAWindow                 80
+#define kCGLPFAMultiScreen            81
+#define kCGLPFACompliant              83
+#define kCGLPFADisplayMask            84
+#define kCGLPFAPBuffer                90
+#define kCGLPFARemotePBuffer          91
+#define kCGLPFAAllowOfflineRenderers  96
+#define kCGLPFAAcceleratedCompute     97
+#define kCGLPFAOpenGLProfile          99
+#define kCGLPFAVirtualScreenCount    128
+
+#define kCGLOGLPVersion_Legacy   0x1000
+#define kCGLOGLPVersion_3_2_Core 0x3200
+
+
 using namespace glretrace;
 
 
 typedef std::map<unsigned long long, glws::Drawable *> DrawableMap;
-typedef std::map<unsigned long long, glws::Context *> ContextMap;
+typedef std::map<unsigned long long, Context *> ContextMap;
 static DrawableMap drawable_map;
 static ContextMap context_map;
-static glws::Context *sharedContext = NULL;
+static Context *sharedContext = NULL;
 
 
 static glws::Drawable *
@@ -60,7 +103,7 @@ getDrawable(unsigned long drawable_id) {
 }
 
 
-static glws::Context *
+static Context *
 getContext(unsigned long long ctx) {
     if (ctx == 0) {
         return NULL;
@@ -69,7 +112,7 @@ getContext(unsigned long long ctx) {
     ContextMap::const_iterator it;
     it = context_map.find(ctx);
     if (it == context_map.end()) {
-        glws::Context *context;
+        Context *context;
         context_map[ctx] = context = glretrace::createContext(sharedContext);
         if (!sharedContext) {
             sharedContext = context;
@@ -81,30 +124,196 @@ getContext(unsigned long long ctx) {
 }
 
 
+static void retrace_CGLChoosePixelFormat(trace::Call &call) {
+    int profile = kCGLOGLPVersion_Legacy;
+
+    const trace::Array * attribs = dynamic_cast<const trace::Array *>(&call.arg(0));
+    if (attribs) {
+        size_t i = 0;
+        while (i < attribs->values.size()) {
+            int param = attribs->values[i++]->toSInt();
+            if (param == 0) {
+                break;
+            }
+
+            switch (param) {
+            case kCGLPFAAllRenderers:
+            case kCGLPFADoubleBuffer:
+            case kCGLPFAStereo:
+            case kCGLPFAAuxBuffers:
+            case kCGLPFAMinimumPolicy:
+            case kCGLPFAMaximumPolicy:
+            case kCGLPFAOffScreen:
+            case kCGLPFAFullScreen:
+            case kCGLPFAAuxDepthStencil:
+            case kCGLPFAColorFloat:
+            case kCGLPFAMultisample:
+            case kCGLPFASupersample:
+            case kCGLPFASampleAlpha:
+            case kCGLPFASingleRenderer:
+            case kCGLPFANoRecovery:
+            case kCGLPFAAccelerated:
+            case kCGLPFAClosestPolicy:
+            case kCGLPFARobust:
+            case kCGLPFABackingStore:
+            case kCGLPFAMPSafe:
+            case kCGLPFAWindow:
+            case kCGLPFAMultiScreen:
+            case kCGLPFACompliant:
+            case kCGLPFAPBuffer:
+            case kCGLPFARemotePBuffer:
+            case kCGLPFAAllowOfflineRenderers:
+            case kCGLPFAAcceleratedCompute:
+                break;
+
+            case kCGLPFAColorSize:
+            case kCGLPFAAlphaSize:
+            case kCGLPFADepthSize:
+            case kCGLPFAStencilSize:
+            case kCGLPFAAccumSize:
+            case kCGLPFASampleBuffers:
+            case kCGLPFASamples:
+            case kCGLPFARendererID:
+            case kCGLPFADisplayMask:
+            case kCGLPFAVirtualScreenCount:
+                ++i;
+                break;
+
+            case kCGLPFAOpenGLProfile:
+                profile = attribs->values[i++]->toSInt();
+                break;
+
+            default:
+                retrace::warning(call) << "unexpected attribute " << param << "\n";
+                break;
+            }
+        }
+    }
+
+    if (profile == kCGLOGLPVersion_3_2_Core) {
+        // TODO: Do this on a per visual basis
+        retrace::coreProfile = true;
+    }
+}
+
+
+static void retrace_CGLCreateContext(trace::Call &call) {
+    unsigned long long share = call.arg(1).toUIntPtr();
+    Context *sharedContext = getContext(share);
+
+    const trace::Array *ctx_ptr = dynamic_cast<const trace::Array *>(&call.arg(2));
+    unsigned long long ctx = ctx_ptr->values[0]->toUIntPtr();
+
+    Context *context = glretrace::createContext(sharedContext);
+    context_map[ctx] = context;
+}
+
+
+static void retrace_CGLDestroyContext(trace::Call &call) {
+    unsigned long long ctx = call.arg(0).toUIntPtr();
+
+    ContextMap::iterator it;
+    it = context_map.find(ctx);
+    if (it == context_map.end()) {
+        return;
+    }
+
+    delete it->second;
+
+    context_map.erase(it);
+}
+
+
 static void retrace_CGLSetCurrentContext(trace::Call &call) {
     unsigned long long ctx = call.arg(0).toUIntPtr();
 
     glws::Drawable *new_drawable = getDrawable(ctx);
-    glws::Context *new_context = getContext(ctx);
+    Context *new_context = getContext(ctx);
 
     glretrace::makeCurrent(call, new_drawable, new_context);
 }
 
 
 static void retrace_CGLFlushDrawable(trace::Call &call) {
-    if (currentDrawable && currentContext) {
-        if (retrace::doubleBuffer) {
-            currentDrawable->swapBuffers();
+    unsigned long long ctx = call.arg(0).toUIntPtr();
+    Context *context = getContext(ctx);
+
+    if (context) {
+        if (context->drawable) {
+            if (retrace::doubleBuffer) {
+                context->drawable->swapBuffers();
+            } else {
+                glFlush();
+            }
+            frame_complete(call);
         } else {
-            glFlush();
+            if (retrace::debug) {
+                retrace::warning(call) << "context has no drawable\n";
+            }
+        }
+    }
+}
+
+
+/**
+ * We can't fully reimplement CGLTexImageIOSurface2D, as external IOSurface are
+ * no longer present.  Simply emit a glTexImage2D to ensure the texture storage
+ * is present.
+ *
+ * See also:
+ * - /System/Library/Frameworks/OpenGL.framework/Headers/CGLIOSurface.h
+ */
+static void retrace_CGLTexImageIOSurface2D(trace::Call &call) {
+    if (retrace::debug) {
+        retrace::warning(call) << "external IOSurface not supported\n";
+    }
+
+    unsigned long long ctx = call.arg(0).toUIntPtr();
+    Context *context = getContext(ctx);
+
+    GLenum target;
+    target = static_cast<GLenum>((call.arg(1)).toSInt());
+
+    GLint level = 0;
+
+    GLint internalformat;
+    internalformat = static_cast<GLenum>((call.arg(2)).toSInt());
+
+    GLsizei width;
+    width = (call.arg(3)).toSInt();
+
+    GLsizei height;
+    height = (call.arg(4)).toSInt();
+
+    GLint border = 0;
+
+    GLenum format;
+    format = static_cast<GLenum>((call.arg(5)).toSInt());
+
+    GLenum type;
+    type = static_cast<GLenum>((call.arg(6)).toSInt());
+
+    GLvoid * pixels = NULL;
+
+    if (glretrace::getCurrentContext() != context) {
+        if (retrace::debug) {
+            retrace::warning(call) << "current context mismatch\n";
         }
+    }
+
+    glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
 
-        frame_complete(call);
+    if (retrace::debug && !glretrace::insideGlBeginEnd) {
+        glretrace::checkGlError(call);
     }
 }
 
 
 const retrace::Entry glretrace::cgl_callbacks[] = {
+    {"CGLChoosePixelFormat", &retrace_CGLChoosePixelFormat},
+    {"CGLDestroyPixelFormat", &retrace::ignore},
+    {"CGLCreateContext", &retrace_CGLCreateContext},
+    {"CGLDestroyContext", &retrace_CGLDestroyContext},
     {"CGLSetCurrentContext", &retrace_CGLSetCurrentContext},
     {"CGLGetCurrentContext", &retrace::ignore},
     {"CGLEnable", &retrace::ignore},
@@ -112,6 +321,8 @@ const retrace::Entry glretrace::cgl_callbacks[] = {
     {"CGLSetParameter", &retrace::ignore},
     {"CGLGetParameter", &retrace::ignore},
     {"CGLFlushDrawable", &retrace_CGLFlushDrawable},
+    {"CGLUpdateContext", &retrace::ignore},
+    {"CGLTexImageIOSurface2D", &retrace_CGLTexImageIOSurface2D},
     {NULL, NULL},
 };
 
index 70fe3546835e704aa00ec1687025758a864fdf5d..45855643f5b55272e494be1bcef8a799e26c928f 100644 (file)
@@ -32,6 +32,7 @@
 #include "retrace.hpp"
 #include "glretrace.hpp"
 #include "os.hpp"
+#include "eglsize.hpp"
 
 #ifndef EGL_OPENGL_ES_API
 #define EGL_OPENGL_ES_API              0x30A0
@@ -45,7 +46,7 @@ using namespace glretrace;
 
 
 typedef std::map<unsigned long long, glws::Drawable *> DrawableMap;
-typedef std::map<unsigned long long, glws::Context *> ContextMap;
+typedef std::map<unsigned long long, Context *> ContextMap;
 typedef std::map<unsigned long long, glws::Profile> ProfileMap;
 static DrawableMap drawable_map;
 static ContextMap context_map;
@@ -76,7 +77,7 @@ getDrawable(unsigned long long surface_ptr) {
     return (it != drawable_map.end()) ? it->second : NULL;
 }
 
-static glws::Context *
+static Context *
 getContext(unsigned long long context_ptr) {
     if (context_ptr == 0) {
         return NULL;
@@ -126,7 +127,8 @@ static void retrace_eglDestroySurface(trace::Call &call) {
     it = drawable_map.find(orig_surface);
 
     if (it != drawable_map.end()) {
-        if (it->second != currentDrawable) {
+        glretrace::Context *currentContext = glretrace::getCurrentContext();
+        if (!currentContext || it->second != currentContext->drawable) {
             // TODO: reference count
             delete it->second;
         }
@@ -141,7 +143,7 @@ static void retrace_eglBindAPI(trace::Call &call) {
 static void retrace_eglCreateContext(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
     unsigned long long orig_config = call.arg(1).toUIntPtr();
-    glws::Context *share_context = getContext(call.arg(2).toUIntPtr());
+    Context *share_context = getContext(call.arg(2).toUIntPtr());
     trace::Array *attrib_array = dynamic_cast<trace::Array *>(&call.arg(3));
     glws::Profile profile;
 
@@ -167,7 +169,7 @@ static void retrace_eglCreateContext(trace::Call &call) {
     }
 
 
-    glws::Context *context = glretrace::createContext(share_context, profile);
+    Context *context = glretrace::createContext(share_context, profile);
     if (!context) {
         const char *name;
         switch (profile) {
@@ -201,24 +203,32 @@ static void retrace_eglDestroyContext(trace::Call &call) {
     it = context_map.find(orig_context);
 
     if (it != context_map.end()) {
-        delete it->second;
+        glretrace::Context *currentContext = glretrace::getCurrentContext();
+        if (it->second != currentContext) {
+            // TODO: reference count
+            delete it->second;
+        }
         context_map.erase(it);
     }
 }
 
 static void retrace_eglMakeCurrent(trace::Call &call) {
     glws::Drawable *new_drawable = getDrawable(call.arg(1).toUIntPtr());
-    glws::Context *new_context = getContext(call.arg(3).toUIntPtr());
+    Context *new_context = getContext(call.arg(3).toUIntPtr());
 
     glretrace::makeCurrent(call, new_drawable, new_context);
 }
 
 
 static void retrace_eglSwapBuffers(trace::Call &call) {
+    glws::Drawable *drawable = getDrawable(call.arg(1).toUIntPtr());
+
     frame_complete(call);
 
-    if (retrace::doubleBuffer && currentDrawable) {
-        currentDrawable->swapBuffers();
+    if (retrace::doubleBuffer) {
+        if (drawable) {
+            drawable->swapBuffers();
+        }
     } else {
         glFlush();
     }
@@ -259,5 +269,8 @@ const retrace::Entry glretrace::egl_callbacks[] = {
     {"eglSwapBuffers", &retrace_eglSwapBuffers},
     //{"eglCopyBuffers", &retrace::ignore},
     {"eglGetProcAddress", &retrace::ignore},
+    {"eglCreateImageKHR", &retrace::ignore},
+    {"eglDestroyImageKHR", &retrace::ignore},
+    {"glEGLImageTargetTexture2DOES", &retrace::ignore},
     {NULL, NULL},
 };
index 9d1b5e5099d015941ff3adfd52716a78e4af7fb7..4ab3d676c189f4984fbc0bb1b6c329c4037e5d86 100644 (file)
 #include "glretrace.hpp"
 
 
+#ifndef GLX_PBUFFER_HEIGHT
+#define GLX_PBUFFER_HEIGHT 0x8040
+#endif
+
+#ifndef GLX_PBUFFER_WIDTH
+#define GLX_PBUFFER_WIDTH 0x8041
+#endif
+
+
 using namespace glretrace;
 
 
 typedef std::map<unsigned long, glws::Drawable *> DrawableMap;
-typedef std::map<unsigned long long, glws::Context *> ContextMap;
+typedef std::map<unsigned long long, Context *> ContextMap;
 static DrawableMap drawable_map;
 static ContextMap context_map;
 
@@ -53,7 +62,7 @@ getDrawable(unsigned long drawable_id) {
     return it->second;
 }
 
-static glws::Context *
+static Context *
 getContext(unsigned long long context_ptr) {
     if (context_ptr == 0) {
         return NULL;
@@ -70,30 +79,30 @@ getContext(unsigned long long context_ptr) {
 
 static void retrace_glXCreateContext(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
-    glws::Context *share_context = getContext(call.arg(2).toUIntPtr());
+    Context *share_context = getContext(call.arg(2).toUIntPtr());
 
-    glws::Context *context = glretrace::createContext(share_context);
+    Context *context = glretrace::createContext(share_context);
     context_map[orig_context] = context;
 }
 
 static void retrace_glXCreateContextAttribsARB(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
-    glws::Context *share_context = getContext(call.arg(2).toUIntPtr());
+    Context *share_context = getContext(call.arg(2).toUIntPtr());
 
-    glws::Context *context = glretrace::createContext(share_context);
+    Context *context = glretrace::createContext(share_context);
     context_map[orig_context] = context;
 }
 
 static void retrace_glXMakeCurrent(trace::Call &call) {
     glws::Drawable *new_drawable = getDrawable(call.arg(1).toUInt());
-    glws::Context *new_context = getContext(call.arg(2).toUIntPtr());
+    Context *new_context = getContext(call.arg(2).toUIntPtr());
 
     glretrace::makeCurrent(call, new_drawable, new_context);
 }
 
 
 static void retrace_glXDestroyContext(trace::Call &call) {
-    glws::Context *context = getContext(call.arg(1).toUIntPtr());
+    Context *context = getContext(call.arg(1).toUIntPtr());
 
     if (!context) {
         return;
@@ -103,9 +112,13 @@ static void retrace_glXDestroyContext(trace::Call &call) {
 }
 
 static void retrace_glXSwapBuffers(trace::Call &call) {
+    glws::Drawable *drawable = getDrawable(call.arg(1).toUInt());
+
     frame_complete(call);
     if (retrace::doubleBuffer) {
-        currentDrawable->swapBuffers();
+        if (drawable) {
+            drawable->swapBuffers();
+        }
     } else {
         glFlush();
     }
@@ -113,15 +126,37 @@ static void retrace_glXSwapBuffers(trace::Call &call) {
 
 static void retrace_glXCreateNewContext(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
-    glws::Context *share_context = getContext(call.arg(3).toUIntPtr());
+    Context *share_context = getContext(call.arg(3).toUIntPtr());
 
-    glws::Context *context = glretrace::createContext(share_context);
+    Context *context = glretrace::createContext(share_context);
     context_map[orig_context] = context;
 }
 
+static void retrace_glXCreatePbuffer(trace::Call &call) {
+    const trace::Value *attrib_list = dynamic_cast<const trace::Array *>(&call.arg(2));
+    int width = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_WIDTH, 0);
+    int height = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_HEIGHT, 0);
+
+    unsigned long long orig_drawable = call.ret->toUInt();
+
+    glws::Drawable *drawable = glretrace::createPbuffer(width, height);
+    
+    drawable_map[orig_drawable] = drawable;
+}
+
+static void retrace_glXDestroyPbuffer(trace::Call &call) {
+    glws::Drawable *drawable = getDrawable(call.arg(1).toUInt());
+
+    if (!drawable) {
+        return;
+    }
+
+    delete drawable;
+}
+
 static void retrace_glXMakeContextCurrent(trace::Call &call) {
     glws::Drawable *new_drawable = getDrawable(call.arg(1).toUInt());
-    glws::Context *new_context = getContext(call.arg(3).toUIntPtr());
+    Context *new_context = getContext(call.arg(3).toUIntPtr());
 
     glretrace::makeCurrent(call, new_drawable, new_context);
 }
@@ -146,14 +181,14 @@ const retrace::Entry glretrace::glx_callbacks[] = {
     //{"glXCreateGLXPixmap", &retrace_glXCreateGLXPixmap},
     //{"glXCreateGLXPixmapWithConfigSGIX", &retrace_glXCreateGLXPixmapWithConfigSGIX},
     {"glXCreateNewContext", &retrace_glXCreateNewContext},
-    //{"glXCreatePbuffer", &retrace_glXCreatePbuffer},
+    {"glXCreatePbuffer", &retrace_glXCreatePbuffer},
     //{"glXCreatePixmap", &retrace_glXCreatePixmap},
     //{"glXCreateWindow", &retrace_glXCreateWindow},
     //{"glXCushionSGI", &retrace_glXCushionSGI},
     {"glXDestroyContext", &retrace_glXDestroyContext},
     //{"glXDestroyGLXPbufferSGIX", &retrace_glXDestroyGLXPbufferSGIX},
     //{"glXDestroyGLXPixmap", &retrace_glXDestroyGLXPixmap},
-    //{"glXDestroyPbuffer", &retrace_glXDestroyPbuffer},
+    {"glXDestroyPbuffer", &retrace_glXDestroyPbuffer},
     //{"glXDestroyPixmap", &retrace_glXDestroyPixmap},
     //{"glXDestroyWindow", &retrace_glXDestroyWindow},
     //{"glXFreeContextEXT", &retrace_glXFreeContextEXT},
@@ -176,6 +211,7 @@ const retrace::Entry glretrace::glx_callbacks[] = {
     {"glXGetProcAddress", &retrace::ignore},
     {"glXGetSelectedEvent", &retrace::ignore},
     {"glXGetSelectedEventSGIX", &retrace::ignore},
+    {"glXGetSwapIntervalMESA", &retrace::ignore},
     {"glXGetSyncValuesOML", &retrace::ignore},
     {"glXGetVideoSyncSGI", &retrace::ignore},
     {"glXGetVisualFromFBConfig", &retrace::ignore},
old mode 100644 (file)
new mode 100755 (executable)
index 49be505..5ccb2e2
 #include "glproc.hpp"
 #include "glstate.hpp"
 #include "glretrace.hpp"
+#include "os_time.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
 
 namespace glretrace {
 
+bool insideList = false;
 bool insideGlBeginEnd = false;
 
+struct CallQuery
+{
+    GLuint ids[3];
+    unsigned call;
+    bool isDraw;
+    GLuint program;
+    const trace::FunctionSig *sig;
+    int64_t cpuStart;
+    int64_t cpuEnd;
+};
+
+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, GLvoid* userParam);
 
 void
 checkGlError(trace::Call &call) {
     GLenum error = glGetError();
-    if (error == GL_NO_ERROR) {
-        return;
+    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;
+        }
+        os << "\n";
+    
+        error = glGetError();
     }
+}
 
-    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;
+static void
+getCurrentTimes(int64_t& cpuTime, int64_t& gpuTime) {
+    GLuint query;
+
+    if (retrace::profilingGpuTimes && supportsTimestamp) {
+        glGenQueries(1, &query);
+        glQueryCounter(query, GL_TIMESTAMP);
+        glGetQueryObjecti64vEXT(query, GL_QUERY_RESULT, &gpuTime);
+    } else {
+        gpuTime = 0;
+    }
+
+    if (retrace::profilingCpuTimes) {
+        cpuTime = os::getTime();
+    } else {
+        cpuTime = 0;
+    }
+
+    if (retrace::profilingGpuTimes && supportsTimestamp) {
+        glDeleteQueries(1, &query);
+    }
+}
+
+static void
+completeCallQuery(CallQuery& query) {
+    /* Get call start and duration */
+    int64_t gpuStart = 0, gpuDuration = 0, cpuDuration = 0, pixels = 0;
+
+    if (query.isDraw) {
+        if (retrace::profilingGpuTimes) {
+            if (supportsTimestamp) {
+                glGetQueryObjecti64vEXT(query.ids[0], GL_QUERY_RESULT, &gpuStart);
+            }
+
+            glGetQueryObjecti64vEXT(query.ids[1], GL_QUERY_RESULT, &gpuDuration);
+        }
+
+        if (retrace::profilingPixelsDrawn) {
+            glGetQueryObjecti64vEXT(query.ids[2], GL_QUERY_RESULT, &pixels);
+        }
+
+        glDeleteQueries(3, query.ids);
+    } else {
+        pixels = -1;
+    }
+
+    if (retrace::profilingCpuTimes) {
+        cpuDuration = query.cpuEnd - query.cpuStart;
+    }
+
+    /* Add call to profile */
+    retrace::profiler.addCall(query.call, query.sig->name, query.program, pixels, gpuStart, gpuDuration, query.cpuStart, cpuDuration);
+}
+
+void
+flushQueries() {
+    for (std::list<CallQuery>::iterator itr = callQueries.begin(); itr != callQueries.end(); ++itr) {
+        completeCallQuery(*itr);
+    }
+
+    callQueries.clear();
+}
+
+void
+beginProfile(trace::Call &call, bool isDraw) {
+    glretrace::Context *currentContext = glretrace::getCurrentContext();
+
+    /* Create call query */
+    CallQuery query;
+    query.isDraw = isDraw;
+    query.call = call.no;
+    query.sig = call.sig;
+    query.program = currentContext ? currentContext->activeProgram : 0;
+
+    /* GPU profiling only for draw calls */
+    if (isDraw) {
+        glGenQueries(3, query.ids);
+
+        if (retrace::profilingGpuTimes) {
+            if (supportsTimestamp) {
+                glQueryCounter(query.ids[0], GL_TIMESTAMP);
+            }
+
+            glBeginQuery(GL_TIME_ELAPSED, query.ids[1]);
+        }
+
+        if (retrace::profilingPixelsDrawn) {
+            glBeginQuery(GL_SAMPLES_PASSED, query.ids[2]);
+        }
+    }
+
+    callQueries.push_back(query);
+
+    /* CPU profiling for all calls */
+    if (retrace::profilingCpuTimes) {
+       callQueries.back().cpuStart = os::getTime();
+    }
+}
+
+void
+endProfile(trace::Call &call, bool isDraw) {
+    GLint64 time = os::getTime();
+
+    /* CPU profiling for all calls */
+    if (retrace::profilingCpuTimes) {
+        CallQuery& query = callQueries.back();
+        query.cpuEnd = time;
+    }
+
+    /* GPU profiling only for draw calls */
+    if (isDraw) {
+        if (retrace::profilingGpuTimes) {
+            glEndQuery(GL_TIME_ELAPSED);
+        }
+
+        if (retrace::profilingPixelsDrawn) {
+            glEndQuery(GL_SAMPLES_PASSED);
+        }
     }
-    os << "\n";
 }
 
+void
+initContext() {
+    glretrace::Context *currentContext = glretrace::getCurrentContext();
+
+    /* Ensure we have adequate extension support */
+    assert(currentContext);
+    supportsTimestamp   = 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");
+
+    /* Check for timer query support */
+    if (retrace::profilingGpuTimes) {
+        if (!supportsTimestamp && !supportsElapsed) {
+            std::cout << "Error: Cannot run profile, GL_EXT_timer_query extension is not supported." << std::endl;
+            exit(-1);
+        }
+
+        GLint bits = 0;
+        glGetQueryiv(GL_TIME_ELAPSED, GL_QUERY_COUNTER_BITS, &bits);
+
+        if (!bits) {
+            std::cout << "Error: Cannot run 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;
+        exit(-1);
+    }
+
+    /* Setup debug message call back */
+    if (retrace::debug && supportsDebugOutput) {
+        glretrace::Context *currentContext = glretrace::getCurrentContext();
+        glDebugMessageCallbackARB(&debugOutputCallback, currentContext);
+
+        if (DEBUG_OUTPUT_SYNCHRONOUS) {
+            glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
+        }
+    }
+
+    /* Sync the gpu and cpu start times */
+    if (retrace::profilingCpuTimes || retrace::profilingGpuTimes) {
+        if (!retrace::profiler.hasBaseTimes()) {
+            GLint64 gpuTime, cpuTime;
+
+            getCurrentTimes(cpuTime, gpuTime);
+            retrace::profiler.setBaseCpuTime(cpuTime);
+            retrace::profiler.setBaseGpuTime(gpuTime);
+        }
+    }
+}
+
+void
+frame_complete(trace::Call &call) {
+    if (retrace::profiling) {
+        /* Complete any remaining queries */
+        flushQueries();
+
+        /* GPU time drifts due to being relative times, not absolute and can be
+         * affected by the gpu switch between processes.
+         *
+         * To attempt to compensate we resynchronise on frame end however there is
+         * still noticeable drift within a single frame which we do not account for.
+         */
+        if (retrace::profilingCpuTimes || retrace::profilingGpuTimes) {
+            int64_t cpuTime, gpuTime, error;
+
+            getCurrentTimes(cpuTime, gpuTime);
+            cpuTime = cpuTime - retrace::profiler.getBaseCpuTime();
+            gpuTime = gpuTime - retrace::profiler.getBaseGpuTime();
+            error   = gpuTime - cpuTime * (1.0E9 / os::timeFrequency);
+
+            retrace::profiler.setBaseGpuTime(retrace::profiler.getBaseGpuTime() + error);
+        }
+
+        /* Indicate end of current frame */
+        retrace::profiler.addFrameEnd();
+    }
 
-void frame_complete(trace::Call &call) {
     retrace::frameComplete(call);
 
-    if (!currentDrawable) {
+    glretrace::Context *currentContext = glretrace::getCurrentContext();
+    if (!currentContext) {
         return;
     }
 
-    if (retrace::debug && !currentDrawable->visible) {
+    assert(currentContext->drawable);
+    if (retrace::debug && !currentContext->drawable->visible) {
         retrace::warning(call) << "could not infer drawable size (glViewport never called)\n";
     }
 }
 
+static const char*
+getDebugOutputSource(GLenum source) {
+    switch(source) {
+    case GL_DEBUG_SOURCE_API_ARB:
+        return "API";
+    case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
+        return "Window System";
+    case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
+        return "Shader Compiler";
+    case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
+        return "Third Party";
+    case GL_DEBUG_SOURCE_APPLICATION_ARB:
+        return "Application";
+    case GL_DEBUG_SOURCE_OTHER_ARB:
+    default:
+        return "";
+    }
+}
+
+static const char*
+getDebugOutputType(GLenum type) {
+    switch(type) {
+    case GL_DEBUG_TYPE_ERROR_ARB:
+        return "error";
+    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
+        return "deprecated behaviour";
+    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
+        return "undefined behaviour";
+    case GL_DEBUG_TYPE_PORTABILITY_ARB:
+        return "portability issue";
+    case GL_DEBUG_TYPE_PERFORMANCE_ARB:
+        return "performance issue";
+    case GL_DEBUG_TYPE_OTHER_ARB:
+    default:
+        return "unknown issue";
+    }
+}
+
+static const char*
+getDebugOutputSeverity(GLenum severity) {
+    switch(severity) {
+    case GL_DEBUG_SEVERITY_HIGH_ARB:
+        return "High";
+    case GL_DEBUG_SEVERITY_MEDIUM_ARB:
+        return "Medium";
+    case GL_DEBUG_SEVERITY_LOW_ARB:
+        return "Low";
+    default:
+        return "usnknown";
+    }
+}
+
+static void APIENTRY
+debugOutputCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam) {
+    std::cerr << retrace::callNo << ": ";
+    std::cerr << "glDebugOutputCallback: ";
+    std::cerr << getDebugOutputSeverity(severity) << " severity ";
+    std::cerr << getDebugOutputSource(source) << " " << getDebugOutputType(type);
+    std::cerr << " " << id;
+    std::cerr << ", " << message;
+    std::cerr << std::endl;
+}
 
 } /* namespace glretrace */
 
@@ -118,7 +410,7 @@ retrace::addCallbacks(retrace::Retracer &retracer)
 
 image::Image *
 retrace::getSnapshot(void) {
-    if (!glretrace::currentDrawable) {
+    if (!glretrace::getCurrentContext()) {
         return NULL;
     }
 
@@ -129,9 +421,10 @@ retrace::getSnapshot(void) {
 bool
 retrace::dumpState(std::ostream &os)
 {
+    glretrace::Context *currentContext = glretrace::getCurrentContext();
+
     if (glretrace::insideGlBeginEnd ||
-        !glretrace::currentDrawable ||
-        !glretrace::currentContext) {
+        !currentContext) {
         return false;
     }
 
@@ -142,12 +435,17 @@ retrace::dumpState(std::ostream &os)
 
 void
 retrace::flushRendering(void) {
-    glFlush();
+    glretrace::Context *currentContext = glretrace::getCurrentContext();
+    if (currentContext) {
+        glretrace::flushQueries();
+        glFlush();
+    }
 }
 
 void
 retrace::waitForInput(void) {
     while (glws::processEvents()) {
+        os::sleep(100*1000);
     }
 }
 
index c3e109657846c03fda5e127b5fccfd5ee76fa3c0..abcf068a057056f88bdefbe1d8c002bd2e9e0459 100644 (file)
@@ -33,7 +33,7 @@ using namespace glretrace;
 
 
 typedef std::map<unsigned long long, glws::Drawable *> DrawableMap;
-typedef std::map<unsigned long long, glws::Context *> ContextMap;
+typedef std::map<unsigned long long, Context *> ContextMap;
 static DrawableMap drawable_map;
 static DrawableMap pbuffer_map;
 static ContextMap context_map;
@@ -56,16 +56,27 @@ getDrawable(unsigned long long hdc) {
 
 static void retrace_wglCreateContext(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
-    glws::Context *context = glretrace::createContext();
+    Context *context = glretrace::createContext();
     context_map[orig_context] = context;
 }
 
 static void retrace_wglDeleteContext(trace::Call &call) {
+    unsigned long long hglrc = call.arg(0).toUIntPtr();
+
+    ContextMap::iterator it;
+    it = context_map.find(hglrc);
+    if (it == context_map.end()) {
+        return;
+    }
+
+    delete it->second;
+    
+    context_map.erase(it);
 }
 
 static void retrace_wglMakeCurrent(trace::Call &call) {
     glws::Drawable *new_drawable = getDrawable(call.arg(0).toUIntPtr());
-    glws::Context *new_context = context_map[call.arg(1).toUIntPtr()];
+    Context *new_context = context_map[call.arg(1).toUIntPtr()];
 
     glretrace::makeCurrent(call, new_drawable, new_context);
 }
@@ -83,9 +94,18 @@ static void retrace_wglSetPixelFormat(trace::Call &call) {
 }
 
 static void retrace_wglSwapBuffers(trace::Call &call) {
+    glws::Drawable *drawable = getDrawable(call.arg(0).toUIntPtr());
+
     frame_complete(call);
     if (retrace::doubleBuffer) {
-        currentDrawable->swapBuffers();
+        if (drawable) {
+            drawable->swapBuffers();
+        } else {
+            glretrace::Context *currentContext = glretrace::getCurrentContext();
+            if (currentContext) {
+                currentContext->drawable->swapBuffers();
+            }
+        }
     } else {
         glFlush();
     }
@@ -95,13 +115,14 @@ static void retrace_wglShareLists(trace::Call &call) {
     unsigned long long hglrc1 = call.arg(0).toUIntPtr();
     unsigned long long hglrc2 = call.arg(1).toUIntPtr();
 
-    glws::Context *share_context = context_map[hglrc1];
-    glws::Context *old_context = context_map[hglrc2];
+    Context *share_context = context_map[hglrc1];
+    Context *old_context = context_map[hglrc2];
 
-    glws::Context *new_context = glretrace::createContext(share_context);
+    Context *new_context = glretrace::createContext(share_context);
     if (new_context) {
+        glretrace::Context *currentContext = glretrace::getCurrentContext();
         if (currentContext == old_context) {
-            glretrace::makeCurrent(call, currentDrawable, new_context);
+            glretrace::makeCurrent(call, currentContext->drawable, new_context);
         }
 
         context_map[hglrc2] = new_context;
@@ -165,10 +186,7 @@ static void retrace_wglCreatePbufferARB(trace::Call &call) {
     int iHeight = call.arg(3).toUInt();
 
     unsigned long long orig_pbuffer = call.ret->toUIntPtr();
-    glws::Drawable *drawable = glretrace::createDrawable();
-
-    drawable->resize(iWidth, iHeight);
-    drawable->show();
+    glws::Drawable *drawable = glretrace::createPbuffer(iWidth, iHeight);
 
     pbuffer_map[orig_pbuffer] = drawable;
 }
@@ -201,13 +219,13 @@ static void retrace_wglSetPbufferAttribARB(trace::Call &call) {
 
 static void retrace_wglCreateContextAttribsARB(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
-    glws::Context *share_context = NULL;
+    Context *share_context = NULL;
 
     if (call.arg(1).toPointer()) {
         share_context = context_map[call.arg(1).toUIntPtr()];
     }
 
-    glws::Context *context = glretrace::createContext(share_context);
+    Context *context = glretrace::createContext(share_context);
     context_map[orig_context] = context;
 }
 
index ceb5d7f3db9f292c93450334b84a4fea69863c93..ac03fcc97de6d56390f807a3b1661e6571d489c1 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <string.h>
 
+#include "os_thread.hpp"
 #include "retrace.hpp"
 #include "glproc.hpp"
 #include "glstate.hpp"
 namespace glretrace {
 
 
-glws::Drawable *currentDrawable = NULL;
-glws::Context *currentContext = NULL;
-
-
 static glws::Visual *
 visuals[glws::PROFILE_MAX];
 
@@ -53,6 +50,10 @@ getVisual(glws::Profile profile) {
     glws::Visual * & visual = visuals[profile];
     if (!visual) {
         visual = glws::createVisual(retrace::doubleBuffer, profile);
+        if (!visual) {
+            std::cerr << "error: failed to create OpenGL visual\n";
+            exit(1);
+        }
     }
     return visual;
 }
@@ -69,59 +70,91 @@ getDefaultProfile(void)
 }
 
 
-glws::Drawable *
-createDrawable(glws::Profile profile) {
-    glws::Drawable *draw = glws::createDrawable(getVisual(profile));
+static glws::Drawable *
+createDrawableHelper(glws::Profile profile, int width = 32, int height = 32, bool pbuffer = false) {
+    glws::Visual *visual = getVisual(profile);
+    glws::Drawable *draw = glws::createDrawable(visual, width, height, pbuffer);
     if (!draw) {
         std::cerr << "error: failed to create OpenGL drawable\n";
         exit(1);
-        return NULL;
     }
 
     return draw;
 }
 
 
+glws::Drawable *
+createDrawable(glws::Profile profile) {
+    return createDrawableHelper(profile);
+}
+
+
 glws::Drawable *
 createDrawable(void) {
-    return glretrace::createDrawable(getDefaultProfile());
+    return createDrawable(getDefaultProfile());
+}
+
+
+glws::Drawable *
+createPbuffer(int width, int height) {
+    return createDrawableHelper(getDefaultProfile(), width, height, true);
 }
 
 
-glws::Context *
-createContext(glws::Context *shareContext, glws::Profile profile) {
-    glws::Context *ctx = glws::createContext(getVisual(profile), shareContext, profile, retrace::debug);
+Context *
+createContext(Context *shareContext, glws::Profile profile) {
+    glws::Visual *visual = getVisual(profile);
+    glws::Context *shareWsContext = shareContext ? shareContext->wsContext : NULL;
+    glws::Context *ctx = glws::createContext(visual, shareWsContext, profile, retrace::debug);
     if (!ctx) {
         std::cerr << "error: failed to create OpenGL context\n";
         exit(1);
         return NULL;
     }
 
-    return ctx;
+    return new Context(ctx);
 }
 
 
-glws::Context *
-createContext(glws::Context *shareContext) {
+Context *
+createContext(Context *shareContext) {
     return createContext(shareContext, getDefaultProfile());
 }
 
 
+Context::~Context()
+{
+    //assert(this != getCurrentContext());
+    if (this != getCurrentContext()) {
+        delete wsContext;
+    }
+}
+
+
+static thread_specific Context *
+currentContextPtr;
+
+
 bool
-makeCurrent(trace::Call &call, glws::Drawable *drawable, glws::Context *context)
+makeCurrent(trace::Call &call, glws::Drawable *drawable, Context *context)
 {
+    Context *currentContext = currentContextPtr;
+    glws::Drawable *currentDrawable = currentContext ? currentContext->drawable : NULL;
+
     if (drawable == currentDrawable && context == currentContext) {
         return true;
     }
 
-    if (currentDrawable && currentContext) {
+    if (currentContext) {
         glFlush();
         if (!retrace::doubleBuffer) {
             frame_complete(call);
         }
     }
 
-    bool success = glws::makeCurrent(drawable, context);
+    flushQueries();
+
+    bool success = glws::makeCurrent(drawable, context ? context->wsContext : NULL);
 
     if (!success) {
         std::cerr << "error: failed to make current OpenGL context and drawable\n";
@@ -129,18 +162,25 @@ makeCurrent(trace::Call &call, glws::Drawable *drawable, glws::Context *context)
         return false;
     }
 
+    currentContextPtr = context;
+
     if (drawable && context) {
-        currentDrawable = drawable;
-        currentContext = context;
-    } else {
-        currentDrawable = NULL;
-        currentContext = NULL;
+        context->drawable = drawable;
+        
+        if (!context->used) {
+            initContext();
+            context->used = true;
+        }
     }
 
     return true;
 }
 
 
+Context *
+getCurrentContext(void) {
+    return currentContextPtr;
+}
 
 
 /**
@@ -151,7 +191,15 @@ makeCurrent(trace::Call &call, glws::Drawable *drawable, glws::Context *context)
  */
 void
 updateDrawable(int width, int height) {
-    if (!currentDrawable) {
+    Context *currentContext = getCurrentContext();
+    if (!currentContext) {
+        return;
+    }
+
+    glws::Drawable *currentDrawable = currentContext->drawable;
+    assert(currentDrawable);
+
+    if (currentDrawable->pbuffer) {
         return;
     }
 
@@ -180,4 +228,26 @@ updateDrawable(int width, int height) {
 }
 
 
+int
+parseAttrib(const trace::Value *attribs, int param, int default_ = 0) {
+    const trace::Array *attribs_ = dynamic_cast<const trace::Array *>(attribs);
+
+    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) {
+                break;
+            }
+
+            if (param_i == param) {
+                int value = attribs_->values[i + 1]->toSInt();
+                return value;
+            }
+        }
+    }
+
+    return default_;
+}
+
+
 } /* namespace glretrace */
index 55afdd0a00392eba28c69b3eae459f1fe2d92f94..e534a654320ef55bafbe1adda4d847df0af3e6da 100644 (file)
@@ -88,6 +88,31 @@ struct ImageDesc
 };
 
 
+/**
+ * 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);
+    }
+}
+
+
 /**
  * OpenGL ES does not support glGetTexLevelParameteriv, but it is possible to
  * probe whether a texture has a given size by crafting a dummy glTexSubImage()
@@ -232,6 +257,8 @@ getActiveTextureLevelDescOES(Context &context, GLenum target, GLint level, Image
 static inline bool
 getActiveTextureLevelDesc(Context &context, GLenum target, GLint level, ImageDesc &desc)
 {
+    assert(target != GL_TEXTURE_CUBE_MAP);
+
     if (context.ES) {
         return getActiveTextureLevelDescOES(context, target, level, desc);
     }
@@ -386,7 +413,7 @@ dumpActiveTextureLevel(JSONWriter &json, Context &context, GLenum target, GLint
     json.writeNumberMember("__height__", desc.height);
     json.writeNumberMember("__depth__", desc.depth);
 
-    json.writeStringMember("__format__", enumToString(desc.internalFormat));
+    json.writeStringMember("__format__", formatToString(desc.internalFormat));
 
     // Hardcoded for now, but we could chose types more adequate to the
     // texture internal format
@@ -409,7 +436,7 @@ dumpActiveTextureLevel(JSONWriter &json, Context &context, GLenum target, GLint
     json.beginMember("__data__");
     char *pngBuffer;
     int pngBufferSize;
-    image::writePixelsToBuffer(pixels, desc.width, desc.height, channels, true, &pngBuffer, &pngBufferSize);
+    image::writePixelsToBuffer(pixels, desc.width, desc.depth * desc.height, channels, true, &pngBuffer, &pngBufferSize);
     json.writeBase64(pngBuffer, pngBufferSize);
     free(pngBuffer);
     json.endMember(); // __data__
@@ -431,15 +458,18 @@ dumpTexture(JSONWriter &json, Context &context, GLenum target, GLenum binding)
     GLint level = 0;
     do {
         ImageDesc desc;
-        if (!getActiveTextureLevelDesc(context, target, level, desc)) {
-            break;
-        }
 
         if (target == GL_TEXTURE_CUBE_MAP) {
             for (int face = 0; face < 6; ++face) {
+                if (!getActiveTextureLevelDesc(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, desc)) {
+                    return;
+                }
                 dumpActiveTextureLevel(json, context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
             }
         } else {
+            if (!getActiveTextureLevelDesc(context, target, level, desc)) {
+                return;
+            }
             dumpActiveTextureLevel(json, context, target, level);
         }
 
@@ -818,6 +848,10 @@ dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format,
 {
     GLint channels = _gl_format_channels(format);
 
+    if (internalFormat == GL_NONE) {
+        internalFormat = format;
+    }
+
     Context context;
 
     json.beginObject();
@@ -829,7 +863,7 @@ dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format,
     json.writeNumberMember("__height__", height);
     json.writeNumberMember("__depth__", 1);
 
-    json.writeStringMember("__format__", enumToString(internalFormat));
+    json.writeStringMember("__format__", formatToString(internalFormat));
 
     // Hardcoded for now, but we could chose types more adequate to the
     // texture internal format
index 4e07ede9d227a856e0bffe091300906638771604..f89f980c5f8094928f0a5d8db391d78db792508b 100644 (file)
@@ -24,6 +24,9 @@
  **************************************************************************/
 
 
+#include <assert.h>
+
+#include "glproc.hpp"
 #include "glws.hpp"
 
 
@@ -33,26 +36,68 @@ namespace glws {
 bool
 checkExtension(const char *extName, const char *extString)
 {
-   const char *p = extString;
-   const char *q = extName;
-   char c;
-   do {
-       c = *p++;
-       if (c == '\0' || c == ' ') {
-           if (q && *q == '\0') {
-               return true;
-           } else {
-               q = extName;
-           }
-       } else {
-           if (q && *q == c) {
-               ++q;
-           } else {
-               q = 0;
-           }
-       }
-   } while (c);
-   return false;
+    assert(extName);
+    assert(extString);
+
+    const char *p = extString;
+    const char *q = extName;
+    char c;
+    do {
+        c = *p++;
+        if (c == '\0' || c == ' ') {
+            if (q && *q == '\0') {
+                return true;
+            } else {
+                q = extName;
+            }
+        } else {
+            if (q && *q == c) {
+                ++q;
+            } else {
+                q = 0;
+            }
+        }
+    } while (c);
+    return false;
+}
+
+
+bool
+Context::hasExtension(const char *string) {
+    if (extensions.empty()) {
+        if (profile == PROFILE_CORE) {
+            // Use glGetStringi
+            GLint num_extensions = 0;
+            glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
+            for (int i = 0; i < num_extensions; ++i) {
+                const char *extension = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
+                if (extension) {
+                    extensions.insert(extension);
+                }
+            }
+        } else {
+            // Use glGetString
+            const char *begin = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
+            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);
+        }
+    }
+
+    return extensions.find(string) != extensions.end();
 }
 
 
index 05903a7b55281b96b6d00058c844fe551a2b9f7e..c76e19321706a5c8a02fca80dfcce7774ad2ce6f 100644 (file)
 #define _GLWS_HPP_
 
 
+#include <assert.h>
+
 #include <vector>
+#include <set>
+#include <string>
 
 
 namespace glws {
@@ -98,12 +102,14 @@ public:
     const Visual *visual;
     int width;
     int height;
+    bool pbuffer;
     bool visible;
 
-    Drawable(const Visual *vis, int w, int h) :
+    Drawable(const Visual *vis, int w, int h, bool pb) :
         visual(vis),
         width(w),
         height(h),
+        pbuffer(pb),
         visible(false)
     {}
 
@@ -117,6 +123,7 @@ public:
 
     virtual void
     show(void) {
+        assert(!pbuffer);
         visible = true;
     }
 
@@ -130,12 +137,18 @@ public:
     const Visual *visual;
     Profile profile;
     
+    std::set<std::string> extensions;
+
     Context(const Visual *vis, Profile prof) :
         visual(vis),
         profile(prof)
     {}
 
     virtual ~Context() {}
+
+    // Context must be current
+    bool
+    hasExtension(const char *extension);
 };
 
 
@@ -149,7 +162,7 @@ Visual *
 createVisual(bool doubleBuffer = false, Profile profile = PROFILE_COMPAT);
 
 Drawable *
-createDrawable(const Visual *visual, int width = 32, int height = 32);
+createDrawable(const Visual *visual, int width, int height, bool pbuffer = false);
 
 Context *
 createContext(const Visual *visual, Context *shareContext = 0, Profile profile = PROFILE_COMPAT, bool debug = false);
index 2ac30913d515e3f5405c4f8f019a62eea1fce7c9..e410862f1996aa278d64db22c2ec3ba4eac81694 100644 (file)
  * - http://developer.apple.com/library/mac/#samplecode/glut/Introduction/Intro.html
  * - http://developer.apple.com/library/mac/#samplecode/GLEssentials/Introduction/Intro.html
  * - http://www.glfw.org/
+ * - http://cocoasamurai.blogspot.co.uk/2008/04/guide-to-threading-on-leopard.html
+ * - http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html
  */
 
 
+#include "glproc.hpp"
+
 #include <stdlib.h>
 #include <iostream>
 
+#include <dlfcn.h>
+
 #include <Cocoa/Cocoa.h>
 
 #include "glws.hpp"
 
 
+/**
+ * Dummy thread to force Cocoa to enter multithreading mode.
+ */
+@interface DummyThread : NSObject
+    + (void)enterMultiThreaded;
+    + (void)dummyThreadMethod:(id)unused;
+@end
+
+@implementation DummyThread
+    + (void)dummyThreadMethod:(id)unused {
+        (void)unused;
+    }
+
+    + (void)enterMultiThreaded {
+        [NSThread detachNewThreadSelector:@selector(dummyThreadMethod:)
+                  toTarget:self
+                  withObject:nil];
+    }
+@end
+
+
 namespace glws {
 
 
-NSAutoreleasePool *autoreleasePool = nil;
+static __thread NSAutoreleasePool *
+autoreleasePool = nil;
 
 
 class CocoaVisual : public Visual
@@ -69,10 +97,11 @@ class CocoaDrawable : public Drawable
 {
 public:
     NSWindow *window;
+    NSOpenGLView *view;
     NSOpenGLContext *currentContext;
 
-    CocoaDrawable(const Visual *vis, int w, int h) :
-        Drawable(vis, w, h),
+    CocoaDrawable(const Visual *vis, int w, int h, bool pbuffer) :
+        Drawable(vis, w, h, pbuffer),
         currentContext(nil)
     {
         NSOpenGLPixelFormat *pixelFormat = static_cast<const CocoaVisual *>(visual)->pixelFormat;
@@ -88,9 +117,9 @@ public:
                                        defer:NO];
         assert(window != nil);
 
-        NSOpenGLView *view = [[NSOpenGLView alloc]
-                              initWithFrame:winRect
-                                pixelFormat:pixelFormat];
+        view = [[NSOpenGLView alloc]
+                initWithFrame:winRect
+                  pixelFormat:pixelFormat];
         assert(view != nil);
 
         [window setContentView:view];
@@ -113,7 +142,7 @@ public:
         if (currentContext != nil) {
             [currentContext update];
             [window makeKeyAndOrderFront:nil];
-            [currentContext setView:[window contentView]];
+            [currentContext setView:view];
             [currentContext makeCurrentContext];
         }
 
@@ -154,11 +183,29 @@ public:
 };
 
 
+static inline void
+initThread(void) {
+    if (autoreleasePool == nil) {
+        autoreleasePool = [[NSAutoreleasePool alloc] init];
+    }
+}
+
 void
 init(void) {
-    [NSApplication sharedApplication];
+    // Prevent glproc to load system's OpenGL, so that we can trace glretrace.
+    _libGlHandle = dlopen("OpenGL", RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
 
-    autoreleasePool = [[NSAutoreleasePool alloc] init];
+    initThread();
+
+    [DummyThread enterMultiThreaded];
+
+    bool isMultiThreaded = [NSThread isMultiThreaded];
+    if (!isMultiThreaded) {
+        std::cerr << "error: failed to enable Cocoa multi-threading\n";
+       exit(1);
+    }
+
+    [NSApplication sharedApplication];
 
     [NSApp finishLaunching];
 }
@@ -172,6 +219,9 @@ cleanup(void) {
 
 Visual *
 createVisual(bool doubleBuffer, Profile profile) {
+
+    initThread();
+
     if (profile != PROFILE_COMPAT &&
         profile != PROFILE_CORE) {
         return nil;
@@ -193,6 +243,12 @@ createVisual(bool doubleBuffer, Profile profile) {
        return NULL;
 #endif
     }
+    
+    // Use Apple software rendering for debugging purposes.
+    if (0) {
+        attribs.add(NSOpenGLPFARendererID, 0x00020200); // kCGLRendererGenericID
+    }
+
     attribs.end();
 
     NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc]
@@ -202,14 +258,18 @@ createVisual(bool doubleBuffer, Profile profile) {
 }
 
 Drawable *
-createDrawable(const Visual *visual, int width, int height)
+createDrawable(const Visual *visual, int width, int height, bool pbuffer)
 {
-    return new CocoaDrawable(visual, width, height);
+    initThread();
+
+    return new CocoaDrawable(visual, width, height, pbuffer);
 }
 
 Context *
 createContext(const Visual *visual, Context *shareContext, Profile profile, bool debug)
 {
+    initThread();
+
     NSOpenGLPixelFormat *pixelFormat = static_cast<const CocoaVisual *>(visual)->pixelFormat;
     NSOpenGLContext *share_context = nil;
     NSOpenGLContext *context;
@@ -234,6 +294,8 @@ createContext(const Visual *visual, Context *shareContext, Profile profile, bool
 bool
 makeCurrent(Drawable *drawable, Context *context)
 {
+    initThread();
+
     if (!drawable || !context) {
         [NSOpenGLContext clearCurrentContext];
     } else {
@@ -252,8 +314,9 @@ makeCurrent(Drawable *drawable, Context *context)
 
 bool
 processEvents(void) {
-   NSEvent* event;
+    initThread();
 
+    NSEvent* event;
     do {
         event = [NSApp nextEventMatchingMask:NSAnyEventMask
                                    untilDate:[NSDate distantPast]
index 0b8f34c17bc595d192d297cf5517901632abbb05..5aacdfed2b5bea5c0b738b907711d936610a93f8 100644 (file)
@@ -92,8 +92,9 @@ public:
     EGLSurface surface;
     EGLint api;
 
-    EglDrawable(const Visual *vis, int w, int h) :
-        Drawable(vis, w, h), api(EGL_OPENGL_ES_API)
+    EglDrawable(const Visual *vis, int w, int h, bool pbuffer) :
+        Drawable(vis, w, h, pbuffer),
+        api(EGL_OPENGL_ES_API)
     {
         XVisualInfo *visinfo = static_cast<const EglVisual *>(visual)->visinfo;
 
@@ -155,6 +156,28 @@ public:
         eglWaitNative(EGL_CORE_NATIVE_ENGINE);
     }
 
+    void
+    recreate(void) {
+        EGLContext currentContext = eglGetCurrentContext();
+        EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+        EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_DRAW);
+        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);
+
+        EGLConfig config = static_cast<const EglVisual *>(visual)->config;
+        surface = eglCreateWindowSurface(eglDisplay, config, (EGLNativeWindowType)window, NULL);
+
+        if (rebindDrawSurface || rebindReadSurface) {
+            eglMakeCurrent(eglDisplay, surface, surface, currentContext);
+        }
+    }
+
     void
     resize(int w, int h) {
         if (w == width && h == height) {
@@ -182,6 +205,27 @@ public:
         waitForEvent(ConfigureNotify);
 
         eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+
+        /*
+         * Some implementations won't update the backbuffer unless we recreate
+         * the EGL surface.
+         */
+
+        int eglWidth;
+        int eglHeight;
+
+        eglQuerySurface(eglDisplay, surface, EGL_WIDTH, &eglWidth);
+        eglQuerySurface(eglDisplay, surface, EGL_HEIGHT, &eglHeight);
+
+        if (eglWidth != width || eglHeight != height) {
+            recreate();
+
+            eglQuerySurface(eglDisplay, surface, EGL_WIDTH, &eglWidth);
+            eglQuerySurface(eglDisplay, surface, EGL_HEIGHT, &eglHeight);
+        }
+
+        assert(eglWidth == width);
+        assert(eglHeight == height);
     }
 
     void show(void) {
@@ -350,9 +394,9 @@ createVisual(bool doubleBuffer, Profile profile) {
 }
 
 Drawable *
-createDrawable(const Visual *visual, int width, int height)
+createDrawable(const Visual *visual, int width, int height, bool pbuffer)
 {
-    return new EglDrawable(visual, width, height);
+    return new EglDrawable(visual, width, height, pbuffer);
 }
 
 Context *
index 1573bb9d69ec80c41fdb3db4d59db8d5bda2e2c4..1494d060d7245cae687637db7c5452cc6a6c2f2b 100644 (file)
@@ -60,7 +60,8 @@ public:
 };
 
 
-static void describeEvent(const XEvent &event) {
+static void
+processEvent(XEvent &event) {
     if (0) {
         switch (event.type) {
         case ConfigureNotify:
@@ -83,6 +84,19 @@ static void describeEvent(const XEvent &event) {
         }
         std::cerr << " " << event.xany.window << "\n";
     }
+
+    switch (event.type) {
+    case KeyPress:
+        {
+            char buffer[32];
+            KeySym keysym;
+            XLookupString(&event.xkey, buffer, sizeof buffer - 1, &keysym, NULL);
+            if (keysym == XK_Escape) {
+                exit(0);
+            }
+        }
+        break;
+    }
 }
 
 class GlxDrawable : public Drawable
@@ -90,8 +104,8 @@ class GlxDrawable : public Drawable
 public:
     Window window;
 
-    GlxDrawable(const Visual *vis, int w, int h) :
-        Drawable(vis, w, h)
+    GlxDrawable(const Visual *vis, int w, int h, bool pbuffer) :
+        Drawable(vis, w, h, pbuffer)
     {
         XVisualInfo *visinfo = static_cast<const GlxVisual *>(visual)->visinfo;
 
@@ -102,7 +116,7 @@ public:
         attr.background_pixel = 0;
         attr.border_pixel = 0;
         attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
-        attr.event_mask = StructureNotifyMask;
+        attr.event_mask = StructureNotifyMask | KeyPressMask;
 
         unsigned long mask;
         mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
@@ -135,11 +149,18 @@ public:
         glXWaitX();
     }
 
+    void processKeys(void) {
+        XEvent event;
+        while (XCheckWindowEvent(display, window, StructureNotifyMask | KeyPressMask, &event)) {
+            processEvent(event);
+        }
+    }
+
     void waitForEvent(int type) {
         XEvent event;
         do {
-            XWindowEvent(display, window, StructureNotifyMask, &event);
-            describeEvent(event);
+            XWindowEvent(display, window, StructureNotifyMask | KeyPressMask, &event);
+            processEvent(event);
         } while (event.type != type);
     }
 
@@ -194,6 +215,8 @@ public:
 
     void swapBuffers(void) {
         glXSwapBuffers(display, window);
+
+        processKeys();
     }
 };
 
@@ -215,6 +238,8 @@ public:
 
 void
 init(void) {
+    XInitThreads();
+
     display = XOpenDisplay(NULL);
     if (!display) {
         std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
@@ -290,9 +315,9 @@ createVisual(bool doubleBuffer, Profile profile) {
 }
 
 Drawable *
-createDrawable(const Visual *visual, int width, int height)
+createDrawable(const Visual *visual, int width, int height, bool pbuffer)
 {
-    return new GlxDrawable(visual, width, height);
+    return new GlxDrawable(visual, width, height, pbuffer);
 }
 
 Context *
@@ -368,7 +393,7 @@ processEvents(void) {
     while (XPending(display) > 0) {
         XEvent event;
         XNextEvent(display, &event);
-        describeEvent(event);
+        processEvent(event);
     }
     return true;
 }
index c6e4a3fb39b1935e3c29a2a806fdcf007250f211..de6c7d6b546161fe4c1968cb1f3305632cb1dee9 100644 (file)
@@ -100,8 +100,8 @@ public:
     PIXELFORMATDESCRIPTOR pfd;
     int iPixelFormat;
 
-    WglDrawable(const Visual *vis, int width, int height) :
-        Drawable(vis, width, height)
+    WglDrawable(const Visual *vis, int width, int height, bool pbuffer) :
+        Drawable(vis, width, height, pbuffer)
     {
         static bool first = TRUE;
         RECT rect;
@@ -243,6 +243,34 @@ public:
             wglDeleteContext(hglrc);
         }
     }
+
+    bool
+    create(WglDrawable *wglDrawable) {
+        if (!hglrc) {
+            hglrc = wglCreateContext(wglDrawable->hDC);
+            if (!hglrc) {
+                std::cerr << "error: wglCreateContext failed\n";
+                exit(1);
+                return false;
+            }
+            if (shareContext) {
+                if (shareContext->create(wglDrawable)) {
+                    BOOL bRet;
+                    bRet = wglShareLists(shareContext->hglrc,
+                                         hglrc);
+                    if (!bRet) {
+                        std::cerr
+                            << "warning: wglShareLists failed: "
+                            << std::hex << GetLastError() << std::dec
+                            << "\n";
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
 };
 
 
@@ -275,7 +303,8 @@ cleanup(void) {
 
 Visual *
 createVisual(bool doubleBuffer, Profile profile) {
-    if (profile != PROFILE_COMPAT) {
+    if (profile != PROFILE_COMPAT &&
+        profile != PROFILE_CORE) {
         return NULL;
     }
 
@@ -287,18 +316,23 @@ createVisual(bool doubleBuffer, Profile profile) {
 }
 
 Drawable *
-createDrawable(const Visual *visual, int width, int height)
+createDrawable(const Visual *visual, int width, int height, bool pbuffer)
 {
-    return new WglDrawable(visual, width, height);
+    return new WglDrawable(visual, width, height, pbuffer);
 }
 
 Context *
 createContext(const Visual *visual, Context *shareContext, Profile profile, bool debug)
 {
-    if (profile != PROFILE_COMPAT) {
+    if (profile != PROFILE_COMPAT &&
+        profile != PROFILE_CORE) {
         return NULL;
     }
 
+    if (profile == PROFILE_CORE) {
+        std::cerr << "warning: ignoring OpenGL core profile request\n";
+    }
+
     return new WglContext(visual, profile, static_cast<WglContext *>(shareContext));
 }
 
@@ -311,22 +345,7 @@ makeCurrent(Drawable *drawable, Context *context)
         WglDrawable *wglDrawable = static_cast<WglDrawable *>(drawable);
         WglContext *wglContext = static_cast<WglContext *>(context);
 
-        if (!wglContext->hglrc) {
-            wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
-            if (!wglContext->hglrc) {
-                std::cerr << "error: wglCreateContext failed\n";
-                exit(1);
-                return false;
-            }
-            if (wglContext->shareContext) {
-                BOOL bRet;
-                bRet = wglShareLists(wglContext->shareContext->hglrc,
-                                     wglContext->hglrc);
-                if (!bRet) {
-                    std::cerr << "warning: wglShareLists failed\n";
-                }
-            }
-        }
+        wglContext->create(wglDrawable);
 
         return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
     }
index 6af1f4c6c4fab898fae8ca730c5092cefc850459..4ad2ab35d2fd9f270fd4c53845b4ef0293b0b422 100644 (file)
 #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 <iomanip>
 #include <limits>
 #include <ostream>
@@ -328,15 +336,21 @@ public:
 
     template<class T>
     inline void writeNumber(T n) {
-        if (n != n) {
-            // NaN
-            writeNull();
+        separator();
+        if (isnan(n)) {
+            // NaN is non-standard but widely supported
+            os << "NaN";
+        } else if (!isfinite(n)) {
+            // Infinite is non-standard but widely supported
+            if (n < 0) {
+                os << '-';
+            }
+            os << "Infinity";
         } else {
-            separator();
             os << std::dec << std::setprecision(std::numeric_limits<T>::digits10 + 1) << n;
-            value = true;
-            space = ' ';
         }
+        value = true;
+        space = ' ';
     }
     
     inline void writeStringMember(const char *name, const char *s) {
index 25c3f646de2dc2e5ae46f83a1ab3262c7edd4367..ee876ca3eae2c5ebe092c374df1340b1c4a42020 100644 (file)
@@ -40,6 +40,7 @@ static bool call_dumped = false;
 
 static void dumpCall(trace::Call &call) {
     if (verbosity >= 0 && !call_dumped) {
+        std::cout << std::hex << call.thread_id << std::dec << " ";
         std::cout << call;
         std::cout.flush();
         call_dumped = true;
@@ -82,13 +83,6 @@ void Retracer::addCallbacks(const Entry *entries) {
 void Retracer::retrace(trace::Call &call) {
     call_dumped = false;
 
-    if (verbosity >= 1) {
-        if (verbosity >= 2 ||
-            !(call.flags & trace::CALL_FLAG_VERBOSE)) {
-            dumpCall(call);
-        }
-    }
-
     Callback callback = 0;
 
     trace::Id id = call.sig->id;
@@ -112,20 +106,15 @@ void Retracer::retrace(trace::Call &call) {
     assert(callback);
     assert(callbacks[id] == callback);
 
-    if (retrace::profiling) {
-        long long startTime = os::getTime();
-        callback(call);
-        long long stopTime = os::getTime();
-        float timeInterval = (stopTime - startTime) * (1.0E6 / os::timeFrequency);
-
-        std::cout
-            << call.no << " "
-            << "[" << timeInterval << " usec] "
-        ;
-        trace::dump(call, std::cout, trace::DUMP_FLAG_NO_CALL_NO | trace::DUMP_FLAG_NO_COLOR);
-    } else {
-        callback(call);
+    if (verbosity >= 1) {
+        if (verbosity >= 2 ||
+            (!(call.flags & trace::CALL_FLAG_VERBOSE) &&
+             callback != &ignore)) {
+            dumpCall(call);
+        }
     }
+
+    callback(call);
 }
 
 
index a019de787cae5de55432ba2797f9355cca45c3ad..56cebc6195135dfcd7f7e0bf51158f1bf0ede755 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "trace_model.hpp"
 #include "trace_parser.hpp"
+#include "trace_profiler.hpp"
 
 
 namespace image {
@@ -47,6 +48,7 @@ namespace retrace {
 
 
 extern trace::Parser parser;
+extern trace::Profiler profiler;
 
 
 /**
@@ -146,6 +148,9 @@ extern bool debug;
  * Add profiling data to the dump when retracing.
  */
 extern bool profiling;
+extern bool profilingCpuTimes;
+extern bool profilingGpuTimes;
+extern bool profilingPixelsDrawn;
 
 /**
  * State dumping.
@@ -156,6 +161,9 @@ extern bool dumpingState;
 extern bool doubleBuffer;
 extern bool coreProfile;
 
+extern unsigned frameNo;
+extern unsigned callNo;
+
 
 std::ostream &warning(trace::Call &call);
 
index f7fb7113e4178cb757fb6eefe73a13c1c3855cdc..7e171e67bf97f504744ab2268f94d84362a6f7a7 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "os_binary.hpp"
 #include "os_time.hpp"
+#include "os_thread.hpp"
 #include "image.hpp"
 #include "trace_callset.hpp"
 #include "trace_dump.hpp"
@@ -44,24 +45,30 @@ static trace::CallSet compareFrequency;
 
 static unsigned dumpStateCallNo = ~0;
 
+retrace::Retracer retracer;
+
 
 namespace retrace {
 
 
 trace::Parser parser;
+trace::Profiler profiler;
 
 
 int verbosity = 0;
 bool debug = true;
-bool profiling = false;
 bool dumpingState = false;
 
-
 bool doubleBuffer = true;
 bool coreProfile = false;
 
+bool profiling = false;
+bool profilingGpuTimes = false;
+bool profilingCpuTimes = false;
+bool profilingPixelsDrawn = false;
 
-static unsigned frameNo = 0;
+unsigned frameNo = 0;
+unsigned callNo = 0;
 
 
 void
@@ -70,6 +77,9 @@ frameComplete(trace::Call &call) {
 }
 
 
+/**
+ * Take/compare snapshots.
+ */
 static void
 takeSnapshot(unsigned call_no) {
     assert(snapshotPrefix || comparePrefix);
@@ -116,55 +126,342 @@ takeSnapshot(unsigned call_no) {
 }
 
 
+/**
+ * Retrace one call.
+ *
+ * Take snapshots before/after retracing (as appropriate) and dispatch it to
+ * the respective handler.
+ */
 static void
-mainLoop() {
-    retrace::Retracer retracer;
+retraceCall(trace::Call *call) {
+    bool swapRenderTarget = call->flags &
+        trace::CALL_FLAG_SWAP_RENDERTARGET;
+    bool doSnapshot = snapshotFrequency.contains(*call) ||
+        compareFrequency.contains(*call);
+
+    // For calls which cause rendertargets to be swaped, we take the
+    // snapshot _before_ swapping the rendertargets.
+    if (doSnapshot && swapRenderTarget) {
+        if (call->flags & trace::CALL_FLAG_END_FRAME) {
+            // For swapbuffers/presents we still use this
+            // call number, spite not have been executed yet.
+            takeSnapshot(call->no);
+        } else {
+            // Whereas for ordinate fbo/rendertarget changes we
+            // use the previous call's number.
+            takeSnapshot(call->no - 1);
+        }
+    }
 
-    addCallbacks(retracer);
+    callNo = call->no;
+    retracer.retrace(*call);
 
-    long long startTime = 0; 
-    frameNo = 0;
+    if (doSnapshot && !swapRenderTarget)
+        takeSnapshot(call->no);
 
-    startTime = os::getTime();
-    trace::Call *call;
+    if (call->no >= dumpStateCallNo &&
+        dumpState(std::cout)) {
+        exit(0);
+    }
+}
 
-    while ((call = retrace::parser.parse_call())) {
-        bool swapRenderTarget = call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET;
-        bool doSnapshot =
-            snapshotFrequency.contains(*call) ||
-            compareFrequency.contains(*call)
-        ;
-
-        // For calls which cause rendertargets to be swaped, we take the
-        // snapshot _before_ swapping the rendertargets.
-        if (doSnapshot && swapRenderTarget) {
-            if (call->flags & trace::CALL_FLAG_END_FRAME) {
-                // For swapbuffers/presents we still use this call number,
-                // spite not have been executed yet.
-                takeSnapshot(call->no);
-            } else {
-                // Whereas for ordinate fbo/rendertarget changes we use the
-                // previous call's number.
-                takeSnapshot(call->no - 1);
+
+class RelayRunner;
+
+
+/**
+ * Implement multi-threading by mimicking a relay race.
+ */
+class RelayRace
+{
+private:
+    /**
+     * Runners indexed by the leg they run (i.e, the thread_ids from the
+     * trace).
+     */
+    std::vector<RelayRunner*> runners;
+
+public:
+    RelayRace();
+
+    ~RelayRace();
+
+    RelayRunner *
+    getRunner(unsigned leg);
+
+    inline RelayRunner *
+    getForeRunner() {
+        return getRunner(0);
+    }
+
+    void
+    run(void);
+
+    void
+    passBaton(trace::Call *call);
+
+    void
+    finishLine();
+
+    void
+    stopRunners();
+};
+
+
+/**
+ * Each runner is a thread.
+ *
+ * The fore runner doesn't have its own thread, but instead uses the thread
+ * where the race started.
+ */
+class RelayRunner
+{
+private:
+    friend class RelayRace;
+
+    RelayRace *race;
+
+    unsigned leg;
+    
+    os::mutex mutex;
+    os::condition_variable wake_cond;
+
+    /**
+     * There are protected by the mutex.
+     */
+    bool finished;
+    trace::Call *baton;
+
+    os::thread thread;
+
+    static void *
+    runnerThread(RelayRunner *_this);
+
+public:
+    RelayRunner(RelayRace *race, unsigned _leg) :
+        race(race),
+        leg(_leg),
+        finished(false),
+        baton(0)
+    {
+        /* The fore runner does not need a new thread */
+        if (leg) {
+            thread = os::thread(runnerThread, this);
+        }
+    }
+
+    /**
+     * Thread main loop.
+     */
+    void
+    runRace(void) {
+        os::unique_lock<os::mutex> lock(mutex);
+
+        while (1) {
+            while (!finished && !baton) {
+                wake_cond.wait(lock);
+            }
+
+            if (finished) {
+                break;
             }
+
+            assert(baton);
+            trace::Call *call = baton;
+            baton = 0;
+
+            runLeg(call);
         }
 
-        retracer.retrace(*call);
+        if (0) std::cerr << "leg " << leg << " actually finishing\n";
 
-        if (doSnapshot && !swapRenderTarget) {
-            takeSnapshot(call->no);
+        if (leg == 0) {
+            race->stopRunners();
         }
+    }
 
-        if (call->no >= dumpStateCallNo &&
-            dumpState(std::cout)) {
-            exit(0);
+    /**
+     * Interpret successive calls.
+     */
+    void
+    runLeg(trace::Call *call) {
+        /* Consume successive calls for this thread. */
+        do {
+            assert(call);
+            assert(call->thread_id == leg);
+            retraceCall(call);
+            delete call;
+            call = parser.parse_call();
+        } while (call && call->thread_id == leg);
+
+        if (call) {
+            /* Pass the baton */
+            assert(call->thread_id != leg);
+            flushRendering();
+            race->passBaton(call);
+        } else {
+            /* Reached the finish line */
+            if (0) std::cerr << "finished on leg " << leg << "\n";
+            if (leg) {
+                /* Notify the fore runner */
+                race->finishLine();
+            } else {
+                /* We are the fore runner */
+                finished = true;
+            }
         }
+    }
 
-        delete call;
+    /**
+     * Called by other threads when relinquishing the baton.
+     */
+    void
+    receiveBaton(trace::Call *call) {
+        assert (call->thread_id == leg);
+
+        mutex.lock();
+        baton = call;
+        mutex.unlock();
+
+        wake_cond.signal();
     }
 
-    // Reached the end of trace
-    flushRendering();
+    /**
+     * Called by the fore runner when the race is over.
+     */
+    void
+    finishRace() {
+        if (0) std::cerr << "notify finish to leg " << leg << "\n";
+
+        mutex.lock();
+        finished = true;
+        mutex.unlock();
+
+        wake_cond.signal();
+    }
+};
+
+
+void *
+RelayRunner::runnerThread(RelayRunner *_this) {
+    _this->runRace();
+    return 0;
+}
+
+
+RelayRace::RelayRace() {
+    runners.push_back(new RelayRunner(this, 0));
+}
+
+
+RelayRace::~RelayRace() {
+    assert(runners.size() >= 1);
+    std::vector<RelayRunner*>::const_iterator it;
+    for (it = runners.begin(); it != runners.end(); ++it) {
+        RelayRunner* runner = *it;
+        if (runner) {
+            delete runner;
+        }
+    }
+}
+
+
+/**
+ * Get (or instantiate) a runner for the specified leg.
+ */
+RelayRunner *
+RelayRace::getRunner(unsigned leg) {
+    RelayRunner *runner;
+
+    if (leg >= runners.size()) {
+        runners.resize(leg + 1);
+        runner = 0;
+    } else {
+        runner = runners[leg];
+    }
+    if (!runner) {
+        runner = new RelayRunner(this, leg);
+        runners[leg] = runner;
+    }
+    return runner;
+}
+
+
+/**
+ * Start the race.
+ */
+void
+RelayRace::run(void) {
+    trace::Call *call;
+    call = parser.parse_call();
+    if (!call) {
+        /* Nothing to do */
+        return;
+    }
+
+    RelayRunner *foreRunner = getForeRunner();
+    if (call->thread_id == 0) {
+        /* We are the forerunner thread, so no need to pass baton */
+        foreRunner->baton = call;
+    } else {
+        passBaton(call);
+    }
+
+    /* Start the forerunner thread */
+    foreRunner->runRace();
+}
+
+
+/**
+ * Pass the baton (i.e., the call) to the appropriate thread.
+ */
+void
+RelayRace::passBaton(trace::Call *call) {
+    if (0) std::cerr << "switching to thread " << call->thread_id << "\n";
+    RelayRunner *runner = getRunner(call->thread_id);
+    runner->receiveBaton(call);
+}
+
+
+/**
+ * Called when a runner other than the forerunner reaches the finish line.
+ *
+ * Only the fore runner can finish the race, so inform him that the race is
+ * finished.
+ */
+void
+RelayRace::finishLine(void) {
+    RelayRunner *foreRunner = getForeRunner();
+    foreRunner->finishRace();
+}
+
+
+/**
+ * Called by the fore runner after finish line to stop all other runners.
+ */
+void
+RelayRace::stopRunners(void) {
+    std::vector<RelayRunner*>::const_iterator it;
+    for (it = runners.begin() + 1; it != runners.end(); ++it) {
+        RelayRunner* runner = *it;
+        if (runner) {
+            runner->finishRace();
+        }
+    }
+}
+
+
+static void
+mainLoop() {
+    addCallbacks(retracer);
+
+    long long startTime = 0; 
+    frameNo = 0;
+
+    startTime = os::getTime();
+
+    RelayRace race;
+    race.run();
 
     long long endTime = os::getTime();
     float timeInterval = (endTime - startTime) * (1.0 / os::timeFrequency);
@@ -194,7 +491,9 @@ usage(const char *argv0) {
         "Replay TRACE.\n"
         "\n"
         "  -b           benchmark mode (no error checking or warning messages)\n"
-        "  -p           profiling mode (run whole trace, dump profiling info)\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"
         "  -c PREFIX    compare against snapshots\n"
         "  -C CALLSET   calls to compare (default is every frame)\n"
         "  -core        use core profile\n"
@@ -229,10 +528,6 @@ int main(int argc, char **argv)
         } else if (!strcmp(arg, "-b")) {
             retrace::debug = false;
             retrace::verbosity = -1;
-        } else if (!strcmp(arg, "-p")) {
-            retrace::debug = false;
-            retrace::profiling = true;
-            retrace::verbosity = -1;
         } else if (!strcmp(arg, "-c")) {
             comparePrefix = argv[++i];
             if (compareFrequency.empty()) {
@@ -274,6 +569,18 @@ int main(int argc, char **argv)
             ++retrace::verbosity;
         } else if (!strcmp(arg, "-w")) {
             waitOnFinish = true;
+        } else if (arg[1] == 'p') {
+            retrace::debug = false;
+            retrace::profiling = true;
+            retrace::verbosity = -1;
+
+            if (!strcmp(arg, "-pcpu")) {
+                retrace::profilingCpuTimes = true;
+            } else if (!strcmp(arg, "-pgpu")) {
+                retrace::profilingGpuTimes = true;
+            } else if (!strcmp(arg, "-ppd")) {
+                retrace::profilingPixelsDrawn = true;
+            }
         } else {
             std::cerr << "error: unknown option " << arg << "\n";
             usage(argv[0]);
@@ -282,6 +589,9 @@ int main(int argc, char **argv)
     }
 
     retrace::setUp();
+    if (retrace::profiling) {
+        retrace::profiler.setup(retrace::profilingCpuTimes, retrace::profilingGpuTimes, retrace::profilingPixelsDrawn);
+    }
 
     for ( ; i < argc; ++i) {
         if (!retrace::parser.open(argv[i])) {
index 52d1d74dfd251eeb20cc9ce8c462a4f81a970313..a7e777d45cba26e8da0abe4a6bf92900a1db5162 100644 (file)
@@ -75,6 +75,12 @@ lowerBound(unsigned long long address) {
         }
     }
 
+#ifndef NDEBUG
+    if (it != regionMap.end()) {
+        assert(contains(it, address) || it->first > address);
+    }
+#endif
+
     return it;
 }
 
@@ -83,6 +89,12 @@ static RegionMap::iterator
 upperBound(unsigned long long address) {
     RegionMap::iterator it = regionMap.upper_bound(address);
 
+#ifndef NDEBUG
+    if (it != regionMap.end()) {
+        assert(it->first >= address);
+    }
+#endif
+
     return it;
 }
 
@@ -108,7 +120,7 @@ addRegion(unsigned long long address, void *buffer, unsigned long long size)
 
 #ifndef NDEBUG
     RegionMap::iterator start = lowerBound(address);
-    RegionMap::iterator stop = upperBound(address + size);
+    RegionMap::iterator stop = upperBound(address + size - 1);
     if (0) {
         // Forget all regions that intersect this new one.
         regionMap.erase(start, stop);
diff --git a/scripts/profileshader.py b/scripts/profileshader.py
new file mode 100755 (executable)
index 0000000..d31130e
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# 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.
+#
+##########################################################################/
+
+
+import sys
+
+
+def process(stream):
+    times = {}
+
+    # call no gpu_start gpu_dura cpu_start cpu_dura pixels program name
+
+    for line in stream:
+        words = line.split(' ')
+
+        if line.startswith('#'):
+            continue
+
+        if words[0] == 'call':
+            id = long(words[1])
+            duration = long(words[3])
+            shader = long(words[7])
+            func = words[8]
+
+            if times.has_key(shader):
+                times[shader]['draws'] += 1
+                times[shader]['duration'] += duration
+
+                if duration > times[shader]['longestDuration']:
+                    times[shader]['longest'] = id
+                    times[shader]['longestDuration'] = duration
+            else:
+                times[shader] = {'draws': 1, 'duration': duration, 'longest': id, 'longestDuration': duration}
+
+    times = sorted(times.items(), key=lambda x: x[1]['duration'], reverse=True)
+
+    print '+------------+--------------+--------------------+--------------+-------------+'
+    print '| Shader[id] |   Draws [#]  |   Duration [ns]  v | Per Call[ns] | Longest[id] |'
+    print '+------------+--------------+--------------------+--------------+-------------+'
+
+    for shader in times:
+        id = str(shader[0]).rjust(10)
+        draw = str(shader[1]['draws']).rjust(12)
+        dura = str(shader[1]['duration']).rjust(18)
+        perCall = str(shader[1]['duration'] / shader[1]['draws']).rjust(12)
+        longest = str(shader[1]['longest']).rjust(11)
+        print "| %s | %s | %s | %s | %s |" % (id, draw, dura, perCall, longest)
+
+    print '+------------+--------------+--------------------+--------------+-------------+'
+
+
+def main():
+    if len(sys.argv) > 1:
+        for arg in sys.argv[1:]:
+            process(open(arg, 'rt'))
+    else:
+        process(sys.stdin)
+
+
+if __name__ == '__main__':
+    main()
index 8a0837a82bf6a17d9e973c62db70cdbaf6b9860c..d665c7601b7acf7a91ef3708fd521c4165e0891f 100755 (executable)
@@ -98,7 +98,15 @@ def read_pnm(stream):
     magic = stream.readline()
     if not magic:
         return None, None
-    assert magic.rstrip() == 'P6'
+    magic = magic.rstrip()
+    if magic == 'P5':
+        channels = 1
+        mode = 'L'
+    elif magic == 'P6':
+        channels = 3
+        mode = 'RGB'
+    else:
+        raise Exception('Unsupported magic `%s`' % magic)
     comment = ''
     line = stream.readline()
     while line.startswith('#'):
@@ -107,8 +115,8 @@ def read_pnm(stream):
     width, height = map(int, line.strip().split())
     maximum = int(stream.readline().strip())
     assert maximum == 255
-    data = stream.read(height * width * 3)
-    image = Image.frombuffer('RGB', (width, height), data, 'raw', 'RGB', 0, 1)
+    data = stream.read(height * width * channels)
+    image = Image.frombuffer(mode, (width, height), data, 'raw', mode, 0, 1)
     return image, comment
 
 
index 86d1e0020f1e55a72c196b93c8ba9a20c727e7a9..26395879a10b8c54f3308f6a3a8eeab2e5506414 100755 (executable)
@@ -70,6 +70,8 @@ else:
 
 def diff(ref_trace, src_trace):
 
+    isatty = sys.stdout.isatty()
+
     ref_dumper = Dumper(ref_trace, options.ref_calls)
     src_dumper = Dumper(src_trace, options.src_calls)
 
@@ -78,6 +80,9 @@ def diff(ref_trace, src_trace):
         diff_args = [
                 'diff',
                 '--speed-large-files',
+            ]
+        if isatty:
+            diff_args += [
                 '--old-line-format=' + start_delete + '%l' + end_delete + '\n',
                 '--new-line-format=' + start_insert + '%l' + end_insert + '\n',
             ]
@@ -92,6 +97,9 @@ def diff(ref_trace, src_trace):
                 'wdiff',
                 #'--terminal',
                 '--avoid-wraps',
+            ]
+        if isatty:
+            diff_args += [
                 '--start-delete=' + start_delete,
                 '--end-delete=' + end_delete,
                 '--start-insert=' + start_insert,
@@ -105,7 +113,7 @@ def diff(ref_trace, src_trace):
     src_dumper.dump.wait()
 
     less = None
-    if sys.stdout.isatty():
+    if isatty:
         less = subprocess.Popen(
             args = ['less', '-FRXn'],
             stdin = subprocess.PIPE
index 0f59d87983df51be1a23bb8400c3c601d172402b..255191e8c5bf93bd9a744ef558b4c28e7f386e2d 100755 (executable)
@@ -58,7 +58,7 @@ class Blob:
         return 'blob(%u)' % self.size
 
     def __eq__(self, other):
-        return self.size == other.size and self.hash == other.hash
+        return isinstance(other, Blob) and self.size == other.size and self.hash == other.hash
 
     def __hash__(self):
         return self.hash
index b2c49c9e04d9a64c4ebfb0eec72717206465613d..50d8480aac948143f78c091bb5198d2a04ec4773 100755 (executable)
@@ -218,25 +218,42 @@ class Unpickler:
 
 class Counter(Unpickler):
 
-    def __init__(self, stream, quiet):
+    def __init__(self, stream, verbose = False):
         Unpickler.__init__(self, stream)
-        self.quiet = quiet
-        self.calls = 0
+        self.verbose = verbose
+        self.numCalls = 0
+        self.functionFrequencies = {}
+
+    def parse(self):
+        Unpickler.parse(self)
+
+        functionFrequencies = self.functionFrequencies.items()
+        functionFrequencies.sort(lambda (name1, freq1), (name2, freq2): cmp(freq1, freq2))
+        for name, frequency in functionFrequencies:
+            sys.stdout.write('%8u %s\n' % (frequency, name))
 
     def handleCall(self, call):
-        if not self.quiet:
+        if self.verbose:
             sys.stdout.write(str(call))
             sys.stdout.write('\n')
-        self.calls += 1
+        self.numCalls += 1
+        try:
+            self.functionFrequencies[call.functionName] += 1
+        except KeyError:
+            self.functionFrequencies[call.functionName] = 1
 
 
 def main():
     optparser = optparse.OptionParser(
-        usage="\n\tapitrace pickle trace. %prog [options]")
+        usage="\n\tapitrace pickle <trace> | %prog [options]")
+    optparser.add_option(
+        '-p', '--profile',
+        action="store_true", dest="profile", default=False,
+        help="profile call parsing")
     optparser.add_option(
-        '-q', '--quiet',
-        action="store_true", dest="quiet", default=False,
-        help="don't dump calls to stdout")
+        '-v', '--verbose',
+        action="store_true", dest="verbose", default=False,
+        help="dump calls to stdout")
 
     (options, args) = optparser.parse_args(sys.argv[1:])
 
@@ -253,11 +270,13 @@ def main():
         msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
 
     startTime = time.time()
-    parser = Counter(sys.stdin, options.quiet)
+    parser = Counter(sys.stdin, options.verbose)
     parser.parse()
     stopTime = time.time()
     duration = stopTime - startTime
-    sys.stderr.write('%u calls, %.03f secs, %u calls/sec\n' % (parser.calls, duration, parser.calls/duration))
+
+    if options.profile:
+        sys.stderr.write('Processed %u calls in %.03f secs, at %u calls/sec\n' % (parser.numCalls, duration, parser.numCalls/duration))
 
 
 if __name__ == '__main__':
index c5930f6e55500538f49ad37a68de58a620b68332..fbae1b149eecd539d171845a9aac963f868940b6 100644 (file)
@@ -233,7 +233,7 @@ cglapi.addFunctions([
     Function(CGLError, "CGLLockContext", [(CGLContextObj, "ctx")]),
     Function(CGLError, "CGLUnlockContext", [(CGLContextObj, "ctx")]),
     Function(Void, "CGLGetVersion", [Out(Pointer(GLint), "majorvers"), Out(Pointer(GLint), "minorvers")]),
-    Function(Const(CString), "CGLErrorString", [(CGLError, "error")]),
+    Function(ConstCString, "CGLErrorString", [(CGLError, "error")]),
 
     # CGLIOSurface.h, OpenGL framework
     Function(CGLError, "CGLTexImageIOSurface2D", [(CGLContextObj, "ctx"), (GLenum, "target"), (GLenum, "internal_format"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (IOSurfaceRef, "ioSurface"), (GLuint, "plane")]),
index b7c3e653af5a2b7f1447545216da7436daf70461..7b0f1824158405aa7b7bc535764baebd9d3681a7 100644 (file)
@@ -544,7 +544,7 @@ D3D10_BOX = Struct("D3D10_BOX", [
 ])
 
 D3D10_SUBRESOURCE_DATA = Struct("D3D10_SUBRESOURCE_DATA", [
-    (OpaquePointer(Const(Void)), "pSysMem"),
+    (Blob(Const(Void), "_calcSubresourceSize(pDesc, {i}, {self}.SysMemPitch, {self}.SysMemSlicePitch)"), "pSysMem"),
     (UINT, "SysMemPitch"),
     (UINT, "SysMemSlicePitch"),
 ])
@@ -824,7 +824,7 @@ ID3D10Device.methods += [
     Method(Void, "RSSetScissorRects", [(UINT, "NumRects"), (Array(Const(D3D10_RECT), "NumRects"), "pRects")]),
     Method(Void, "CopySubresourceRegion", [(ObjPointer(ID3D10Resource), "pDstResource"), (UINT, "DstSubresource"), (UINT, "DstX"), (UINT, "DstY"), (UINT, "DstZ"), (ObjPointer(ID3D10Resource), "pSrcResource"), (UINT, "SrcSubresource"), (Pointer(Const(D3D10_BOX)), "pSrcBox")]),
     Method(Void, "CopyResource", [(ObjPointer(ID3D10Resource), "pDstResource"), (ObjPointer(ID3D10Resource), "pSrcResource")]),
-    Method(Void, "UpdateSubresource", [(ObjPointer(ID3D10Resource), "pDstResource"), (UINT, "DstSubresource"), (Pointer(Const(D3D10_BOX)), "pDstBox"), (OpaquePointer(Const(Void)), "pSrcData"), (UINT, "SrcRowPitch"), (UINT, "SrcDepthPitch")]),
+    Method(Void, "UpdateSubresource", [(ObjPointer(ID3D10Resource), "pDstResource"), (UINT, "DstSubresource"), (Pointer(Const(D3D10_BOX)), "pDstBox"), (Blob(Const(Void), "_calcSubresourceSize(pDstResource, DstSubresource, pDstBox, SrcRowPitch, SrcDepthPitch)"), "pSrcData"), (UINT, "SrcRowPitch"), (UINT, "SrcDepthPitch")]),
     Method(Void, "ClearRenderTargetView", [(ObjPointer(ID3D10RenderTargetView), "pRenderTargetView"), (Array(Const(FLOAT), 4), "ColorRGBA")]),
     Method(Void, "ClearDepthStencilView", [(ObjPointer(ID3D10DepthStencilView), "pDepthStencilView"), (D3D10_CLEAR_FLAG, "ClearFlags"), (FLOAT, "Depth"), (UINT8, "Stencil")]),
     Method(Void, "GenerateMips", [(ObjPointer(ID3D10ShaderResourceView), "pShaderResourceView")]),
@@ -861,10 +861,10 @@ ID3D10Device.methods += [
     Method(HRESULT, "SetPrivateDataInterface", [(REFGUID, "guid"), (OpaquePointer(Const(IUnknown)), "pData")], sideeffects=False),
     Method(Void, "ClearState", []),
     Method(Void, "Flush", []),
-    Method(HRESULT, "CreateBuffer", [(Pointer(Const(D3D10_BUFFER_DESC)), "pDesc"), (Pointer(Const(D3D10_SUBRESOURCE_DATA)), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Buffer)), "ppBuffer")]),
-    Method(HRESULT, "CreateTexture1D", [(Pointer(Const(D3D10_TEXTURE1D_DESC)), "pDesc"), (Pointer(Const(D3D10_SUBRESOURCE_DATA)), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture1D)), "ppTexture1D")]),
-    Method(HRESULT, "CreateTexture2D", [(Pointer(Const(D3D10_TEXTURE2D_DESC)), "pDesc"), (Pointer(Const(D3D10_SUBRESOURCE_DATA)), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture2D)), "ppTexture2D")]),
-    Method(HRESULT, "CreateTexture3D", [(Pointer(Const(D3D10_TEXTURE3D_DESC)), "pDesc"), (Pointer(Const(D3D10_SUBRESOURCE_DATA)), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture3D)), "ppTexture3D")]),
+    Method(HRESULT, "CreateBuffer", [(Pointer(Const(D3D10_BUFFER_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), "1"), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Buffer)), "ppBuffer")]),
+    Method(HRESULT, "CreateTexture1D", [(Pointer(Const(D3D10_TEXTURE1D_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture1D)), "ppTexture1D")]),
+    Method(HRESULT, "CreateTexture2D", [(Pointer(Const(D3D10_TEXTURE2D_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture2D)), "ppTexture2D")]),
+    Method(HRESULT, "CreateTexture3D", [(Pointer(Const(D3D10_TEXTURE3D_DESC)), "pDesc"), (Array(Const(D3D10_SUBRESOURCE_DATA), "_getNumSubResources(pDesc)"), "pInitialData"), Out(Pointer(ObjPointer(ID3D10Texture3D)), "ppTexture3D")]),
     Method(HRESULT, "CreateShaderResourceView", [(ObjPointer(ID3D10Resource), "pResource"), (Pointer(Const(D3D10_SHADER_RESOURCE_VIEW_DESC)), "pDesc"), Out(Pointer(ObjPointer(ID3D10ShaderResourceView)), "ppSRView")]),
     Method(HRESULT, "CreateRenderTargetView", [(ObjPointer(ID3D10Resource), "pResource"), (Pointer(Const(D3D10_RENDER_TARGET_VIEW_DESC)), "pDesc"), Out(Pointer(ObjPointer(ID3D10RenderTargetView)), "ppRTView")]),
     Method(HRESULT, "CreateDepthStencilView", [(ObjPointer(ID3D10Resource), "pResource"), (Pointer(Const(D3D10_DEPTH_STENCIL_VIEW_DESC)), "pDesc"), Out(Pointer(ObjPointer(ID3D10DepthStencilView)), "ppDepthStencilView")]),
index 8f5c59f29b7368eb0ae9acdfcad97abf1d69c738..7dd5cc8b0ea2a74d4c91dae6266320280cacb351 100644 (file)
@@ -561,7 +561,7 @@ D3D10_MESSAGE = Struct("D3D10_MESSAGE", [
     (D3D10_MESSAGE_CATEGORY, "Category"),
     (D3D10_MESSAGE_SEVERITY, "Severity"),
     (D3D10_MESSAGE_ID, "ID"),
-    (Const(CString), "pDescription"),
+    (ConstCString, "pDescription"),
     (SIZE_T, "DescriptionByteLength"),
 ])
 
index 5c7925e4427d62eec7a6a54f35e4453bfe9cbaff..45af484d138637763ed89d967991666cad32adf3 100644 (file)
@@ -284,6 +284,6 @@ IDXGIDevice1.methods += [
 
 dxgi = API('dxgi')
 dxgi.addFunctions([
-    StdFunction(HRESULT, "CreateDXGIFactory", [(REFIID, "riid"), (Pointer(ObjPointer(Void)), "ppFactory")]),
-    StdFunction(HRESULT, "CreateDXGIFactory1", [(REFIID, "riid"), (Pointer(ObjPointer(Void)), "ppFactory")]),
+    StdFunction(HRESULT, "CreateDXGIFactory", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppFactory")]),
+    StdFunction(HRESULT, "CreateDXGIFactory1", [(REFIID, "riid"), Out(Pointer(ObjPointer(Void)), "ppFactory")]),
 ])
index d1ba6478a1f75d0197dd3ad8824f25ab71a86997..74584784fac766cd5c3770e1d3326d304564a63a 100644 (file)
@@ -307,7 +307,7 @@ eglapi.addFunctions([
     Function(EGLBoolean, "eglInitialize", [(EGLDisplay, "dpy"), Out(Pointer(EGLint), "major"), Out(Pointer(EGLint), "minor")]),
     Function(EGLBoolean, "eglTerminate", [(EGLDisplay, "dpy")]),
 
-    Function(Const(String("char *")), "eglQueryString", [(EGLDisplay, "dpy"), (EGLName, "name")], sideeffects=False),
+    Function(ConstCString, "eglQueryString", [(EGLDisplay, "dpy"), (EGLName, "name")], sideeffects=False),
 
     Function(EGLBoolean, "eglGetConfigs", [(EGLDisplay, "dpy"), (Array(EGLConfig, "config_size"), "configs"), (EGLint, "config_size"), Out(Pointer(EGLint), "num_config")]),
     Function(EGLBoolean, "eglChooseConfig", [(EGLDisplay, "dpy"), (EGLAttribList, "attrib_list"), (Array(EGLConfig, "config_size"), "configs"), (EGLint, "config_size"), Out(Pointer(EGLint), "num_config")]),
@@ -349,7 +349,7 @@ eglapi.addFunctions([
     Function(EGLBoolean, "eglSwapBuffers", [(EGLDisplay, "dpy"), (EGLSurface, "surface")]),
     Function(EGLBoolean, "eglCopyBuffers", [(EGLDisplay, "dpy"), (EGLSurface, "surface"), (EGLNativePixmapType, "target")]),
 
-    Function(EGLProc, "eglGetProcAddress", [(Const(CString), "procname")]),
+    Function(EGLProc, "eglGetProcAddress", [(ConstCString, "procname")]),
 
     # EGL_KHR_lock_surface
     Function(EGLBoolean, "eglLockSurfaceKHR", [(EGLDisplay, "display"), (EGLSurface, "surface"), (EGLAttribList, "attrib_list")]),
index 7bde5e41a6548dd4d400797ea840a8a42806f529..3db0739dc3767b5608e350ac00007affcbea6dc9 100644 (file)
@@ -64,9 +64,9 @@ glapi.addFunctions([
     GlFunction(Void, "glTexImage2D", [(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, "glDrawBuffer", [(GLenum, "mode")]),
     GlFunction(Void, "glClear", [(GLbitfield_attrib, "mask")]),
-    GlFunction(Void, "glClearColor", [(GLclampf, "red"), (GLclampf, "green"), (GLclampf, "blue"), (GLclampf, "alpha")]),
+    GlFunction(Void, "glClearColor", [(GLfloat, "red"), (GLfloat, "green"), (GLfloat, "blue"), (GLfloat, "alpha")]),
     GlFunction(Void, "glClearStencil", [(GLint, "s")]),
-    GlFunction(Void, "glClearDepth", [(GLclampd, "depth")]),
+    GlFunction(Void, "glClearDepth", [(GLdouble, "depth")]),
     GlFunction(Void, "glStencilMask", [(GLuint, "mask")]),
     GlFunction(Void, "glColorMask", [(GLboolean, "red"), (GLboolean, "green"), (GLboolean, "blue"), (GLboolean, "alpha")]),
     GlFunction(Void, "glDepthMask", [(GLboolean, "flag")]),
@@ -88,14 +88,14 @@ glapi.addFunctions([
     GlFunction(GLenum_error, "glGetError", [], sideeffects=False),
     GlFunction(Void, "glGetFloatv", [(GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetIntegerv", [(GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
-    GlFunction(String("const GLubyte *"), "glGetString", [(GLenum, "name")], sideeffects=False),
+    GlFunction(String(Const(GLubyte)), "glGetString", [(GLenum, "name")], sideeffects=False),
     GlFunction(Void, "glGetTexImage", [(GLenum, "target"), (GLint, "level"), (GLenum, "format"), (GLenum, "type"), Out(GLpointer, "pixels")]),
     GlFunction(Void, "glGetTexParameterfv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetTexParameteriv", [(GLenum, "target"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetTexLevelParameterfv", [(GLenum, "target"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLfloat, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetTexLevelParameteriv", [(GLenum, "target"), (GLint, "level"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(GLboolean, "glIsEnabled", [(GLenum, "cap")], sideeffects=False),
-    GlFunction(Void, "glDepthRange", [(GLclampd, "zNear"), (GLclampd, "zFar")]),
+    GlFunction(Void, "glDepthRange", [(GLdouble, "zNear"), (GLdouble, "zFar")]),
     GlFunction(Void, "glViewport", [(GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
 
     # GL_VERSION_1_0_DEPRECATED
@@ -314,7 +314,7 @@ glapi.addFunctions([
     GlFunction(Void, "glEvalPoint1", [(GLint, "i")]),
     GlFunction(Void, "glEvalMesh2", [(GLenum, "mode"), (GLint, "i1"), (GLint, "i2"), (GLint, "j1"), (GLint, "j2")]),
     GlFunction(Void, "glEvalPoint2", [(GLint, "i"), (GLint, "j")]),
-    GlFunction(Void, "glAlphaFunc", [(GLenum, "func"), (GLclampf, "ref")]),
+    GlFunction(Void, "glAlphaFunc", [(GLenum, "func"), (GLfloat, "ref")]),
     GlFunction(Void, "glPixelZoom", [(GLfloat, "xfactor"), (GLfloat, "yfactor")]),
     GlFunction(Void, "glPixelTransferf", [(GLenum, "pname"), (GLfloat, "param")]),
     GlFunction(Void, "glPixelTransferi", [(GLenum, "pname"), (GLint, "param")]),
@@ -376,7 +376,7 @@ glapi.addFunctions([
 
     # GL_VERSION_1_1_DEPRECATED
     GlFunction(Void, "glArrayElement", [(GLint, "i")]),
-    GlFunction(Void, "glColorPointer", [(GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+    GlFunction(Void, "glColorPointer", [(size_bgra, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
     GlFunction(Void, "glDisableClientState", [(GLenum, "array")]),
     GlFunction(Void, "glEdgeFlagPointer", [(GLsizei, "stride"), (GLpointerConst, "pointer")]),
     GlFunction(Void, "glEnableClientState", [(GLenum, "array")]),
@@ -393,7 +393,7 @@ glapi.addFunctions([
     GlFunction(Void, "glPushClientAttrib", [(GLbitfield_client_attrib, "mask")]),
 
     # GL_VERSION_1_2
-    GlFunction(Void, "glBlendColor", [(GLclampf, "red"), (GLclampf, "green"), (GLclampf, "blue"), (GLclampf, "alpha")]),
+    GlFunction(Void, "glBlendColor", [(GLfloat, "red"), (GLfloat, "green"), (GLfloat, "blue"), (GLfloat, "alpha")]),
     GlFunction(Void, "glBlendEquation", [(GLenum, "mode")]),
     GlFunction(Void, "glDrawRangeElements", [(GLenum_mode, "mode"), (GLuint, "start"), (GLuint, "end"), (GLsizei, "count"), (GLenum, "type"), (GLpointerConst, "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")]),
@@ -436,7 +436,7 @@ glapi.addFunctions([
 
     # GL_VERSION_1_3
     GlFunction(Void, "glActiveTexture", [(GLenum, "texture")]),
-    GlFunction(Void, "glSampleCoverage", [(GLclampf, "value"), (GLboolean, "invert")]),
+    GlFunction(Void, "glSampleCoverage", [(GLfloat, "value"), (GLboolean, "invert")]),
     GlFunction(Void, "glCompressedTexImage3D", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "data")]),
     GlFunction(Void, "glCompressedTexImage2D", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "data")]),
     GlFunction(Void, "glCompressedTexImage1D", [(GLenum, "target"), (GLint, "level"), (GLenum, "internalformat"), (GLsizei, "width"), (GLint, "border"), (GLsizei, "imageSize"), (Blob(Const(GLvoid), "imageSize"), "data")]),
@@ -486,8 +486,8 @@ glapi.addFunctions([
 
     # GL_VERSION_1_4
     GlFunction(Void, "glBlendFuncSeparate", [(GLenum, "sfactorRGB"), (GLenum, "dfactorRGB"), (GLenum, "sfactorAlpha"), (GLenum, "dfactorAlpha")]),
-    GlFunction(Void, "glMultiDrawArrays", [(GLenum_mode, "mode"), (Array(Const(GLint), "primcount"), "first"), (Array(Const(GLsizei), "primcount"), "count"), (GLsizei, "primcount")]),
-    GlFunction(Void, "glMultiDrawElements", [(GLenum_mode, "mode"), (Array(Const(GLsizei), "primcount"), "count"), (GLenum, "type"), (Array(GLpointerConst, "primcount"), "indices"), (GLsizei, "primcount")]),
+    GlFunction(Void, "glMultiDrawArrays", [(GLenum_mode, "mode"), (Array(Const(GLint), "drawcount"), "first"), (Array(Const(GLsizei), "drawcount"), "count"), (GLsizei, "drawcount")]),
+    GlFunction(Void, "glMultiDrawElements", [(GLenum_mode, "mode"), (Array(Const(GLsizei), "drawcount"), "count"), (GLenum, "type"), (Array(Const(GLpointerConst), "drawcount"), "indices"), (GLsizei, "drawcount")]),
     GlFunction(Void, "glPointParameterf", [(GLenum, "pname"), (GLfloat, "param")]),
     GlFunction(Void, "glPointParameterfv", [(GLenum, "pname"), (Array(Const(GLfloat), "_gl_param_size(pname)"), "params")]),
     GlFunction(Void, "glPointParameteri", [(GLenum, "pname"), (GLint, "param")]),
@@ -515,7 +515,7 @@ glapi.addFunctions([
     GlFunction(Void, "glSecondaryColor3uiv", [(Array(Const(GLuint), 3), "v")]),
     GlFunction(Void, "glSecondaryColor3us", [(GLushort, "red"), (GLushort, "green"), (GLushort, "blue")]),
     GlFunction(Void, "glSecondaryColor3usv", [(Array(Const(GLushort), 3), "v")]),
-    GlFunction(Void, "glSecondaryColorPointer", [(GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+    GlFunction(Void, "glSecondaryColorPointer", [(size_bgra, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
     GlFunction(Void, "glWindowPos2d", [(GLdouble, "x"), (GLdouble, "y")]),
     GlFunction(Void, "glWindowPos2dv", [(Array(Const(GLdouble), 2), "v")]),
     GlFunction(Void, "glWindowPos2f", [(GLfloat, "x"), (GLfloat, "y")]),
@@ -561,7 +561,7 @@ glapi.addFunctions([
     GlFunction(Void, "glStencilFuncSeparate", [(GLenum, "face"), (GLenum, "func"), (GLint, "ref"), (GLuint, "mask")]),
     GlFunction(Void, "glStencilMaskSeparate", [(GLenum, "face"), (GLuint, "mask")]),
     GlFunction(Void, "glAttachShader", [(GLprogram, "program"), (GLshader, "shader")]),
-    GlFunction(Void, "glBindAttribLocation", [(GLprogram, "program"), (GLuint, "index"), (Const(GLstring), "name")]),
+    GlFunction(Void, "glBindAttribLocation", [(GLprogram, "program"), (GLuint, "index"), (GLstringConst, "name")]),
     GlFunction(Void, "glCompileShader", [(GLshader, "shader")]),
     GlFunction(GLprogram, "glCreateProgram", []),
     GlFunction(GLshader, "glCreateShader", [(GLenum, "type")]),
@@ -573,13 +573,13 @@ glapi.addFunctions([
     GlFunction(Void, "glGetActiveAttrib", [(GLprogram, "program"), (GLuint, "index"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLint), "size"), Out(Pointer(GLenum), "type"), Out(GLstring, "name")], sideeffects=False),
     GlFunction(Void, "glGetActiveUniform", [(GLprogram, "program"), (GLuint, "index"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLint), "size"), Out(Pointer(GLenum), "type"), Out(GLstring, "name")], sideeffects=False),
     GlFunction(Void, "glGetAttachedShaders", [(GLprogram, "program"), (GLsizei, "maxCount"), Out(Pointer(GLsizei), "count"), Out(Array(GLuint, "(count ? *count : maxCount)"), "obj")], sideeffects=False),
-    GlFunction(GLint, "glGetAttribLocation", [(GLprogram, "program"), (Const(GLstring), "name")]),
+    GlFunction(GLint, "glGetAttribLocation", [(GLprogram, "program"), (GLstringConst, "name")]),
     GlFunction(Void, "glGetProgramiv", [(GLprogram, "program"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetProgramInfoLog", [(GLprogram, "program"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(GLstring, "infoLog")], sideeffects=False),
     GlFunction(Void, "glGetShaderiv", [(GLshader, "shader"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetShaderInfoLog", [(GLshader, "shader"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(GLstring, "infoLog")], sideeffects=False),
-    GlFunction(Void, "glGetShaderSource", [(GLshader, "shader"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(String("GLchar *", "*length"), "source")], sideeffects=False),
-    GlFunction(GLlocation, "glGetUniformLocation", [(GLprogram, "program"), (Const(GLstring), "name")]),
+    GlFunction(Void, "glGetShaderSource", [(GLshader, "shader"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(String(GLchar, "*length"), "source")], sideeffects=False),
+    GlFunction(GLlocation, "glGetUniformLocation", [(GLprogram, "program"), (GLstringConst, "name")]),
     GlFunction(Void, "glGetUniformfv", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaquePointer(GLfloat), "params")], sideeffects=False),
     GlFunction(Void, "glGetUniformiv", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaquePointer(GLint), "params")], sideeffects=False),
     GlFunction(Void, "glGetVertexAttribdv", [(GLuint, "index"), (GLenum, "pname"), Out(Array(GLdouble, "_gl_param_size(pname)"), "params")], sideeffects=False),
@@ -589,7 +589,7 @@ glapi.addFunctions([
     GlFunction(GLboolean, "glIsProgram", [(GLprogram, "program")], sideeffects=False),
     GlFunction(GLboolean, "glIsShader", [(GLshader, "shader")], sideeffects=False),
     GlFunction(Void, "glLinkProgram", [(GLprogram, "program")]),
-    GlFunction(Void, "glShaderSource", [(GLshader, "shader"), (GLsizei, "count"), (Const(Array(Const(GLstringARB), "count")), "string"), (Array(Const(GLint), "count"), "length")]),
+    GlFunction(Void, "glShaderSource", [(GLshader, "shader"), (GLsizei, "count"), (Array(Const(GLstringConstARB), "count"), "string"), (Array(Const(GLint), "count"), "length")]),
     GlFunction(Void, "glUseProgram", [(GLprogram, "program")]),
     GlFunction(Void, "glUniform1f", [(GLlocation, "location"), (GLfloat, "v0")]),
     GlFunction(Void, "glUniform2f", [(GLlocation, "location"), (GLfloat, "v0"), (GLfloat, "v1")]),
@@ -647,7 +647,7 @@ glapi.addFunctions([
     GlFunction(Void, "glVertexAttrib4ubv", [(GLuint, "index"), (Array(Const(GLubyte), 4), "v")]),
     GlFunction(Void, "glVertexAttrib4uiv", [(GLuint, "index"), (Array(Const(GLuint), 4), "v")]),
     GlFunction(Void, "glVertexAttrib4usv", [(GLuint, "index"), (Array(Const(GLushort), 4), "v")]),
-    GlFunction(Void, "glVertexAttribPointer", [(GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+    GlFunction(Void, "glVertexAttribPointer", [(GLuint, "index"), (size_bgra, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
 
     # GL_VERSION_2_1
     GlFunction(Void, "glUniformMatrix2x3fv", [(GLlocation, "location"), (GLsizei, "count"), (GLboolean, "transpose"), (Array(Const(GLfloat), "count*2*3"), "value")]),
@@ -668,7 +668,7 @@ glapi.addFunctions([
     GlFunction(Void, "glEndTransformFeedback", []),
     GlFunction(Void, "glBindBufferRange", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
     GlFunction(Void, "glBindBufferBase", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer")]),
-    GlFunction(Void, "glTransformFeedbackVaryings", [(GLprogram, "program"), (GLsizei, "count"), (Const(Array(Const(GLstring), "count")), "varyings"), (GLenum, "bufferMode")]),
+    GlFunction(Void, "glTransformFeedbackVaryings", [(GLprogram, "program"), (GLsizei, "count"), (Array(Const(GLstringConst), "count"), "varyings"), (GLenum, "bufferMode")]),
     GlFunction(Void, "glGetTransformFeedbackVarying", [(GLprogram, "program"), (GLuint, "index"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLsizei), "size"), Out(Pointer(GLenum), "type"), Out(GLstring, "name")], sideeffects=False),
     GlFunction(Void, "glClampColor", [(GLenum, "target"), (GLenum, "clamp")]),
     GlFunction(Void, "glBeginConditionalRender", [(GLuint, "id"), (GLenum, "mode")]),
@@ -697,8 +697,8 @@ glapi.addFunctions([
     GlFunction(Void, "glVertexAttribI4ubv", [(GLuint, "index"), (Array(Const(GLubyte), 4), "v")]),
     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"), (Const(GLstring), "name")]),
-    GlFunction(GLlocation, "glGetFragDataLocation", [(GLprogram, "program"), (Const(GLstring), "name")]),
+    GlFunction(Void, "glBindFragDataLocation", [(GLprogram, "program"), (GLuint, "color"), (GLstringConst, "name")]),
+    GlFunction(GLlocation, "glGetFragDataLocation", [(GLprogram, "program"), (GLstringConst, "name")]),
     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")]),
@@ -715,7 +715,7 @@ glapi.addFunctions([
     GlFunction(Void, "glClearBufferuiv", [(GLenum, "buffer"), (GLint, "drawbuffer"), (Array(Const(GLuint), "_glClearBuffer_size(buffer)"), "value")]),
     GlFunction(Void, "glClearBufferfv", [(GLenum, "buffer"), (GLint, "drawbuffer"), (Array(Const(GLfloat), "_glClearBuffer_size(buffer)"), "value")]),
     GlFunction(Void, "glClearBufferfi", [(GLenum, "buffer"), (GLint, "drawbuffer"), (GLfloat, "depth"), (GLint, "stencil")]),
-    GlFunction(String("const GLubyte *"), "glGetStringi", [(GLenum, "name"), (GLuint, "index")], sideeffects=False),
+    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")]),
@@ -732,7 +732,7 @@ glapi.addFunctions([
     GlFunction(Void, "glVertexAttribDivisor", [(GLuint, "index"), (GLuint, "divisor")]),
 
     # GL_VERSION_4_0
-    GlFunction(Void, "glMinSampleShading", [(GLclampf, "value")]),
+    GlFunction(Void, "glMinSampleShading", [(GLfloat, "value")]),
     GlFunction(Void, "glBlendEquationi", [(GLuint, "buf"), (GLenum, "mode")]),
     GlFunction(Void, "glBlendEquationSeparatei", [(GLuint, "buf"), (GLenum, "modeRGB"), (GLenum, "modeAlpha")]),
     GlFunction(Void, "glBlendFunci", [(GLuint, "buf"), (GLenum, "src"), (GLenum, "dst")]),
@@ -781,7 +781,7 @@ glapi.addFunctions([
     GlFunction(Void, "glMultTransposeMatrixdARB", [(Array(Const(GLdouble), 16), "m")]),
 
     # GL_ARB_multisample
-    GlFunction(Void, "glSampleCoverageARB", [(GLclampf, "value"), (GLboolean, "invert")]),
+    GlFunction(Void, "glSampleCoverageARB", [(GLfloat, "value"), (GLboolean, "invert")]),
 
     # 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")]),
@@ -870,10 +870,10 @@ glapi.addFunctions([
     GlFunction(Void, "glVertexAttrib4ubvARB", [(GLuint, "index"), (Array(Const(GLubyte), 4), "v")]),
     GlFunction(Void, "glVertexAttrib4uivARB", [(GLuint, "index"), (Array(Const(GLuint), 4), "v")]),
     GlFunction(Void, "glVertexAttrib4usvARB", [(GLuint, "index"), (Array(Const(GLushort), 4), "v")]),
-    GlFunction(Void, "glVertexAttribPointerARB", [(GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+    GlFunction(Void, "glVertexAttribPointerARB", [(GLuint, "index"), (size_bgra, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
     GlFunction(Void, "glEnableVertexAttribArrayARB", [(GLuint, "index")]),
     GlFunction(Void, "glDisableVertexAttribArrayARB", [(GLuint, "index")]),
-    GlFunction(Void, "glProgramStringARB", [(GLenum, "target"), (GLenum, "format"), (GLsizei, "len"), (String("const void *", "len"), "string")]),
+    GlFunction(Void, "glProgramStringARB", [(GLenum, "target"), (GLenum, "format"), (GLsizei, "len"), (String(Const(Void), "len"), "string")]),
     GlFunction(Void, "glBindProgramARB", [(GLenum, "target"), (GLprogramARB, "program")]),
     GlFunction(Void, "glDeleteProgramsARB", [(GLsizei, "n"), (Array(Const(GLprogramARB), "n"), "programs")]),
     GlFunction(Void, "glGenProgramsARB", [(GLsizei, "n"), Out(Array(GLprogramARB, "n"), "programs")]),
@@ -925,7 +925,7 @@ glapi.addFunctions([
     GlFunction(GLhandleARB, "glGetHandleARB", [(GLenum, "pname")], sideeffects=False),
     GlFunction(Void, "glDetachObjectARB", [(GLhandleARB, "containerObj"), (GLhandleARB, "attachedObj")]),
     GlFunction(GLhandleARB, "glCreateShaderObjectARB", [(GLenum, "shaderType")]),
-    GlFunction(Void, "glShaderSourceARB", [(GLhandleARB, "shaderObj"), (GLsizei, "count"), (Const(Array(Const(GLstringARB), "count")), "string"), (Array(Const(GLint), "count"), "length")]),
+    GlFunction(Void, "glShaderSourceARB", [(GLhandleARB, "shaderObj"), (GLsizei, "count"), (Const(Array(GLstringConstARB, "count")), "string"), (Array(Const(GLint), "count"), "length")]),
     GlFunction(Void, "glCompileShaderARB", [(GLhandleARB, "shaderObj")]),
     GlFunction(GLhandleARB, "glCreateProgramObjectARB", []),
     GlFunction(Void, "glAttachObjectARB", [(GLhandleARB, "containerObj"), (GLhandleARB, "obj")]),
@@ -955,16 +955,16 @@ glapi.addFunctions([
     GlFunction(Void, "glGetObjectParameterivARB", [(GLhandleARB, "obj"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetInfoLogARB", [(GLhandleARB, "obj"), (GLsizei, "maxLength"), Out(Pointer(GLsizei), "length"), Out(GLstringARB, "infoLog")], sideeffects=False),
     GlFunction(Void, "glGetAttachedObjectsARB", [(GLhandleARB, "containerObj"), (GLsizei, "maxCount"), Out(Pointer(GLsizei), "count"), Out(Array(GLhandleARB, "(count ? *count : maxCount)"), "obj")], sideeffects=False),
-    GlFunction(GLlocationARB, "glGetUniformLocationARB", [(GLhandleARB, "programObj"), (Const(GLstringARB), "name")]),
+    GlFunction(GLlocationARB, "glGetUniformLocationARB", [(GLhandleARB, "programObj"), (GLstringConstARB, "name")]),
     GlFunction(Void, "glGetActiveUniformARB", [(GLhandleARB, "programObj"), (GLuint, "index"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLint), "size"), Out(Pointer(GLenum), "type"), Out(GLstringARB, "name")], sideeffects=False),
     GlFunction(Void, "glGetUniformfvARB", [(GLhandleARB, "programObj"), (GLlocationARB, "location"), Out(OpaquePointer(GLfloat), "params")], sideeffects=False),
     GlFunction(Void, "glGetUniformivARB", [(GLhandleARB, "programObj"), (GLlocationARB, "location"), Out(OpaquePointer(GLint), "params")], sideeffects=False),
     GlFunction(Void, "glGetShaderSourceARB", [(GLhandleARB, "obj"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(GLstringARB, "source")], sideeffects=False),
 
     # GL_ARB_vertex_shader
-    GlFunction(Void, "glBindAttribLocationARB", [(GLhandleARB, "programObj"), (GLuint, "index"), (Const(GLstringARB), "name")]),
+    GlFunction(Void, "glBindAttribLocationARB", [(GLhandleARB, "programObj"), (GLuint, "index"), (GLstringConstARB, "name")]),
     GlFunction(Void, "glGetActiveAttribARB", [(GLhandleARB, "programObj"), (GLuint, "index"), (GLsizei, "maxLength"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLint), "size"), Out(Pointer(GLenum), "type"), Out(GLstringARB, "name")], sideeffects=False),
-    GlFunction(GLint, "glGetAttribLocationARB", [(GLhandleARB, "programObj"), (Const(GLstringARB), "name")]),
+    GlFunction(GLint, "glGetAttribLocationARB", [(GLhandleARB, "programObj"), (GLstringConstARB, "name")]),
 
     # GL_ARB_draw_buffers
     GlFunction(Void, "glDrawBuffersARB", [(GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
@@ -1021,10 +1021,10 @@ glapi.addFunctions([
     GlFunction(GLboolean, "glIsVertexArray", [(GLarray, "array")], sideeffects=False),
 
     # GL_ARB_uniform_buffer_object
-    GlFunction(Void, "glGetUniformIndices", [(GLprogram, "program"), (GLsizei, "uniformCount"), (Array(Const(GLstring), "uniformCount"), "uniformNames"), Out(Array(GLuint, "uniformCount"), "uniformIndices")], sideeffects=False),
+    GlFunction(Void, "glGetUniformIndices", [(GLprogram, "program"), (GLsizei, "uniformCount"), (Array(Const(GLstringConst), "uniformCount"), "uniformNames"), Out(Array(GLuint, "uniformCount"), "uniformIndices")], sideeffects=False),
     GlFunction(Void, "glGetActiveUniformsiv", [(GLprogram, "program"), (GLsizei, "uniformCount"), (Array(Const(GLuint), "uniformCount"), "uniformIndices"), (GLenum, "pname"), Out(OpaqueArray(GLint, "_glGetActiveUniformsiv_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetActiveUniformName", [(GLprogram, "program"), (GLuint, "uniformIndex"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLchar, "bufSize"), "uniformName")], sideeffects=False),
-    GlFunction(GLuint, "glGetUniformBlockIndex", [(GLprogram, "program"), (Const(GLstring), "uniformBlockName")]),
+    GlFunction(GLuint, "glGetUniformBlockIndex", [(GLprogram, "program"), (GLstringConst, "uniformBlockName")]),
     GlFunction(Void, "glGetActiveUniformBlockiv", [(GLprogram, "program"), (GLuint, "uniformBlockIndex"), (GLenum, "pname"), Out(OpaqueArray(GLint, "_glGetActiveUniformBlockiv_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetActiveUniformBlockName", [(GLprogram, "program"), (GLuint, "uniformBlockIndex"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLchar, "bufSize"), "uniformBlockName")], sideeffects=False),
     GlFunction(Void, "glUniformBlockBinding", [(GLprogram, "program"), (GLuint, "uniformBlockIndex"), (GLuint, "uniformBlockBinding")]),
@@ -1036,7 +1036,7 @@ glapi.addFunctions([
     GlFunction(Void, "glDrawElementsBaseVertex", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLpointerConst, "indices"), (GLint, "basevertex")]),
     GlFunction(Void, "glDrawRangeElementsBaseVertex", [(GLenum_mode, "mode"), (GLuint, "start"), (GLuint, "end"), (GLsizei, "count"), (GLenum, "type"), (GLpointerConst, "indices"), (GLint, "basevertex")]),
     GlFunction(Void, "glDrawElementsInstancedBaseVertex", [(GLenum_mode, "mode"), (GLsizei, "count"), (GLenum, "type"), (GLpointerConst, "indices"), (GLsizei, "primcount"), (GLint, "basevertex")]),
-    GlFunction(Void, "glMultiDrawElementsBaseVertex", [(GLenum_mode, "mode"), (Array(Const(GLsizei), "primcount"), "count"), (GLenum, "type"), (Array(GLpointerConst, "primcount"), "indices"), (GLsizei, "primcount"), (Array(Const(GLint), "primcount"), "basevertex")]),
+    GlFunction(Void, "glMultiDrawElementsBaseVertex", [(GLenum_mode, "mode"), (Array(Const(GLsizei), "drawcount"), "count"), (GLenum, "type"), (Array(Const(GLpointerConst), "drawcount"), "indices"), (GLsizei, "drawcount"), (Array(Const(GLint), "drawcount"), "basevertex")]),
 
     # GL_ARB_provoking_vertex
     GlFunction(Void, "glProvokingVertex", [(GLenum, "mode")]),
@@ -1063,19 +1063,19 @@ glapi.addFunctions([
     GlFunction(Void, "glBlendFuncSeparateiARB", [(GLuint, "buf"), (GLenum, "srcRGB"), (GLenum, "dstRGB"), (GLenum, "srcAlpha"), (GLenum, "dstAlpha")]),
 
     # GL_ARB_sample_shading
-    GlFunction(Void, "glMinSampleShadingARB", [(GLclampf, "value")]),
+    GlFunction(Void, "glMinSampleShadingARB", [(GLfloat, "value")]),
 
     # GL_ARB_shading_language_include
-    GlFunction(Void, "glNamedStringARB", [(GLenum, "type"), (GLint, "namelen"), (Const(String('GLchar *', "namelen")), "name"), (GLint, "stringlen"), (Const(String('GLchar *', "stringlen")), "string")]),
-    GlFunction(Void, "glDeleteNamedStringARB", [(GLint, "namelen"), (Const(String('GLchar *', "namelen")), "name")]),
-    GlFunction(Void, "glCompileShaderIncludeARB", [(GLshader, "shader"), (GLsizei, "count"), (Array(String("const GLchar *"), "count"), "path"), (Array(Const(GLint), "count"), "length")]),
-    GlFunction(GLboolean, "glIsNamedStringARB", [(GLint, "namelen"), (Const(String('GLchar *', "namelen")), "name")], sideeffects=False),
-    GlFunction(Void, "glGetNamedStringARB", [(GLint, "namelen"), (Const(String('GLchar *', "namelen")), "name"), (GLsizei, "bufSize"), Out(Pointer(GLint), "stringlen"), Out(Array(GLchar, "bufSize"), "string")], sideeffects=False),
-    GlFunction(Void, "glGetNamedStringivARB", [(GLint, "namelen"), (Const(String('GLchar *', "namelen")), "name"), (GLenum, "pname"), Out(OpaqueArray(GLint, "_glGetNamedStringivARB_size(pname)"), "params")], sideeffects=False),
+    GlFunction(Void, "glNamedStringARB", [(GLenum, "type"), (GLint, "namelen"), (String(Const(GLchar), "namelen"), "name"), (GLint, "stringlen"), (String(Const(GLchar), "stringlen"), "string")]),
+    GlFunction(Void, "glDeleteNamedStringARB", [(GLint, "namelen"), (String(Const(GLchar), "namelen"), "name")]),
+    GlFunction(Void, "glCompileShaderIncludeARB", [(GLshader, "shader"), (GLsizei, "count"), (Array(String(Const(GLchar)), "count"), "path"), (Array(Const(GLint), "count"), "length")]),
+    GlFunction(GLboolean, "glIsNamedStringARB", [(GLint, "namelen"), (String(Const(GLchar), "namelen"), "name")], sideeffects=False),
+    GlFunction(Void, "glGetNamedStringARB", [(GLint, "namelen"), (String(Const(GLchar), "namelen"), "name"), (GLsizei, "bufSize"), Out(Pointer(GLint), "stringlen"), Out(Array(GLchar, "bufSize"), "string")], sideeffects=False),
+    GlFunction(Void, "glGetNamedStringivARB", [(GLint, "namelen"), (String(Const(GLchar), "namelen"), "name"), (GLenum, "pname"), Out(OpaqueArray(GLint, "_glGetNamedStringivARB_size(pname)"), "params")], sideeffects=False),
 
     # GL_ARB_blend_func_extended
-    GlFunction(Void, "glBindFragDataLocationIndexed", [(GLprogram, "program"), (GLuint, "colorNumber"), (GLuint, "index"), (Const(GLstring), "name")]),
-    GlFunction(GLint, "glGetFragDataIndex", [(GLprogram, "program"), (Const(GLstring), "name")], sideeffects=False),
+    GlFunction(Void, "glBindFragDataLocationIndexed", [(GLprogram, "program"), (GLuint, "colorNumber"), (GLuint, "index"), (GLstringConst, "name")]),
+    GlFunction(GLint, "glGetFragDataIndex", [(GLprogram, "program"), (GLstringConst, "name")], sideeffects=False),
 
     # GL_ARB_sampler_objects
     GlFunction(Void, "glGenSamplers", [(GLsizei, "count"), Out(Array(GLsampler, "count"), "samplers")]),
@@ -1163,8 +1163,8 @@ glapi.addFunctions([
     GlFunction(Void, "glGetUniformdv", [(GLprogram, "program"), (GLlocation, "location"), Out(OpaqueArray(GLdouble, "_glGetUniformdv_size(location)"), "params")], sideeffects=False),
 
     # GL_ARB_shader_subroutine
-    GlFunction(GLlocation, "glGetSubroutineUniformLocation", [(GLprogram, "program"), (GLenum, "shadertype"), (Const(GLstring), "name")]),
-    GlFunction(GLuint, "glGetSubroutineIndex", [(GLprogram, "program"), (GLenum, "shadertype"), (Const(GLstring), "name")]),
+    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"), Out(Array(GLchar, "bufsize"), "name")], sideeffects=False),
     GlFunction(Void, "glGetActiveSubroutineName", [(GLprogram, "program"), (GLenum, "shadertype"), (GLuint, "index"), (GLsizei, "bufsize"), Out(Pointer(GLsizei), "length"), Out(Array(GLchar, "bufsize"), "name")], sideeffects=False),
@@ -1195,8 +1195,8 @@ glapi.addFunctions([
     GlFunction(Void, "glReleaseShaderCompiler", []),
     GlFunction(Void, "glShaderBinary", [(GLsizei, "count"), (Array(Const(GLuint), "count"), "shaders"), (GLenum, "binaryformat"), (Blob(Const(GLvoid), "length"), "binary"), (GLsizei, "length")]),
     GlFunction(Void, "glGetShaderPrecisionFormat", [(GLenum, "shadertype"), (GLenum, "precisiontype"), Out(Array(GLint, 2), "range"), Out(Array(GLint, 2), "precision")], sideeffects=False),
-    GlFunction(Void, "glDepthRangef", [(GLclampf, "n"), (GLclampf, "f")]),
-    GlFunction(Void, "glClearDepthf", [(GLclampf, "d")]),
+    GlFunction(Void, "glDepthRangef", [(GLfloat, "n"), (GLfloat, "f")]),
+    GlFunction(Void, "glClearDepthf", [(GLfloat, "d")]),
 
     # 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),
@@ -1206,7 +1206,7 @@ glapi.addFunctions([
     # GL_ARB_separate_shader_objects
     GlFunction(Void, "glUseProgramStages", [(GLpipeline, "pipeline"), (GLbitfield_shader, "stages"), (GLprogram, "program")]),
     GlFunction(Void, "glActiveShaderProgram", [(GLpipeline, "pipeline"), (GLprogram, "program")]),
-    GlFunction(GLprogram, "glCreateShaderProgramv", [(GLenum, "type"), (GLsizei, "count"), (Const(Array(Const(GLstring), "count")), "strings")]),
+    GlFunction(GLprogram, "glCreateShaderProgramv", [(GLenum, "type"), (GLsizei, "count"), (Array(Const(GLstringConst), "count"), "strings")]),
     GlFunction(Void, "glBindProgramPipeline", [(GLpipeline, "pipeline")]),
     GlFunction(Void, "glDeleteProgramPipelines", [(GLsizei, "n"), (Array(Const(GLuint), "n"), "pipelines")]),
     GlFunction(Void, "glGenProgramPipelines", [(GLsizei, "n"), Out(Array(GLpipeline, "n"), "pipelines")]),
@@ -1284,14 +1284,14 @@ glapi.addFunctions([
     GlFunction(Void, "glScissorArrayv", [(GLuint, "first"), (GLsizei, "count"), (Array(Const(GLint), "count*4"), "v")]),
     GlFunction(Void, "glScissorIndexed", [(GLuint, "index"), (GLint, "left"), (GLint, "bottom"), (GLsizei, "width"), (GLsizei, "height")]),
     GlFunction(Void, "glScissorIndexedv", [(GLuint, "index"), (Array(Const(GLint), 4), "v")]),
-    GlFunction(Void, "glDepthRangeArrayv", [(GLuint, "first"), (GLsizei, "count"), (Array(Const(GLclampd), "count*2"), "v")]),
-    GlFunction(Void, "glDepthRangeIndexed", [(GLuint, "index"), (GLclampd, "n"), (GLclampd, "f")]),
+    GlFunction(Void, "glDepthRangeArrayv", [(GLuint, "first"), (GLsizei, "count"), (Array(Const(GLdouble), "count*2"), "v")]),
+    GlFunction(Void, "glDepthRangeIndexed", [(GLuint, "index"), (GLdouble, "n"), (GLdouble, "f")]),
     GlFunction(Void, "glGetFloati_v", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLfloat, "_gl_param_size(target)"), "data")], sideeffects=False),
     GlFunction(Void, "glGetDoublei_v", [(GLenum, "target"), (GLuint, "index"), Out(Array(GLdouble, "_gl_param_size(target)"), "data")], sideeffects=False),
 
     # GL_ARB_debug_output
     GlFunction(Void, "glDebugMessageControlARB", [(GLenum, "source"), (GLenum, "type"), (GLenum, "severity"), (GLsizei, "count"), (Array(Const(GLuint), "count"), "ids"), (GLboolean, "enabled")], sideeffects=False),
-    GlFunction(Void, "glDebugMessageInsertARB", [(GLenum, "source"), (GLenum, "type"), (GLuint, "id"), (GLenum, "severity"), (GLsizei, "length"), (Const(String("GLchar *", "length")), "buf")], sideeffects=False),
+    GlFunction(Void, "glDebugMessageInsertARB", [(GLenum, "source"), (GLenum, "type"), (GLuint, "id"), (GLenum, "severity"), (GLsizei, "length"), (String(Const(GLchar), "length"), "buf")], sideeffects=False),
     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(GLstring, "messageLog")], sideeffects=False),
 
@@ -1344,8 +1344,92 @@ glapi.addFunctions([
     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_KHR_debug
+    GlFunction(Void, "glDebugMessageControl", [(GLenum, "source"), (GLenum, "type"), (GLenum, "severity"), (GLsizei, "count"), (Array(Const(GLuint), "count"), "ids"), (GLboolean, "enabled")], sideeffects=False),
+    GlFunction(Void, "glDebugMessageInsert", [(GLenum, "source"), (GLenum, "type"), (GLuint, "id"), (GLenum, "severity"), (GLsizei, "length"), (OpaqueArray(Const(GLchar), "_glDebugMessageInsert_size(buf, length)"), "buf")], sideeffects=False),
+    GlFunction(Void, "glDebugMessageCallback", [(GLDEBUGPROC, "callback"), (OpaquePointer(Const(Void)), "userParam")], sideeffects=False),
+    GlFunction(GLuint, "glGetDebugMessageLog", [(GLuint, "count"), (GLsizei, "bufsize"), Out(OpaqueArray(GLenum, "_glGetDebugMessageLog_size(count)"), "sources"), Out(OpaqueArray(GLenum, "_glGetDebugMessageLog_size(count)"), "types"), Out(OpaqueArray(GLuint, "_glGetDebugMessageLog_size(count)"), "ids"), Out(OpaqueArray(GLenum, "_glGetDebugMessageLog_size(count)"), "severities"), Out(OpaqueArray(GLsizei, "_glGetDebugMessageLog_size(count)"), "lengths"), Out(OpaqueArray(GLchar, "_glGetDebugMessageLog_size(bufsize)"), "messageLog")], sideeffects=False),
+    GlFunction(Void, "glPushDebugGroup", [(GLenum, "source"), (GLuint, "id"), (GLsizei, "length"), (OpaqueArray(Const(GLchar), "_glPushDebugGroup_size(message, length)"), "message")], sideeffects=False),
+    GlFunction(Void, "glPopDebugGroup", [], sideeffects=False),
+    GlFunction(Void, "glObjectLabel", [(GLenum, "identifier"), (GLuint, "name"), (GLsizei, "length"), (OpaqueArray(Const(GLchar), "_glObjectLabel_size(label, length)"), "label")], sideeffects=False),
+    GlFunction(Void, "glGetObjectLabel", [(GLenum, "identifier"), (GLuint, "name"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLchar, "bufSize"), "label")], sideeffects=False),
+    GlFunction(Void, "glObjectPtrLabel", [(OpaquePointer(Const(Void)), "ptr"), (GLsizei, "length"), (OpaqueArray(Const(GLchar), "_glObjectPtrLabel_size(label, length)"), "label")], sideeffects=False),
+    GlFunction(Void, "glGetObjectPtrLabel", [(OpaquePointer(Const(Void)), "ptr"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLchar, "bufSize"), "label")], sideeffects=False),
+
+    # GL_ARB_clear_buffer_object
+    GlFunction(Void, "glClearBufferData", [(GLenum, "target"), (GLenum, "internalformat"), (GLenum, "format"), (GLenum, "type"), (OpaqueArray(Const(Void), "_glClearBufferData_size(format, type)"), "data")]),
+    GlFunction(Void, "glClearBufferSubData", [(GLenum, "target"), (GLenum, "internalformat"), (GLintptr, "offset"), (GLsizeiptr, "size"), (GLenum, "format"), (GLenum, "type"), (OpaqueArray(Const(Void), "_glClearBufferSubData_size(format, type)"), "data")]),
+    GlFunction(Void, "glClearNamedBufferDataEXT", [(GLbuffer, "buffer"), (GLenum, "internalformat"), (GLenum, "format"), (GLenum, "type"), (OpaqueArray(Const(Void), "_glClearNamedBufferDataEXT_size(format, type)"), "data")]),
+    GlFunction(Void, "glClearNamedBufferSubDataEXT", [(GLbuffer, "buffer"), (GLenum, "internalformat"), (GLenum, "format"), (GLenum, "type"), (GLsizeiptr, "offset"), (GLsizeiptr, "size"), (OpaqueArray(Const(Void), "_glClearNamedBufferSubDataEXT_size(format, type)"), "data")]),
+
+    # GL_ARB_compute_shader
+    GlFunction(Void, "glDispatchCompute", [(GLuint, "num_groups_x"), (GLuint, "num_groups_y"), (GLuint, "num_groups_z")]),
+    GlFunction(Void, "glDispatchComputeIndirect", [(GLintptr, "indirect")]),
+
+    # GL_ARB_copy_image
+    GlFunction(Void, "glCopyImageSubData", [(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")]),
+
+    # 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", [(GLuint, "framebuffer"), (GLenum, "pname"), (GLint, "param")]),
+    GlFunction(Void, "glGetNamedFramebufferParameterivEXT", [(GLuint, "framebuffer"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+
+    # GL_ARB_internalformat_query2
+    GlFunction(Void, "glGetInternalformati64v", [(GLenum, "target"), (GLenum, "internalformat"), (GLenum, "pname"), (GLsizei, "bufSize"), Out(Array(GLint64, "bufSize"), "params")], sideeffects=False),
+
+    # GL_ARB_invalidate_subdata
+    GlFunction(Void, "glInvalidateTexSubImage", [(GLtexture, "texture"), (GLint, "level"), (GLint, "xoffset"), (GLint, "yoffset"), (GLint, "zoffset"), (GLsizei, "width"), (GLsizei, "height"), (GLsizei, "depth")]),
+    GlFunction(Void, "glInvalidateTexImage", [(GLtexture, "texture"), (GLint, "level")]),
+    GlFunction(Void, "glInvalidateBufferSubData", [(GLuint, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "length")]),
+    GlFunction(Void, "glInvalidateBufferData", [(GLbuffer, "buffer")]),
+    GlFunction(Void, "glInvalidateFramebuffer", [(GLenum, "target"), (GLsizei, "numAttachments"), (Array(Const(GLenum), "numAttachments"), "attachments")]),
+    GlFunction(Void, "glInvalidateSubFramebuffer", [(GLenum, "target"), (GLsizei, "numAttachments"), (Array(Const(GLenum), "numAttachments"), "attachments"), (GLint, "x"), (GLint, "y"), (GLsizei, "width"), (GLsizei, "height")]),
+
+    # GL_ARB_multi_draw_indirect
+    GlFunction(Void, "glMultiDrawArraysIndirect", [(GLenum, "mode"), (OpaqueArray(Const(Void), "_glMultiDrawArraysIndirect_size(drawcount, stride)"), "indirect"), (GLsizei, "drawcount"), (GLsizei, "stride")]),
+    GlFunction(Void, "glMultiDrawElementsIndirect", [(GLenum, "mode"), (GLenum, "type"), (OpaqueArray(Const(Void), "_glMultiDrawElementsIndirect_size(drawcount, stride)"), "indirect"), (GLsizei, "drawcount"), (GLsizei, "stride")]),
+
+    # 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(Void, "glGetProgramResourceName", [(GLprogram, "program"), (GLenum, "programInterface"), (GLuint, "index"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Array(GLchar, "bufSize"), "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),
+
+    # GL_ARB_shader_storage_buffer_object
+    GlFunction(Void, "glShaderStorageBlockBinding", [(GLprogram, "program"), (GLuint, "storageBlockIndex"), (GLuint, "storageBlockBinding")]),
+
+    # GL_ARB_texture_buffer_range
+    GlFunction(Void, "glTexBufferRange", [(GLenum, "target"), (GLenum, "internalformat"), (GLuint, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
+    GlFunction(Void, "glTextureBufferRangeEXT", [(GLtexture, "texture"), (GLenum, "target"), (GLenum, "internalformat"), (GLuint, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
+
+    # 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")]),
+
+    # GL_ARB_vertex_attrib_binding
+    GlFunction(Void, "glBindVertexBuffer", [(GLuint, "bindingindex"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizei, "stride")]),
+    GlFunction(Void, "glVertexAttribFormat", [(GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLboolean, "normalized"), (GLuint, "relativeoffset")]),
+    GlFunction(Void, "glVertexAttribIFormat", [(GLuint, "attribindex"), (GLint, "size"), (GLenum, "type"), (GLuint, "relativeoffset")]),
+    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_EXT_blend_color
-    GlFunction(Void, "glBlendColorEXT", [(GLclampf, "red"), (GLclampf, "green"), (GLclampf, "blue"), (GLclampf, "alpha")]),
+    GlFunction(Void, "glBlendColorEXT", [(GLfloat, "red"), (GLfloat, "green"), (GLfloat, "blue"), (GLfloat, "alpha")]),
 
     # GL_EXT_polygon_offset
     GlFunction(Void, "glPolygonOffsetEXT", [(GLfloat, "factor"), (GLfloat, "bias")]),
@@ -1442,7 +1526,7 @@ glapi.addFunctions([
 
     # GL_EXT_vertex_array
     GlFunction(Void, "glArrayElementEXT", [(GLint, "i")]),
-    GlFunction(Void, "glColorPointerEXT", [(GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLsizei, "count"), (GLpointerConst, "pointer")]),
+    GlFunction(Void, "glColorPointerEXT", [(size_bgra, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLsizei, "count"), (GLpointerConst, "pointer")]),
     GlFunction(Void, "glDrawArraysEXT", [(GLenum_mode, "mode"), (GLint, "first"), (GLsizei, "count")]),
     GlFunction(Void, "glEdgeFlagPointerEXT", [(GLsizei, "stride"), (GLsizei, "count"), (OpaquePointer(Const(GLboolean)), "pointer")]),
     GlFunction(Void, "glGetPointervEXT", [(GLenum, "pname"), Out(Pointer(GLpointer), "params")], sideeffects=False),
@@ -1580,7 +1664,7 @@ glapi.addFunctions([
     # GL_INTEL_parallel_arrays
     GlFunction(Void, "glVertexPointervINTEL", [(GLint, "size"), (GLenum, "type"), (OpaqueArray(GLpointerConst, "size"), "pointer")]),
     GlFunction(Void, "glNormalPointervINTEL", [(GLenum, "type"), (OpaqueArray(GLpointerConst, "size"), "pointer")]),
-    GlFunction(Void, "glColorPointervINTEL", [(GLint, "size"), (GLenum, "type"), (OpaqueArray(GLpointerConst, "size"), "pointer")]),
+    GlFunction(Void, "glColorPointervINTEL", [(size_bgra, "size"), (GLenum, "type"), (OpaqueArray(GLpointerConst, "size"), "pointer")]),
     GlFunction(Void, "glTexCoordPointervINTEL", [(GLint, "size"), (GLenum, "type"), (OpaqueArray(GLpointerConst, "size"), "pointer")]),
 
     # GL_EXT_pixel_transform
@@ -1606,7 +1690,7 @@ glapi.addFunctions([
     GlFunction(Void, "glSecondaryColor3uivEXT", [(Array(Const(GLuint), 3), "v")]),
     GlFunction(Void, "glSecondaryColor3usEXT", [(GLushort, "red"), (GLushort, "green"), (GLushort, "blue")]),
     GlFunction(Void, "glSecondaryColor3usvEXT", [(Array(Const(GLushort), 3), "v")]),
-    GlFunction(Void, "glSecondaryColorPointerEXT", [(GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+    GlFunction(Void, "glSecondaryColorPointerEXT", [(size_bgra, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
 
     # GL_EXT_texture_perturb_normal
     GlFunction(Void, "glTextureNormalEXT", [(GLenum, "mode")]),
@@ -1774,8 +1858,8 @@ glapi.addFunctions([
     GlFunction(Void, "glMultiModeDrawElementsIBM", [(Array(Const(GLenum), "primcount"), "mode"), (Array(Const(GLsizei), "primcount"), "count"), (GLenum, "type"), (Array(Const(GLpointerConst), "primcount"), "indices"), (GLsizei, "primcount"), (GLint, "modestride")]),
 
     # GL_IBM_vertex_array_lists
-    GlFunction(Void, "glColorPointerListIBM", [(GLint, "size"), (GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
-    GlFunction(Void, "glSecondaryColorPointerListIBM", [(GLint, "size"), (GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
+    GlFunction(Void, "glColorPointerListIBM", [(size_bgra, "size"), (GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
+    GlFunction(Void, "glSecondaryColorPointerListIBM", [(size_bgra, "size"), (GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
     GlFunction(Void, "glEdgeFlagPointerListIBM", [(GLint, "stride"), (OpaquePointer(Opaque("const GLboolean *")), "pointer"), (GLint, "ptrstride")]),
     GlFunction(Void, "glFogCoordPointerListIBM", [(GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
     GlFunction(Void, "glIndexPointerListIBM", [(GLenum, "type"), (GLint, "stride"), (OpaquePointer(GLpointerConst), "pointer"), (GLint, "ptrstride")]),
@@ -1797,13 +1881,13 @@ glapi.addFunctions([
     GlFunction(Void, "glIglooInterfaceSGIX", [(GLenum, "pname"), (OpaqueBlob(Const(GLvoid), "_glIglooInterfaceSGIX_size(pname)"), "params")]),
 
     # GL_NV_fence
-    GlFunction(Void, "glDeleteFencesNV", [(GLsizei, "n"), (Array(Const(GLuint), "n"), "fences")]),
-    GlFunction(Void, "glGenFencesNV", [(GLsizei, "n"), Out(Array(GLuint, "n"), "fences")]),
-    GlFunction(GLboolean, "glIsFenceNV", [(GLuint, "fence")], sideeffects=False),
-    GlFunction(GLboolean, "glTestFenceNV", [(GLuint, "fence")]),
-    GlFunction(Void, "glGetFenceivNV", [(GLuint, "fence"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
-    GlFunction(Void, "glFinishFenceNV", [(GLuint, "fence")]),
-    GlFunction(Void, "glSetFenceNV", [(GLuint, "fence"), (GLenum, "condition")]),
+    GlFunction(Void, "glDeleteFencesNV", [(GLsizei, "n"), (Array(Const(GLfence), "n"), "fences")]),
+    GlFunction(Void, "glGenFencesNV", [(GLsizei, "n"), Out(Array(GLfence, "n"), "fences")]),
+    GlFunction(GLboolean, "glIsFenceNV", [(GLfence, "fence")], sideeffects=False),
+    GlFunction(GLboolean, "glTestFenceNV", [(GLfence, "fence")]),
+    GlFunction(Void, "glGetFenceivNV", [(GLfence, "fence"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
+    GlFunction(Void, "glFinishFenceNV", [(GLfence, "fence")]),
+    GlFunction(Void, "glSetFenceNV", [(GLfence, "fence"), (GLenum, "condition")]),
 
     # GL_NV_evaluators
     GlFunction(Void, "glMapControlPointsNV", [(GLenum, "target"), (GLuint, "index"), (GLenum, "type"), (GLsizei, "ustride"), (GLsizei, "vstride"), (GLint, "uorder"), (GLint, "vorder"), (GLboolean, "packed"), (OpaqueBlob(Const(GLvoid), "_glMapControlPointsNV_size(target, uorder, vorder)"), "points")]),
@@ -1836,7 +1920,7 @@ glapi.addFunctions([
     GlFunction(Void, "glGetVertexAttribivNV", [(GLuint, "index"), (GLenum, "pname"), Out(Array(GLint, "_gl_param_size(pname)"), "params")], sideeffects=False),
     GlFunction(Void, "glGetVertexAttribPointervNV", [(GLuint, "index"), (GLenum, "pname"), Out(Pointer(GLpointer), "pointer")], sideeffects=False),
     GlFunction(GLboolean, "glIsProgramNV", [(GLprogramARB, "program")], sideeffects=False),
-    GlFunction(Void, "glLoadProgramNV", [(GLenum, "target"), (GLprogramARB, "id"), (GLsizei, "len"), (String("const GLubyte *", "len"), "program")]),
+    GlFunction(Void, "glLoadProgramNV", [(GLenum, "target"), (GLprogramARB, "id"), (GLsizei, "len"), (String(Const(GLubyte), "len"), "program")]),
     GlFunction(Void, "glProgramParameter4dNV", [(GLenum, "target"), (GLuint, "index"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z"), (GLdouble, "w")]),
     GlFunction(Void, "glProgramParameter4dvNV", [(GLenum, "target"), (GLuint, "index"), (Array(Const(GLdouble), 4), "v")]),
     GlFunction(Void, "glProgramParameter4fNV", [(GLenum, "target"), (GLuint, "index"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z"), (GLfloat, "w")]),
@@ -1845,7 +1929,7 @@ glapi.addFunctions([
     GlFunction(Void, "glProgramParameters4fvNV", [(GLenum, "target"), (GLuint, "index"), (GLsizei, "count"), (Array(Const(GLfloat), "count*4"), "v")]),
     GlFunction(Void, "glRequestResidentProgramsNV", [(GLsizei, "n"), (Array(Const(GLprogramARB), "n"), "programs")]),
     GlFunction(Void, "glTrackMatrixNV", [(GLenum, "target"), (GLuint, "address"), (GLenum, "matrix"), (GLenum, "transform")]),
-    GlFunction(Void, "glVertexAttribPointerNV", [(GLuint, "index"), (GLint, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
+    GlFunction(Void, "glVertexAttribPointerNV", [(GLuint, "index"), (size_bgra, "size"), (GLenum, "type"), (GLsizei, "stride"), (GLpointerConst, "pointer")]),
     GlFunction(Void, "glVertexAttrib1dNV", [(GLuint, "index"), (GLdouble, "x")]),
     GlFunction(Void, "glVertexAttrib1dvNV", [(GLuint, "index"), (Pointer(Const(GLdouble)), "v")]),
     GlFunction(Void, "glVertexAttrib1fNV", [(GLuint, "index"), (GLfloat, "x")]),
@@ -2049,20 +2133,20 @@ glapi.addFunctions([
     GlFunction(Void, "glMultiDrawRangeElementArrayAPPLE", [(GLenum_mode, "mode"), (GLuint, "start"), (GLuint, "end"), (Array(Const(GLint), "primcount"), "first"), (Array(Const(GLsizei), "primcount"), "count"), (GLsizei, "primcount")]),
 
     # GL_APPLE_fence
-    GlFunction(Void, "glGenFencesAPPLE", [(GLsizei, "n"), Out(Array(GLuint, "n"), "fences")]),
-    GlFunction(Void, "glDeleteFencesAPPLE", [(GLsizei, "n"), (Array(Const(GLuint), "n"), "fences")]),
-    GlFunction(Void, "glSetFenceAPPLE", [(GLuint, "fence")]),
-    GlFunction(GLboolean, "glIsFenceAPPLE", [(GLuint, "fence")], sideeffects=False),
-    GlFunction(GLboolean, "glTestFenceAPPLE", [(GLuint, "fence")]),
-    GlFunction(Void, "glFinishFenceAPPLE", [(GLuint, "fence")]),
-    GlFunction(GLboolean, "glTestObjectAPPLE", [(GLenum, "object"), (GLuint, "name")]),
-    GlFunction(Void, "glFinishObjectAPPLE", [(GLenum, "object"), (GLint, "name")]),
+    GlFunction(Void, "glGenFencesAPPLE", [(GLsizei, "n"), Out(Array(GLfence, "n"), "fences")]),
+    GlFunction(Void, "glDeleteFencesAPPLE", [(GLsizei, "n"), (Array(Const(GLfence), "n"), "fences")]),
+    GlFunction(Void, "glSetFenceAPPLE", [(GLfence, "fence")]),
+    GlFunction(GLboolean, "glIsFenceAPPLE", [(GLfence, "fence")], sideeffects=False),
+    GlFunction(GLboolean, "glTestFenceAPPLE", [(GLfence, "fence")]),
+    GlFunction(Void, "glFinishFenceAPPLE", [(GLfence, "fence")]),
+    GlFunction(GLboolean, "glTestObjectAPPLE", [(GLenum, "object"), (GLuint, "name")]), # XXX: name needs swizzling
+    GlFunction(Void, "glFinishObjectAPPLE", [(GLenum, "object"), (GLint, "name")]), # XXX: name needs swizzling
 
     # GL_APPLE_vertex_array_object
-    GlFunction(Void, "glBindVertexArrayAPPLE", [(GLuint, "array")]),
-    GlFunction(Void, "glDeleteVertexArraysAPPLE", [(GLsizei, "n"), (Array(Const(GLuint), "n"), "arrays")]),
-    GlFunction(Void, "glGenVertexArraysAPPLE", [(GLsizei, "n"), Out(Array(GLuint, "n"), "arrays")]),
-    GlFunction(GLboolean, "glIsVertexArrayAPPLE", [(GLuint, "array")], sideeffects=False),
+    GlFunction(Void, "glBindVertexArrayAPPLE", [(GLarrayAPPLE, "array")]),
+    GlFunction(Void, "glDeleteVertexArraysAPPLE", [(GLsizei, "n"), (Array(Const(GLarrayAPPLE), "n"), "arrays")]),
+    GlFunction(Void, "glGenVertexArraysAPPLE", [(GLsizei, "n"), Out(Array(GLarrayAPPLE, "n"), "arrays")]),
+    GlFunction(GLboolean, "glIsVertexArrayAPPLE", [(GLarrayAPPLE, "array")], sideeffects=False),
 
     # GL_APPLE_vertex_array_range
     GlFunction(Void, "glVertexArrayRangeAPPLE", [(GLsizei, "length"), (GLpointer, "pointer")]),
@@ -2078,12 +2162,12 @@ glapi.addFunctions([
     GlFunction(Void, "glDrawBuffersATI", [(GLsizei, "n"), (Array(Const(GLenum), "n"), "bufs")]),
 
     # GL_NV_fragment_program
-    GlFunction(Void, "glProgramNamedParameter4fNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String("const GLubyte *", "len"), "name"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z"), (GLfloat, "w")]),
-    GlFunction(Void, "glProgramNamedParameter4dNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String("const GLubyte *", "len"), "name"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z"), (GLdouble, "w")]),
-    GlFunction(Void, "glProgramNamedParameter4fvNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String("const GLubyte *", "len"), "name"), (Array(Const(GLfloat), 4), "v")]),
-    GlFunction(Void, "glProgramNamedParameter4dvNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String("const GLubyte *", "len"), "name"), (Array(Const(GLdouble), 4), "v")]),
-    GlFunction(Void, "glGetProgramNamedParameterdvNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String("const GLubyte *", "len"), "name"), Out(Array(GLdouble, 4), "params")], sideeffects=False),
-    GlFunction(Void, "glGetProgramNamedParameterfvNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String("const GLubyte *", "len"), "name"), Out(Array(GLfloat, 4), "params")], sideeffects=False),
+    GlFunction(Void, "glProgramNamedParameter4fNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String(Const(GLubyte), "len"), "name"), (GLfloat, "x"), (GLfloat, "y"), (GLfloat, "z"), (GLfloat, "w")]),
+    GlFunction(Void, "glProgramNamedParameter4dNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String(Const(GLubyte), "len"), "name"), (GLdouble, "x"), (GLdouble, "y"), (GLdouble, "z"), (GLdouble, "w")]),
+    GlFunction(Void, "glProgramNamedParameter4fvNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String(Const(GLubyte), "len"), "name"), (Array(Const(GLfloat), 4), "v")]),
+    GlFunction(Void, "glProgramNamedParameter4dvNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String(Const(GLubyte), "len"), "name"), (Array(Const(GLdouble), 4), "v")]),
+    GlFunction(Void, "glGetProgramNamedParameterdvNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String(Const(GLubyte), "len"), "name"), Out(Array(GLdouble, 4), "params")], sideeffects=False),
+    GlFunction(Void, "glGetProgramNamedParameterfvNV", [(GLprogramARB, "id"), (GLsizei, "len"), (String(Const(GLubyte), "len"), "name"), Out(Array(GLfloat, 4), "params")], sideeffects=False),
 
     # GL_NV_half_float
     GlFunction(Void, "glVertex2hNV", [(GLhalfNV, "x"), (GLhalfNV, "y")]),
@@ -2134,7 +2218,7 @@ glapi.addFunctions([
     GlFunction(Void, "glVertexAttribs4hvNV", [(GLuint, "index"), (GLsizei, "n"), (Array(Const(GLhalfNV), "n"), "v")]),
 
     # GL_NV_pixel_data_range
-    GlFunction(Void, "glPixelDataRangeNV", [(GLenum, "target"), (GLsizei, "length"), (OpaqueBlob(GLvoid, "length"), "pointer")]),
+    GlFunction(Void, "glPixelDataRangeNV", [(GLenum, "target"), (GLsizei, "length"), (OpaqueBlob(Const(GLvoid), "length"), "pointer")]),
     GlFunction(Void, "glFlushPixelDataRangeNV", [(GLenum, "target")]),
 
     # GL_NV_primitive_restart
@@ -2180,7 +2264,7 @@ glapi.addFunctions([
     GlFunction(Void, "glGenerateMipmapEXT", [(GLenum, "target")]),
 
     # GL_GREMEDY_string_marker
-    GlFunction(Void, "glStringMarkerGREMEDY", [(GLsizei, "len"), (Const(String("GLvoid *", "len ? len : strlen((const char *)string)")), "string")], sideeffects=False),
+    GlFunction(Void, "glStringMarkerGREMEDY", [(GLsizei, "len"), (String(Const(GLvoid), "len ? len : strlen((const char *)string)"), "string")], sideeffects=False),
 
     # GL_EXT_stencil_clear_tag
     GlFunction(Void, "glStencilClearTagEXT", [(GLsizei, "stencilTagBits"), (GLuint, "stencilClearTag")]),
@@ -2257,8 +2341,8 @@ 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"), (Const(GLstring), "name")]),
-    GlFunction(GLlocation, "glGetFragDataLocationEXT", [(GLprogram, "program"), (Const(GLstring), "name")]),
+    GlFunction(Void, "glBindFragDataLocationEXT", [(GLprogram, "program"), (GLuint, "color"), (GLstringConst, "name")]),
+    GlFunction(GLlocation, "glGetFragDataLocationEXT", [(GLprogram, "program"), (GLstringConst, "name")]),
     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")]),
@@ -2304,8 +2388,8 @@ glapi.addFunctions([
     GlFunction(Void, "glBindBufferOffsetNV", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer"), (GLintptr, "offset")]),
     GlFunction(Void, "glBindBufferBaseNV", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer")]),
     GlFunction(Void, "glTransformFeedbackVaryingsNV", [(GLprogram, "program"), (GLsizei, "count"), (Array(Const(GLint), "count"), "locations"), (GLenum, "bufferMode")]),
-    GlFunction(Void, "glActiveVaryingNV", [(GLprogram, "program"), (Const(GLstring), "name")]),
-    GlFunction(GLlocation, "glGetVaryingLocationNV", [(GLprogram, "program"), (Const(GLstring), "name")]),
+    GlFunction(Void, "glActiveVaryingNV", [(GLprogram, "program"), (GLstringConst, "name")]),
+    GlFunction(GLlocation, "glGetVaryingLocationNV", [(GLprogram, "program"), (GLstringConst, "name")]),
     GlFunction(Void, "glGetActiveVaryingNV", [(GLprogram, "program"), (GLuint, "index"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLsizei), "size"), Out(Pointer(GLenum), "type"), Out(GLstring, "name")], sideeffects=False),
     GlFunction(Void, "glGetTransformFeedbackVaryingNV", [(GLprogram, "program"), (GLuint, "index"), Out(Pointer(GLlocation), "location")], sideeffects=False),
     GlFunction(Void, "glTransformFeedbackStreamAttribsNV", [(GLsizei, "count"), (Array(Const(GLint), "count"), "attribs"), (GLsizei, "nbuffers"), (Array(Const(GLint), "nbuffers"), "bufstreams"), (GLenum, "bufferMode")]),
@@ -2344,7 +2428,7 @@ glapi.addFunctions([
     GlFunction(Void, "glBindBufferRangeEXT", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer"), (GLintptr, "offset"), (GLsizeiptr, "size")]),
     GlFunction(Void, "glBindBufferOffsetEXT", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer"), (GLintptr, "offset")]),
     GlFunction(Void, "glBindBufferBaseEXT", [(GLenum, "target"), (GLuint, "index"), (GLbuffer, "buffer")]),
-    GlFunction(Void, "glTransformFeedbackVaryingsEXT", [(GLprogram, "program"), (GLsizei, "count"), (Const(Array(Const(GLstring), "count")), "varyings"), (GLenum, "bufferMode")]),
+    GlFunction(Void, "glTransformFeedbackVaryingsEXT", [(GLprogram, "program"), (GLsizei, "count"), (Const(Array(GLstringConst, "count")), "varyings"), (GLenum, "bufferMode")]),
     GlFunction(Void, "glGetTransformFeedbackVaryingEXT", [(GLprogram, "program"), (GLuint, "index"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(Pointer(GLsizei), "size"), Out(Pointer(GLenum), "type"), Out(GLstring, "name")], sideeffects=False),
 
     # GL_EXT_direct_state_access
@@ -2445,7 +2529,7 @@ glapi.addFunctions([
     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")], sideeffects=False),
-    GlFunction(Void, "glNamedProgramStringEXT", [(GLprogram, "program"), (GLenum, "target"), (GLenum, "format"), (GLsizei, "len"), (Const(String("GLvoid *", "len")), "string")]),
+    GlFunction(Void, "glNamedProgramStringEXT", [(GLprogram, "program"), (GLenum, "target"), (GLenum, "format"), (GLsizei, "len"), (String(Const(GLvoid), "len"), "string")]),
     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")]),
@@ -2652,7 +2736,7 @@ glapi.addFunctions([
     # GL_EXT_separate_shader_objects
     GlFunction(Void, "glUseShaderProgramEXT", [(GLenum, "type"), (GLprogram, "program")]),
     GlFunction(Void, "glActiveProgramEXT", [(GLprogram, "program")]),
-    GlFunction(GLprogram, "glCreateShaderProgramEXT", [(GLenum, "type"), (Const(GLstring), "string")]),
+    GlFunction(GLprogram, "glCreateShaderProgramEXT", [(GLenum, "type"), (GLstringConst, "string")]),
 
     # GL_NV_shader_buffer_load
     GlFunction(Void, "glMakeBufferResidentNV", [(GLenum, "target"), (GLenum, "access")]),
index 2bf2853167d891dad3c8e782e13b316593fcbe0c..46c6ef02888e363f5b93aa4633e26c9ed1be9cb8 100644 (file)
@@ -207,12 +207,12 @@ glesapi.addFunctions([
     GlFunction(Void, "glReadBufferNV", [(GLenum, "mode")]),
 
     # GL_EXT_debug_label
-    GlFunction(Void, "glLabelObjectEXT", [(GLenum, "type"), (GLuint, "object"), (GLsizei, "length"), (Const(GLstring), "label")]),
+    GlFunction(Void, "glLabelObjectEXT", [(GLenum, "type"), (GLuint, "object"), (GLsizei, "length"), (GLstringConst, "label")]),
     GlFunction(Void, "glGetObjectLabelEXT", [(GLenum, "type"), (GLuint, "object"), (GLsizei, "bufSize"), Out(Pointer(GLsizei), "length"), Out(GLstring, "label")], sideeffects=False),
 
     # GL_EXT_debug_marker
-    GlFunction(Void, "glInsertEventMarkerEXT", [(GLsizei, "length"), (Const(String("GLchar *", "length ? length : strlen(marker)")), "marker")], sideeffects=False),
-    GlFunction(Void, "glPushGroupMarkerEXT", [(GLsizei, "length"), (Const(String("GLchar *", "length ? length : strlen(marker)")), "marker")], sideeffects=False),
+    GlFunction(Void, "glInsertEventMarkerEXT", [(GLsizei, "length"), (String(Const(GLchar), "length ? length : strlen(marker)"), "marker")], sideeffects=False),
+    GlFunction(Void, "glPushGroupMarkerEXT", [(GLsizei, "length"), (String(Const(GLchar), "length ? length : strlen(marker)"), "marker")], sideeffects=False),
     GlFunction(Void, "glPopGroupMarkerEXT", [], sideeffects=False),
 
     # GL_EXT_occlusion_query_boolean
@@ -227,7 +227,7 @@ glesapi.addFunctions([
     # 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(Const(GLstring), "count")), "strings")]),
+    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")]),
index e4031b072229f7846f8f36571d982d3fc5a2bd5b..3be99a89bebc9cf45513bf8817d8ede604ced25b 100644 (file)
@@ -968,22 +968,22 @@ parameters = [
     ("",       X,      1,      "GL_RG32UI"),   # 0x823C
     ("",       X,      1,      "GL_SYNC_CL_EVENT_ARB"),        # 0x8240
     ("",       X,      1,      "GL_SYNC_CL_EVENT_COMPLETE_ARB"),       # 0x8241
-    ("glGet",  B,      1,      "GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB"),     # 0x8242
-    ("glGet",  I,      1,      "GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB"),     # 0x8243
-    ("glGet",  P,      1,      "GL_DEBUG_CALLBACK_FUNCTION_ARB"),      # 0x8244
-    ("glGet",  P,      1,      "GL_DEBUG_CALLBACK_USER_PARAM_ARB"),    # 0x8245
-    ("",       X,      1,      "GL_DEBUG_SOURCE_API_ARB"),     # 0x8246
-    ("",       X,      1,      "GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB"),   # 0x8247
-    ("",       X,      1,      "GL_DEBUG_SOURCE_SHADER_COMPILER_ARB"), # 0x8248
-    ("",       X,      1,      "GL_DEBUG_SOURCE_THIRD_PARTY_ARB"),     # 0x8249
-    ("",       X,      1,      "GL_DEBUG_SOURCE_APPLICATION_ARB"),     # 0x824A
-    ("",       X,      1,      "GL_DEBUG_SOURCE_OTHER_ARB"),   # 0x824B
-    ("",       X,      1,      "GL_DEBUG_TYPE_ERROR_ARB"),     # 0x824C
-    ("",       X,      1,      "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB"),       # 0x824D
-    ("",       X,      1,      "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB"),        # 0x824E
-    ("",       X,      1,      "GL_DEBUG_TYPE_PORTABILITY_ARB"),       # 0x824F
-    ("",       X,      1,      "GL_DEBUG_TYPE_PERFORMANCE_ARB"),       # 0x8250
-    ("",       X,      1,      "GL_DEBUG_TYPE_OTHER_ARB"),     # 0x8251
+    ("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
+    ("",       X,      1,      "GL_DEBUG_SOURCE_API"), # 0x8246
+    ("",       X,      1,      "GL_DEBUG_SOURCE_WINDOW_SYSTEM"),       # 0x8247
+    ("",       X,      1,      "GL_DEBUG_SOURCE_SHADER_COMPILER"),     # 0x8248
+    ("",       X,      1,      "GL_DEBUG_SOURCE_THIRD_PARTY"), # 0x8249
+    ("",       X,      1,      "GL_DEBUG_SOURCE_APPLICATION"), # 0x824A
+    ("",       X,      1,      "GL_DEBUG_SOURCE_OTHER"),       # 0x824B
+    ("",       X,      1,      "GL_DEBUG_TYPE_ERROR"), # 0x824C
+    ("",       X,      1,      "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"),   # 0x824D
+    ("",       X,      1,      "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"),    # 0x824E
+    ("",       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
@@ -1000,6 +1000,139 @@ parameters = [
     ("glGet",  E,      1,      "GL_VIEWPORT_INDEX_PROVOKING_VERTEX"),  # 0x825F
     ("",       X,      1,      "GL_UNDEFINED_VERTEX"), # 0x8260
     ("",       X,      1,      "GL_NO_RESET_NOTIFICATION_ARB"),        # 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
+    ("glGet",  I,      1,      "GL_MAX_COMPUTE_ATOMIC_COUNTERS"),      # 0x8265
+    ("glGet",  I,      1,      "GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS"),  # 0x8266
+    ("",       X,      1,      "GL_COMPUTE_LOCAL_WORK_SIZE"),  # 0x8267
+    ("",       X,      1,      "GL_DEBUG_TYPE_MARKER"),        # 0x8268
+    ("",       X,      1,      "GL_DEBUG_TYPE_PUSH_GROUP"),    # 0x8269
+    ("",       X,      1,      "GL_DEBUG_TYPE_POP_GROUP"),     # 0x826A
+    ("",       X,      1,      "GL_DEBUG_SEVERITY_NOTIFICATION"),      # 0x826B
+    ("",       X,      1,      "GL_MAX_DEBUG_GROUP_STACK_DEPTH"),      # 0x826C
+    ("",       X,      1,      "GL_DEBUG_GROUP_STACK_DEPTH"),  # 0x826D
+    ("glGet",  I,      1,      "GL_MAX_UNIFORM_LOCATIONS"),    # 0x826E
+    ("",       X,      1,      "GL_INTERNALFORMAT_SUPPORTED"), # 0x826F
+    ("",       X,      1,      "GL_INTERNALFORMAT_PREFERRED"), # 0x8270
+    ("",       X,      1,      "GL_INTERNALFORMAT_RED_SIZE"),  # 0x8271
+    ("",       X,      1,      "GL_INTERNALFORMAT_GREEN_SIZE"),        # 0x8272
+    ("",       X,      1,      "GL_INTERNALFORMAT_BLUE_SIZE"), # 0x8273
+    ("",       X,      1,      "GL_INTERNALFORMAT_ALPHA_SIZE"),        # 0x8274
+    ("",       X,      1,      "GL_INTERNALFORMAT_DEPTH_SIZE"),        # 0x8275
+    ("",       X,      1,      "GL_INTERNALFORMAT_STENCIL_SIZE"),      # 0x8276
+    ("",       X,      1,      "GL_INTERNALFORMAT_SHARED_SIZE"),       # 0x8277
+    ("",       X,      1,      "GL_INTERNALFORMAT_RED_TYPE"),  # 0x8278
+    ("",       X,      1,      "GL_INTERNALFORMAT_GREEN_TYPE"),        # 0x8279
+    ("",       X,      1,      "GL_INTERNALFORMAT_BLUE_TYPE"), # 0x827A
+    ("",       X,      1,      "GL_INTERNALFORMAT_ALPHA_TYPE"),        # 0x827B
+    ("",       X,      1,      "GL_INTERNALFORMAT_DEPTH_TYPE"),        # 0x827C
+    ("",       X,      1,      "GL_INTERNALFORMAT_STENCIL_TYPE"),      # 0x827D
+    ("",       X,      1,      "GL_MAX_WIDTH"),        # 0x827E
+    ("",       X,      1,      "GL_MAX_HEIGHT"),       # 0x827F
+    ("",       X,      1,      "GL_MAX_DEPTH"),        # 0x8280
+    ("",       X,      1,      "GL_MAX_LAYERS"),       # 0x8281
+    ("",       X,      1,      "GL_MAX_COMBINED_DIMENSIONS"),  # 0x8282
+    ("",       X,      1,      "GL_COLOR_COMPONENTS"), # 0x8283
+    ("",       X,      1,      "GL_DEPTH_COMPONENTS"), # 0x8284
+    ("",       X,      1,      "GL_STENCIL_COMPONENTS"),       # 0x8285
+    ("",       X,      1,      "GL_COLOR_RENDERABLE"), # 0x8286
+    ("",       X,      1,      "GL_DEPTH_RENDERABLE"), # 0x8287
+    ("",       X,      1,      "GL_STENCIL_RENDERABLE"),       # 0x8288
+    ("",       X,      1,      "GL_FRAMEBUFFER_RENDERABLE"),   # 0x8289
+    ("",       X,      1,      "GL_FRAMEBUFFER_RENDERABLE_LAYERED"),   # 0x828A
+    ("",       X,      1,      "GL_FRAMEBUFFER_BLEND"),        # 0x828B
+    ("",       X,      1,      "GL_READ_PIXELS"),      # 0x828C
+    ("",       X,      1,      "GL_READ_PIXELS_FORMAT"),       # 0x828D
+    ("",       X,      1,      "GL_READ_PIXELS_TYPE"), # 0x828E
+    ("",       X,      1,      "GL_TEXTURE_IMAGE_FORMAT"),     # 0x828F
+    ("",       X,      1,      "GL_TEXTURE_IMAGE_TYPE"),       # 0x8290
+    ("",       X,      1,      "GL_GET_TEXTURE_IMAGE_FORMAT"), # 0x8291
+    ("",       X,      1,      "GL_GET_TEXTURE_IMAGE_TYPE"),   # 0x8292
+    ("",       X,      1,      "GL_MIPMAP"),   # 0x8293
+    ("",       X,      1,      "GL_MANUAL_GENERATE_MIPMAP"),   # 0x8294
+    ("",       X,      1,      "GL_AUTO_GENERATE_MIPMAP"),     # 0x8295
+    ("",       X,      1,      "GL_COLOR_ENCODING"),   # 0x8296
+    ("",       X,      1,      "GL_SRGB_READ"),        # 0x8297
+    ("",       X,      1,      "GL_SRGB_WRITE"),       # 0x8298
+    ("",       X,      1,      "GL_SRGB_DECODE_ARB"),  # 0x8299
+    ("",       X,      1,      "GL_FILTER"),   # 0x829A
+    ("",       X,      1,      "GL_VERTEX_TEXTURE"),   # 0x829B
+    ("",       X,      1,      "GL_TESS_CONTROL_TEXTURE"),     # 0x829C
+    ("",       X,      1,      "GL_TESS_EVALUATION_TEXTURE"),  # 0x829D
+    ("",       X,      1,      "GL_GEOMETRY_TEXTURE"), # 0x829E
+    ("",       X,      1,      "GL_FRAGMENT_TEXTURE"), # 0x829F
+    ("",       X,      1,      "GL_COMPUTE_TEXTURE"),  # 0x82A0
+    ("",       X,      1,      "GL_TEXTURE_SHADOW"),   # 0x82A1
+    ("",       X,      1,      "GL_TEXTURE_GATHER"),   # 0x82A2
+    ("",       X,      1,      "GL_TEXTURE_GATHER_SHADOW"),    # 0x82A3
+    ("",       X,      1,      "GL_SHADER_IMAGE_LOAD"),        # 0x82A4
+    ("",       X,      1,      "GL_SHADER_IMAGE_STORE"),       # 0x82A5
+    ("",       X,      1,      "GL_SHADER_IMAGE_ATOMIC"),      # 0x82A6
+    ("",       X,      1,      "GL_IMAGE_TEXEL_SIZE"), # 0x82A7
+    ("",       X,      1,      "GL_IMAGE_COMPATIBILITY_CLASS"),        # 0x82A8
+    ("",       X,      1,      "GL_IMAGE_PIXEL_FORMAT"),       # 0x82A9
+    ("",       X,      1,      "GL_IMAGE_PIXEL_TYPE"), # 0x82AA
+    ("",       X,      1,      "GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST"),      # 0x82AC
+    ("",       X,      1,      "GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST"),    # 0x82AD
+    ("",       X,      1,      "GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE"),     # 0x82AE
+    ("",       X,      1,      "GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE"),   # 0x82AF
+    ("",       X,      1,      "GL_TEXTURE_COMPRESSED_BLOCK_WIDTH"),   # 0x82B1
+    ("",       X,      1,      "GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT"),  # 0x82B2
+    ("",       X,      1,      "GL_TEXTURE_COMPRESSED_BLOCK_SIZE"),    # 0x82B3
+    ("",       X,      1,      "GL_CLEAR_BUFFER"),     # 0x82B4
+    ("",       X,      1,      "GL_TEXTURE_VIEW"),     # 0x82B5
+    ("",       X,      1,      "GL_VIEW_COMPATIBILITY_CLASS"), # 0x82B6
+    ("",       X,      1,      "GL_FULL_SUPPORT"),     # 0x82B7
+    ("",       X,      1,      "GL_CAVEAT_SUPPORT"),   # 0x82B8
+    ("",       X,      1,      "GL_IMAGE_CLASS_4_X_32"),       # 0x82B9
+    ("",       X,      1,      "GL_IMAGE_CLASS_2_X_32"),       # 0x82BA
+    ("",       X,      1,      "GL_IMAGE_CLASS_1_X_32"),       # 0x82BB
+    ("",       X,      1,      "GL_IMAGE_CLASS_4_X_16"),       # 0x82BC
+    ("",       X,      1,      "GL_IMAGE_CLASS_2_X_16"),       # 0x82BD
+    ("",       X,      1,      "GL_IMAGE_CLASS_1_X_16"),       # 0x82BE
+    ("",       X,      1,      "GL_IMAGE_CLASS_4_X_8"),        # 0x82BF
+    ("",       X,      1,      "GL_IMAGE_CLASS_2_X_8"),        # 0x82C0
+    ("",       X,      1,      "GL_IMAGE_CLASS_1_X_8"),        # 0x82C1
+    ("",       X,      1,      "GL_IMAGE_CLASS_11_11_10"),     # 0x82C2
+    ("",       X,      1,      "GL_IMAGE_CLASS_10_10_10_2"),   # 0x82C3
+    ("",       X,      1,      "GL_VIEW_CLASS_128_BITS"),      # 0x82C4
+    ("",       X,      1,      "GL_VIEW_CLASS_96_BITS"),       # 0x82C5
+    ("",       X,      1,      "GL_VIEW_CLASS_64_BITS"),       # 0x82C6
+    ("",       X,      1,      "GL_VIEW_CLASS_48_BITS"),       # 0x82C7
+    ("",       X,      1,      "GL_VIEW_CLASS_32_BITS"),       # 0x82C8
+    ("",       X,      1,      "GL_VIEW_CLASS_24_BITS"),       # 0x82C9
+    ("",       X,      1,      "GL_VIEW_CLASS_16_BITS"),       # 0x82CA
+    ("",       X,      1,      "GL_VIEW_CLASS_8_BITS"),        # 0x82CB
+    ("",       X,      1,      "GL_VIEW_CLASS_S3TC_DXT1_RGB"), # 0x82CC
+    ("",       X,      1,      "GL_VIEW_CLASS_S3TC_DXT1_RGBA"),        # 0x82CD
+    ("",       X,      1,      "GL_VIEW_CLASS_S3TC_DXT3_RGBA"),        # 0x82CE
+    ("",       X,      1,      "GL_VIEW_CLASS_S3TC_DXT5_RGBA"),        # 0x82CF
+    ("",       X,      1,      "GL_VIEW_CLASS_RGTC1_RED"),     # 0x82D0
+    ("",       X,      1,      "GL_VIEW_CLASS_RGTC2_RG"),      # 0x82D1
+    ("",       X,      1,      "GL_VIEW_CLASS_BPTC_UNORM"),    # 0x82D2
+    ("",       X,      1,      "GL_VIEW_CLASS_BPTC_FLOAT"),    # 0x82D3
+    ("",       I,      1,      "GL_VERTEX_ATTRIB_BINDING"),    # 0x82D4
+    ("",       I,      1,      "GL_VERTEX_ATTRIB_RELATIVE_OFFSET"),    # 0x82D5
+    ("",       I,      1,      "GL_VERTEX_BINDING_DIVISOR"),   # 0x82D6
+    ("",       I,      1,      "GL_VERTEX_BINDING_OFFSET"),    # 0x82D7
+    ("",       I,      1,      "GL_VERTEX_BINDING_STRIDE"),    # 0x82D8
+    ("",       I,      1,      "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET"),        # 0x82D9
+    ("",       I,      1,      "GL_MAX_VERTEX_ATTRIB_BINDINGS"),       # 0x82DA
+    ("glGetTexParameter",      I,      1,      "GL_TEXTURE_VIEW_MIN_LEVEL"),   # 0x82DB
+    ("glGetTexParameter",      I,      1,      "GL_TEXTURE_VIEW_NUM_LEVELS"),  # 0x82DC
+    ("glGetTexParameter",      I,      1,      "GL_TEXTURE_VIEW_MIN_LAYER"),   # 0x82DD
+    ("glGetTexParameter",      I,      1,      "GL_TEXTURE_VIEW_NUM_LAYERS"),  # 0x82DE
+    ("glGetTexParameter",      I,      1,      "GL_TEXTURE_IMMUTABLE_LEVELS"), # 0x82DF
+    ("",       X,      1,      "GL_BUFFER"),   # 0x82E0
+    ("",       X,      1,      "GL_SHADER"),   # 0x82E1
+    ("",       X,      1,      "GL_PROGRAM"),  # 0x82E2
+    ("",       X,      1,      "GL_QUERY"),    # 0x82E3
+    ("",       X,      1,      "GL_PROGRAM_PIPELINE"), # 0x82E4
+    ("",       X,      1,      "GL_SAMPLER"),  # 0x82E6
+    ("",       X,      1,      "GL_DISPLAY_LIST"),     # 0x82E7
+    ("",       X,      1,      "GL_MAX_LABEL_LENGTH"), # 0x82E8
+    ("",       X,      1,      "GL_NUM_SHADING_LANGUAGE_VERSIONS"),    # 0x82E9
     ("",       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
@@ -1982,7 +2115,7 @@ parameters = [
     ("glGet",  I,      1,      "GL_PIXEL_PACK_BUFFER_BINDING"),        # 0x88ED
     ("glGet",  I,      1,      "GL_PIXEL_UNPACK_BUFFER_BINDING"),      # 0x88EF
     ("",       X,      1,      "GL_DEPTH24_STENCIL8"), # 0x88F0
-    ("",       X,      1,      "GL_TEXTURE_STENCIL_SIZE"),     # 0x88F1
+    ("glGetTexLevelParameter", I,      1,      "GL_TEXTURE_STENCIL_SIZE"),     # 0x88F1
     ("",       X,      1,      "GL_STENCIL_TAG_BITS_EXT"),     # 0x88F2
     ("",       X,      1,      "GL_STENCIL_CLEAR_TAG_VALUE_EXT"),      # 0x88F3
     ("glGetProgramARB",        I,      1,      "GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV"), # 0x88F4
@@ -2364,7 +2497,7 @@ parameters = [
     ("",       X,      1,      "GL_TRANSFORM_FEEDBACK_RECORD_NV"),     # 0x8C86
     ("",       X,      1,      "GL_PRIMITIVES_GENERATED"),     # 0x8C87
     ("",       X,      1,      "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"),    # 0x8C88
-    ("",       X,      1,      "GL_RASTERIZER_DISCARD"),       # 0x8C89
+    ("glGet",  B,      1,      "GL_RASTERIZER_DISCARD"),       # 0x8C89
     ("",       X,      1,      "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS"),    # 0x8C8A
     ("",       X,      1,      "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"),  # 0x8C8B
     ("",       X,      1,      "GL_INTERLEAVED_ATTRIBS"),      # 0x8C8C
@@ -2444,6 +2577,10 @@ parameters = [
     #("",      X,      1,      "GL_SAMPLER_EXTERNAL_OES"),     # 0x8D66
     #("",      X,      1,      "GL_TEXTURE_BINDING_EXTERNAL_OES"),     # 0x8D67
     #("",      X,      1,      "GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES"), # 0x8D68
+    ("",       B,      1,      "GL_PRIMITIVE_RESTART_FIXED_INDEX"),    # 0x8D69
+    ("",       X,      1,      "GL_ANY_SAMPLES_PASSED_CONSERVATIVE"),  # 0x8D6A
+    ("glGet",  I,      1,      "GL_MAX_ELEMENT_INDEX"),        # 0x8D6B
+    #("",      X,      1,      "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT"),       # 0x8D6C
     ("",       X,      1,      "GL_RGBA32UI"), # 0x8D70
     ("",       X,      1,      "GL_RGB32UI"),  # 0x8D71
     ("",       X,      1,      "GL_ALPHA32UI_EXT"),    # 0x8D72
@@ -2863,9 +3000,86 @@ parameters = [
     ("",       X,      1,      "GL_MAX_IMAGE_SAMPLES"),        # 0x906D
     ("",       X,      1,      "GL_IMAGE_BINDING_FORMAT"),     # 0x906E
     ("",       X,      1,      "GL_RGB10_A2UI"),       # 0x906F
+    ("",       X,      1,      "GL_PATH_FORMAT_SVG_NV"),       # 0x9070
+    ("",       X,      1,      "GL_PATH_FORMAT_PS_NV"),        # 0x9071
+    ("",       X,      1,      "GL_STANDARD_FONT_NAME_NV"),    # 0x9072
+    ("",       X,      1,      "GL_SYSTEM_FONT_NAME_NV"),      # 0x9073
+    ("",       X,      1,      "GL_FILE_NAME_NV"),     # 0x9074
+    ("",       X,      1,      "GL_PATH_STROKE_WIDTH_NV"),     # 0x9075
+    ("",       X,      1,      "GL_PATH_END_CAPS_NV"), # 0x9076
+    ("",       X,      1,      "GL_PATH_INITIAL_END_CAP_NV"),  # 0x9077
+    ("",       X,      1,      "GL_PATH_TERMINAL_END_CAP_NV"), # 0x9078
+    ("",       X,      1,      "GL_PATH_JOIN_STYLE_NV"),       # 0x9079
+    ("",       X,      1,      "GL_PATH_MITER_LIMIT_NV"),      # 0x907A
+    ("",       X,      1,      "GL_PATH_DASH_CAPS_NV"),        # 0x907B
+    ("",       X,      1,      "GL_PATH_INITIAL_DASH_CAP_NV"), # 0x907C
+    ("",       X,      1,      "GL_PATH_TERMINAL_DASH_CAP_NV"),        # 0x907D
+    ("",       X,      1,      "GL_PATH_DASH_OFFSET_NV"),      # 0x907E
+    ("",       X,      1,      "GL_PATH_CLIENT_LENGTH_NV"),    # 0x907F
+    ("",       X,      1,      "GL_PATH_FILL_MODE_NV"),        # 0x9080
+    ("",       X,      1,      "GL_PATH_FILL_MASK_NV"),        # 0x9081
+    ("",       X,      1,      "GL_PATH_FILL_COVER_MODE_NV"),  # 0x9082
+    ("",       X,      1,      "GL_PATH_STROKE_COVER_MODE_NV"),        # 0x9083
+    ("",       X,      1,      "GL_PATH_STROKE_MASK_NV"),      # 0x9084
+    ("",       X,      1,      "GL_PATH_SAMPLE_QUALITY_NV"),   # 0x9085
+    ("",       X,      1,      "GL_PATH_STROKE_BOUND_NV"),     # 0x9086
+    ("",       X,      1,      "GL_PATH_STROKE_OVERSAMPLE_COUNT_NV"),  # 0x9087
+    ("",       X,      1,      "GL_COUNT_UP_NV"),      # 0x9088
+    ("",       X,      1,      "GL_COUNT_DOWN_NV"),    # 0x9089
+    ("",       X,      1,      "GL_PATH_OBJECT_BOUNDING_BOX_NV"),      # 0x908A
+    ("",       X,      1,      "GL_CONVEX_HULL_NV"),   # 0x908B
+    ("",       X,      1,      "GL_MULTI_HULLS_NV"),   # 0x908C
+    ("",       X,      1,      "GL_BOUNDING_BOX_NV"),  # 0x908D
+    ("",       X,      1,      "GL_TRANSLATE_X_NV"),   # 0x908E
+    ("",       X,      1,      "GL_TRANSLATE_Y_NV"),   # 0x908F
+    ("",       X,      1,      "GL_TRANSLATE_2D_NV"),  # 0x9090
+    ("",       X,      1,      "GL_TRANSLATE_3D_NV"),  # 0x9091
+    ("",       X,      1,      "GL_AFFINE_2D_NV"),     # 0x9092
+    ("",       X,      1,      "GL_PROJECTIVE_2D_NV"), # 0x9093
+    ("",       X,      1,      "GL_AFFINE_3D_NV"),     # 0x9094
+    ("",       X,      1,      "GL_PROJECTIVE_3D_NV"), # 0x9095
+    ("",       X,      1,      "GL_TRANSPOSE_AFFINE_2D_NV"),   # 0x9096
+    ("",       X,      1,      "GL_TRANSPOSE_PROJECTIVE_2D_NV"),       # 0x9097
+    ("",       X,      1,      "GL_TRANSPOSE_AFFINE_3D_NV"),   # 0x9098
+    ("",       X,      1,      "GL_TRANSPOSE_PROJECTIVE_3D_NV"),       # 0x9099
+    ("",       X,      1,      "GL_UTF8_NV"),  # 0x909A
+    ("",       X,      1,      "GL_UTF16_NV"), # 0x909B
+    ("",       X,      1,      "GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV"),        # 0x909C
+    ("",       X,      1,      "GL_PATH_COMMAND_COUNT_NV"),    # 0x909D
+    ("",       X,      1,      "GL_PATH_COORD_COUNT_NV"),      # 0x909E
+    ("",       X,      1,      "GL_PATH_DASH_ARRAY_COUNT_NV"), # 0x909F
+    ("",       X,      1,      "GL_PATH_COMPUTED_LENGTH_NV"),  # 0x90A0
+    ("",       X,      1,      "GL_PATH_FILL_BOUNDING_BOX_NV"),        # 0x90A1
+    ("",       X,      1,      "GL_PATH_STROKE_BOUNDING_BOX_NV"),      # 0x90A2
+    ("",       X,      1,      "GL_SQUARE_NV"),        # 0x90A3
+    ("",       X,      1,      "GL_ROUND_NV"), # 0x90A4
+    ("",       X,      1,      "GL_TRIANGULAR_NV"),    # 0x90A5
+    ("",       X,      1,      "GL_BEVEL_NV"), # 0x90A6
+    ("",       X,      1,      "GL_MITER_REVERT_NV"),  # 0x90A7
+    ("",       X,      1,      "GL_MITER_TRUNCATE_NV"),        # 0x90A8
+    ("",       X,      1,      "GL_SKIP_MISSING_GLYPH_NV"),    # 0x90A9
+    ("",       X,      1,      "GL_USE_MISSING_GLYPH_NV"),     # 0x90AA
+    ("",       X,      1,      "GL_PATH_ERROR_POSITION_NV"),   # 0x90AB
+    ("",       X,      1,      "GL_PATH_FOG_GEN_MODE_NV"),     # 0x90AC
+    ("",       X,      1,      "GL_ACCUM_ADJACENT_PAIRS_NV"),  # 0x90AD
+    ("",       X,      1,      "GL_ADJACENT_PAIRS_NV"),        # 0x90AE
+    ("",       X,      1,      "GL_FIRST_TO_REST_NV"), # 0x90AF
+    ("",       X,      1,      "GL_PATH_GEN_MODE_NV"), # 0x90B0
+    ("",       X,      1,      "GL_PATH_GEN_COEFF_NV"),        # 0x90B1
+    ("",       X,      1,      "GL_PATH_GEN_COLOR_FORMAT_NV"), # 0x90B2
+    ("",       X,      1,      "GL_PATH_GEN_COMPONENTS_NV"),   # 0x90B3
+    ("",       X,      1,      "GL_PATH_DASH_OFFSET_RESET_NV"),        # 0x90B4
+    ("",       X,      1,      "GL_MOVE_TO_RESETS_NV"),        # 0x90B5
+    ("",       X,      1,      "GL_MOVE_TO_CONTINUES_NV"),     # 0x90B6
+    ("",       X,      1,      "GL_PATH_STENCIL_FUNC_NV"),     # 0x90B7
+    ("",       X,      1,      "GL_PATH_STENCIL_REF_NV"),      # 0x90B8
+    ("",       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
+    ("",       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
     ("",       X,      1,      "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"),  # 0x90C7
     ("",       X,      1,      "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE"),       # 0x90C8
     ("",       X,      1,      "GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS"),      # 0x90C9
@@ -2875,7 +3089,27 @@ parameters = [
     ("",       X,      1,      "GL_MAX_GEOMETRY_IMAGE_UNIFORMS"),      # 0x90CD
     ("",       X,      1,      "GL_MAX_FRAGMENT_IMAGE_UNIFORMS"),      # 0x90CE
     ("",       X,      1,      "GL_MAX_COMBINED_IMAGE_UNIFORMS"),      # 0x90CF
+    ("",       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
+    ("",       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
+    ("",       I,      1,      "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"),        # 0x90D9
+    ("",       I,      1,      "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS"),       # 0x90DA
+    ("glGet",  I,      1,      "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"),        # 0x90DB
+    ("",       I,      1,      "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS"),       # 0x90DC
+    ("",       I,      1,      "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS"),       # 0x90DD
+    ("",       I,      1,      "GL_MAX_SHADER_STORAGE_BLOCK_SIZE"),    # 0x90DE
+    ("",       X,      1,      "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT"),   # 0x90DF
     ("",       X,      1,      "GL_SYNC_X11_FENCE_EXT"),       # 0x90E1
+    ("glGetTexParameter",      E,      1,      "GL_DEPTH_STENCIL_TEXTURE_MODE"),       # 0x90EA
+    ("glGet",  I,      1,      "GL_MAX_COMPUTE_LOCAL_INVOCATIONS"),    # 0x90EB
+    ("",       X,      1,      "GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER"),       # 0x90EC
+    ("",       X,      1,      "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER"),       # 0x90ED
+    ("",       X,      1,      "GL_DISPATCH_INDIRECT_BUFFER"), # 0x90EE
+    ("glGet",  I,      1,      "GL_DISPATCH_INDIRECT_BUFFER_BINDING"), # 0x90EF
     ("",       X,      1,      "GL_TEXTURE_2D_MULTISAMPLE"),   # 0x9100
     ("",       X,      1,      "GL_PROXY_TEXTURE_2D_MULTISAMPLE"),     # 0x9101
     ("",       X,      1,      "GL_TEXTURE_2D_MULTISAMPLE_ARRAY"),     # 0x9102
@@ -2928,12 +3162,12 @@ parameters = [
     #("",      X,      1,      "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG"),   # 0x9134
     #("",      X,      1,      "GL_MAX_SAMPLES_IMG"),  # 0x9135
     #("",      X,      1,      "GL_TEXTURE_SAMPLES_IMG"),      # 0x9136
-    ("glGet",  I,      1,      "GL_MAX_DEBUG_MESSAGE_LENGTH_ARB"),     # 0x9143
-    ("glGet",  I,      1,      "GL_MAX_DEBUG_LOGGED_MESSAGES_ARB"),    # 0x9144
-    ("glGet",  I,      1,      "GL_DEBUG_LOGGED_MESSAGES_ARB"),        # 0x9145
-    ("",       X,      1,      "GL_DEBUG_SEVERITY_HIGH_ARB"),  # 0x9146
-    ("",       X,      1,      "GL_DEBUG_SEVERITY_MEDIUM_ARB"),        # 0x9147
-    ("",       X,      1,      "GL_DEBUG_SEVERITY_LOW_ARB"),   # 0x9148
+    ("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
+    ("",       X,      1,      "GL_DEBUG_SEVERITY_HIGH"),      # 0x9146
+    ("",       X,      1,      "GL_DEBUG_SEVERITY_MEDIUM"),    # 0x9147
+    ("",       X,      1,      "GL_DEBUG_SEVERITY_LOW"),       # 0x9148
     ("",       X,      1,      "GL_DEBUG_CATEGORY_API_ERROR_AMD"),     # 0x9149
     ("",       X,      1,      "GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD"), # 0x914A
     ("",       X,      1,      "GL_DEBUG_CATEGORY_DEPRECATION_AMD"),   # 0x914B
@@ -2942,12 +3176,36 @@ parameters = [
     ("",       X,      1,      "GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD"),       # 0x914E
     ("",       X,      1,      "GL_DEBUG_CATEGORY_APPLICATION_AMD"),   # 0x914F
     ("",       X,      1,      "GL_DEBUG_CATEGORY_OTHER_AMD"), # 0x9150
-    ("",       X,      1,      "GL_DATA_BUFFER_AMD"),  # 0x9151
+    ("",       X,      1,      "GL_BUFFER_OBJECT_EXT"),        # 0x9151
     ("",       X,      1,      "GL_PERFORMANCE_MONITOR_AMD"),  # 0x9152
-    ("",       X,      1,      "GL_QUERY_OBJECT_AMD"), # 0x9153
-    ("",       X,      1,      "GL_VERTEX_ARRAY_OBJECT_AMD"),  # 0x9154
+    ("",       X,      1,      "GL_QUERY_OBJECT_EXT"), # 0x9153
+    ("",       X,      1,      "GL_VERTEX_ARRAY_OBJECT_EXT"),  # 0x9154
     ("",       X,      1,      "GL_SAMPLER_OBJECT_AMD"),       # 0x9155
-    #("",      X,      1,      "GL_SHADER_BINARY_DMP"),        # 0x9250
+    ("",       X,      1,      "GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD"),       # 0x9160
+    ("",       X,      1,      "GL_QUERY_BUFFER_AMD"), # 0x9192
+    ("",       X,      1,      "GL_QUERY_BUFFER_BINDING_AMD"), # 0x9193
+    ("",       X,      1,      "GL_QUERY_RESULT_NO_WAIT_AMD"), # 0x9194
+    ("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_COMPUTE_SHADER"),   # 0x91B9
+    ("glGet",  I,      1,      "GL_MAX_COMPUTE_UNIFORM_BLOCKS"),       # 0x91BB
+    ("glGet",  I,      1,      "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"),  # 0x91BC
+    ("glGet",  I,      1,      "GL_MAX_COMPUTE_IMAGE_UNIFORMS"),       # 0x91BD
+    ("glGet",  I,      3,      "GL_MAX_COMPUTE_WORK_GROUP_COUNT"),     # 0x91BE
+    ("glGet",  I,      3,      "GL_MAX_COMPUTE_WORK_GROUP_SIZE"),      # 0x91BF
+    ("",       X,      1,      "GL_SHADER_BINARY_DMP"),        # 0x9250
+    #("",      X,      1,      "GL_GCCSO_SHADER_BINARY_FJ"),   # 0x9260
+    ("",       X,      1,      "GL_COMPRESSED_R11_EAC"),       # 0x9270
+    ("",       X,      1,      "GL_COMPRESSED_SIGNED_R11_EAC"),        # 0x9271
+    ("",       X,      1,      "GL_COMPRESSED_RG11_EAC"),      # 0x9272
+    ("",       X,      1,      "GL_COMPRESSED_SIGNED_RG11_EAC"),       # 0x9273
+    ("",       X,      1,      "GL_COMPRESSED_RGB8_ETC2"),     # 0x9274
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ETC2"),    # 0x9275
+    ("",       X,      1,      "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2"), # 0x9276
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2"),        # 0x9277
+    ("",       X,      1,      "GL_COMPRESSED_RGBA8_ETC2_EAC"),        # 0x9278
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"), # 0x9279
     ("",       X,      1,      "GL_ATOMIC_COUNTER_BUFFER"),    # 0x92C0
     ("",       X,      1,      "GL_ATOMIC_COUNTER_BUFFER_BINDING"),    # 0x92C1
     ("",       X,      1,      "GL_ATOMIC_COUNTER_BUFFER_START"),      # 0x92C2
@@ -2977,7 +3235,105 @@ parameters = [
     ("",       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",  B,      1,      "GL_DEBUG_OUTPUT"),     # 0x92E0
+    ("",       X,      1,      "GL_UNIFORM"),  # 0x92E1
+    ("",       X,      1,      "GL_UNIFORM_BLOCK"),    # 0x92E2
+    ("",       X,      1,      "GL_PROGRAM_INPUT"),    # 0x92E3
+    ("",       X,      1,      "GL_PROGRAM_OUTPUT"),   # 0x92E4
+    ("",       X,      1,      "GL_BUFFER_VARIABLE"),  # 0x92E5
+    ("",       X,      1,      "GL_SHADER_STORAGE_BLOCK"),     # 0x92E6
+    ("",       X,      1,      "GL_IS_PER_PATCH"),     # 0x92E7
+    ("",       X,      1,      "GL_VERTEX_SUBROUTINE"),        # 0x92E8
+    ("",       X,      1,      "GL_TESS_CONTROL_SUBROUTINE"),  # 0x92E9
+    ("",       X,      1,      "GL_TESS_EVALUATION_SUBROUTINE"),       # 0x92EA
+    ("",       X,      1,      "GL_GEOMETRY_SUBROUTINE"),      # 0x92EB
+    ("",       X,      1,      "GL_FRAGMENT_SUBROUTINE"),      # 0x92EC
+    ("",       X,      1,      "GL_COMPUTE_SUBROUTINE"),       # 0x92ED
+    ("",       X,      1,      "GL_VERTEX_SUBROUTINE_UNIFORM"),        # 0x92EE
+    ("",       X,      1,      "GL_TESS_CONTROL_SUBROUTINE_UNIFORM"),  # 0x92EF
+    ("",       X,      1,      "GL_TESS_EVALUATION_SUBROUTINE_UNIFORM"),       # 0x92F0
+    ("",       X,      1,      "GL_GEOMETRY_SUBROUTINE_UNIFORM"),      # 0x92F1
+    ("",       X,      1,      "GL_FRAGMENT_SUBROUTINE_UNIFORM"),      # 0x92F2
+    ("",       X,      1,      "GL_COMPUTE_SUBROUTINE_UNIFORM"),       # 0x92F3
+    ("",       X,      1,      "GL_TRANSFORM_FEEDBACK_VARYING"),       # 0x92F4
+    ("",       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
+    ("",       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_NUM_SAMPLE_COUNTS"),        # 0x9380
+    ("",       X,      1,      "GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE"),    # 0x93A0
+    ("",       X,      1,      "GL_TEXTURE_USAGE_ANGLE"),      # 0x93A2
+    ("",       X,      1,      "GL_FRAMEBUFFER_ATTACHMENT_ANGLE"),     # 0x93A3
+    ("",       X,      1,      "GL_PACK_REVERSE_ROW_ORDER_ANGLE"),     # 0x93A4
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_4x4_KHR"),     # 0x93B0
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_5x4_KHR"),     # 0x93B1
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_5x5_KHR"),     # 0x93B2
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_6x5_KHR"),     # 0x93B3
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_6x6_KHR"),     # 0x93B4
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_8x5_KHR"),     # 0x93B5
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_8x6_KHR"),     # 0x93B6
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_8x8_KHR"),     # 0x93B7
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_10x5_KHR"),    # 0x93B8
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_10x6_KHR"),    # 0x93B9
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_10x8_KHR"),    # 0x93BA
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_10x10_KHR"),   # 0x93BB
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_12x10_KHR"),   # 0x93BC
+    ("",       X,      1,      "GL_COMPRESSED_RGBA_ASTC_12x12_KHR"),   # 0x93BD
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"),     # 0x93D0
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"),     # 0x93D1
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"),     # 0x93D2
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"),     # 0x93D3
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"),     # 0x93D4
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"),     # 0x93D5
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"),     # 0x93D6
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"),     # 0x93D7
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"),    # 0x93D8
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"),    # 0x93D9
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"),    # 0x93DA
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"),   # 0x93DB
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"),   # 0x93DC
+    ("",       X,      1,      "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"),   # 0x93DD
+    #("",      X,      1,      "GL_RESTART_PATH_NV"),  # 0xF0
+    #("",      X,      1,      "GL_DUP_FIRST_CUBIC_CURVE_TO_NV"),      # 0xF2
+    #("",      X,      1,      "GL_DUP_LAST_CUBIC_CURVE_TO_NV"),       # 0xF4
+    #("",      X,      1,      "GL_RECT_NV"),  # 0xF6
+    #("",      X,      1,      "GL_CIRCULAR_CCW_ARC_TO_NV"),   # 0xF8
+    #("",      X,      1,      "GL_CIRCULAR_CW_ARC_TO_NV"),    # 0xFA
+    #("",      X,      1,      "GL_CIRCULAR_TANGENT_ARC_TO_NV"),       # 0xFC
+    #("",      X,      1,      "GL_ARC_TO_NV"),        # 0xFE
+    #("",      X,      1,      "GL_TIMEOUT_IGNORED"),  # 0xFFFFFFFFFFFFFFFFull
     ("",       X,      1,      "GL_INVALID_INDEX"),    # 0xFFFFFFFFu
 ]
 
index 71d7cd613e110e5ed224b4777901e1b9ede87beb..23af3279e54f2e51a33e8ebba9ad6166131a7d36 100644 (file)
@@ -53,11 +53,9 @@ GLfloat = Alias("GLfloat", Float)
 GLclampf = Alias("GLclampf", Float)
 GLdouble = Alias("GLdouble", Double)
 GLclampd = Alias("GLclampd", Double)
-GLchar = Alias("GLchar", SChar)
-GLstring = String("GLchar *")
+GLchar = Alias("GLchar", Char)
 
 GLcharARB = Alias("GLcharARB", SChar)
-GLstringARB = String("GLcharARB *")
 GLintptrARB = Alias("GLintptrARB", Int)
 GLsizeiptrARB = Alias("GLsizeiptrARB", Int)
 GLhandleARB = Handle("handleARB", Alias("GLhandleARB", UInt))
@@ -65,9 +63,15 @@ GLhalfARB = Alias("GLhalfARB", UShort)
 GLhalfNV = Alias("GLhalfNV", UShort)
 GLint64EXT = Alias("GLint64EXT", Int64)
 GLuint64EXT = Alias("GLuint64EXT", UInt64)
+GLDEBUGPROC = Opaque("GLDEBUGPROC")
 GLDEBUGPROCARB = Opaque("GLDEBUGPROCARB")
 GLDEBUGPROCAMD = Opaque("GLDEBUGPROCAMD")
 
+GLstring = String(GLchar)
+GLstringConst = String(Const(GLchar))
+GLstringARB = String(GLcharARB)
+GLstringConstARB = String(Const(GLcharARB))
+
 GLpointer = OpaquePointer(GLvoid)
 GLpointerConst = OpaquePointer(Const(GLvoid))
 
@@ -96,15 +100,19 @@ GLshader = Handle("shader", GLuint)
 GLlocation = Handle("location", GLint, key=('program', GLhandleARB))
 GLlocationARB = Handle("location", GLint, key=('programObj', GLhandleARB))
 
+contextKey = ('reinterpret_cast<uintptr_t>(glretrace::getCurrentContext())', UIntPtr)
+
 GLprogramARB = Handle("programARB", GLuint)
 GLframebuffer = Handle("framebuffer", GLuint)
 GLrenderbuffer = Handle("renderbuffer", GLuint)
 GLfragmentShaderATI = Handle("fragmentShaderATI", GLuint)
-GLarray = Handle("array", GLuint)
+GLarray = Handle("array", GLuint, key=contextKey) # per-context
+GLarrayAPPLE = Handle("arrayAPPLE", GLuint) # shared
 GLregion = Handle("region", GLuint)
 GLpipeline = Handle("pipeline", GLuint)
 GLsampler = Handle("sampler", GLuint)
 GLfeedback = Handle("feedback", GLuint)
+GLfence = Handle("fence", GLuint)
 
 # GL mappings are pointers to linear memory regions.
 #
@@ -192,6 +200,7 @@ GLbitfield_shader = Flags(GLbitfield, [
     "GL_GEOMETRY_SHADER_BIT",                    # 0x00000004
     "GL_TESS_CONTROL_SHADER_BIT",                # 0x00000008
     "GL_TESS_EVALUATION_SHADER_BIT",             # 0x00000010
+    "GL_COMPUTE_SHADER_BIT",                     # 0x00000020
 ])
 
 GLbitfield_access = Flags(GLbitfield, [
@@ -224,3 +233,7 @@ GLbitfield_barrier = Flags(GLbitfield, [
     "GL_ATOMIC_COUNTER_BARRIER_BIT",            # 0x00001000
 ])
 
+# GL_ARB_vertex_array_bgra
+size_bgra = FakeEnum(GLint, [
+    "GL_BGRA",
+])
index f64e79487e84ad6d08689b390d80e113b241463b..157752719c87c5692e2f98c5dcd44e268dd67278 100644 (file)
@@ -270,9 +270,9 @@ glxapi.addFunctions([
     Function(Void, "glXUseXFont", [(Font, "font"), (Int, "first"), (Int, "count"), (Int, "list")]),
 
     # GLX 1.1 and later
-    Function((Const(String("char *"))), "glXQueryExtensionsString", [(Display, "dpy"), (Int, "screen")]),
-    Function((Const(String("char *"))), "glXQueryServerString",  [(Display, "dpy"), (Int, "screen"), (GLXname, "name")]),
-    Function((Const(String("char *"))), "glXGetClientString", [(Display, "dpy"), (GLXname, "name")]),
+    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 1.2 and later
     Function(Display, "glXGetCurrentDisplay", [], sideeffects=False),
@@ -385,7 +385,7 @@ glxapi.addFunctions([
 
     # GLX_MESA_swap_control
     Function(Int, "glXSwapIntervalMESA", [(UInt, "interval")]),
-    Function(Int, "glXGetSwapIntervalMESA", []),
+    Function(Int, "glXGetSwapIntervalMESA", [], sideeffects=False),
 
     # GLX_OML_sync_control
     Function(Bool, "glXGetSyncValuesOML", [(Display, "dpy"), (GLXDrawable, "drawable"), (OpaquePointer(Int64), "ust"), (OpaquePointer(Int64), "msc"), (OpaquePointer(Int64), "sbc")]),
@@ -449,8 +449,8 @@ glxapi.addFunctions([
     Function(Void, "glXFreeMemoryNV", [(OpaquePointer(Void), "pointer")]),
 
     # Must be last
-    Function(PROC, "glXGetProcAddressARB", [(Alias("const GLubyte *", CString), "procName")]),
-    Function(PROC, "glXGetProcAddress", [(Alias("const GLubyte *", CString), "procName")]),
+    Function(PROC, "glXGetProcAddressARB", [(String(Const(GLubyte)), "procName")]),
+    Function(PROC, "glXGetProcAddress", [(String(Const(GLubyte)), "procName")]),
 ])
 
 
index 1511bf3b26568833984529deffc7b7deaf1f57c9..f21b08d5bf82f6670ecea07a44a77d537cfc4f24 100755 (executable)
@@ -235,12 +235,16 @@ class SpecParser(LineParser):
                     try:
                         int(length)
                     except ValueError:
-                        length = "%s" % length
+                        length = '"%s"' % length
                     arg_type = '%s(%s, %s)' % (constructor, base_type, length)
                 else:
-                    length = length.replace("COMPSIZE", "_%s_size" % function_name)
-                    length = length.replace("/", ", ")
-                    arg_type = 'Opaque%s(%s, %s)' % (constructor, base_type, length)
+                    if length == "COMPSIZE(pname)":
+                        length = "_gl_param_size(pname)"
+                        arg_type = '%s(%s, "%s")' % (constructor, base_type, length)
+                    else:
+                        length = length.replace("COMPSIZE", "_%s_size" % function_name)
+                        length = length.replace("/", ", ")
+                        arg_type = 'Opaque%s(%s, "%s")' % (constructor, base_type, length)
         else:
             assert False
         
index b2bd904075b6ae4383326f1d830bad19cf933cd1..8a5a5a7fa5b647f3e45a29fbe3c06db114d87b6c 100644 (file)
@@ -102,17 +102,43 @@ class Literal(Type):
         return visitor.visitLiteral(self, *args, **kwargs)
 
 
+Bool = Literal("bool", "Bool")
+SChar = Literal("signed char", "SInt")
+UChar = Literal("unsigned char", "UInt")
+Short = Literal("short", "SInt")
+Int = Literal("int", "SInt")
+Long = Literal("long", "SInt")
+LongLong = Literal("long long", "SInt")
+UShort = Literal("unsigned short", "UInt")
+UInt = Literal("unsigned int", "UInt")
+ULong = Literal("unsigned long", "UInt")
+ULongLong = Literal("unsigned long long", "UInt")
+Float = Literal("float", "Float")
+Double = Literal("double", "Double")
+SizeT = Literal("size_t", "UInt")
+
+Char = Literal("char", "SInt")
+WChar = Literal("wchar_t", "SInt")
+
+Int8 = Literal("int8_t", "SInt")
+UInt8 = Literal("uint8_t", "UInt")
+Int16 = Literal("int16_t", "SInt")
+UInt16 = Literal("uint16_t", "UInt")
+Int32 = Literal("int32_t", "SInt")
+UInt32 = Literal("uint32_t", "UInt")
+Int64 = Literal("int64_t", "SInt")
+UInt64 = Literal("uint64_t", "UInt")
+
+IntPtr = Literal("intptr_t", "SInt")
+UIntPtr = Literal("uintptr_t", "UInt")
+
 class Const(Type):
 
     def __init__(self, type):
         # While "const foo" and "foo const" are synonymous, "const foo *" and
         # "foo * const" are not quite the same, and some compilers do enforce
         # strict const correctness.
-        if isinstance(type, String) or type is WString:
-            # For strings we never intend to say a const pointer to chars, but
-            # rather a point to const chars.
-            expr = "const " + type.expr
-        elif type.expr.startswith("const ") or '*' in type.expr:
+        if type.expr.startswith("const ") or '*' in type.expr:
             expr = type.expr + " const"
         else:
             # The most legible
@@ -453,11 +479,14 @@ def StdMethod(*args, **kwargs):
 
 
 class String(Type):
+    '''Human-legible character string.'''
 
-    def __init__(self, expr = "char *", length = None, kind = 'String'):
-        Type.__init__(self, expr)
+    def __init__(self, type = Char, length = None, wide = False):
+        assert isinstance(type, Type)
+        Type.__init__(self, type.expr + ' *')
+        self.type = type
         self.length = length
-        self.kind = kind
+        self.wide = wide
 
     def visit(self, visitor, *args, **kwargs):
         return visitor.visitString(self, *args, **kwargs)
@@ -610,7 +639,11 @@ class Rebuilder(Visitor):
         return literal
 
     def visitString(self, string):
-        return string
+        string_type = self.visit(string.type)
+        if string_type is string.type:
+            return string
+        else:
+            return String(string_type, string.length, string.wide)
 
     def visitConst(self, const):
         const_type = self.visit(const.type)
@@ -699,6 +732,9 @@ class Rebuilder(Visitor):
 class MutableRebuilder(Rebuilder):
     '''Type visitor which derives a mutable type.'''
 
+    def visitString(self, string):
+        return string
+
     def visitConst(self, const):
         # Strip out const qualifier
         return const.type
@@ -859,30 +895,8 @@ class API:
         return None
 
 
-Bool = Literal("bool", "Bool")
-SChar = Literal("signed char", "SInt")
-UChar = Literal("unsigned char", "UInt")
-Short = Literal("short", "SInt")
-Int = Literal("int", "SInt")
-Long = Literal("long", "SInt")
-LongLong = Literal("long long", "SInt")
-UShort = Literal("unsigned short", "UInt")
-UInt = Literal("unsigned int", "UInt")
-ULong = Literal("unsigned long", "UInt")
-ULongLong = Literal("unsigned long long", "UInt")
-Float = Literal("float", "Float")
-Double = Literal("double", "Double")
-SizeT = Literal("size_t", "UInt")
-
 # C string (i.e., zero terminated)
-CString = String()
-WString = String("wchar_t *", kind="WString")
-
-Int8 = Literal("int8_t", "SInt")
-UInt8 = Literal("uint8_t", "UInt")
-Int16 = Literal("int16_t", "SInt")
-UInt16 = Literal("uint16_t", "UInt")
-Int32 = Literal("int32_t", "SInt")
-UInt32 = Literal("uint32_t", "UInt")
-Int64 = Literal("int64_t", "SInt")
-UInt64 = Literal("uint64_t", "UInt")
+CString = String(Char)
+WString = String(WChar, wide=True)
+ConstCString = String(Const(Char))
+ConstWString = String(Const(WChar), wide=True)
index ff789377027a5381ff429e44bee5ff5a0ffccdf5..e3d8b2366f593fd53f4f72cd6902280af92489b7 100644 (file)
@@ -175,7 +175,7 @@ wglapi.addFunctions([
     StdFunction(BOOL, "wglRestoreBufferRegionARB", [(HANDLE, "hRegion"), (Int, "x"), (Int, "y"), (Int, "width"), (Int, "height"), (Int, "xSrc"), (Int, "ySrc")]),
 
     # WGL_ARB_extensions_string
-    StdFunction(Const(CString), "wglGetExtensionsStringARB", [(HDC, "hdc")], sideeffects=False),
+    StdFunction(ConstCString, "wglGetExtensionsStringARB", [(HDC, "hdc")], sideeffects=False),
 
     # 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),
@@ -202,7 +202,7 @@ wglapi.addFunctions([
     StdFunction(HGLRC, "wglCreateContextAttribsARB", [(HDC, "hDC"), (HGLRC, "hShareContext"), (Array(Const(WGLenum), "_AttribPairList_size(attribList)"), "attribList")]),
 
     # WGL_EXT_extensions_string
-    StdFunction(Const(CString), "wglGetExtensionsStringEXT", [], sideeffects=False),
+    StdFunction(ConstCString, "wglGetExtensionsStringEXT", [], sideeffects=False),
 
     # WGL_EXT_make_current_read
     StdFunction(BOOL, "wglMakeContextCurrentEXT", [(HDC, "hDrawDC"), (HDC, "hReadDC"), (HGLRC, "hglrc")]),
index c27d0be12897ed5b05e2497c0c78a276cc8241ba..23d6419f36bab0051f025a30f3b195d32233333c 100644 (file)
@@ -65,9 +65,9 @@ LPDWORD = Pointer(DWORD)
 LPBOOL = Pointer(BOOL)
 
 LPSTR = CString
-LPCSTR = Const(CString)
+LPCSTR = ConstCString
 LPWSTR = WString
-LPCWSTR = Const(WString)
+LPCWSTR = ConstWString
 
 LARGE_INTEGER = Struct("LARGE_INTEGER", [
     (LONGLONG, 'QuadPart'),
index b55d8f25f7f37df209afcddaea42ebbcc318db43..0b6d2899397a35bf735c0456a82fa6b965de2f69 100644 (file)
@@ -34,8 +34,8 @@ extern "C" {
 
 /* Header file version number */
 /* Current version at http://www.khronos.org/registry/egl/ */
-/* $Revision: 16996 $ on $Date: 2012-02-29 18:38:19 -0800 (Wed, 29 Feb 2012) $ */
-#define EGL_EGLEXT_VERSION 11
+/* $Revision: 18699 $ on $Date: 2012-07-31 03:04:59 -0700 (Tue, 31 Jul 2012) $ */
+#define EGL_EGLEXT_VERSION 14
 
 #ifndef EGL_KHR_config_attribs
 #define EGL_KHR_config_attribs 1
@@ -208,12 +208,12 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EG
 typedef void* EGLSyncNV;
 typedef khronos_utime_nanoseconds_t EGLTimeNV;
 #ifdef EGL_EGLEXT_PROTOTYPES
-EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
-EGLBoolean eglDestroySyncNV (EGLSyncNV sync);
-EGLBoolean eglFenceNV (EGLSyncNV sync);
-EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
-EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
-EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
+EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
 #endif /* EGL_EGLEXT_PROTOTYPES */
 typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
@@ -313,7 +313,7 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay
 #define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV    0x3133
 #endif
 
-#if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
+#if KHRONOS_SUPPORT_INT64   /* EGLuint64NV requires 64-bit uint support */
 #ifndef EGL_NV_system_time
 #define EGL_NV_system_time 1
 
@@ -328,6 +328,86 @@ typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
 #endif
 #endif
 
+#if KHRONOS_SUPPORT_INT64 /* EGLuint64KHR requires 64-bit uint support */
+#ifndef EGL_KHR_stream
+#define EGL_KHR_stream 1
+typedef void* EGLStreamKHR;
+typedef khronos_uint64_t EGLuint64KHR;
+#define EGL_NO_STREAM_KHR                      ((EGLStreamKHR)0)
+#define EGL_CONSUMER_LATENCY_USEC_KHR          0x3210
+#define EGL_PRODUCER_FRAME_KHR                 0x3212
+#define EGL_CONSUMER_FRAME_KHR                 0x3213
+#define EGL_STREAM_STATE_KHR                   0x3214
+#define EGL_STREAM_STATE_CREATED_KHR           0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR                0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR             0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR    0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR    0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR      0x321A
+#define EGL_BAD_STREAM_KHR                     0x321B
+#define EGL_BAD_STATE_KHR                      0x321C
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC)(EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#endif
+#endif
+
+#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
+#ifndef EGL_KHR_stream_consumer_gltexture
+#define EGL_KHR_stream_consumer_gltexture 1
+#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR  0x321E
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif
+
+#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
+#ifndef EGL_KHR_stream_producer_eglsurface
+#define EGL_KHR_stream_producer_eglsurface 1
+#define EGL_STREAM_BIT_KHR                     0x0800
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#endif
+#endif
+
+#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
+#ifndef EGL_KHR_stream_producer_aldatalocator
+#define EGL_KHR_stream_producer_aldatalocator 1
+#endif
+#endif
+
+#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
+#ifndef EGL_KHR_stream_fifo
+#define EGL_KHR_stream_fifo 1
+/* reuse EGLTimeKHR */
+#define EGL_STREAM_FIFO_LENGTH_KHR             0x31FC
+#define EGL_STREAM_TIME_NOW_KHR                        0x31FD
+#define EGL_STREAM_TIME_CONSUMER_KHR           0x31FE
+#define EGL_STREAM_TIME_PRODUCER_KHR           0x31FF
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#endif
+#endif
+
 #ifndef EGL_EXT_create_context_robustness
 #define EGL_EXT_create_context_robustness 1
 #define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT   0x30BF
@@ -341,6 +421,42 @@ typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
 /* reuse EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE */
 #endif
 
+#ifndef EGL_KHR_create_context
+#define EGL_KHR_create_context 1
+#define EGL_CONTEXT_MAJOR_VERSION_KHR                      EGL_CONTEXT_CLIENT_VERSION
+#define EGL_CONTEXT_MINOR_VERSION_KHR                      0x30FB
+#define EGL_CONTEXT_FLAGS_KHR                              0x30FC
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR                0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR  0x31BD
+#define EGL_NO_RESET_NOTIFICATION_KHR                      0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR                      0x31BF
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR                   0x00000001
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR      0x00000002
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR           0x00000004
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR                    0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR    0x00000002
+#endif
+
+#ifndef EGL_KHR_surfaceless_context
+#define EGL_KHR_surfaceless_context 1
+/* No tokens/entry points, just relaxes an error condition */
+#endif
+
+#ifdef EGL_KHR_stream /* Requires KHR_stream extension */
+#ifndef EGL_KHR_stream_cross_process_fd
+#define EGL_KHR_stream_cross_process_fd 1
+typedef int EGLNativeFileDescriptorKHR;
+#define EGL_NO_FILE_DESCRIPTOR_KHR             ((EGLNativeFileDescriptorKHR)(-1))
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR(EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR(EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC)(EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC)(EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 9c0cf282eac7fb6430672ba1799b412eb452a2ad..f8b102a565fa4decb0dc1a2bf8f3e16d73e06a9b 100644 (file)
@@ -29,9 +29,9 @@ extern "C" {
 */
 
 /* Header file version number, required by OpenGL ABI for Linux */
-/* glext.h last updated $Date: 2012-03-05 02:52:51 -0800 (Mon, 05 Mar 2012) $ */
+/* glext.h last updated $Date: 2012-08-06 02:01:01 -0700 (Mon, 06 Aug 2012) $ */
 /* Current version at http://www.opengl.org/registry/ */
-#define GL_GLEXT_VERSION 76
+#define GL_GLEXT_VERSION 83
 /* Function declaration macros - to move into glplatform.h */
 
 #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
@@ -1019,6 +1019,7 @@ extern "C" {
 /* reuse GL_MAX_VERTEX_UNIFORM_VECTORS */
 /* reuse GL_MAX_VARYING_VECTORS */
 /* reuse GL_MAX_FRAGMENT_UNIFORM_VECTORS */
+/* reuse GL_RGB565 */
 /* Reuse tokens from ARB_get_program_binary */
 /* reuse GL_PROGRAM_BINARY_RETRIEVABLE_HINT */
 /* reuse GL_PROGRAM_BINARY_LENGTH */
@@ -1163,6 +1164,290 @@ extern "C" {
 /* reuse GL_TEXTURE_IMMUTABLE_FORMAT */
 #endif
 
+#ifndef GL_VERSION_4_3
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS  0x82E9
+#define GL_VERTEX_ATTRIB_ARRAY_LONG       0x874E
+/* Reuse tokens from ARB_arrays_of_arrays (none, GLSL only) */
+/* Reuse tokens from ARB_fragment_layer_viewport (none, GLSL only) */
+/* Reuse tokens from ARB_shader_image_size (none, GLSL only) */
+/* Reuse tokens from ARB_ES3_compatibility */
+/* reuse GL_COMPRESSED_RGB8_ETC2 */
+/* reuse GL_COMPRESSED_SRGB8_ETC2 */
+/* reuse GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 */
+/* reuse GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 */
+/* reuse GL_COMPRESSED_RGBA8_ETC2_EAC */
+/* reuse GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC */
+/* reuse GL_COMPRESSED_R11_EAC */
+/* reuse GL_COMPRESSED_SIGNED_R11_EAC */
+/* reuse GL_COMPRESSED_RG11_EAC */
+/* reuse GL_COMPRESSED_SIGNED_RG11_EAC */
+/* reuse GL_PRIMITIVE_RESTART_FIXED_INDEX */
+/* reuse GL_ANY_SAMPLES_PASSED_CONSERVATIVE */
+/* reuse GL_MAX_ELEMENT_INDEX */
+/* Reuse tokens from ARB_clear_buffer_object (none) */
+/* Reuse tokens from ARB_compute_shader */
+/* reuse GL_COMPUTE_SHADER */
+/* reuse GL_MAX_COMPUTE_UNIFORM_BLOCKS */
+/* reuse GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS */
+/* reuse GL_MAX_COMPUTE_IMAGE_UNIFORMS */
+/* reuse GL_MAX_COMPUTE_SHARED_MEMORY_SIZE */
+/* reuse GL_MAX_COMPUTE_UNIFORM_COMPONENTS */
+/* reuse GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS */
+/* reuse GL_MAX_COMPUTE_ATOMIC_COUNTERS */
+/* reuse GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS */
+/* reuse GL_MAX_COMPUTE_LOCAL_INVOCATIONS */
+/* reuse GL_MAX_COMPUTE_WORK_GROUP_COUNT */
+/* reuse GL_MAX_COMPUTE_WORK_GROUP_SIZE */
+/* reuse GL_COMPUTE_LOCAL_WORK_SIZE */
+/* reuse GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER */
+/* reuse GL_DISPATCH_INDIRECT_BUFFER */
+/* reuse GL_DISPATCH_INDIRECT_BUFFER_BINDING */
+/* Reuse tokens from ARB_copy_image (none) */
+/* Reuse tokens from KHR_debug */
+/* reuse GL_DEBUG_OUTPUT_SYNCHRONOUS */
+/* reuse GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH */
+/* reuse GL_DEBUG_CALLBACK_FUNCTION */
+/* reuse GL_DEBUG_CALLBACK_USER_PARAM */
+/* reuse GL_DEBUG_SOURCE_API */
+/* reuse GL_DEBUG_SOURCE_WINDOW_SYSTEM */
+/* reuse GL_DEBUG_SOURCE_SHADER_COMPILER */
+/* reuse GL_DEBUG_SOURCE_THIRD_PARTY */
+/* reuse GL_DEBUG_SOURCE_APPLICATION */
+/* reuse GL_DEBUG_SOURCE_OTHER */
+/* reuse GL_DEBUG_TYPE_ERROR */
+/* reuse GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR */
+/* reuse GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR */
+/* reuse GL_DEBUG_TYPE_PORTABILITY */
+/* reuse GL_DEBUG_TYPE_PERFORMANCE */
+/* reuse GL_DEBUG_TYPE_OTHER */
+/* reuse GL_MAX_DEBUG_MESSAGE_LENGTH */
+/* reuse GL_MAX_DEBUG_LOGGED_MESSAGES */
+/* reuse GL_DEBUG_LOGGED_MESSAGES */
+/* reuse GL_DEBUG_SEVERITY_HIGH */
+/* reuse GL_DEBUG_SEVERITY_MEDIUM */
+/* reuse GL_DEBUG_SEVERITY_LOW */
+/* reuse GL_DEBUG_TYPE_MARKER */
+/* reuse GL_DEBUG_TYPE_PUSH_GROUP */
+/* reuse GL_DEBUG_TYPE_POP_GROUP */
+/* reuse GL_DEBUG_SEVERITY_NOTIFICATION */
+/* reuse GL_MAX_DEBUG_GROUP_STACK_DEPTH */
+/* reuse GL_DEBUG_GROUP_STACK_DEPTH */
+/* reuse GL_BUFFER */
+/* reuse GL_SHADER */
+/* reuse GL_PROGRAM */
+/* reuse GL_QUERY */
+/* reuse GL_PROGRAM_PIPELINE */
+/* reuse GL_SAMPLER */
+/* reuse GL_DISPLAY_LIST */
+/* reuse GL_MAX_LABEL_LENGTH */
+/* reuse GL_DEBUG_OUTPUT */
+/* reuse GL_CONTEXT_FLAG_DEBUG_BIT */
+/* reuse GL_STACK_UNDERFLOW */
+/* reuse GL_STACK_OVERFLOW */
+/* Reuse tokens from ARB_explicit_uniform_location */
+/* reuse GL_MAX_UNIFORM_LOCATIONS */
+/* Reuse tokens from ARB_framebuffer_no_attachments */
+/* reuse GL_FRAMEBUFFER_DEFAULT_WIDTH */
+/* reuse GL_FRAMEBUFFER_DEFAULT_HEIGHT */
+/* reuse GL_FRAMEBUFFER_DEFAULT_LAYERS */
+/* reuse GL_FRAMEBUFFER_DEFAULT_SAMPLES */
+/* reuse GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS */
+/* reuse GL_MAX_FRAMEBUFFER_WIDTH */
+/* reuse GL_MAX_FRAMEBUFFER_HEIGHT */
+/* reuse GL_MAX_FRAMEBUFFER_LAYERS */
+/* reuse GL_MAX_FRAMEBUFFER_SAMPLES */
+/* Reuse tokens from ARB_internalformat_query2 */
+/* reuse GL_INTERNALFORMAT_SUPPORTED */
+/* reuse GL_INTERNALFORMAT_PREFERRED */
+/* reuse GL_INTERNALFORMAT_RED_SIZE */
+/* reuse GL_INTERNALFORMAT_GREEN_SIZE */
+/* reuse GL_INTERNALFORMAT_BLUE_SIZE */
+/* reuse GL_INTERNALFORMAT_ALPHA_SIZE */
+/* reuse GL_INTERNALFORMAT_DEPTH_SIZE */
+/* reuse GL_INTERNALFORMAT_STENCIL_SIZE */
+/* reuse GL_INTERNALFORMAT_SHARED_SIZE */
+/* reuse GL_INTERNALFORMAT_RED_TYPE */
+/* reuse GL_INTERNALFORMAT_GREEN_TYPE */
+/* reuse GL_INTERNALFORMAT_BLUE_TYPE */
+/* reuse GL_INTERNALFORMAT_ALPHA_TYPE */
+/* reuse GL_INTERNALFORMAT_DEPTH_TYPE */
+/* reuse GL_INTERNALFORMAT_STENCIL_TYPE */
+/* reuse GL_MAX_WIDTH */
+/* reuse GL_MAX_HEIGHT */
+/* reuse GL_MAX_DEPTH */
+/* reuse GL_MAX_LAYERS */
+/* reuse GL_MAX_COMBINED_DIMENSIONS */
+/* reuse GL_COLOR_COMPONENTS */
+/* reuse GL_DEPTH_COMPONENTS */
+/* reuse GL_STENCIL_COMPONENTS */
+/* reuse GL_COLOR_RENDERABLE */
+/* reuse GL_DEPTH_RENDERABLE */
+/* reuse GL_STENCIL_RENDERABLE */
+/* reuse GL_FRAMEBUFFER_RENDERABLE */
+/* reuse GL_FRAMEBUFFER_RENDERABLE_LAYERED */
+/* reuse GL_FRAMEBUFFER_BLEND */
+/* reuse GL_READ_PIXELS */
+/* reuse GL_READ_PIXELS_FORMAT */
+/* reuse GL_READ_PIXELS_TYPE */
+/* reuse GL_TEXTURE_IMAGE_FORMAT */
+/* reuse GL_TEXTURE_IMAGE_TYPE */
+/* reuse GL_GET_TEXTURE_IMAGE_FORMAT */
+/* reuse GL_GET_TEXTURE_IMAGE_TYPE */
+/* reuse GL_MIPMAP */
+/* reuse GL_MANUAL_GENERATE_MIPMAP */
+/* reuse GL_AUTO_GENERATE_MIPMAP */
+/* reuse GL_COLOR_ENCODING */
+/* reuse GL_SRGB_READ */
+/* reuse GL_SRGB_WRITE */
+/* reuse GL_FILTER */
+/* reuse GL_VERTEX_TEXTURE */
+/* reuse GL_TESS_CONTROL_TEXTURE */
+/* reuse GL_TESS_EVALUATION_TEXTURE */
+/* reuse GL_GEOMETRY_TEXTURE */
+/* reuse GL_FRAGMENT_TEXTURE */
+/* reuse GL_COMPUTE_TEXTURE */
+/* reuse GL_TEXTURE_SHADOW */
+/* reuse GL_TEXTURE_GATHER */
+/* reuse GL_TEXTURE_GATHER_SHADOW */
+/* reuse GL_SHADER_IMAGE_LOAD */
+/* reuse GL_SHADER_IMAGE_STORE */
+/* reuse GL_SHADER_IMAGE_ATOMIC */
+/* reuse GL_IMAGE_TEXEL_SIZE */
+/* reuse GL_IMAGE_COMPATIBILITY_CLASS */
+/* reuse GL_IMAGE_PIXEL_FORMAT */
+/* reuse GL_IMAGE_PIXEL_TYPE */
+/* reuse GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST */
+/* reuse GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST */
+/* reuse GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE */
+/* reuse GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE */
+/* reuse GL_TEXTURE_COMPRESSED_BLOCK_WIDTH */
+/* reuse GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT */
+/* reuse GL_TEXTURE_COMPRESSED_BLOCK_SIZE */
+/* reuse GL_CLEAR_BUFFER */
+/* reuse GL_TEXTURE_VIEW */
+/* reuse GL_VIEW_COMPATIBILITY_CLASS */
+/* reuse GL_FULL_SUPPORT */
+/* reuse GL_CAVEAT_SUPPORT */
+/* reuse GL_IMAGE_CLASS_4_X_32 */
+/* reuse GL_IMAGE_CLASS_2_X_32 */
+/* reuse GL_IMAGE_CLASS_1_X_32 */
+/* reuse GL_IMAGE_CLASS_4_X_16 */
+/* reuse GL_IMAGE_CLASS_2_X_16 */
+/* reuse GL_IMAGE_CLASS_1_X_16 */
+/* reuse GL_IMAGE_CLASS_4_X_8 */
+/* reuse GL_IMAGE_CLASS_2_X_8 */
+/* reuse GL_IMAGE_CLASS_1_X_8 */
+/* reuse GL_IMAGE_CLASS_11_11_10 */
+/* reuse GL_IMAGE_CLASS_10_10_10_2 */
+/* reuse GL_VIEW_CLASS_128_BITS */
+/* reuse GL_VIEW_CLASS_96_BITS */
+/* reuse GL_VIEW_CLASS_64_BITS */
+/* reuse GL_VIEW_CLASS_48_BITS */
+/* reuse GL_VIEW_CLASS_32_BITS */
+/* reuse GL_VIEW_CLASS_24_BITS */
+/* reuse GL_VIEW_CLASS_16_BITS */
+/* reuse GL_VIEW_CLASS_8_BITS */
+/* reuse GL_VIEW_CLASS_S3TC_DXT1_RGB */
+/* reuse GL_VIEW_CLASS_S3TC_DXT1_RGBA */
+/* reuse GL_VIEW_CLASS_S3TC_DXT3_RGBA */
+/* reuse GL_VIEW_CLASS_S3TC_DXT5_RGBA */
+/* reuse GL_VIEW_CLASS_RGTC1_RED */
+/* reuse GL_VIEW_CLASS_RGTC2_RG */
+/* reuse GL_VIEW_CLASS_BPTC_UNORM */
+/* reuse GL_VIEW_CLASS_BPTC_FLOAT */
+/* Reuse tokens from ARB_invalidate_subdata (none) */
+/* Reuse tokens from ARB_multi_draw_indirect (none) */
+/* Reuse tokens from ARB_program_interface_query */
+/* reuse GL_UNIFORM */
+/* reuse GL_UNIFORM_BLOCK */
+/* reuse GL_PROGRAM_INPUT */
+/* reuse GL_PROGRAM_OUTPUT */
+/* reuse GL_BUFFER_VARIABLE */
+/* reuse GL_SHADER_STORAGE_BLOCK */
+/* reuse GL_VERTEX_SUBROUTINE */
+/* reuse GL_TESS_CONTROL_SUBROUTINE */
+/* reuse GL_TESS_EVALUATION_SUBROUTINE */
+/* reuse GL_GEOMETRY_SUBROUTINE */
+/* reuse GL_FRAGMENT_SUBROUTINE */
+/* reuse GL_COMPUTE_SUBROUTINE */
+/* reuse GL_VERTEX_SUBROUTINE_UNIFORM */
+/* reuse GL_TESS_CONTROL_SUBROUTINE_UNIFORM */
+/* reuse GL_TESS_EVALUATION_SUBROUTINE_UNIFORM */
+/* reuse GL_GEOMETRY_SUBROUTINE_UNIFORM */
+/* reuse GL_FRAGMENT_SUBROUTINE_UNIFORM */
+/* reuse GL_COMPUTE_SUBROUTINE_UNIFORM */
+/* reuse GL_TRANSFORM_FEEDBACK_VARYING */
+/* reuse GL_ACTIVE_RESOURCES */
+/* reuse GL_MAX_NAME_LENGTH */
+/* reuse GL_MAX_NUM_ACTIVE_VARIABLES */
+/* reuse GL_MAX_NUM_COMPATIBLE_SUBROUTINES */
+/* reuse GL_NAME_LENGTH */
+/* reuse GL_TYPE */
+/* reuse GL_ARRAY_SIZE */
+/* reuse GL_OFFSET */
+/* reuse GL_BLOCK_INDEX */
+/* reuse GL_ARRAY_STRIDE */
+/* reuse GL_MATRIX_STRIDE */
+/* reuse GL_IS_ROW_MAJOR */
+/* reuse GL_ATOMIC_COUNTER_BUFFER_INDEX */
+/* reuse GL_BUFFER_BINDING */
+/* reuse GL_BUFFER_DATA_SIZE */
+/* reuse GL_NUM_ACTIVE_VARIABLES */
+/* reuse GL_ACTIVE_VARIABLES */
+/* reuse GL_REFERENCED_BY_VERTEX_SHADER */
+/* reuse GL_REFERENCED_BY_TESS_CONTROL_SHADER */
+/* reuse GL_REFERENCED_BY_TESS_EVALUATION_SHADER */
+/* reuse GL_REFERENCED_BY_GEOMETRY_SHADER */
+/* reuse GL_REFERENCED_BY_FRAGMENT_SHADER */
+/* reuse GL_REFERENCED_BY_COMPUTE_SHADER */
+/* reuse GL_TOP_LEVEL_ARRAY_SIZE */
+/* reuse GL_TOP_LEVEL_ARRAY_STRIDE */
+/* reuse GL_LOCATION */
+/* reuse GL_LOCATION_INDEX */
+/* reuse GL_IS_PER_PATCH */
+/* Reuse tokens from ARB_robust_buffer_access_behavior (none) */
+/* Reuse tokens from ARB_shader_storage_buffer_object */
+/* reuse GL_SHADER_STORAGE_BUFFER */
+/* reuse GL_SHADER_STORAGE_BUFFER_BINDING */
+/* reuse GL_SHADER_STORAGE_BUFFER_START */
+/* reuse GL_SHADER_STORAGE_BUFFER_SIZE */
+/* reuse GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS */
+/* reuse GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS */
+/* reuse GL_MAX_SHADER_STORAGE_BLOCK_SIZE */
+/* reuse GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT */
+/* reuse GL_SHADER_STORAGE_BARRIER_BIT */
+/* reuse GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES */
+/* Reuse tokens from ARB_stencil_texturing */
+/* reuse GL_DEPTH_STENCIL_TEXTURE_MODE */
+/* Reuse tokens from ARB_texture_buffer_range */
+/* reuse GL_TEXTURE_BUFFER_OFFSET */
+/* reuse GL_TEXTURE_BUFFER_SIZE */
+/* reuse GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT */
+/* Reuse tokens from ARB_texture_query_levels (none) */
+/* Reuse tokens from ARB_texture_storage_multisample (none) */
+/* Reuse tokens from ARB_texture_view */
+/* reuse GL_TEXTURE_VIEW_MIN_LEVEL */
+/* reuse GL_TEXTURE_VIEW_NUM_LEVELS */
+/* reuse GL_TEXTURE_VIEW_MIN_LAYER */
+/* reuse GL_TEXTURE_VIEW_NUM_LAYERS */
+/* reuse GL_TEXTURE_IMMUTABLE_LEVELS */
+/* Reuse tokens from ARB_vertex_attrib_binding */
+/* reuse GL_VERTEX_ATTRIB_BINDING */
+/* reuse GL_VERTEX_ATTRIB_RELATIVE_OFFSET */
+/* reuse GL_VERTEX_BINDING_DIVISOR */
+/* reuse GL_VERTEX_BINDING_OFFSET */
+/* reuse GL_VERTEX_BINDING_STRIDE */
+/* reuse GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET */
+/* reuse GL_MAX_VERTEX_ATTRIB_BINDINGS */
+#endif
+
 #ifndef GL_ARB_multitexture
 #define GL_TEXTURE0_ARB                   0x84C0
 #define GL_TEXTURE1_ARB                   0x84C1
@@ -1882,8 +2167,10 @@ extern "C" {
 #endif
 
 #ifndef GL_ARB_copy_buffer
-#define GL_COPY_READ_BUFFER               0x8F36
-#define GL_COPY_WRITE_BUFFER              0x8F37
+#define GL_COPY_READ_BUFFER_BINDING       0x8F36
+#define GL_COPY_READ_BUFFER               GL_COPY_READ_BUFFER_BINDING
+#define GL_COPY_WRITE_BUFFER_BINDING      0x8F37
+#define GL_COPY_WRITE_BUFFER              GL_COPY_WRITE_BUFFER_BINDING
 #endif
 
 #ifndef GL_ARB_shader_texture_lod
@@ -2131,8 +2418,10 @@ extern "C" {
 
 #ifndef GL_ARB_transform_feedback2
 #define GL_TRANSFORM_FEEDBACK             0x8E22
-#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
-#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_PAUSED      0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED GL_TRANSFORM_FEEDBACK_PAUSED
+#define GL_TRANSFORM_FEEDBACK_ACTIVE      0x8E24
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE GL_TRANSFORM_FEEDBACK_ACTIVE
 #define GL_TRANSFORM_FEEDBACK_BINDING     0x8E25
 #endif
 
@@ -2156,6 +2445,7 @@ extern "C" {
 #define GL_MAX_VERTEX_UNIFORM_VECTORS     0x8DFB
 #define GL_MAX_VARYING_VECTORS            0x8DFC
 #define GL_MAX_FRAGMENT_UNIFORM_VECTORS   0x8DFD
+#define GL_RGB565                         0x8D62
 #endif
 
 #ifndef GL_ARB_get_program_binary
@@ -2393,6 +2683,414 @@ extern "C" {
 #define GL_TEXTURE_IMMUTABLE_FORMAT       0x912F
 #endif
 
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR   0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR   0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR   0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR   0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR   0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR   0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR   0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR   0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR  0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR  0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR  0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif
+
+#ifndef GL_KHR_debug
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS       0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION        0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM      0x8245
+#define GL_DEBUG_SOURCE_API               0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM     0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER   0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY       0x8249
+#define GL_DEBUG_SOURCE_APPLICATION       0x824A
+#define GL_DEBUG_SOURCE_OTHER             0x824B
+#define GL_DEBUG_TYPE_ERROR               0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR  0x824E
+#define GL_DEBUG_TYPE_PORTABILITY         0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE         0x8250
+#define GL_DEBUG_TYPE_OTHER               0x8251
+#define GL_DEBUG_TYPE_MARKER              0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP          0x8269
+#define GL_DEBUG_TYPE_POP_GROUP           0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION    0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH    0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH        0x826D
+#define GL_BUFFER                         0x82E0
+#define GL_SHADER                         0x82E1
+#define GL_PROGRAM                        0x82E2
+#define GL_QUERY                          0x82E3
+#define GL_PROGRAM_PIPELINE               0x82E4
+#define GL_SAMPLER                        0x82E6
+#define GL_DISPLAY_LIST                   0x82E7
+#define GL_MAX_LABEL_LENGTH               0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH       0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES      0x9144
+#define GL_DEBUG_LOGGED_MESSAGES          0x9145
+#define GL_DEBUG_SEVERITY_HIGH            0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM          0x9147
+#define GL_DEBUG_SEVERITY_LOW             0x9148
+#define GL_DEBUG_OUTPUT                   0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT         0x00000002
+/* reuse GL_STACK_UNDERFLOW */
+/* reuse GL_STACK_OVERFLOW */
+#endif
+
+#ifndef GL_ARB_arrays_of_arrays
+#endif
+
+#ifndef GL_ARB_clear_buffer_object
+#endif
+
+#ifndef GL_ARB_compute_shader
+#define GL_COMPUTE_SHADER                 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS     0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS     0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS    0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_LOCAL_INVOCATIONS  0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT   0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE    0x91BF
+#define GL_COMPUTE_LOCAL_WORK_SIZE        0x8267
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#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
+#endif
+
+#ifndef GL_ARB_copy_image
+#endif
+
+#ifndef GL_ARB_debug_group
+/* reuse GL_DEBUG_TYPE_MARKER */
+/* reuse GL_DEBUG_TYPE_PUSH_GROUP */
+/* reuse GL_DEBUG_TYPE_POP_GROUP */
+/* reuse GL_DEBUG_SEVERITY_NOTIFICATION */
+/* reuse GL_MAX_DEBUG_GROUP_STACK_DEPTH */
+/* reuse GL_DEBUG_GROUP_STACK_DEPTH */
+/* reuse GL_STACK_UNDERFLOW */
+/* reuse GL_STACK_OVERFLOW */
+#endif
+
+#ifndef GL_ARB_debug_label
+/* reuse GL_BUFFER */
+/* reuse GL_SHADER */
+/* reuse GL_PROGRAM */
+/* reuse GL_QUERY */
+/* reuse GL_PROGRAM_PIPELINE */
+/* reuse GL_SAMPLER */
+/* DISPLAY_LIST used in compatibility profile only */
+/* reuse GL_DISPLAY_LIST */
+/* reuse GL_MAX_LABEL_LENGTH */
+/* reuse GL_VERTEX_ARRAY */
+#endif
+
+#ifndef GL_ARB_debug_output2
+/* reuse GL_CONTEXT_FLAG_DEBUG_BIT */
+/* reuse GL_DEBUG_OUTPUT */
+#endif
+
+#ifndef GL_ARB_ES3_compatibility
+#define GL_COMPRESSED_RGB8_ETC2           0x9274
+#define GL_COMPRESSED_SRGB8_ETC2          0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC      0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_COMPRESSED_R11_EAC             0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC      0x9271
+#define GL_COMPRESSED_RG11_EAC            0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC     0x9273
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX  0x8D69
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_MAX_ELEMENT_INDEX              0x8D6B
+#endif
+
+#ifndef GL_ARB_explicit_uniform_location
+#define GL_MAX_UNIFORM_LOCATIONS          0x826E
+#endif
+
+#ifndef GL_ARB_fragment_layer_viewport
+#endif
+
+#ifndef GL_ARB_framebuffer_no_attachments
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH      0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT     0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS     0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES    0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH          0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT         0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS         0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES        0x9318
+#endif
+
+#ifndef GL_ARB_internalformat_query2
+/* reuse GL_IMAGE_FORMAT_COMPATIBILITY_TYPE */
+/* reuse GL_NUM_SAMPLE_COUNTS */
+/* reuse GL_RENDERBUFFER */
+/* reuse GL_SAMPLES */
+/* reuse GL_TEXTURE_1D */
+/* reuse GL_TEXTURE_1D_ARRAY */
+/* reuse GL_TEXTURE_2D */
+/* reuse GL_TEXTURE_2D_ARRAY */
+/* reuse GL_TEXTURE_3D */
+/* reuse GL_TEXTURE_CUBE_MAP */
+/* reuse GL_TEXTURE_CUBE_MAP_ARRAY */
+/* reuse GL_TEXTURE_RECTANGLE */
+/* reuse GL_TEXTURE_BUFFER */
+/* reuse GL_TEXTURE_2D_MULTISAMPLE */
+/* reuse GL_TEXTURE_2D_MULTISAMPLE_ARRAY */
+/* reuse GL_TEXTURE_COMPRESSED */
+#define GL_INTERNALFORMAT_SUPPORTED       0x826F
+#define GL_INTERNALFORMAT_PREFERRED       0x8270
+#define GL_INTERNALFORMAT_RED_SIZE        0x8271
+#define GL_INTERNALFORMAT_GREEN_SIZE      0x8272
+#define GL_INTERNALFORMAT_BLUE_SIZE       0x8273
+#define GL_INTERNALFORMAT_ALPHA_SIZE      0x8274
+#define GL_INTERNALFORMAT_DEPTH_SIZE      0x8275
+#define GL_INTERNALFORMAT_STENCIL_SIZE    0x8276
+#define GL_INTERNALFORMAT_SHARED_SIZE     0x8277
+#define GL_INTERNALFORMAT_RED_TYPE        0x8278
+#define GL_INTERNALFORMAT_GREEN_TYPE      0x8279
+#define GL_INTERNALFORMAT_BLUE_TYPE       0x827A
+#define GL_INTERNALFORMAT_ALPHA_TYPE      0x827B
+#define GL_INTERNALFORMAT_DEPTH_TYPE      0x827C
+#define GL_INTERNALFORMAT_STENCIL_TYPE    0x827D
+#define GL_MAX_WIDTH                      0x827E
+#define GL_MAX_HEIGHT                     0x827F
+#define GL_MAX_DEPTH                      0x8280
+#define GL_MAX_LAYERS                     0x8281
+#define GL_MAX_COMBINED_DIMENSIONS        0x8282
+#define GL_COLOR_COMPONENTS               0x8283
+#define GL_DEPTH_COMPONENTS               0x8284
+#define GL_STENCIL_COMPONENTS             0x8285
+#define GL_COLOR_RENDERABLE               0x8286
+#define GL_DEPTH_RENDERABLE               0x8287
+#define GL_STENCIL_RENDERABLE             0x8288
+#define GL_FRAMEBUFFER_RENDERABLE         0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FRAMEBUFFER_BLEND              0x828B
+#define GL_READ_PIXELS                    0x828C
+#define GL_READ_PIXELS_FORMAT             0x828D
+#define GL_READ_PIXELS_TYPE               0x828E
+#define GL_TEXTURE_IMAGE_FORMAT           0x828F
+#define GL_TEXTURE_IMAGE_TYPE             0x8290
+#define GL_GET_TEXTURE_IMAGE_FORMAT       0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE         0x8292
+#define GL_MIPMAP                         0x8293
+#define GL_MANUAL_GENERATE_MIPMAP         0x8294
+#define GL_AUTO_GENERATE_MIPMAP           0x8295
+#define GL_COLOR_ENCODING                 0x8296
+#define GL_SRGB_READ                      0x8297
+#define GL_SRGB_WRITE                     0x8298
+#define GL_SRGB_DECODE_ARB                0x8299
+#define GL_FILTER                         0x829A
+#define GL_VERTEX_TEXTURE                 0x829B
+#define GL_TESS_CONTROL_TEXTURE           0x829C
+#define GL_TESS_EVALUATION_TEXTURE        0x829D
+#define GL_GEOMETRY_TEXTURE               0x829E
+#define GL_FRAGMENT_TEXTURE               0x829F
+#define GL_COMPUTE_TEXTURE                0x82A0
+#define GL_TEXTURE_SHADOW                 0x82A1
+#define GL_TEXTURE_GATHER                 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW          0x82A3
+#define GL_SHADER_IMAGE_LOAD              0x82A4
+#define GL_SHADER_IMAGE_STORE             0x82A5
+#define GL_SHADER_IMAGE_ATOMIC            0x82A6
+#define GL_IMAGE_TEXEL_SIZE               0x82A7
+#define GL_IMAGE_COMPATIBILITY_CLASS      0x82A8
+#define GL_IMAGE_PIXEL_FORMAT             0x82A9
+#define GL_IMAGE_PIXEL_TYPE               0x82AA
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE  0x82B3
+#define GL_CLEAR_BUFFER                   0x82B4
+#define GL_TEXTURE_VIEW                   0x82B5
+#define GL_VIEW_COMPATIBILITY_CLASS       0x82B6
+#define GL_FULL_SUPPORT                   0x82B7
+#define GL_CAVEAT_SUPPORT                 0x82B8
+#define GL_IMAGE_CLASS_4_X_32             0x82B9
+#define GL_IMAGE_CLASS_2_X_32             0x82BA
+#define GL_IMAGE_CLASS_1_X_32             0x82BB
+#define GL_IMAGE_CLASS_4_X_16             0x82BC
+#define GL_IMAGE_CLASS_2_X_16             0x82BD
+#define GL_IMAGE_CLASS_1_X_16             0x82BE
+#define GL_IMAGE_CLASS_4_X_8              0x82BF
+#define GL_IMAGE_CLASS_2_X_8              0x82C0
+#define GL_IMAGE_CLASS_1_X_8              0x82C1
+#define GL_IMAGE_CLASS_11_11_10           0x82C2
+#define GL_IMAGE_CLASS_10_10_10_2         0x82C3
+#define GL_VIEW_CLASS_128_BITS            0x82C4
+#define GL_VIEW_CLASS_96_BITS             0x82C5
+#define GL_VIEW_CLASS_64_BITS             0x82C6
+#define GL_VIEW_CLASS_48_BITS             0x82C7
+#define GL_VIEW_CLASS_32_BITS             0x82C8
+#define GL_VIEW_CLASS_24_BITS             0x82C9
+#define GL_VIEW_CLASS_16_BITS             0x82CA
+#define GL_VIEW_CLASS_8_BITS              0x82CB
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB       0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA      0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA      0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA      0x82CF
+#define GL_VIEW_CLASS_RGTC1_RED           0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG            0x82D1
+#define GL_VIEW_CLASS_BPTC_UNORM          0x82D2
+#define GL_VIEW_CLASS_BPTC_FLOAT          0x82D3
+#endif
+
+#ifndef GL_ARB_invalidate_subdata
+#endif
+
+#ifndef GL_ARB_multi_draw_indirect
+#endif
+
+#ifndef GL_ARB_program_interface_query
+#define GL_UNIFORM                        0x92E1
+#define GL_UNIFORM_BLOCK                  0x92E2
+#define GL_PROGRAM_INPUT                  0x92E3
+#define GL_PROGRAM_OUTPUT                 0x92E4
+#define GL_BUFFER_VARIABLE                0x92E5
+#define GL_SHADER_STORAGE_BLOCK           0x92E6
+/* reuse GL_ATOMIC_COUNTER_BUFFER */
+#define GL_VERTEX_SUBROUTINE              0x92E8
+#define GL_TESS_CONTROL_SUBROUTINE        0x92E9
+#define GL_TESS_EVALUATION_SUBROUTINE     0x92EA
+#define GL_GEOMETRY_SUBROUTINE            0x92EB
+#define GL_FRAGMENT_SUBROUTINE            0x92EC
+#define GL_COMPUTE_SUBROUTINE             0x92ED
+#define GL_VERTEX_SUBROUTINE_UNIFORM      0x92EE
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM    0x92F1
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM    0x92F2
+#define GL_COMPUTE_SUBROUTINE_UNIFORM     0x92F3
+#define GL_TRANSFORM_FEEDBACK_VARYING     0x92F4
+#define GL_ACTIVE_RESOURCES               0x92F5
+#define GL_MAX_NAME_LENGTH                0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES       0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_NAME_LENGTH                    0x92F9
+#define GL_TYPE                           0x92FA
+#define GL_ARRAY_SIZE                     0x92FB
+#define GL_OFFSET                         0x92FC
+#define GL_BLOCK_INDEX                    0x92FD
+#define GL_ARRAY_STRIDE                   0x92FE
+#define GL_MATRIX_STRIDE                  0x92FF
+#define GL_IS_ROW_MAJOR                   0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX    0x9301
+#define GL_BUFFER_BINDING                 0x9302
+#define GL_BUFFER_DATA_SIZE               0x9303
+#define GL_NUM_ACTIVE_VARIABLES           0x9304
+#define GL_ACTIVE_VARIABLES               0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER    0x9306
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_GEOMETRY_SHADER  0x9309
+#define GL_REFERENCED_BY_FRAGMENT_SHADER  0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER   0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE           0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE         0x930D
+#define GL_LOCATION                       0x930E
+#define GL_LOCATION_INDEX                 0x930F
+#define GL_IS_PER_PATCH                   0x92E7
+/* reuse GL_NUM_COMPATIBLE_SUBROUTINES */
+/* reuse GL_COMPATIBLE_SUBROUTINES */
+#endif
+
+#ifndef GL_ARB_robust_buffer_access_behavior
+#endif
+
+#ifndef GL_ARB_shader_image_size
+#endif
+
+#ifndef GL_ARB_shader_storage_buffer_object
+#define GL_SHADER_STORAGE_BUFFER          0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING  0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START    0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE     0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE  0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT     0x2000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS
+/* reuse GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS */
+#endif
+
+#ifndef GL_ARB_stencil_texturing
+#define GL_DEPTH_STENCIL_TEXTURE_MODE     0x90EA
+#endif
+
+#ifndef GL_ARB_texture_buffer_range
+#define GL_TEXTURE_BUFFER_OFFSET          0x919D
+#define GL_TEXTURE_BUFFER_SIZE            0x919E
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#endif
+
+#ifndef GL_ARB_texture_query_levels
+#endif
+
+#ifndef GL_ARB_texture_storage_multisample
+#endif
+
+#ifndef GL_ARB_texture_view
+#define GL_TEXTURE_VIEW_MIN_LEVEL         0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS        0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER         0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS        0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
+#endif
+
+#ifndef GL_ARB_vertex_attrib_binding
+#define GL_VERTEX_ATTRIB_BINDING          0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET  0x82D5
+#define GL_VERTEX_BINDING_DIVISOR         0x82D6
+#define GL_VERTEX_BINDING_OFFSET          0x82D7
+#define GL_VERTEX_BINDING_STRIDE          0x82D8
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS     0x82DA
+#endif
+
+#ifndef GL_ARB_robustness_isolation
+#endif
+
 #ifndef GL_EXT_abgr
 #define GL_ABGR_EXT                       0x8000
 #endif
@@ -5460,6 +6158,24 @@ extern "C" {
 #define GL_STENCIL_BACK_OP_VALUE_AMD      0x874D
 #endif
 
+#ifndef GL_AMD_vertex_shader_viewport_index
+#endif
+
+#ifndef GL_AMD_vertex_shader_layer
+#endif
+
+#ifndef GL_NV_bindless_texture
+#endif
+
+#ifndef GL_NV_shader_atomic_float
+#endif
+
+#ifndef GL_AMD_query_buffer_object
+#define GL_QUERY_BUFFER_AMD               0x9192
+#define GL_QUERY_BUFFER_BINDING_AMD       0x9193
+#define GL_QUERY_RESULT_NO_WAIT_AMD       0x9194
+#endif
+
 
 /*************************************************************/
 
@@ -5563,6 +6279,10 @@ typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLen
 typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
 #endif
 
+#ifndef GL_KHR_debug
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#endif
+
 #ifndef GL_NV_vdpau_interop
 typedef GLintptr GLvdpauSurfaceNV;
 #endif
@@ -5570,14 +6290,14 @@ typedef GLintptr GLvdpauSurfaceNV;
 #ifndef GL_VERSION_1_2
 #define GL_VERSION_1_2 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
 GLAPI void APIENTRY glBlendEquation (GLenum mode);
 GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
 GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
 GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
 GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
 typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
 typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
 typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
@@ -5659,7 +6379,7 @@ typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);
 #define GL_VERSION_1_3 1
 #ifdef GL_GLEXT_PROTOTYPES
 GLAPI void APIENTRY glActiveTexture (GLenum texture);
-GLAPI void APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
 GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
 GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
 GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
@@ -5669,7 +6389,7 @@ GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint
 GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, GLvoid *img);
 #endif /* GL_GLEXT_PROTOTYPES */
 typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
-typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
 typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
 typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
 typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
@@ -5763,16 +6483,16 @@ typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);
 #define GL_VERSION_1_4 1
 #ifdef GL_GLEXT_PROTOTYPES
 GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
-GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
-GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount);
 GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param);
 GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params);
 GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param);
 GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params);
 #endif /* GL_GLEXT_PROTOTYPES */
 typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
-typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount);
 typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
 typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
 typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
@@ -5942,7 +6662,7 @@ GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoi
 GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
 GLAPI GLboolean APIENTRY glIsShader (GLuint shader);
 GLAPI void APIENTRY glLinkProgram (GLuint program);
-GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);
+GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length);
 GLAPI void APIENTRY glUseProgram (GLuint program);
 GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0);
 GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
@@ -6036,7 +6756,7 @@ typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum
 typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
 typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
 typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
-typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length);
 typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
 typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
 typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
@@ -6132,7 +6852,7 @@ GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
 GLAPI void APIENTRY glEndTransformFeedback (void);
 GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
 GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
-GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode);
+GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* const *varyings, GLenum bufferMode);
 GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
 GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp);
 GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode);
@@ -6191,7 +6911,7 @@ typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
 typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
 typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
 typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
-typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar* *varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar* const *varyings, GLenum bufferMode);
 typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
 typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp);
 typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode);
@@ -6247,13 +6967,13 @@ typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint ind
 /* ARB_copy_buffer */
 /* ARB_uniform_buffer_object */
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount);
 GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
 GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount);
 typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
 typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index);
 #endif
@@ -6308,13 +7028,13 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divi
 /* ARB_transform_feedback2 */
 /* ARB_transform_feedback3 */
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glMinSampleShading (GLclampf value);
+GLAPI void APIENTRY glMinSampleShading (GLfloat value);
 GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
 GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
 GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
 GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLclampf value);
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value);
 typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
 typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
 typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
@@ -6348,6 +7068,36 @@ typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB,
 /* ARB_texture_storage */
 #endif
 
+#ifndef GL_VERSION_4_3
+#define GL_VERSION_4_3 1
+/* OpenGL 4.3 reuses entry points from these extensions: */
+/* ARB_arrays_of_arrays (no entry points, GLSL only) */
+/* ARB_fragment_layer_viewport (no entry points, GLSL only) */
+/* ARB_shader_image_size (no entry points, GLSL only) */
+/* ARB_ES3_compatibility (no entry points) */
+/* ARB_clear_buffer_object */
+/* ARB_compute_shader */
+/* ARB_copy_image */
+/* ARB_debug_group */
+/* ARB_debug_label */
+/* KHR_debug (ARB_debug_output promoted to KHR without suffixes) */
+/* ARB_debug_output2 (no entry points) */
+/* ARB_explicit_uniform_location (no entry points) */
+/* ARB_framebuffer_no_attachments */
+/* ARB_internalformat_query2 */
+/* ARB_invalidate_subdata */
+/* ARB_multi_draw_indirect */
+/* ARB_program_interface_query */
+/* ARB_robust_buffer_access_behavior (no entry points) */
+/* ARB_shader_storage_buffer_object */
+/* ARB_stencil_texturing (no entry points) */
+/* ARB_texture_buffer_range */
+/* ARB_texture_query_levels (no entry points) */
+/* ARB_texture_storage_multisample */
+/* ARB_texture_view */
+/* ARB_vertex_attrib_binding */
+#endif
+
 #ifndef GL_ARB_multitexture
 #define GL_ARB_multitexture 1
 #ifdef GL_GLEXT_PROTOTYPES
@@ -6439,9 +7189,9 @@ typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
 #ifndef GL_ARB_multisample
 #define GL_ARB_multisample 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glSampleCoverageARB (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSampleCoverageARB (GLfloat value, GLboolean invert);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLfloat value, GLboolean invert);
 #endif
 
 #ifndef GL_ARB_texture_env_add
@@ -7060,7 +7810,7 @@ typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
 #ifndef GL_ARB_uniform_buffer_object
 #define GL_ARB_uniform_buffer_object 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* *uniformNames, GLuint *uniformIndices);
+GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const *uniformNames, GLuint *uniformIndices);
 GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
 GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
 GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
@@ -7068,7 +7818,7 @@ GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlo
 GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
 GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar* *uniformNames, GLuint *uniformIndices);
+typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar* const *uniformNames, GLuint *uniformIndices);
 typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
 typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
 typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
@@ -7102,13 +7852,13 @@ typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum w
 #ifdef GL_GLEXT_PROTOTYPES
 GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
 GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
-GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex);
-GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint *basevertex);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount, GLint basevertex);
+GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount, const GLint *basevertex);
 #endif /* GL_GLEXT_PROTOTYPES */
 typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
 typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex);
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex);
-typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint *basevertex);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instancecount, GLint basevertex);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount, const GLint *basevertex);
 #endif
 
 #ifndef GL_ARB_fragment_coord_conventions
@@ -7182,9 +7932,9 @@ typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcR
 #ifndef GL_ARB_sample_shading
 #define GL_ARB_sample_shading 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glMinSampleShadingARB (GLclampf value);
+GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value);
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLfloat value);
 #endif
 
 #ifndef GL_ARB_texture_cube_map_array
@@ -7511,14 +8261,14 @@ typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index
 GLAPI void APIENTRY glReleaseShaderCompiler (void);
 GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length);
 GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
-GLAPI void APIENTRY glDepthRangef (GLclampf n, GLclampf f);
-GLAPI void APIENTRY glClearDepthf (GLclampf d);
+GLAPI void APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GLAPI void APIENTRY glClearDepthf (GLfloat d);
 #endif /* GL_GLEXT_PROTOTYPES */
 typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
 typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const GLvoid *binary, GLsizei length);
 typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
-typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f);
-typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLclampf d);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
 #endif
 
 #ifndef GL_ARB_get_program_binary
@@ -7538,7 +8288,7 @@ typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pnam
 #ifdef GL_GLEXT_PROTOTYPES
 GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
 GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
-GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar* *strings);
+GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar* const *strings);
 GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline);
 GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
 GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
@@ -7599,7 +8349,7 @@ GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSiz
 #endif /* GL_GLEXT_PROTOTYPES */
 typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
 typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
-typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar* *strings);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar* const *strings);
 typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
 typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
 typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
@@ -7694,8 +8444,8 @@ GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v);
 GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v);
 GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
 GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v);
-GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLclampd *v);
-GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLclampd n, GLclampd f);
+GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLdouble n, GLdouble f);
 GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data);
 GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data);
 #endif /* GL_GLEXT_PROTOTYPES */
@@ -7705,8 +8455,8 @@ typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat
 typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v);
 typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
 typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v);
-typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd *v);
-typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f);
+typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLdouble n, GLdouble f);
 typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
 typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
 #endif
@@ -7786,13 +8536,13 @@ typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint locati
 #ifndef GL_ARB_base_instance
 #define GL_ARB_base_instance 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei primcount, GLuint baseinstance);
-GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount, GLuint baseinstance);
-GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance);
+GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount, GLuint baseinstance);
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount, GLuint baseinstance);
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
 #endif
 
 #ifndef GL_ARB_shading_language_420pack
@@ -7802,11 +8552,11 @@ typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (G
 #ifndef GL_ARB_transform_feedback_instanced
 #define GL_ARB_transform_feedback_instanced 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glDrawTransformFeedbackInstanced (GLenum mode, GLuint id, GLsizei primcount);
-GLAPI void APIENTRY glDrawTransformFeedbackStreamInstanced (GLenum mode, GLuint id, GLuint stream, GLsizei primcount);
+GLAPI void APIENTRY glDrawTransformFeedbackInstanced (GLenum mode, GLuint id, GLsizei instancecount);
+GLAPI void APIENTRY glDrawTransformFeedbackStreamInstanced (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei primcount);
-typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
 #endif
 
 #ifndef GL_ARB_compressed_texture_pixel_storage
@@ -7869,6 +8619,257 @@ typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum ta
 typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 #endif
 
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+/* KHR_debug also reuses entry points from ARB_debug_group and ARB_debug_label */
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GLAPI void APIENTRY glPopDebugGroup (void);
+GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+#ifndef GL_ARB_arrays_of_arrays
+#define GL_ARB_arrays_of_arrays 1
+#endif
+
+#ifndef GL_ARB_clear_buffer_object
+#define GL_ARB_clear_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClearBufferData (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearNamedBufferDataEXT (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, GLsizeiptr offset, GLsizeiptr size, const void *data);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, GLsizeiptr offset, GLsizeiptr size, const void *data);
+#endif
+
+#ifndef GL_ARB_compute_shader
+#define GL_ARB_compute_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+#endif
+
+#ifndef GL_ARB_copy_image
+#define GL_ARB_copy_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyImageSubData (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 /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (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
+
+#ifndef GL_ARB_debug_group
+#define GL_ARB_debug_group 1
+/* ARB_debug_group reuses entry points from KHR_debug */
+#endif
+
+#ifndef GL_ARB_debug_label
+#define GL_ARB_debug_label 1
+/* ARB_debug_label reuses entry points from KHR_debug */
+#endif
+
+#ifndef GL_ARB_debug_output2
+#define GL_ARB_debug_output2 1
+#endif
+
+#ifndef GL_ARB_ES3_compatibility
+#define GL_ARB_ES3_compatibility 1
+#endif
+
+#ifndef GL_ARB_explicit_uniform_location
+#define GL_ARB_explicit_uniform_location 1
+#endif
+
+#ifndef GL_ARB_fragment_layer_viewport
+#define GL_ARB_fragment_layer_viewport 1
+#endif
+
+#ifndef GL_ARB_framebuffer_no_attachments
+#define GL_ARB_framebuffer_no_attachments 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glNamedFramebufferParameteriEXT (GLuint framebuffer, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetNamedFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params);
+#endif
+
+#ifndef GL_ARB_internalformat_query2
+#define GL_ARB_internalformat_query2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+#endif
+
+#ifndef GL_ARB_invalidate_subdata
+#define GL_ARB_invalidate_subdata 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level);
+GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glInvalidateBufferData (GLuint buffer);
+GLAPI void APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GLAPI void APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_ARB_multi_draw_indirect
+#define GL_ARB_multi_draw_indirect 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirect (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#endif
+
+#ifndef GL_ARB_program_interface_query
+#define GL_ARB_program_interface_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+#endif
+
+#ifndef GL_ARB_robust_buffer_access_behavior
+#define GL_ARB_robust_buffer_access_behavior 1
+#endif
+
+#ifndef GL_ARB_shader_image_size
+#define GL_ARB_shader_image_size 1
+#endif
+
+#ifndef GL_ARB_shader_storage_buffer_object
+#define GL_ARB_shader_storage_buffer_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+#endif
+
+#ifndef GL_ARB_stencil_texturing
+#define GL_ARB_stencil_texturing 1
+#endif
+
+#ifndef GL_ARB_texture_buffer_range
+#define GL_ARB_texture_buffer_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glTextureBufferRangeEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif
+
+#ifndef GL_ARB_texture_query_levels
+#define GL_ARB_texture_query_levels 1
+#endif
+
+#ifndef GL_ARB_texture_storage_multisample
+#define GL_ARB_texture_storage_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureStorage2DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureStorage3DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif
+
+#ifndef GL_ARB_texture_view
+#define GL_ARB_texture_view 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureView (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif
+
+#ifndef GL_ARB_vertex_attrib_binding
+#define GL_ARB_vertex_attrib_binding 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribLFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glVertexArrayBindVertexBufferEXT (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexArrayVertexAttribFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribIFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+#endif
+
+#ifndef GL_ARB_robustness_isolation
+#define GL_ARB_robustness_isolation 1
+#endif
+
 #ifndef GL_EXT_abgr
 #define GL_EXT_abgr 1
 #endif
@@ -7876,9 +8877,9 @@ typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum ta
 #ifndef GL_EXT_blend_color
 #define GL_EXT_blend_color 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glBlendColorEXT (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GLAPI void APIENTRY glBlendColorEXT (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
 #endif
 
 #ifndef GL_EXT_polygon_offset
@@ -10034,10 +11035,10 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, c
 #ifndef GL_NV_pixel_data_range
 #define GL_NV_pixel_data_range 1
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glPixelDataRangeNV (GLenum target, GLsizei length, GLvoid *pointer);
+GLAPI void APIENTRY glPixelDataRangeNV (GLenum target, GLsizei length, const GLvoid *pointer);
 GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum target);
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer);
+typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
 #endif
 
@@ -11747,6 +12748,54 @@ GLAPI void APIENTRY glStencilOpValueAMD (GLenum face, GLuint value);
 typedef void (APIENTRYP PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint value);
 #endif
 
+#ifndef GL_AMD_vertex_shader_viewport_index
+#define GL_AMD_vertex_shader_viewport_index 1
+#endif
+
+#ifndef GL_AMD_vertex_shader_layer
+#define GL_AMD_vertex_shader_layer 1
+#endif
+
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint64 APIENTRY glGetTextureHandleNV (GLuint texture);
+GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler);
+GLAPI void APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle);
+GLAPI void APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle);
+GLAPI GLuint64 APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GLAPI void APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access);
+GLAPI void APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle);
+GLAPI void APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value);
+GLAPI void APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value);
+GLAPI void APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GLAPI GLboolean APIENTRY glIsTextureHandleResidentNV (GLuint64 handle);
+GLAPI GLboolean APIENTRY glIsImageHandleResidentNV (GLuint64 handle);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+#endif
+
+#ifndef GL_NV_shader_atomic_float
+#define GL_NV_shader_atomic_float 1
+#endif
+
+#ifndef GL_AMD_query_buffer_object
+#define GL_AMD_query_buffer_object 1
+#endif
+
 
 #ifdef __cplusplus
 }
index 90fd2c363bd434433db226662baf44ef4e0c9ab8..1b4cda6bace83e37ed11b7bc52c3126d490b936f 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __gles_glext_h_
 #define __gles_glext_h_
 
-/* $Revision: 16481 $ on $Date:: 2012-01-04 10:43:56 -0800 #$ */
+/* $Revision: 18482 $ on $Date:: 2012-07-11 18:08:18 -0700 #$ */
 
 #ifdef __cplusplus
 extern "C" {
@@ -165,6 +165,9 @@ typedef void* GLeglImageOES;
 #define GL_DEPTH24_STENCIL8_OES                                 0x88F0
 #endif
 
+/* GL_OES_required_internalformat */
+/* No new tokens introduced by this extension. */
+
 /* GL_OES_rgb8_rgba8 */
 #ifndef GL_OES_rgb8_rgba8
 #define GL_RGB8_OES                                             0x8051
@@ -291,9 +294,10 @@ typedef void* GLeglImageOES;
 /* GL_EXT_multisampled_render_to_texture */
 #ifndef GL_EXT_multisampled_render_to_texture
 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT           0x8D6C
-#define GL_RENDERBUFFER_SAMPLES_EXT                             0x9133
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x9134
-#define GL_MAX_SAMPLES_EXT                                      0x9135
+/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */ 
+#define GL_RENDERBUFFER_SAMPLES_EXT                             0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x8D56
+#define GL_MAX_SAMPLES_EXT                                      0x8D57
 #endif
 
 /* GL_EXT_multi_draw_arrays */
@@ -771,6 +775,11 @@ typedef void (GL_APIENTRYP PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type,
 #define GL_OES_packed_depth_stencil 1
 #endif
 
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#endif
+
 /* GL_OES_query_matrix */
 #ifndef GL_OES_query_matrix
 #define GL_OES_query_matrix 1
@@ -1068,8 +1077,8 @@ typedef void (GL_APIENTRYP PFNGLCLIPPLANEXIMGPROC) (GLenum p, const GLfixed *eqn
 GL_API void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
 GL_API void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
 #endif
-typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
 #endif
 
 /*------------------------------------------------------------------------*
index e4016a5ad7a0e37af20b90ccaa6d12b828fbed66..206785cd924a5360b677c67c7af8affa8bdcc1b1 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __gl2ext_h_
 #define __gl2ext_h_
 
-/* $Revision: 16994 $ on $Date:: 2012-02-29 18:29:34 -0800 #$ */
+/* $Revision: 18481 $ on $Date:: 2012-07-11 18:07:26 -0700 #$ */
 
 #ifdef __cplusplus
 extern "C" {
@@ -93,6 +93,9 @@ typedef void* GLeglImageOES;
 #define GL_DEPTH24_STENCIL8_OES                                 0x88F0
 #endif
 
+/* GL_OES_required_internalformat */
+/* No new tokens introduced by this extension. */
+
 /* GL_OES_rgb8_rgba8 */
 #ifndef GL_OES_rgb8_rgba8
 #define GL_RGB8_OES                                             0x8051
@@ -325,9 +328,10 @@ typedef void* GLeglImageOES;
 /* GL_EXT_multisampled_render_to_texture */
 #ifndef GL_EXT_multisampled_render_to_texture
 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT           0x8D6C
-#define GL_RENDERBUFFER_SAMPLES_EXT                             0x9133
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x9134
-#define GL_MAX_SAMPLES_EXT                                      0x9135
+/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */ 
+#define GL_RENDERBUFFER_SAMPLES_EXT                             0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x8D56
+#define GL_MAX_SAMPLES_EXT                                      0x8D57
 #endif
 
 /* GL_EXT_multi_draw_arrays */
@@ -463,6 +467,15 @@ typedef void* GLeglImageOES;
 #define GL_SHADER_BINARY_DMP                                    0x9250
 #endif
 
+/*------------------------------------------------------------------------*
+ * FJ extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GCCSO_SHADER_BINARY_FJ                                  0x9260
+#endif
+
 /*------------------------------------------------------------------------*
  * IMG extension tokens
  *------------------------------------------------------------------------*/
@@ -775,6 +788,11 @@ typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum
 #define GL_OES_packed_depth_stencil 1
 #endif
 
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#endif
+
 /* GL_OES_rgb8_rgba8 */
 #ifndef GL_OES_rgb8_rgba8
 #define GL_OES_rgb8_rgba8 1
@@ -1266,6 +1284,15 @@ typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum
 #define GL_DMP_shader_binary 1
 #endif
 
+/*------------------------------------------------------------------------*
+ * FJ extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_FJ_shader_binary_GCCSO 1
+#endif
+
 /*------------------------------------------------------------------------*
  * IMG extension functions
  *------------------------------------------------------------------------*/
@@ -1297,8 +1324,8 @@ typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum
 GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei);
 GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
 #endif
-typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
 #endif
 
 /*------------------------------------------------------------------------*
diff --git a/thirdparty/qjson/.gitignore b/thirdparty/qjson/.gitignore
new file mode 100644 (file)
index 0000000..b2b8eb2
--- /dev/null
@@ -0,0 +1 @@
+moc_*.cxx
index 14bda2c2dcf2b5cd197c1bd328dd5890c5614e8a..512efc83ef33629a5a7cc9bdf4fb96f68fa260fc 100644 (file)
@@ -1,4 +1,8 @@
-add_definitions (-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII -DQT_NO_DEBUG_OUTPUT)
+add_definitions (
+    -DQT_NO_CAST_FROM_ASCII
+    -DQT_NO_CAST_TO_ASCII
+    -DQT_NO_DEBUG_OUTPUT
+)
 
 set (QT_DONT_USE_QTGUI TRUE)
 
@@ -8,11 +12,19 @@ include_directories (${CMAKE_CURRENT_BINARY_DIR})
 
 set (qjson_MOC_HDRS
     parserrunnable.h
-    serializerrunnable.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)
+set (qjson_SRCS
+    parser.cpp
+    qobjecthelper.cpp
+    json_scanner.cpp
+    json_parser.cc
+    parserrunnable.cpp
+    #serializer.cpp
+    #serializerrunnable.cpp
+)
 
 add_library (qjson_bundled STATIC ${qjson_SRCS} ${qjson_MOC_SRCS})
diff --git a/thirdparty/qjson/COPYING b/thirdparty/qjson/COPYING
deleted file mode 100644 (file)
index 5ab7695..0000000
+++ /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.
-\f
-  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.
-\f
-                 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.
-\f
-  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.
-\f
-  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.
-\f
-  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.
-\f
-  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.
-\f
-  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.
-\f
-  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
-\f
-           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 as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    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/COPYING.lib b/thirdparty/qjson/COPYING.lib
new file mode 100644 (file)
index 0000000..08f25cd
--- /dev/null
@@ -0,0 +1,504 @@
+                 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.
+\f
+  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.
+\f
+                 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.
+\f
+  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.
+\f
+  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.
+\f
+  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.
+\f
+  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.
+\f
+  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.
+\f
+  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
+\f
+           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!
+
+
index 9e7b037c9d1bdea24e74afa27ea7a6ec9ccda5b3..fe4853de1f7ef3e6c80d24e020c47bc9989afde0 100644 (file)
@@ -1,6 +1,5 @@
-QJson version 0.5.0
+QJson
 -------------------------------------------------
-Date: April 3rd, 2009
 Website: http://qjson.sourceforge.net/
 Mailing List: https://lists.sourceforge.net/mailman/listinfo/qjson-devel
 
@@ -13,8 +12,8 @@ Install
 
 License
 -------
-  This library is licensed under the Lesser GNU General Public License.  See
-  the COPYING file for more information.
+  This library is licensed under the Lesser GNU General Public License version 2.1.
+  See the COPYING.lib file for more information.
 
 Description
 -----------
index a99be6c6f2d07ccfd8180a64194b4540beea48cb..620e135a85bb50ed23d56fdf31249ec387f2293e 100644 (file)
@@ -42,7 +42,7 @@
 #line 43 "json_parser.cc"
 
 #ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* FIXME: INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -384,7 +384,7 @@ namespace yy
     switch (yyn)
       {
          case 2:
-#line 80 "json_parser.yy"
+#line 84 "json_parser.yy"
     {
               driver->m_result = (yysemantic_stack_[(1) - (1)]);
               qjsonDebug() << "json_parser - parsing finished";
@@ -392,36 +392,31 @@ namespace yy
     break;
 
   case 3:
-#line 85 "json_parser.yy"
-    {(yyval) = (yysemantic_stack_[(1) - (1)]); ;}
+#line 89 "json_parser.yy"
+    { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
     break;
 
   case 4:
-#line 86 "json_parser.yy"
-    {(yyval) = (yysemantic_stack_[(1) - (1)]); ;}
-    break;
-
-  case 5:
-#line 88 "json_parser.yy"
+#line 91 "json_parser.yy"
     {
             qCritical()<< "json_parser - syntax error found, "
-                    << "forcing abort";
+                    << "forcing abort, Line" << (yyloc).begin.line << "Column" << (yyloc).begin.column;
             YYABORT;
           ;}
     break;
 
-  case 7:
-#line 95 "json_parser.yy"
+  case 6:
+#line 98 "json_parser.yy"
     { (yyval) = (yysemantic_stack_[(3) - (2)]); ;}
     break;
 
-  case 8:
-#line 97 "json_parser.yy"
+  case 7:
+#line 100 "json_parser.yy"
     { (yyval) = QVariant (QVariantMap()); ;}
     break;
 
-  case 9:
-#line 98 "json_parser.yy"
+  case 8:
+#line 101 "json_parser.yy"
     {
             QVariantMap members = (yysemantic_stack_[(2) - (2)]).toMap();
             (yysemantic_stack_[(2) - (2)]) = QVariant(); // Allow reuse of map
@@ -429,13 +424,13 @@ namespace yy
           ;}
     break;
 
-  case 10:
-#line 104 "json_parser.yy"
+  case 9:
+#line 107 "json_parser.yy"
     { (yyval) = QVariant (QVariantMap()); ;}
     break;
 
-  case 11:
-#line 105 "json_parser.yy"
+  case 10:
+#line 108 "json_parser.yy"
     {
           QVariantMap members = (yysemantic_stack_[(3) - (3)]).toMap();
           (yysemantic_stack_[(3) - (3)]) = QVariant(); // Allow reuse of map
@@ -443,8 +438,8 @@ namespace yy
           ;}
     break;
 
-  case 12:
-#line 111 "json_parser.yy"
+  case 11:
+#line 114 "json_parser.yy"
     {
             QVariantMap pair;
             pair.insert ((yysemantic_stack_[(3) - (1)]).toString(), QVariant((yysemantic_stack_[(3) - (3)])));
@@ -452,18 +447,18 @@ namespace yy
           ;}
     break;
 
-  case 13:
-#line 117 "json_parser.yy"
+  case 12:
+#line 120 "json_parser.yy"
     { (yyval) = (yysemantic_stack_[(3) - (2)]); ;}
     break;
 
-  case 14:
-#line 119 "json_parser.yy"
+  case 13:
+#line 122 "json_parser.yy"
     { (yyval) = QVariant (QVariantList()); ;}
     break;
 
-  case 15:
-#line 120 "json_parser.yy"
+  case 14:
+#line 123 "json_parser.yy"
     {
           QVariantList members = (yysemantic_stack_[(2) - (2)]).toList();
           (yysemantic_stack_[(2) - (2)]) = QVariant(); // Allow reuse of list
@@ -472,13 +467,13 @@ namespace yy
         ;}
     break;
 
-  case 16:
-#line 127 "json_parser.yy"
+  case 15:
+#line 130 "json_parser.yy"
     { (yyval) = QVariant (QVariantList()); ;}
     break;
 
-  case 17:
-#line 128 "json_parser.yy"
+  case 16:
+#line 131 "json_parser.yy"
     {
             QVariantList members = (yysemantic_stack_[(3) - (3)]).toList();
             (yysemantic_stack_[(3) - (3)]) = QVariant(); // Allow reuse of list
@@ -487,46 +482,61 @@ namespace yy
           ;}
     break;
 
+  case 17:
+#line 138 "json_parser.yy"
+    { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
+    break;
+
   case 18:
-#line 135 "json_parser.yy"
+#line 139 "json_parser.yy"
     { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
     break;
 
   case 19:
-#line 136 "json_parser.yy"
+#line 140 "json_parser.yy"
     { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
     break;
 
   case 20:
-#line 137 "json_parser.yy"
+#line 141 "json_parser.yy"
     { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
     break;
 
   case 21:
-#line 138 "json_parser.yy"
-    { (yyval) = (yysemantic_stack_[(1) - (1)]); ;}
-    break;
-
-  case 22:
-#line 139 "json_parser.yy"
+#line 142 "json_parser.yy"
     { (yyval) = QVariant (true); ;}
     break;
 
-  case 23:
-#line 140 "json_parser.yy"
+  case 22:
+#line 143 "json_parser.yy"
     { (yyval) = QVariant (false); ;}
     break;
 
-  case 24:
-#line 141 "json_parser.yy"
+  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 146 "json_parser.yy"
+#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);
@@ -539,8 +549,8 @@ namespace yy
           ;}
     break;
 
-  case 26:
-#line 156 "json_parser.yy"
+  case 29:
+#line 164 "json_parser.yy"
     {
             const QByteArray value = (yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray();
             (yyval) = QVariant(QVariant::Double);
@@ -548,65 +558,65 @@ namespace yy
           ;}
     break;
 
-  case 27:
-#line 161 "json_parser.yy"
+  case 30:
+#line 169 "json_parser.yy"
     { (yyval) = QVariant ((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;}
     break;
 
-  case 28:
-#line 162 "json_parser.yy"
+  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 29:
-#line 167 "json_parser.yy"
+  case 32:
+#line 175 "json_parser.yy"
     { (yyval) = QVariant ((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;}
     break;
 
-  case 30:
-#line 168 "json_parser.yy"
+  case 33:
+#line 176 "json_parser.yy"
     { (yyval) = QVariant (QByteArray("-") + (yysemantic_stack_[(3) - (2)]).toByteArray() + (yysemantic_stack_[(3) - (3)]).toByteArray()); ;}
     break;
 
-  case 31:
-#line 170 "json_parser.yy"
+  case 34:
+#line 178 "json_parser.yy"
     { (yyval) = QVariant (QByteArray("")); ;}
     break;
 
-  case 32:
-#line 171 "json_parser.yy"
+  case 35:
+#line 179 "json_parser.yy"
     {
           (yyval) = QVariant((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray());
         ;}
     break;
 
-  case 33:
-#line 175 "json_parser.yy"
+  case 36:
+#line 183 "json_parser.yy"
     {
           (yyval) = QVariant(QByteArray(".") + (yysemantic_stack_[(2) - (2)]).toByteArray());
         ;}
     break;
 
-  case 34:
-#line 179 "json_parser.yy"
+  case 37:
+#line 187 "json_parser.yy"
     { (yyval) = QVariant((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;}
     break;
 
-  case 35:
-#line 181 "json_parser.yy"
+  case 38:
+#line 189 "json_parser.yy"
     { (yyval) = (yysemantic_stack_[(3) - (2)]); ;}
     break;
 
-  case 36:
-#line 183 "json_parser.yy"
+  case 39:
+#line 191 "json_parser.yy"
     { (yyval) = QVariant (QString(QLatin1String(""))); ;}
     break;
 
-  case 37:
-#line 184 "json_parser.yy"
+  case 40:
+#line 192 "json_parser.yy"
     {
                 (yyval) = (yysemantic_stack_[(1) - (1)]);
               ;}
@@ -614,7 +624,7 @@ namespace yy
 
 
     /* Line 675 of lalr1.cc.  */
-#line 618 "json_parser.cc"
+#line 628 "json_parser.cc"
        default: break;
       }
     YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc);
@@ -821,16 +831,16 @@ namespace yy
 
   /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
      STATE-NUM.  */
-  const signed char json_parser::yypact_ninf_ = -18;
+  const signed char json_parser::yypact_ninf_ = -21;
   const signed char
   json_parser::yypact_[] =
   {
-         5,   -18,   -18,     1,    -2,    19,   -18,   -18,   -18,     2,
-      20,    17,    21,    16,    18,   -18,   -18,   -18,   -18,   -18,
-      24,    23,   -18,    -8,   -18,   -18,   -18,    15,   -18,     1,
-     -18,    -2,    18,    18,   -18,   -18,    -2,   -18,    18,    18,
-      22,   -18,   -18,    17,   -18,   -18,   -18,    23,   -18,   -18,
-     -18,   -18,   -18
+         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
@@ -839,28 +849,28 @@ namespace yy
   const unsigned char
   json_parser::yydefact_[] =
   {
-         0,     6,     5,     8,    14,     0,     2,     3,     4,    36,
-       0,    10,     0,     0,    31,    22,    23,    24,    20,    21,
-       0,    16,    19,    25,    18,     1,    37,     0,     7,     0,
-       9,     0,    31,    31,    29,    13,     0,    15,    31,    31,
-      26,    27,    35,    10,    12,    30,    32,    16,    33,    34,
-      28,    11,    17
+         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_[] =
   {
-       -18,   -18,   -18,    33,   -18,    -7,     6,    37,   -18,    -9,
-     -13,   -18,   -18,   -17,   -18,    -1,    -3,   -18
+       -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,     5,     6,    18,    10,    30,    11,    19,    20,    37,
-      21,    22,    23,    34,    40,    41,    24,    27
+        -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
@@ -870,20 +880,24 @@ namespace yy
   const unsigned char
   json_parser::yytable_[] =
   {
-        12,     3,    38,     4,    39,     1,     2,    13,     3,    14,
-       4,    15,    16,    17,     9,    45,    46,     9,    44,    25,
-      26,    48,    49,    47,    28,    29,    12,    32,    31,    33,
-      35,    36,    42,     7,    39,    43,    51,     8,    52,    50
+        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 unsigned char
+  const signed char
   json_parser::yycheck_[] =
   {
-         3,     3,    10,     5,    12,     0,     1,     9,     3,    11,
-       5,    13,    14,    15,    16,    32,    33,    16,    31,     0,
-      18,    38,    39,    36,     4,     8,    29,    11,     7,    11,
-       6,     8,    17,     0,    12,    29,    43,     0,    47,    40
+         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
@@ -891,12 +905,12 @@ namespace yy
   const unsigned char
   json_parser::yystos_[] =
   {
-         0,     0,     1,     3,     5,    20,    21,    22,    26,    16,
-      23,    25,    35,     9,    11,    13,    14,    15,    22,    26,
-      27,    29,    30,    31,    35,     0,    18,    36,     4,     8,
-      24,     7,    11,    11,    32,     6,     8,    28,    10,    12,
-      33,    34,    17,    25,    29,    32,    32,    29,    32,    32,
-      34,    24,    28
+         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
@@ -906,7 +920,8 @@ namespace yy
   json_parser::yytoken_number_[] =
   {
          0,   256,   257,     1,     2,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18
   };
 #endif
 
@@ -914,20 +929,22 @@ namespace yy
   const unsigned char
   json_parser::yyr1_[] =
   {
-         0,    19,    20,    21,    21,    21,    21,    22,    23,    23,
-      24,    24,    25,    26,    27,    27,    28,    28,    29,    29,
-      29,    29,    29,    29,    29,    30,    30,    30,    30,    31,
-      31,    32,    32,    33,    34,    35,    36,    36
+         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,     1,     3,     0,     2,
-       0,     3,     3,     3,     0,     2,     0,     3,     1,     1,
-       1,     1,     1,     1,     1,     1,     2,     2,     3,     2,
-       3,     0,     2,     2,     2,     3,     0,     1
+         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
@@ -940,9 +957,10 @@ namespace yy
   "\"]\"", "\":\"", "\",\"", "\"-\"", "\".\"", "\"digit\"",
   "\"exponential\"", "\"true\"", "\"false\"", "\"null\"",
   "\"open quotation mark\"", "\"close quotation mark\"", "\"string\"",
-  "$accept", "start", "data", "object", "members", "r_members", "pair",
-  "array", "values", "r_values", "value", "number", "int", "digits",
-  "fract", "exp", "string", "string_arg", 0
+  "\"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
 
@@ -951,16 +969,16 @@ namespace yy
   const json_parser::rhs_number_type
   json_parser::yyrhs_[] =
   {
-        20,     0,    -1,    21,    -1,    22,    -1,    26,    -1,     1,
-      -1,     0,    -1,     3,    23,     4,    -1,    -1,    25,    24,
-      -1,    -1,     8,    25,    24,    -1,    35,     7,    29,    -1,
-       5,    27,     6,    -1,    -1,    29,    28,    -1,    -1,     8,
-      29,    28,    -1,    35,    -1,    30,    -1,    22,    -1,    26,
-      -1,    13,    -1,    14,    -1,    15,    -1,    31,    -1,    31,
-      33,    -1,    31,    34,    -1,    31,    33,    34,    -1,    11,
-      32,    -1,     9,    11,    32,    -1,    -1,    11,    32,    -1,
-      10,    32,    -1,    12,    32,    -1,    16,    36,    17,    -1,
-      -1,    18,    -1
+        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
@@ -968,20 +986,22 @@ namespace yy
   const unsigned char
   json_parser::yyprhs_[] =
   {
-         0,     0,     3,     5,     7,     9,    11,    13,    17,    18,
-      21,    22,    26,    30,    34,    35,    38,    39,    43,    45,
-      47,    49,    51,    53,    55,    57,    59,    62,    65,    69,
-      72,    76,    77,    80,    83,    86,    90,    91
+         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,    80,    80,    85,    86,    87,    93,    95,    97,    98,
-     104,   105,   111,   117,   119,   120,   127,   128,   135,   136,
-     137,   138,   139,   140,   141,   146,   156,   161,   162,   167,
-     168,   170,   171,   175,   179,   181,   183,   184
+         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.
@@ -1022,7 +1042,7 @@ namespace yy
     translate_table[] =
     {
            0,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      12,    13,    14,    15,    16,    17,    18,     2,     2,     2,
+      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,
@@ -1055,20 +1075,20 @@ namespace yy
   }
 
   const int json_parser::yyeof_ = 0;
-  const int json_parser::yylast_ = 39;
-  const int json_parser::yynnts_ = 18;
+  const int json_parser::yylast_ = 51;
+  const int json_parser::yynnts_ = 19;
   const int json_parser::yyempty_ = -2;
-  const int json_parser::yyfinal_ = 25;
+  const int json_parser::yyfinal_ = 33;
   const int json_parser::yyterror_ = 1;
   const int json_parser::yyerrcode_ = 256;
-  const int json_parser::yyntokens_ = 19;
+  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 188 "json_parser.yy"
+#line 196 "json_parser.yy"
 
 
 int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver)
index 673923d9e385be51813417b509705889d63ee992..e61ca7c644c6434670257ca6f013bdec1162cab3 100644 (file)
@@ -59,6 +59,8 @@ namespace yy
   #include <QtCore/QString>
   #include <QtCore/QVariant>
 
+  #include <limits>
+
   class JSonScanner;
 
   namespace QJson {
@@ -68,8 +70,8 @@ namespace yy
   #define YYERROR_VERBOSE 1
 
 
-/* Line 303 of lalr1.cc.  */
-#line 73 "json_parser.hh"
+/* Line 35 of lalr1.cc.  */
+#line 75 "json_parser.hh"
 
 #include "location.hh"
 
@@ -146,7 +148,9 @@ namespace yy
      NULL_VAL = 13,
      QUOTMARKOPEN = 14,
      QUOTMARKCLOSE = 15,
-     STRING = 16
+     STRING = 16,
+     INFINITY_VAL = 17,
+     NAN_VAL = 18
    };
 
     };
@@ -241,7 +245,7 @@ namespace yy
     static const unsigned char yytable_[];
     static const signed char yytable_ninf_;
 
-    static const unsigned char yycheck_[];
+    static const signed char yycheck_[];
 
     /// For a state, its accessing symbol.
     static const unsigned char yystos_[];
index ad8e105b73c4488ebd99209ae638ddeb1f56b7ca..2540889bae2647c133bc5daac766262ac83eba3c 100644 (file)
@@ -3,16 +3,16 @@
   * 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 Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
+  * 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
-  * Library General Public License for more details.
+  * Lesser General Public License for more details.
   *
-  * You should have received a copy of the GNU Library General Public License
+  * 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.
@@ -32,6 +32,8 @@
   #include <QtCore/QString>
   #include <QtCore/QVariant>
 
+  #include <limits>
+
   class JSonScanner;
 
   namespace QJson {
@@ -69,6 +71,8 @@
 %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
@@ -82,12 +86,11 @@ start: data {
               qjsonDebug() << "json_parser - parsing finished";
             };
 
-data: object {$$ = $1; }
-      | array {$$ = $1; }
+data: value { $$ = $1; }
       | error
           {
             qCritical()<< "json_parser - syntax error found, "
-                    << "forcing abort";
+                    << "forcing abort, Line" << @$.begin.line << "Column" << @$.begin.column;
             YYABORT;
           }
       | END;
@@ -133,7 +136,7 @@ r_values: /* empty */ { $$ = QVariant (QVariantList()); }
           };
 
 value: string { $$ = $1; }
-        | number { $$ = $1; }
+        | special_or_number { $$ = $1; }
         | object { $$ = $1; }
         | array { $$ = $1; }
         | TRUE_VAL { $$ = QVariant (true); }
@@ -143,6 +146,11 @@ value: string { $$ = $1; }
           $$ = 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);
index 7f7b88fa0a74fe75c41a3af29d5cfb221e2517f1..de0ddc23c53c94cfd1122c8f7248b5a30b0dedb3 100644 (file)
@@ -3,16 +3,16 @@
  * 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 Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * 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
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public License
+ * 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.
@@ -38,12 +38,17 @@ bool ishexnstring(const QString& string) {
 }
 
 JSonScanner::JSonScanner(QIODevice* io)
-  : m_io (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;
@@ -125,7 +130,7 @@ static QString unescape( const QByteArray& ba, bool* ok ) {
 int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
 {
   char ch;
-  
+
   if (!m_io->isOpen()) {
     qCritical() << "JSonScanner::yylex - io device is not open";
     return -1;
@@ -148,32 +153,34 @@ int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
     }
 
     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')
-      || (ch == 'n') || (ch == 'N'))) {
-    // check true & null value
+  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;
 
-    if (buf.length() == 3) {
-      if (buf == "rue") {
-        m_io->read (3);
-        yylloc->columns(3);
-        qjsonDebug() << "JSonScanner::yylex - TRUE_VAL";
-        return yy::json_parser::token::TRUE_VAL;
-      }
-      else if (buf == "ull") {
-        m_io->read (3);
-        yylloc->columns(3);
-        qjsonDebug() << "JSonScanner::yylex - NULL_VAL";
-        return yy::json_parser::token::NULL_VAL;
-      }
     }
   }
   else if (m_quotmarkClosed && ((ch == 'f') || (ch == 'F'))) {
@@ -193,14 +200,24 @@ int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
     const QByteArray buf = m_io->peek(1);
     if (!buf.isEmpty()) {
       if ((buf[0] == '+' ) || (buf[0] == '-' )) {
-        ret += m_io->read (1);  
+        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;
@@ -259,7 +276,38 @@ int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc)
     }
   }
   else if (isdigit(ch) != 0 && m_quotmarkClosed) {
-    *yylval = QVariant(QString::fromLatin1(QByteArray(&ch,1)));
+    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;
   }
index 593426b9636a32db62216c7c140283e4dde383d9..f13e565f5845b1eaa21e8af2d77d306269c11780 100644 (file)
@@ -3,16 +3,16 @@
  * 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 Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * 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
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public License
+ * 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.
@@ -41,9 +41,11 @@ 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;
 };
index 3096d177a378b16e55bf78deb6e3c2bdc941a025..e203b876f76bef989f8b551ac5f11ed6be5fb161 100644 (file)
@@ -3,16 +3,16 @@
  * 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 Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * 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
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public License
+ * 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.
@@ -34,6 +34,8 @@ ParserPrivate::ParserPrivate() :
     m_scanner(0)
   , m_negate(false)
   , m_error(false)
+  , m_errorLine(0)
+  , m_specialNumbersAllowed(false)
 {
 }
 
@@ -82,6 +84,7 @@ QVariant Parser::parse (QIODevice* io, bool* ok)
   }
 
   d->m_scanner = new JSonScanner (io);
+  d->m_scanner->allowSpecialNumbers(d->m_specialNumbersAllowed);
   yy::json_parser parser(d);
   parser.parse();
 
@@ -112,3 +115,11 @@ 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;
+}
index 8d323cd4d5ece52e06f06fc0cbae8348c5c5e57b..6fb58d89f24cce4907349bbb73a068887beffae0 100644 (file)
@@ -3,16 +3,16 @@
  * 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 Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * 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
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public License
+ * 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.
@@ -71,6 +71,20 @@ namespace QJson {
       */
       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;
index e12b565721c7ae1c32e195b3937e59c3b231e6a4..aae86a124c9c92e35c1b2e0fcfcc21874fcb470a 100644 (file)
@@ -4,16 +4,16 @@
  * 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 Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * 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
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public License
+ * 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.
@@ -49,6 +49,7 @@ namespace QJson {
       int m_errorLine;
       QString m_errorMsg;
       QVariant m_result;
+      bool m_specialNumbersAllowed;
   };
 }
 
index d09423e4cbb6c1ab5a7ea697062dedc4ffabc10e..88baf4cf68e24ac3f7ab3385a6e199fdcc660f85 100644 (file)
@@ -3,16 +3,16 @@
   * 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 Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
+  * 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
-  * Library General Public License for more details.
+  * Lesser General Public License for more details.
   *
-  * You should have received a copy of the GNU Library General Public License
+  * 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.
@@ -61,7 +61,7 @@ void ParserRunnable::run()
     qDebug() << "successfully converted json item to QVariant object";
     emit parsingFinished(result, true, QString());
   } else {
-    const QString errorText = tr("An error occured while parsing json: %1").arg(parser.errorString());
+    const QString errorText = tr("An error occurred while parsing json: %1").arg(parser.errorString());
     qCritical() << errorText;
     emit parsingFinished(QVariant(), false, errorText);
   }
index 822e1fdba8f047a1ac78c05eeea7bcea57d92f1e..2badeb64b74635c5b4cf4a21d80e63c360a85ca7 100644 (file)
@@ -3,16 +3,16 @@
   * 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 Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
+  * 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
-  * Library General Public License for more details.
+  * Lesser General Public License for more details.
   *
-  * You should have received a copy of the GNU Library General Public License
+  * 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.
index 5ae1da3a771f82f1ba8317a8425d7544fc7fdfa5..0a511aeef08f29e03598d5f30f8e72375a09dc84 100644 (file)
@@ -3,16 +3,16 @@
   * 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 Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
+  * 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
-  * Library General Public License for more details.
+  * Lesser General Public License for more details.
   *
-  * You should have received a copy of the GNU Library General Public License
+  * 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.
index 67355f5fae125bbbdef19935f93e35e07d67e50b..9a807b91b282ded6dfd62930e976b3ec918d1007 100644 (file)
@@ -2,16 +2,16 @@
     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 Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
+    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
-    Library General Public License for more details.
+    Lesser General Public License for more details.
 
-    You should have received a copy of the GNU Library General Public License
+    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 <QtCore/qglobal.h>
 
-#define QJSON_EXPORT
+#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
index 8bba181b706774dc2b23d0bf56c0db3df3ddfdbe..b756488f07773dbe0fe2b7859a68c07ab1d4cdcc 100644 (file)
@@ -4,16 +4,16 @@
   * 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 Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
+  * 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
-  * Library General Public License for more details.
+  * Lesser General Public License for more details.
   *
-  * You should have received a copy of the GNU Library General Public License
+  * 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.
@@ -62,20 +62,24 @@ QVariantMap QObjectHelper::qobject2qvariant( const QObject* object,
 
 void QObjectHelper::qvariant2qobject(const QVariantMap& variant, QObject* object)
 {
-  QStringList properies;
   const QMetaObject *metaobject = object->metaObject();
-  int count = metaobject->propertyCount();
-  for (int i=0; i<count; ++i) {
-    QMetaProperty metaproperty = metaobject->property(i);
-    if (metaproperty.isWritable()) {
-      properies << QLatin1String( metaproperty.name());
-    }
-  }
 
   QVariantMap::const_iterator iter;
-  for (iter = variant.constBegin(); iter != variant.end(); iter++) {
-    if (properies.contains(iter.key())) {
-      object->setProperty(iter.key().toAscii(), iter.value());
+  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 );
     }
   }
 }
index 7bf6b03570e581db4f05eb778c06d9c55d080c58..514ca1fa1b4b7f09b9688a173e09bbd2fb2b13e1 100644 (file)
@@ -3,16 +3,16 @@
   * 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 Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
+  * 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
-  * Library General Public License for more details.
+  * Lesser General Public License for more details.
   *
-  * You should have received a copy of the GNU Library General Public License
+  * 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.
@@ -34,6 +34,7 @@ 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
index f012246d43f1cded564751922bdb29253928ff13..41407c2745940b7580b31b221a34f2d505fc9b47 100644 (file)
@@ -4,16 +4,16 @@
   * 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 Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
+  * 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
-  * Library General Public License for more details.
+  * Lesser General Public License for more details.
   *
-  * You should have received a copy of the GNU Library General Public License
+  * 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 <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 );
 };
 
-Serializer::Serializer() : d( new SerializerPrivate ) {
-}
-
-Serializer::~Serializer() {
-  delete d;
-}
-
-void Serializer::serialize( const QVariant& v, QIODevice* io, bool* ok )
-{
-  Q_ASSERT( io );
-  if (!io->isOpen()) {
-    if (!io->open(QIODevice::WriteOnly)) {
-      if ( ok != 0 )
-        *ok = false;
-      qCritical ("Error opening device");
-      return;
-    }
-  }
-
-  if (!io->isWritable()) {
-    if (ok != 0)
-      *ok = false;
-    qCritical ("Device is not readable");
-    io->close();
-    return;
-  }
-
-  const QByteArray str = serialize( v );
-  if ( !str.isNull() ) {
-    QDataStream stream( io );
-    stream << str;
-  } else {
-    if ( ok )
-      *ok = false;
-  }
-}
-
-static QString sanitizeString( QString str )
-{
-  str.replace( QLatin1String( "\\" ), QLatin1String( "\\\\" ) );
-  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 );
-}
-
-static 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() )
@@ -89,48 +59,141 @@ static QByteArray join( const QList<QByteArray>& list, const QByteArray& sep ) {
   return res;
 }
 
-QByteArray Serializer::serialize( const QVariant &v )
+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 ) { // variant is a list?
+  } 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& v, list )
+    Q_FOREACH( const QVariant& var, list )
     {
-      QByteArray serializedValue = serialize( v );
+      reserved++;
+      QByteArray serializedValue = serialize( var,reserved );
+      reserved--;
       if ( serializedValue.isNull() ) {
         error = true;
         break;
       }
       values << serializedValue;
     }
-    str = "[ " + join( values, ", " ) + " ]";
+
+    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 );
-    str = "{ ";
+
+    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();
-      QByteArray serializedValue = serialize( it.value() );
+      reserved++;
+      QByteArray serializedValue = serialize( it.value() , reserved);
+      reserved--;
       if ( serializedValue.isNull() ) {
         error = true;
         break;
       }
-      pairs << sanitizeString( it.key() ).toUtf8() + " : " + serializedValue;
+      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, "," );
     }
-    str += join( pairs, ", " );
-    str += " }";
+    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 ) { // a double?
-    str = QByteArray::number( v.toDouble() );
-    if( ! str.contains( "." ) && ! str.contains( "e" ) ) {
-      str += ".0";
+  } 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" );
@@ -146,7 +209,114 @@ QByteArray Serializer::serialize( const QVariant &v )
     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;
+}
index fd301b21c052a4df8c8eaa4b7d97a8d3b3097aad..66b349cf7e5ac226f7a33d369c43328c1439aee5 100644 (file)
@@ -3,16 +3,16 @@
   * 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 Library General Public
-  * License as published by the Free Software Foundation; either
-  * version 2 of the License, or (at your option) any later version.
+  * 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
-  * Library General Public License for more details.
+  * Lesser General Public License for more details.
   *
-  * You should have received a copy of the GNU Library General Public License
+  * 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.
@@ -28,6 +28,42 @@ 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.
   *
@@ -47,7 +83,7 @@ namespace QJson {
       * @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 );
+    void serialize( const QVariant& variant, QIODevice* out, bool* ok = 0);
 
     /**
       * This is a method provided for convenience. It turns the passed in in-memory
@@ -59,7 +95,34 @@ namespace QJson {
       * parser.
       */
 
-    QByteArray serialize( const QVariant& variant );
+    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)
index 2e57c4517e05ea3934c54dda8f78f2548df5907f..9ebf68b7225f952ad9fbe531530ea708c1988973 100644 (file)
@@ -6,16 +6,16 @@
  *               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 Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * 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
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public License
+ * 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.
index c6b5fe1175d4ffb23a6c25edb05fd385239b9ca6..d665fc5138f15a60770e2ab743aafeef9da906ba 100644 (file)
@@ -3,16 +3,16 @@
  * 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 Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * 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
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public License
+ * 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.
index 2f8172099842b4d27e3ee14feb8ebbd0886b438d..eeacd9f1a0e8dcfa1217a5f1dc123acde6b20302 100644 (file)
@@ -1,3 +1,4 @@
+OpenGL
 cgltrace.cpp
 d3d10_1trace.cpp
 d3d10trace.cpp
index f65817d24a333cf671980fe72874bf1b36582912..6fa615c5bc07e173db9a9f4bba63281c7c0b621b 100644 (file)
@@ -127,6 +127,7 @@ if (WIN32)
             COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d10trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d10trace.cpp
             DEPENDS
                 d3d10trace.py
+                d3dcommontrace.py
                 dlltrace.py
                 trace.py
                 ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
@@ -164,6 +165,7 @@ if (WIN32)
             COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d10_1trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d10_1trace.cpp
             DEPENDS
                 d3d10_1trace.py
+                d3dcommontrace.py
                 dlltrace.py
                 trace.py
                 ${CMAKE_SOURCE_DIR}/dispatch/dispatch.py
@@ -177,7 +179,7 @@ if (WIN32)
                 ${CMAKE_SOURCE_DIR}/specs/winapi.py
                 ${CMAKE_SOURCE_DIR}/specs/stdapi.py
         )
-        add_library (d3d10_1trace MODULE d3d10_1.def d3d10_1trace.cpp)
+        add_library (d3d10_1trace MODULE d3d10_1.def d3d10_1trace.cpp d3d10shader.cpp)
         target_link_libraries (d3d10_1trace
             common_trace
             common
@@ -347,7 +349,6 @@ elseif (X11_FOUND)
         common
         ${ZLIB_LIBRARIES}
         ${SNAPPY_LIBRARIES}
-        ${X11_X11_LIB}
         ${CMAKE_THREAD_LIBS_INIT}
         dl
     )
@@ -377,6 +378,7 @@ if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE)
         egltrace.cpp
         glcaps.cpp
         gltrace_state.cpp
+        ${CMAKE_SOURCE_DIR}/helpers/eglsize.cpp
     )
 
     add_dependencies (egltrace glproc)
index 485ec32b672d536b94253313ff5f74c24d73f3c0..d2f72a773c046b71ddd86e06262c7c461105b60c 100644 (file)
@@ -24,7 +24,7 @@
 ##########################################################################/
 
 
-from dlltrace import DllTracer
+from d3dcommontrace import D3DCommonTracer
 from specs.d3d10_1 import d3d10_1
 
 
@@ -35,6 +35,8 @@ if __name__ == '__main__':
     print '#include "os.hpp"'
     print
     print '#include "d3d10_1imports.hpp"'
+    print '#include "d3d10shader.hpp"'
+    print '#include "d3d10size.hpp"'
     print
-    tracer = DllTracer('d3d10_1.dll')
+    tracer = D3DCommonTracer('d3d10_1.dll')
     tracer.traceApi(d3d10_1)
index d43f042b08f2a8e6efa1328f045b524f24cc88ac..adb5dae207c94a0d6eef6554b67585ae0f6eee29 100644 (file)
 ##########################################################################/
 
 
-from dlltrace import DllTracer
-from specs import stdapi
+from d3dcommontrace import D3DCommonTracer
 from specs.d3d10misc import d3d10
 
 
-class D3D10Tracer(DllTracer):
-
-    def serializeArgValue(self, function, arg):
-        # Dump shaders as strings
-        if isinstance(arg.type, stdapi.Blob) and arg.name.startswith('pShaderBytecode'):
-            print '    DumpShader(trace::localWriter, %s, %s);' % (arg.name, arg.type.size)
-            return
-
-        DllTracer.serializeArgValue(self, function, arg)
-
 if __name__ == '__main__':
     print '#define INITGUID'
     print
@@ -47,6 +36,7 @@ if __name__ == '__main__':
     print
     print '#include "d3d10imports.hpp"'
     print '#include "d3d10shader.hpp"'
+    print '#include "d3d10size.hpp"'
     print
-    tracer = D3D10Tracer('d3d10.dll')
+    tracer = D3DCommonTracer('d3d10.dll')
     tracer.traceApi(d3d10)
index f44cad385203612d0b229bb6dfce1033b52daccf..b2a39f6604969d3dff5d9f347ef52e8632a5fd64 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "d3d9shader.hpp"
 #include "d3d9imports.hpp"
-#include "d3dsize.hpp"
+#include "d3d9size.hpp"
 
 
 typedef HRESULT
index 17ebe197d872a17b5dcf779dbcc0b123676861af..33f6e9d9dfbfa18b5fae730d31fb0552803925b6 100644 (file)
@@ -43,6 +43,7 @@ class D3D9Tracer(DllTracer):
     def enumWrapperInterfaceVariables(self, interface):
         variables = DllTracer.enumWrapperInterfaceVariables(self, interface)
         
+        # Add additional members to track locks
         if interface.getMethodByName('Lock') is not None or \
            interface.getMethodByName('LockRect') is not None or \
            interface.getMethodByName('LockBox') is not None:
@@ -84,7 +85,7 @@ if __name__ == '__main__':
     print '#include "os.hpp"'
     print
     print '#include "d3d9imports.hpp"'
-    print '#include "d3dsize.hpp"'
+    print '#include "d3d9size.hpp"'
     print '#include "d3d9shader.hpp"'
     print '#include "dxvaint.h"'
     print
diff --git a/wrappers/d3dcommontrace.py b/wrappers/d3dcommontrace.py
new file mode 100644 (file)
index 0000000..e0927cc
--- /dev/null
@@ -0,0 +1,70 @@
+##########################################################################
+#
+# 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.
+#
+##########################################################################/
+
+
+from dlltrace import DllTracer
+from specs import stdapi
+
+
+class D3DCommonTracer(DllTracer):
+
+    def serializeArgValue(self, function, arg):
+        # Dump shaders as strings
+        if isinstance(arg.type, stdapi.Blob) and arg.name.startswith('pShaderBytecode'):
+            print '    DumpShader(trace::localWriter, %s, %s);' % (arg.name, arg.type.size)
+            return
+
+        DllTracer.serializeArgValue(self, function, arg)
+    
+    def enumWrapperInterfaceVariables(self, interface):
+        variables = DllTracer.enumWrapperInterfaceVariables(self, interface)
+        
+        # Add additional members to track maps
+        if interface.getMethodByName('Map') is not None:
+            variables += [
+                ('VOID *', '_pMappedData', '0'),
+                ('size_t', '_MappedSize', '0'),
+            ]
+
+        return variables
+
+    def implementWrapperInterfaceMethodBody(self, interface, base, method):
+        if method.name == 'Unmap':
+            print '    if (_MappedSize && _pMappedData) {'
+            self.emit_memcpy('_pMappedData', '_pMappedData', '_MappedSize')
+            print '    }'
+
+        DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
+
+        if method.name == 'Map':
+            # NOTE: recursive locks are explicitely forbidden
+            print '    if (SUCCEEDED(_result)) {'
+            print '        _getMapInfo(_this, %s, _pMappedData, _MappedSize);' % ', '.join(method.argNames())
+            print '    } else {'
+            print '        _pMappedData = NULL;'
+            print '        _MappedSize = 0;'
+            print '    }'
+
+
index 18058468049154acf0eb2d78d77a9d13368424ed..a6ff17f8eaa1f37509b6ad094f07e8e2306f02d4 100644 (file)
@@ -81,6 +81,34 @@ class EglTracer(GlTracer):
             print '        gltrace::releaseContext((uintptr_t)ctx);'
             print '    }'
 
+        if function.name == 'glEGLImageTargetTexture2DOES':
+            print '    image_info *info = _EGLImageKHR_get_image_info(target, image);'
+            print '    if (info) {'
+            print '        GLint level = 0;'
+            print '        GLint internalformat = info->internalformat;'
+            print '        GLsizei width = info->width;'
+            print '        GLsizei height = info->height;'
+            print '        GLint border = 0;'
+            print '        GLenum format = info->format;'
+            print '        GLenum type = info->type;'
+            print '        const GLvoid * pixels = info->pixels;'
+            self.emitFakeTexture2D()
+            print '        _EGLImageKHR_free_image_info(info);'
+            print '    }'
+
+    def emitFakeTexture2D(self):
+        function = glapi.getFunctionByName('glTexImage2D')
+        instances = function.argNames()
+        print '        unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
+        for arg in function.args:
+            assert not arg.output
+            self.serializeArg(function, arg)
+        print '        trace::localWriter.endEnter();'
+        print '        trace::localWriter.beginLeave(_fake_call);'
+        print '        trace::localWriter.endLeave();'
+
+
+
 if __name__ == '__main__':
     print '#include <stdlib.h>'
     print '#include <string.h>'
@@ -94,6 +122,7 @@ if __name__ == '__main__':
     print
     print '#include "glproc.hpp"'
     print '#include "glsize.hpp"'
+    print '#include "eglsize.hpp"'
     print
     
     api = API()
index db824bb315ffd5f1044b3752104b83e7de466fac..04c64b6afc0623ad690cbeb80ced17d3687de53f 100644 (file)
 #define _GLTRACE_HPP_
 
 
+#include <string.h>
+#include <stdlib.h>
+#include <map>
+
 #include "glimports.hpp"
 
 
@@ -39,6 +43,52 @@ enum Profile {
     PROFILE_ES2,
 };
 
+
+/**
+ * OpenGL ES buffers cannot be read. This class is used to track index buffer
+ * contents.
+ */
+class Buffer {
+public:
+    GLsizeiptr size;
+    GLvoid *data;
+
+    Buffer() :
+        size(0),
+        data(0)
+    {}
+
+    ~Buffer() {
+        free(data);
+    }
+
+    void
+    bufferData(GLsizeiptr new_size, const void *new_data) {
+        if (new_size < 0) {
+            new_size = 0;
+        }
+        size = new_size;
+        data = realloc(data, new_size);
+        if (new_size && new_data) {
+            memcpy(data, new_data, size);
+        }
+    }
+
+    void
+    bufferSubData(GLsizeiptr offset, GLsizeiptr length, const void *new_data) {
+        if (offset >= 0 && offset < size && length > 0 && offset + length <= size && new_data) {
+            memcpy((GLubyte *)data + offset, new_data, length);
+        }
+    }
+
+    void
+    getSubData(GLsizeiptr offset, GLsizeiptr length, void *out_data) {
+        if (offset >= 0 && offset < size && length > 0 && offset + length <= size && out_data) {
+            memcpy(out_data, (GLubyte *)data + offset, length);
+        }
+    }
+};
+
 class Context {
 public:
     enum Profile profile;
@@ -47,6 +97,9 @@ public:
     bool user_arrays_nv;
     unsigned retain_count;
 
+    // TODO: This will fail for buffers shared by multiple contexts.
+    std::map <GLuint, Buffer> buffers;
+
     Context(void) :
         profile(PROFILE_COMPAT),
         user_arrays(false),
@@ -54,6 +107,12 @@ public:
         user_arrays_nv(false),
         retain_count(0)
     { }
+
+    inline bool
+    needsShadowBuffers(void)
+    {
+        return profile == PROFILE_ES1 || profile == PROFILE_ES2;
+    }
 };
 
 void
index 901e9d749c1d096ca749526b467b6afae17bd6f8..96da4e85c576e25af119696f9c849ae2ecbb3724 100644 (file)
@@ -141,6 +141,8 @@ class GlTracer(Tracer):
         print '}'
         print
 
+        self.defineShadowBufferHelper()
+
         # Whether we need user arrays
         print 'static inline bool _need_user_arrays(void)'
         print '{'
@@ -349,6 +351,52 @@ class GlTracer(Tracer):
         else:
             Tracer.traceApi(self, api)
 
+    def defineShadowBufferHelper(self):
+        print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
+        print '                                GLsizeiptr size, GLvoid *data)'
+        print '{'
+        print '    struct gltrace::Context *ctx = gltrace::getContext();'
+        print '    if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
+        print '        _glGetBufferSubData(target, offset, size, data);'
+        print '        return;'
+        print '    }'
+        print
+        print '    GLint buffer_binding = 0;'
+        print '    _glGetIntegerv(target, &buffer_binding);'
+        print '    if (buffer_binding > 0) {'
+        print '        gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
+        print '        buf.getSubData(offset, size, data);'
+        print '    }'
+        print '}'
+
+    def shadowBufferMethod(self, method):
+        # Emit code to fetch the shadow buffer, and invoke a method
+        print '    gltrace::Context *ctx = gltrace::getContext();'
+        print '    if (ctx->needsShadowBuffers() && target == GL_ELEMENT_ARRAY_BUFFER) {'
+        print '        GLint buffer_binding = 0;'
+        print '        _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &buffer_binding);'
+        print '        if (buffer_binding > 0) {'
+        print '            gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
+        print '            buf.' + method + ';'
+        print '        }'
+        print '    }'
+        print
+
+    def shadowBufferProlog(self, function):
+        if function.name == 'glBufferData':
+            self.shadowBufferMethod('bufferData(size, data)')
+
+        if function.name == 'glBufferSubData':
+            self.shadowBufferMethod('bufferSubData(offset, size, data)')
+
+        if function.name == 'glDeleteBuffers':
+            print '    gltrace::Context *ctx = gltrace::getContext();'
+            print '    if (ctx->needsShadowBuffers()) {'
+            print '        for (GLsizei i = 0; i < n; i++) {'
+            print '            ctx->buffers.erase(buffer[i]);'
+            print '        }'
+            print '    }'
+
     array_pointer_function_names = set((
         "glVertexPointer",
         "glNormalPointer",
@@ -557,6 +605,7 @@ class GlTracer(Tracer):
             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 '        }'
             print '    }'
         if function.name == 'glUnmapNamedBufferEXT':
@@ -632,6 +681,8 @@ class GlTracer(Tracer):
             print '        }'
             print '    }'
 
+        self.shadowBufferProlog(function)
+
         Tracer.traceFunctionImplBody(self, function)
 
     marker_functions = [
@@ -1016,16 +1067,6 @@ class GlTracer(Tracer):
         function = api.getFunctionByName('glClientActiveTexture')
         self.fake_call(function, [texture])
 
-    def fake_call(self, function, args):
-        print '            unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
-        for arg, instance in zip(function.args, args):
-            assert not arg.output
-            print '            trace::localWriter.beginArg(%u);' % (arg.index,)
-            self.serializeValue(arg.type, instance)
-            print '            trace::localWriter.endArg();'
-        print '            trace::localWriter.endEnter();'
-        print '            trace::localWriter.beginLeave(_fake_call);'
-        print '            trace::localWriter.endLeave();'
 
 
 
index cb8e08b1accce6b7818a55528f74809f7da1cd53..68bda100354db46025c678618d3d66f2a9d6749e 100644 (file)
@@ -57,15 +57,13 @@ public:
     }
 };
 
-static os::thread_specific_ptr<struct ThreadState> thread_state;
+static thread_specific ThreadState *thread_state;
 
 static ThreadState *get_ts(void)
 {
-    ThreadState *ts = thread_state.get();
-
+    ThreadState *ts = thread_state;
     if (!ts) {
-        ts = new ThreadState;
-        thread_state.reset(ts);
+        thread_state = ts = new ThreadState;
     }
 
     return ts;
@@ -115,12 +113,17 @@ bool releaseContext(uintptr_t context_id)
 
 void createContext(uintptr_t context_id)
 {
+    // wglCreateContextAttribsARB causes internal calls to wglCreateContext to be
+    // traced, causing context to be defined twice.
+    if (context_map.find(context_id) != context_map.end()) {
+        return;
+    }
+
     context_ptr_t ctx(new Context);
 
     context_map_mutex.lock();
 
     _retainContext(ctx);
-    assert(context_map.find(context_id) == context_map.end());
     context_map[context_id] = ctx;
 
     context_map_mutex.unlock();
index ff3eb4cd62652ec216b0e83e516aefd011c41241..670f8f39a1785254d3b9d8bc497777e22b846a38 100644 (file)
@@ -45,17 +45,34 @@ class GlxTracer(GlTracer):
         "glXGetProcAddressARB",
     ]
 
+    createContextFunctionNames = [
+        'glXCreateContext',
+        'glXCreateContextAttribsARB',
+        'glXCreateContextWithConfigSGIX',
+        'glXCreateNewContext',
+    ]
+
+    destroyContextFunctionNames = [
+        'glXDestroyContext',
+    ]
+
+    makeCurrentFunctionNames = [
+        'glXMakeCurrent',
+        'glXMakeContextCurrent',
+        'glXMakeCurrentReadSGI',
+    ]
+
     def traceFunctionImplBody(self, function):
-        if function.name == 'glXDestroyContext':
+        if function.name in self.destroyContextFunctionNames:
             print '    gltrace::releaseContext((uintptr_t)ctx);'
 
         GlTracer.traceFunctionImplBody(self, function)
 
-        if function.name == 'glXCreateContext':
+        if function.name in self.createContextFunctionNames:
             print '    if (_result != NULL)'
             print '        gltrace::createContext((uintptr_t)_result);'
 
-        if function.name == 'glXMakeCurrent':
+        if function.name in self.makeCurrentFunctionNames:
             print '    if (_result) {'
             print '        if (ctx != NULL)'
             print '            gltrace::setContext((uintptr_t)ctx);'
index 958c07279a1bf55eab84d44d349ef6a3fded764f..30825617ceca523567d69cbc876f8fa0d3a294ef 100644 (file)
@@ -63,21 +63,13 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
         self.visit(const.type)
 
     def visitStruct(self, struct):
-        for type, name in struct.members:
-            self.visit(type)
-        print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr)
-        print '    static const char * members[%u] = {' % (len(struct.members),)
+        print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
         for type, name,  in struct.members:
-            print '        "%s",' % (name,)
-        print '    };'
-        print '    static const trace::StructSig sig = {'
-        print '       %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members))
-        print '    };'
-        print '    trace::localWriter.beginStruct(&sig);'
-        for type, name in struct.members:
-            self.serializer.visit(type, 'value.%s' % (name,))
-        print '    trace::localWriter.endStruct();'
-        print '}'
+            print '    "%s",' % (name,)
+        print '};'
+        print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
+        print '   %u, "%s", %u, _struct%s_members' % (struct.id, struct.name, len(struct.members), struct.tag)
+        print '};'
         print
 
     def visitArray(self, array):
@@ -158,16 +150,37 @@ class ValueSerializer(stdapi.Visitor):
     ComplexValueSerializer visitor above.
     '''
 
+    def __init__(self):
+        #stdapi.Visitor.__init__(self)
+        self.indices = []
+        self.instances = []
+
+    def expand(self, expr):
+        # Expand a C expression, replacing certain variables
+        variables = {}
+        try:
+            variables['self'] = self.instances[-1]
+        except IndexError:
+            pass
+        try:
+            variables['i'] = self.indices[-1]
+        except IndexError:
+            pass
+        expandedExpr = expr.format(**variables)
+        if expandedExpr != expr:
+            sys.stderr.write("  %r -> %r\n" % (expr, expandedExpr))
+        return expandedExpr
+
     def visitLiteral(self, literal, instance):
         print '    trace::localWriter.write%s(%s);' % (literal.kind, instance)
 
     def visitString(self, string, instance):
-        if string.kind == 'String':
+        if not string.wide:
             cast = 'const char *'
-        elif string.kind == 'WString':
-            cast = 'const wchar_t *'
+            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)
@@ -175,13 +188,20 @@ class ValueSerializer(stdapi.Visitor):
             length = ', %s' % string.length
         else:
             length = ''
-        print '    trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
+        print '    trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
 
     def visitConst(self, const, instance):
         self.visit(const.type, instance)
 
     def visitStruct(self, struct, instance):
-        print '    _write__%s(%s);' % (struct.tag, instance)
+        print '    trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
+        self.instances.append(instance)
+        try:
+            for type, name in struct.members:
+                self.visit(type, '(%s).%s' % (instance, name,))
+        finally:
+            self.instances.pop()
+        print '    trace::localWriter.endStruct();'
 
     def visitArray(self, array, instance):
         length = '_c' + array.type.tag
@@ -191,7 +211,11 @@ class ValueSerializer(stdapi.Visitor):
         print '        trace::localWriter.beginArray(%s);' % length
         print '        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
         print '            trace::localWriter.beginElement();'
-        self.visit(array.type, '(%s)[%s]' % (instance, index))
+        self.indices.append(index)
+        try:
+            self.visit(array.type, '(%s)[%s]' % (instance, index))
+        finally:
+            self.indices.pop()
         print '            trace::localWriter.endElement();'
         print '        }'
         print '        trace::localWriter.endArray();'
@@ -200,7 +224,7 @@ class ValueSerializer(stdapi.Visitor):
         print '    }'
 
     def visitBlob(self, blob, instance):
-        print '    trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
+        print '    trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
 
     def visitEnum(self, enum, instance):
         print '    trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
@@ -695,4 +719,15 @@ class Tracer:
         print '        trace::localWriter.endEnter();'
         print '        trace::localWriter.beginLeave(_call);'
         print '        trace::localWriter.endLeave();'
+    
+    def fake_call(self, function, args):
+        print '            unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
+        for arg, instance in zip(function.args, args):
+            assert not arg.output
+            print '            trace::localWriter.beginArg(%u);' % (arg.index,)
+            self.serializeValue(arg.type, instance)
+            print '            trace::localWriter.endArg();'
+        print '            trace::localWriter.endEnter();'
+        print '            trace::localWriter.beginLeave(_fake_call);'
+        print '            trace::localWriter.endLeave();'
        
index 1b0035799fdd648f32bda397b2e4ddb5f86c67e4..317c5422a7d5400e17c9d791c084c630b1ee9d7f 100644 (file)
@@ -39,8 +39,24 @@ class WglTracer(GlTracer):
         "wglGetProcAddress",
     ]
 
+    createContextFunctionNames = [
+        'wglCreateContext',
+        'wglCreateContextAttribsARB',
+        'wglCreateLayerContext',
+    ]
+
+    destroyContextFunctionNames = [
+        'wglDeleteContext',
+    ]
+
+    makeCurrentFunctionNames = [
+        'wglMakeCurrent',
+        'wglMakeContextCurrentARB',
+        'wglMakeContextCurrentEXT',
+    ]
+
     def traceFunctionImplBody(self, function):
-        if function.name == 'wglDeleteContext':
+        if function.name in self.destroyContextFunctionNames:
             # Unlike other GL APIs like EGL or GLX, WGL will make the context
             # inactive if it's currently the active context.
             print '    if (_wglGetCurrentContext() == hglrc) {'
@@ -50,11 +66,11 @@ class WglTracer(GlTracer):
 
         GlTracer.traceFunctionImplBody(self, function)
 
-        if function.name == 'wglCreateContext':
+        if function.name in self.createContextFunctionNames:
             print '    if (_result)'
             print '        gltrace::createContext((uintptr_t)_result);'
 
-        if function.name == 'wglMakeCurrent':
+        if function.name in self.makeCurrentFunctionNames:
             print '    if (_result) {'
             print '        if (hglrc != NULL)'
             print '            gltrace::setContext((uintptr_t)hglrc);'