diff --git a/examples/k22v4l/11to16.bin b/examples/k22v4l/11to16.bin new file mode 100644 index 000000000..f62c5ade8 Binary files /dev/null and b/examples/k22v4l/11to16.bin differ diff --git a/examples/k22v4l/CMakeLists.txt b/examples/k22v4l/CMakeLists.txt new file mode 100644 index 000000000..e519cb6bf --- /dev/null +++ b/examples/k22v4l/CMakeLists.txt @@ -0,0 +1,174 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +PROJECT(libfreenect2) +SET(CMAKE_BUILD_TYPE RelWithDebInfo) + +SET(MY_DIR ${libfreenect2_SOURCE_DIR}) + +OPTION(ENABLE_CXX11 "Enable C++11 support" OFF) +OPTION(ENABLE_OPENCL "Enable OpenCL support" ON) +OPTION(ENABLE_OPENGL "Enable OpenGL support" ON) + +IF(ENABLE_CXX11) + INCLUDE(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + IF(COMPILER_SUPPORTS_CXX11) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + ELSEIF(COMPILER_SUPPORTS_CXX0X) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + ELSE() + MESSAGE(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") + ENDIF() +ENDIF(ENABLE_CXX11) + +# additional cmake modules +LIST(APPEND CMAKE_MODULE_PATH ${MY_DIR}/cmake_modules) + +# setup threading +INCLUDE(SetupLibfreenect2Threading) +INCLUDE_DIRECTORIES(${LIBFREENECT2_THREADING_INCLUDE_DIR}) + +INCLUDE(GenerateResources) + +#set the default path for built executables to the "bin" directory +SET(EXECUTABLE_OUTPUT_PATH ${MY_DIR}/bin) + +#set the default path for built libraries to the "lib" directory +SET(LIBRARY_OUTPUT_PATH ${MY_DIR}/lib) + +FIND_PACKAGE(OpenCL) + +# dependencies +FIND_PACKAGE(OpenCV REQUIRED) + +# OpenCV +INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIR}) + +# LibUSB +INCLUDE_DIRECTORIES("${MY_DIR}/../../depends/libusb/include/libusb-1.0/") +LINK_DIRECTORIES("${MY_DIR}/../../depends/libusb/lib/") + +IF(ENABLE_OPENGL) + # GLFW + SET(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries") + SET(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Build the GLFW example programs") + SET(GLFW_BUILD_TESTS OFF CACHE BOOL "Build the GLFW test programs") + SET(GLFW_BUILD_DOCS OFF CACHE BOOL "Build the GLFW documentation") + + ADD_SUBDIRECTORY(${MY_DIR}/../../depends/glfw_src/ ${MY_DIR}/../../depends/glfw) + INCLUDE_DIRECTORIES(${MY_DIR}/../../depends/glfw_src/include/) +ENDIF(ENABLE_OPENGL) + +if(APPLE) + # libjpeg-turbo + INCLUDE_DIRECTORIES("${MY_DIR}/../../depends/libjpeg_turbo/include/") + LINK_DIRECTORIES("${MY_DIR}/../../depends/libjpeg_turbo/lib/") +endif() + +SET(RESOURCES_INC_FILE "${MY_DIR}/src/resources.inc") + +SET(SOURCES + src/transfer_pool.cpp + src/event_loop.cpp + + src/double_buffer.cpp + src/frame_listener_impl.cpp + src/packet_pipeline.cpp + + src/rgb_packet_stream_parser.cpp + src/rgb_packet_processor.cpp + src/turbo_jpeg_rgb_packet_processor.cpp + + src/depth_packet_stream_parser.cpp + src/depth_packet_processor.cpp + src/cpu_depth_packet_processor.cpp + src/resource.cpp + + src/usb_control.cpp + src/command_transaction.cpp + src/libfreenect2.cpp + ${LIBFREENECT2_THREADING_SOURCE} + ${RESOURCES_INC_FILE} +) + +SET(LIBRARIES + usb-1.0 + ${OpenCV_LIBS} + turbojpeg + ${LIBFREENECT2_THREADING_LIBRARIES} +) + +SET(RESOURCES + 11to16.bin + xTable.bin + zTable.bin +) + + +IF(ENABLE_OPENGL) + SET(LIBFREENECT2_WITH_OPENGL_SUPPORT 1) + LIST(APPEND SOURCES + src/flextGL.c + src/opengl_depth_packet_processor.cpp + ) + + LIST(APPEND LIBRARIES + glfw + ${GLFW_LIBRARIES} + ) + + LIST(APPEND RESOURCES + src/shader/debug.fs + src/shader/default.vs + src/shader/filter1.fs + src/shader/filter2.fs + src/shader/stage1.fs + src/shader/stage2.fs + ) +ENDIF(ENABLE_OPENGL) + +IF(ENABLE_OPENCL AND OPENCL_FOUND) + SET(LIBFREENECT2_WITH_OPENCL_SUPPORT 1) + INCLUDE_DIRECTORIES(${OPENCL_INCLUDE_DIRS}) + + LIST(APPEND SOURCES + src/opencl_depth_packet_processor.cpp + ) + + LIST(APPEND LIBRARIES + ${OPENCL_LIBRARIES} + ) + + LIST(APPEND RESOURCES + src/opencl_depth_packet_processor.cl + ) +ENDIF(ENABLE_OPENCL AND OPENCL_FOUND) + +CONFIGURE_FILE("${MY_DIR}/include/libfreenect2/config.h.in" "${MY_DIR}/include/libfreenect2/config.h" @ONLY) + +GENERATE_RESOURCES(${RESOURCES_INC_FILE} ${MY_DIR} ${RESOURCES}) + +INCLUDE_DIRECTORIES("${MY_DIR}/include") + +ADD_DEFINITIONS(-DRESOURCES_INC) +ADD_LIBRARY(freenect2 SHARED ${SOURCES}) +TARGET_LINK_LIBRARIES(freenect2 ${LIBRARIES}) + +ADD_EXECUTABLE(k22v4l + k22v4l.cpp +) + +TARGET_LINK_LIBRARIES(k22v4l + freenect2 +) + +CONFIGURE_FILE(freenect2.cmake.in "${PROJECT_BINARY_DIR}/freenect2Config.cmake" @ONLY) + +INSTALL(TARGETS freenect2 DESTINATION lib) +INSTALL(DIRECTORY "${MY_DIR}/include/" DESTINATION include PATTERN "*.in" EXCLUDE) +IF(LIBFREENECT2_THREADING_TINYTHREAD) + INSTALL(FILES "${MY_DIR}/src/tinythread/tinythread.h" DESTINATION include/${PROJECT_NAME}/tinythread/) +ENDIF(LIBFREENECT2_THREADING_TINYTHREAD) +INSTALL(FILES "${PROJECT_BINARY_DIR}/freenect2Config.cmake" DESTINATION lib/cmake/freenect2/) + diff --git a/examples/k22v4l/README.md b/examples/k22v4l/README.md new file mode 100644 index 000000000..09e3cca53 --- /dev/null +++ b/examples/k22v4l/README.md @@ -0,0 +1,6 @@ + +Depends on v4l2loopback + +Load kernel module and add 3 devices: + + # modprobe v4l2loopback devices=3 diff --git a/examples/k22v4l/cmake_modules/FindOpenCL.cmake b/examples/k22v4l/cmake_modules/FindOpenCL.cmake new file mode 100644 index 000000000..2c9672b3a --- /dev/null +++ b/examples/k22v4l/cmake_modules/FindOpenCL.cmake @@ -0,0 +1,76 @@ +# - Try to find OpenCL +# This module tries to find an OpenCL implementation on your system. It supports +# AMD / ATI, Apple and NVIDIA implementations, but should work, too. +# +# To set manually the paths, define these environment variables: +# OpenCL_INCPATH - Include path (e.g. OpenCL_INCPATH=/opt/cuda/4.0/cuda/include) +# OpenCL_LIBPATH - Library path (e.h. OpenCL_LIBPATH=/usr/lib64/nvidia) +# +# Once done this will define +# OPENCL_FOUND - system has OpenCL +# OPENCL_INCLUDE_DIRS - the OpenCL include directory +# OPENCL_LIBRARIES - link these to use OpenCL +# +# WIN32 should work, but is untested + +FIND_PACKAGE(PackageHandleStandardArgs) + +SET (OPENCL_VERSION_STRING "0.1.0") +SET (OPENCL_VERSION_MAJOR 0) +SET (OPENCL_VERSION_MINOR 1) +SET (OPENCL_VERSION_PATCH 0) + +IF (APPLE) + + FIND_LIBRARY(OPENCL_LIBRARIES OpenCL DOC "OpenCL lib for OSX") + FIND_PATH(OPENCL_INCLUDE_DIRS OpenCL/cl.h DOC "Include for OpenCL on OSX") + FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS OpenCL/cl.hpp DOC "Include for OpenCL CPP bindings on OSX") + +ELSE (APPLE) + + IF (WIN32) + # The AMD SDK currently installs both x86 and x86_64 libraries + # This is only a hack to find out architecture + IF( ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64" ) + FIND_LIBRARY(OPENCL_LIBRARIES OpenCL.lib PATHS "$ENV{ATISTREAMSDKROOT}" "$ENV{AMDAPPSDKROOT}" PATH_SUFFIXES "/lib/x86_64") + ELSE (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") + FIND_LIBRARY(OPENCL_LIBRARIES OpenCL.lib PATHS "$ENV{ATISTREAMSDKROOT}" "$ENV{AMDAPPSDKROOT}" PATH_SUFFIXES "/lib/x86") + ENDIF( ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64" ) + + # On Win32 search relative to the library + FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS "$ENV{ATISTREAMSDKROOT}" "$ENV{AMDAPPSDKROOT}" PATH_SUFFIXES "/include") + FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS "$ENV{ATISTREAMSDKROOT}" "$ENV{AMDAPPSDKROOT}" PATH_SUFFIXES "/include") + + ELSE (WIN32) + + # Unix style platforms + FIND_LIBRARY(OPENCL_LIBRARIES OpenCL + PATHS ENV LD_LIBRARY_PATH ENV OpenCL_LIBPATH + ) + + GET_FILENAME_COMPONENT(OPENCL_LIB_DIR ${OPENCL_LIBRARIES} PATH) + GET_FILENAME_COMPONENT(_OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE) + + # The AMD SDK currently does not place its headers + # in /usr/include, therefore also search relative + # to the library + FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH) + FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH) + + ENDIF (WIN32) + +ENDIF (APPLE) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenCL DEFAULT_MSG OPENCL_LIBRARIES OPENCL_INCLUDE_DIRS) + +IF(_OPENCL_CPP_INCLUDE_DIRS) + SET( OPENCL_HAS_CPP_BINDINGS TRUE ) + LIST( APPEND OPENCL_INCLUDE_DIRS ${_OPENCL_CPP_INCLUDE_DIRS} ) + # This is often the same, so clean up + LIST( REMOVE_DUPLICATES OPENCL_INCLUDE_DIRS ) +ENDIF(_OPENCL_CPP_INCLUDE_DIRS) + +MARK_AS_ADVANCED( + OPENCL_INCLUDE_DIRS +) + diff --git a/examples/k22v4l/cmake_modules/GenerateResources.cmake b/examples/k22v4l/cmake_modules/GenerateResources.cmake new file mode 100644 index 000000000..712e02b11 --- /dev/null +++ b/examples/k22v4l/cmake_modules/GenerateResources.cmake @@ -0,0 +1,14 @@ +FUNCTION(GENERATE_RESOURCES OUTPUT BASE_FOLDER) + +ADD_EXECUTABLE(generate_resources_tool + src/generate_resources.cpp +) + +ADD_CUSTOM_COMMAND( + OUTPUT ${OUTPUT} + COMMAND generate_resources_tool ${BASE_FOLDER} ${ARGN} > ${OUTPUT} + WORKING_DIRECTORY ${BASE_FOLDER} + DEPENDS generate_resources_tool ${ARGN} +) + +ENDFUNCTION(GENERATE_RESOURCES) diff --git a/examples/k22v4l/cmake_modules/SetupLibfreenect2Threading.cmake b/examples/k22v4l/cmake_modules/SetupLibfreenect2Threading.cmake new file mode 100644 index 000000000..b28861feb --- /dev/null +++ b/examples/k22v4l/cmake_modules/SetupLibfreenect2Threading.cmake @@ -0,0 +1,40 @@ +INCLUDE(CheckCXXSourceCompiles) + +CHECK_CXX_SOURCE_COMPILES(" +#include +#include +#include +#include + +int main(int argc, char** argv) { + std::thread thread; + std::mutex mutex; + std::lock_guard lock_guard(mutex); + std::unique_lock unique_lock(mutex); + std::condition_variable condition_variable; + thread_local int i; + + return 0; +} + +" LIBFREENECT2_THREADING_STDLIB) + +IF(LIBFREENECT2_THREADING_STDLIB) + SET(LIBFREENECT2_THREADING "stdlib") + SET(LIBFREENECT2_THREADING_INCLUDE_DIR "") + SET(LIBFREENECT2_THREADING_SOURCE "") + SET(LIBFREENECT2_THREADING_LIBRARIES "") + SET(LIBFREENECT2_THREADING_STDLIB 1) +ELSE(LIBFREENECT2_THREADING_STDLIB) + SET(LIBFREENECT2_THREADING "tinythread") + SET(LIBFREENECT2_THREADING_INCLUDE_DIR "src/tinythread/") + SET(LIBFREENECT2_THREADING_SOURCE "src/tinythread/tinythread.cpp") + IF(NOT WIN32) + SET(LIBFREENECT2_THREADING_LIBRARIES "pthread") + ELSE(NOT WIN32) + SET(LIBFREENECT2_THREADING_LIBRARIES "") + ENDIF(NOT WIN32) + SET(LIBFREENECT2_THREADING_TINYTHREAD 1) +ENDIF(LIBFREENECT2_THREADING_STDLIB) + +MESSAGE(STATUS "using ${LIBFREENECT2_THREADING} as threading library") diff --git a/examples/k22v4l/freenect2.cmake.in b/examples/k22v4l/freenect2.cmake.in new file mode 100644 index 000000000..677dd59f3 --- /dev/null +++ b/examples/k22v4l/freenect2.cmake.in @@ -0,0 +1,13 @@ +FIND_LIBRARY(freenect2_LIBRARY freenect2 + PATHS @CMAKE_INSTALL_PREFIX@/lib + NO_DEFAULT_PATH +) +SET(freenect2_LIBRARIES ${freenect2_LIBRARY} @LIBFREENECT2_THREADING_LIBRARIES@) +FIND_PATH(freenect2_INCLUDE_DIR @PROJECT_NAME@/libfreenect2.hpp + PATHS @CMAKE_INSTALL_PREFIX@/include + NO_DEFAULT_PATH +) + +IF("@LIBFREENECT2_THREADING_TINYTHREAD@") + SET(freenect2_INCLUDE_DIRS ${freenect2_INCLUDE_DIR} ${freenect2_INCLUDE_DIR}/tinythread) +ENDIF("@LIBFREENECT2_THREADING_TINYTHREAD@") diff --git a/examples/k22v4l/include/libfreenect2/async_packet_processor.h b/examples/k22v4l/include/libfreenect2/async_packet_processor.h new file mode 100644 index 000000000..807dbead7 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/async_packet_processor.h @@ -0,0 +1,114 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef ASYNC_PACKET_PROCESSOR_H_ +#define ASYNC_PACKET_PROCESSOR_H_ + +#include +#include + +namespace libfreenect2 +{ + +template +class AsyncPacketProcessor : public PacketProcessor +{ +public: + typedef PacketProcessor* PacketProcessorPtr; + + AsyncPacketProcessor(PacketProcessorPtr processor) : + processor_(processor), + current_packet_available_(false), + shutdown_(false), + thread_(&AsyncPacketProcessor::static_execute, this) + { + } + virtual ~AsyncPacketProcessor() + { + shutdown_ = true; + packet_condition_.notify_one(); + + thread_.join(); + } + + virtual bool ready() + { + // try to aquire lock, if we succeed the background thread is waiting on packet_condition_ + bool locked = packet_mutex_.try_lock(); + + if(locked) + { + packet_mutex_.unlock(); + } + + return locked; + } + + virtual void process(const PacketT &packet) + { + { + libfreenect2::lock_guard l(packet_mutex_); + current_packet_ = packet; + current_packet_available_ = true; + } + packet_condition_.notify_one(); + } +private: + PacketProcessorPtr processor_; + bool current_packet_available_; + PacketT current_packet_; + + bool shutdown_; + libfreenect2::mutex packet_mutex_; + libfreenect2::condition_variable packet_condition_; + libfreenect2::thread thread_; + + static void static_execute(void *data) + { + static_cast *>(data)->execute(); + } + + void execute() + { + libfreenect2::unique_lock l(packet_mutex_); + + while(!shutdown_) + { + WAIT_CONDITION(packet_condition_, packet_mutex_, l); + + if(current_packet_available_) + { + // invoke process impl + processor_->process(current_packet_); + + current_packet_available_ = false; + } + } + } +}; + +} /* namespace libfreenect2 */ +#endif /* ASYNC_PACKET_PROCESSOR_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/config.h.in b/examples/k22v4l/include/libfreenect2/config.h.in new file mode 100644 index 000000000..f3abf7d43 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/config.h.in @@ -0,0 +1,50 @@ +/* +* This file is part of the OpenKinect Project. http://www.openkinect.org +* +* Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file +* for details. +* +* This code is licensed to you under the terms of the Apache License, version +* 2.0, or, at your option, the terms of the GNU General Public License, +* version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, +* or the following URLs: +* http://www.apache.org/licenses/LICENSE-2.0 +* http://www.gnu.org/licenses/gpl-2.0.txt +* +* If you redistribute this file in source form, modified or unmodified, you +* may: +* 1) Leave this header intact and distribute it under the same terms, +* accompanying it with the APACHE20 and GPL20 files, or +* 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or +* 3) Delete the GPL v2 clause and accompany it with the APACHE20 file +* In all cases you must keep the copyright notice intact and include a copy +* of the CONTRIB file. +* +* Binary distributions must follow the binary distribution requirements of +* either License. +*/ + +#ifndef LIBFREENECT2_CONFIG_H +#define LIBFREENECT2_CONFIG_H + +#ifdef _MSC_VER +#define LIBFREENECT2_PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) +#else +#define LIBFREENECT2_PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#endif + +#ifdef _WIN32 +#define LIBFREENECT2_API __declspec(dllexport) +#else +#define LIBFREENECT2_API +#endif + +#cmakedefine LIBFREENECT2_WITH_OPENGL_SUPPORT + +#cmakedefine LIBFREENECT2_WITH_OPENCL_SUPPORT + +#cmakedefine LIBFREENECT2_THREADING_STDLIB + +#cmakedefine LIBFREENECT2_THREADING_TINYTHREAD + +#endif // LIBFREENECT2_CONFIG_H diff --git a/examples/k22v4l/include/libfreenect2/data_callback.h b/examples/k22v4l/include/libfreenect2/data_callback.h new file mode 100644 index 000000000..2137aaa0d --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/data_callback.h @@ -0,0 +1,45 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + + +#ifndef DATA_CALLBACK_H_ +#define DATA_CALLBACK_H_ + +#include +#include + +namespace libfreenect2 +{ + +class LIBFREENECT2_API DataCallback +{ +public: + virtual void onDataReceived(unsigned char *buffer, size_t n) = 0; +}; + +} // namespace libfreenect2 + +#endif // DATA_CALLBACK_H_ diff --git a/examples/k22v4l/include/libfreenect2/depth_packet_processor.h b/examples/k22v4l/include/libfreenect2/depth_packet_processor.h new file mode 100644 index 000000000..0868d87e0 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/depth_packet_processor.h @@ -0,0 +1,201 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef DEPTH_PACKET_PROCESSOR_H_ +#define DEPTH_PACKET_PROCESSOR_H_ + +#include +#include + +#include +#include +#include + +namespace libfreenect2 +{ + +struct LIBFREENECT2_API DepthPacket +{ + uint32_t sequence; + unsigned char *buffer; + size_t buffer_length; +}; + +// explicit instantiation and export to make vsc++ happy +template class LIBFREENECT2_API PacketProcessor; +typedef PacketProcessor BaseDepthPacketProcessor; + +class LIBFREENECT2_API DepthPacketProcessor : public BaseDepthPacketProcessor +{ +public: + struct LIBFREENECT2_API Config + { + float MinDepth; + float MaxDepth; + + bool EnableBilateralFilter; + bool EnableEdgeAwareFilter; + + Config(); + }; + + struct LIBFREENECT2_API Parameters + { + float ab_multiplier; + float ab_multiplier_per_frq[3]; + float ab_output_multiplier; + + float phase_in_rad[3]; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + float gaussian_kernel[9]; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; + + Parameters(); + }; + + DepthPacketProcessor(); + virtual ~DepthPacketProcessor(); + + virtual void setFrameListener(libfreenect2::FrameListener *listener); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length) = 0; +protected: + libfreenect2::DepthPacketProcessor::Config config_; + libfreenect2::FrameListener *listener_; +}; + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT +class OpenGLDepthPacketProcessorImpl; + +class LIBFREENECT2_API OpenGLDepthPacketProcessor : public DepthPacketProcessor +{ +public: + OpenGLDepthPacketProcessor(void *parent_opengl_context_ptr, bool debug); + virtual ~OpenGLDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + void loadP0TablesFromFiles(const char* p0_filename, const char* p1_filename, const char* p2_filename); + + /** + * GUESS: the x and z table follow some polynomial, until we know the exact polynom formula and its coefficients + * just load them from a memory dump - although they probably vary per camera + */ + void loadXTableFromFile(const char* filename); + + void loadZTableFromFile(const char* filename); + + void load11To16LutFromFile(const char* filename); + + virtual void process(const DepthPacket &packet); +private: + OpenGLDepthPacketProcessorImpl *impl_; +}; +#endif // LIBFREENECT2_WITH_OPENGL_SUPPORT + +// TODO: push this to some internal namespace +// use pimpl to hide opencv dependency +class CpuDepthPacketProcessorImpl; + +class LIBFREENECT2_API CpuDepthPacketProcessor : public DepthPacketProcessor +{ +public: + CpuDepthPacketProcessor(); + virtual ~CpuDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + void loadP0TablesFromFiles(const char* p0_filename, const char* p1_filename, const char* p2_filename); + + /** + * GUESS: the x and z table follow some polynomial, until we know the exact polynom formula and its coefficients + * just load them from a memory dump - although they probably vary per camera + */ + void loadXTableFromFile(const char* filename); + + void loadZTableFromFile(const char* filename); + + void load11To16LutFromFile(const char* filename); + + virtual void process(const DepthPacket &packet); +private: + CpuDepthPacketProcessorImpl *impl_; +}; + +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT +class OpenCLDepthPacketProcessorImpl; + +class LIBFREENECT2_API OpenCLDepthPacketProcessor : public DepthPacketProcessor +{ +public: + OpenCLDepthPacketProcessor(const int deviceId = -1); + virtual ~OpenCLDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + /** + * GUESS: the x and z table follow some polynomial, until we know the exact polynom formula and its coefficients + * just load them from a memory dump - although they probably vary per camera + */ + void loadXTableFromFile(const char* filename); + + void loadZTableFromFile(const char* filename); + + void load11To16LutFromFile(const char* filename); + + virtual void process(const DepthPacket &packet); +private: + OpenCLDepthPacketProcessorImpl *impl_; +}; +#endif // LIBFREENECT2_WITH_OPENCL_SUPPORT +} /* namespace libfreenect2 */ +#endif /* DEPTH_PACKET_PROCESSOR_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/depth_packet_stream_parser.h b/examples/k22v4l/include/libfreenect2/depth_packet_stream_parser.h new file mode 100644 index 000000000..7773cadc4 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/depth_packet_stream_parser.h @@ -0,0 +1,74 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef DEPTH_PACKET_STREAM_PARSER_H_ +#define DEPTH_PACKET_STREAM_PARSER_H_ + +#include +#include + +#include + +#include +#include + +#include + +namespace libfreenect2 +{ + +LIBFREENECT2_PACK(struct LIBFREENECT2_API DepthSubPacketFooter +{ + uint32_t magic0; + uint32_t magic1; + uint32_t timestamp; + uint32_t sequence; + uint32_t subsequence; + uint32_t length; + uint32_t fields[32]; +}); + +class LIBFREENECT2_API DepthPacketStreamParser : public DataCallback +{ +public: + DepthPacketStreamParser(); + virtual ~DepthPacketStreamParser(); + + void setPacketProcessor(libfreenect2::BaseDepthPacketProcessor *processor); + + virtual void onDataReceived(unsigned char* buffer, size_t length); +private: + libfreenect2::BaseDepthPacketProcessor *processor_; + + libfreenect2::DoubleBuffer buffer_; + libfreenect2::Buffer work_buffer_; + + uint32_t current_sequence_; + uint32_t current_subsequence_; +}; + +} /* namespace libfreenect2 */ +#endif /* DEPTH_PACKET_STREAM_PARSER_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/double_buffer.h b/examples/k22v4l/include/libfreenect2/double_buffer.h new file mode 100644 index 000000000..49eb1f155 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/double_buffer.h @@ -0,0 +1,65 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef DOUBLE_BUFFER_H_ +#define DOUBLE_BUFFER_H_ + +#include +#include + +namespace libfreenect2 +{ + +struct LIBFREENECT2_API Buffer +{ +public: + size_t capacity; + size_t length; + unsigned char* data; +}; + +class LIBFREENECT2_API DoubleBuffer +{ +public: + DoubleBuffer(); + virtual ~DoubleBuffer(); + + void allocate(size_t buffer_size); + + void swap(); + + Buffer& front(); + + Buffer& back(); +private: + Buffer buffer_[2]; + unsigned char front_buffer_index_; + + unsigned char* buffer_data_; +}; + +} /* namespace libfreenect2 */ +#endif /* DOUBLE_BUFFER_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/frame_listener.hpp b/examples/k22v4l/include/libfreenect2/frame_listener.hpp new file mode 100644 index 000000000..fbefaeb6b --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/frame_listener.hpp @@ -0,0 +1,71 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef FRAME_LISTENER_HPP_ +#define FRAME_LISTENER_HPP_ + +#include +#include + +namespace libfreenect2 +{ + +struct LIBFREENECT2_API Frame +{ + enum Type + { + Color = 1, + Ir = 2, + Depth = 4 + }; + + size_t width, height, bytes_per_pixel; + unsigned char* data; + + Frame(size_t width, size_t height, size_t bytes_per_pixel) : + width(width), + height(height), + bytes_per_pixel(bytes_per_pixel) + { + data = new unsigned char[width * height * bytes_per_pixel]; + } + + ~Frame() + { + delete[] data; + } +}; + +class LIBFREENECT2_API FrameListener +{ +public: + virtual ~FrameListener(); + + virtual bool onNewFrame(Frame::Type type, Frame *frame) = 0; +}; + +} /* namespace libfreenect2 */ +#endif /* FRAME_LISTENER_HPP_ */ diff --git a/examples/k22v4l/include/libfreenect2/frame_listener_impl.h b/examples/k22v4l/include/libfreenect2/frame_listener_impl.h new file mode 100644 index 000000000..ff6895b62 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/frame_listener_impl.h @@ -0,0 +1,64 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef FRAME_LISTENER_IMPL_H_ +#define FRAME_LISTENER_IMPL_H_ + +#include + +#include +#include + +namespace libfreenect2 +{ + +typedef std::map FrameMap; + +class SyncMultiFrameListenerImpl; + +class LIBFREENECT2_API SyncMultiFrameListener : public FrameListener +{ +public: + SyncMultiFrameListener(unsigned int frame_types); + virtual ~SyncMultiFrameListener(); + + bool hasNewFrame() const; + +#ifdef LIBFREENECT2_THREADING_STDLIB + bool waitForNewFrame(FrameMap &frame, int milliseconds); +#endif // LIBFREENECT2_THREADING_STDLIB + // for now the caller is responsible to release the frames when he is done + void waitForNewFrame(FrameMap &frame); + + void release(FrameMap &frame); + + virtual bool onNewFrame(Frame::Type type, Frame *frame); +private: + SyncMultiFrameListenerImpl *impl_; +}; + +} /* namespace libfreenect2 */ +#endif /* FRAME_LISTENER_IMPL_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/libfreenect2.hpp b/examples/k22v4l/include/libfreenect2/libfreenect2.hpp new file mode 100644 index 000000000..ae52e68b6 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/libfreenect2.hpp @@ -0,0 +1,99 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef LIBFREENECT2_HPP_ +#define LIBFREENECT2_HPP_ + +#include +#include + +namespace libfreenect2 +{ + +class PacketPipeline; + +class LIBFREENECT2_API Freenect2Device +{ +public: + static const unsigned int VendorId = 0x045E; + static const unsigned int ProductId = 0x02D8; + static const unsigned int ProductIdPreview = 0x02C4; + + struct ColorCameraParams + { + float fx, fy, cx, cy; + }; + + struct IrCameraParams + { + float fx, fy, cx, cy, k1, k2, k3, p1, p2; + }; + + virtual ~Freenect2Device(); + + virtual std::string getSerialNumber() = 0; + virtual std::string getFirmwareVersion() = 0; + + virtual Freenect2Device::ColorCameraParams getColorCameraParams() = 0; + virtual Freenect2Device::IrCameraParams getIrCameraParams() = 0; + + + virtual void setColorFrameListener(libfreenect2::FrameListener* rgb_frame_listener) = 0; + virtual void setIrAndDepthFrameListener(libfreenect2::FrameListener* ir_frame_listener) = 0; + + virtual void start() = 0; + virtual void stop() = 0; + virtual void close() = 0; +}; + +class Freenect2Impl; + +class LIBFREENECT2_API Freenect2 +{ +public: + Freenect2(void *usb_context = 0); + virtual ~Freenect2(); + + int enumerateDevices(); + + std::string getDeviceSerialNumber(int idx); + std::string getDefaultDeviceSerialNumber(); + + Freenect2Device *openDevice(int idx); + Freenect2Device *openDevice(int idx, const PacketPipeline *factory); + Freenect2Device *openDevice(const std::string &serial); + Freenect2Device *openDevice(const std::string &serial, const PacketPipeline *factory); + + Freenect2Device *openDefaultDevice(); + Freenect2Device *openDefaultDevice(const PacketPipeline *factory); +protected: + Freenect2Device *openDevice(int idx, const PacketPipeline *factory, bool attempting_reset); +private: + Freenect2Impl *impl_; +}; + +} /* namespace libfreenect2 */ +#endif /* LIBFREENECT2_HPP_ */ diff --git a/examples/k22v4l/include/libfreenect2/packet_pipeline.h b/examples/k22v4l/include/libfreenect2/packet_pipeline.h new file mode 100644 index 000000000..b1bf467c2 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/packet_pipeline.h @@ -0,0 +1,112 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef PACKET_PIPELINE_H_ +#define PACKET_PIPELINE_H_ + +#include +#include +#include +#include +#include +#include + +namespace libfreenect2 +{ + +class LIBFREENECT2_API PacketPipeline +{ +public: + typedef DataCallback PacketParser; + virtual ~PacketPipeline(); + + virtual PacketParser *getRgbPacketParser() const = 0; + virtual PacketParser *getIrPacketParser() const = 0; + + virtual RgbPacketProcessor *getRgbPacketProcessor() const = 0; + virtual DepthPacketProcessor *getDepthPacketProcessor() const = 0; +}; + +class LIBFREENECT2_API BasePacketPipeline : public PacketPipeline +{ +protected: + RgbPacketStreamParser *rgb_parser_; + DepthPacketStreamParser *depth_parser_; + + RgbPacketProcessor *rgb_processor_; + BaseRgbPacketProcessor *async_rgb_processor_; + DepthPacketProcessor *depth_processor_; + BaseDepthPacketProcessor *async_depth_processor_; + + virtual void initialize(); + virtual DepthPacketProcessor *createDepthPacketProcessor() = 0; +public: + virtual ~BasePacketPipeline(); + + virtual PacketParser *getRgbPacketParser() const; + virtual PacketParser *getIrPacketParser() const; + + virtual RgbPacketProcessor *getRgbPacketProcessor() const; + virtual DepthPacketProcessor *getDepthPacketProcessor() const; +}; + +class LIBFREENECT2_API CpuPacketPipeline : public BasePacketPipeline +{ +protected: + virtual DepthPacketProcessor *createDepthPacketProcessor(); +public: + CpuPacketPipeline(); + virtual ~CpuPacketPipeline(); +}; + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT +class LIBFREENECT2_API OpenGLPacketPipeline : public BasePacketPipeline +{ +protected: + void *parent_opengl_context_; + bool debug_; + virtual DepthPacketProcessor *createDepthPacketProcessor(); +public: + OpenGLPacketPipeline(void *parent_opengl_context = 0, bool debug = false); + virtual ~OpenGLPacketPipeline(); +}; +#endif // LIBFREENECT2_WITH_OPENGL_SUPPORT + +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT +class LIBFREENECT2_API OpenCLPacketPipeline : public BasePacketPipeline +{ +protected: + const int deviceId; + virtual DepthPacketProcessor *createDepthPacketProcessor(); +public: + OpenCLPacketPipeline(const int deviceId = -1); + virtual ~OpenCLPacketPipeline(); +}; +#endif // LIBFREENECT2_WITH_OPENCL_SUPPORT + + +} /* namespace libfreenect2 */ +#endif /* PACKET_PIPELINE_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/packet_processor.h b/examples/k22v4l/include/libfreenect2/packet_processor.h new file mode 100644 index 000000000..ea21b9d8a --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/packet_processor.h @@ -0,0 +1,61 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef PACKET_PROCESSOR_H_ +#define PACKET_PROCESSOR_H_ + +namespace libfreenect2 +{ + +template +class PacketProcessor +{ +public: + virtual ~PacketProcessor() {} + + virtual bool ready() { return true; } + virtual void process(const PacketT &packet) = 0; +}; + +template +class NoopPacketProcessor : public PacketProcessor +{ +public: + NoopPacketProcessor() {} + virtual ~NoopPacketProcessor() {} + + virtual void process(const PacketT &packet) {} +}; + +template +PacketProcessor *noopProcessor() +{ + static NoopPacketProcessor noop_processor_; + return &noop_processor_; +} + +} /* namespace libfreenect2 */ +#endif /* PACKET_PROCESSOR_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/protocol/command.h b/examples/k22v4l/include/libfreenect2/protocol/command.h new file mode 100644 index 000000000..77513af99 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/protocol/command.h @@ -0,0 +1,203 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef COMMAND_H_ +#define COMMAND_H_ + +#include + +#define KCMD_READ_FIRMWARE_VERSIONS 0x02 +#define KCMD_INIT_STREAMS 0x09 +#define KCMD_READ_DATA_0x14 0x14 +#define KCMD_READ_STATUS 0x16 +#define KCMD_READ_DATA_PAGE 0x22 +#define KCMD_READ_DATA_0x26 0x26 + +#define KCMD_SET_STREAMING 0x2B +#define KCMD_SET_MODE 0x4B + +#define KCMD_0x46 0x46 +#define KCMD_0x47 0x47 + +// observed in sensor stop/shutdown sequence +#define KCMD_0x0A 0x0A + +namespace libfreenect2 +{ + +namespace protocol +{ + +template +struct CommandData +{ + uint32_t magic; + uint32_t sequence; + uint32_t max_response_length; + uint32_t command; + uint32_t reserved0; + uint32_t parameters[NParam]; + + CommandData() + { + for(int i = 0; i < NParam; ++i) + parameters[i] = 0; + } +}; + +template<> +struct CommandData<0> +{ + uint32_t magic; + uint32_t sequence; + uint32_t max_response_length; + uint32_t command; + uint32_t reserved0; +}; + +struct CommandBase +{ + virtual ~CommandBase() {} + + virtual uint32_t sequence() const = 0; + virtual uint32_t maxResponseLength() const = 0; + + virtual const uint8_t *data() const = 0; + virtual uint32_t size() const = 0; +}; + +template +class Command : public CommandBase +{ +public: + typedef CommandData Data; + + static const uint32_t MagicNumber = 0x06022009; + static const uint32_t Size = sizeof(Data); + + Command(uint32_t seq) + { + data_.magic = MagicNumber; + data_.sequence = seq; + data_.max_response_length = MaxResponseLength; + data_.command = CommandId; + data_.reserved0 = 0; + } + + virtual ~Command() + { + } + + virtual uint32_t sequence() const + { + return data_.sequence; + } + + virtual uint32_t maxResponseLength() const + { + return data_.max_response_length; + } + + virtual const uint8_t *data() const + { + return reinterpret_cast(&data_); + } + + virtual uint32_t size() const + { + return Size; + } + +protected: + Data data_; +}; + +template +struct CommandWith0Params : public Command +{ + CommandWith0Params(uint32_t seq) : Command(seq) + { + } +}; + +template +struct CommandWith1Param : public Command +{ + CommandWith1Param(uint32_t seq) : Command(seq) + { + this->data_.parameters[0] = Param1; + } +}; + +template +struct CommandWith4Params : public Command +{ + CommandWith4Params(uint32_t seq) : Command(seq) + { + this->data_.parameters[0] = Param1; + this->data_.parameters[1] = Param2; + this->data_.parameters[2] = Param3; + this->data_.parameters[3] = Param4; + } +}; + +typedef CommandWith0Params<0x02, 0x200> ReadFirmwareVersionsCommand; + +typedef CommandWith0Params ReadData0x14Command; + +typedef CommandWith0Params InitStreamsCommand; + +typedef CommandWith1Param ReadSerialNumberCommand; +typedef CommandWith1Param ReadP0TablesCommand; +typedef CommandWith1Param ReadDepthCameraParametersCommand; +typedef CommandWith1Param ReadRgbCameraParametersCommand; + +typedef CommandWith1Param ReadStatus0x090000Command; +typedef CommandWith1Param ReadStatus0x100007Command; +// TODO: are they ever used?! +typedef CommandWith1Param ReadStatus0x02006FCommand; +typedef CommandWith1Param ReadStatus0x020070Command; + +// TODO: is the following actually correct? +typedef CommandWith0Params ReadData0x26Command; +//typedef CommandWith1Param ReadData0x26_0x00Command; + +typedef CommandWith1Param SetStreamDisabledCommand; +typedef CommandWith1Param SetStreamEnabledCommand; + +// TODO: are they ever used?! +typedef CommandWith4Params Unknown0x46Command; +typedef CommandWith0Params Unknown0x47Command; + +typedef CommandWith0Params Unknown0x0ACommand; + +typedef CommandWith4Params SetModeDisabledCommand; +typedef CommandWith4Params SetModeEnabledCommand; +typedef CommandWith4Params SetModeEnabledWith0x00640064Command; +typedef CommandWith4Params SetModeEnabledWith0x00500050Command; +} /* namespace protocol */ +} /* namespace libfreenect2 */ +#endif /* COMMAND_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/protocol/command_transaction.h b/examples/k22v4l/include/libfreenect2/protocol/command_transaction.h new file mode 100644 index 000000000..6994c9104 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/protocol/command_transaction.h @@ -0,0 +1,83 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef COMMAND_TRANSACTION_H_ +#define COMMAND_TRANSACTION_H_ + +#include +#include + +namespace libfreenect2 +{ +namespace protocol +{ + +class CommandTransaction +{ +public: + static const int ResponseCompleteLength = 16; + static const uint32_t ResponseCompleteMagic = 0x0A6FE000; + + enum ResultCode + { + Success, + Error + }; + + struct Result + { + ResultCode code; + + unsigned char *data; + int capacity, length; + + Result(); + ~Result(); + + void allocate(size_t size); + void deallocate(); + bool notSuccessfulThenDeallocate(); + }; + + CommandTransaction(libusb_device_handle *handle, int inbound_endpoint, int outbound_endpoint); + ~CommandTransaction(); + + void execute(const CommandBase& command, Result& result); +private: + libusb_device_handle *handle_; + int inbound_endpoint_, outbound_endpoint_, timeout_; + Result response_complete_result_; + + ResultCode send(const CommandBase& command); + + void receive(Result& result); + + bool isResponseCompleteResult(Result& result, uint32_t sequence); +}; + +} /* namespace protocol */ +} /* namespace libfreenect2 */ +#endif /* COMMAND_TRANSACTION_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/protocol/response.h b/examples/k22v4l/include/libfreenect2/protocol/response.h new file mode 100644 index 000000000..de1509e72 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/protocol/response.h @@ -0,0 +1,251 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef RESPONSE_H_ +#define RESPONSE_H_ + +#include +#include +#include +#include +#include +#include + +namespace libfreenect2 +{ +namespace protocol +{ + +class SerialNumberResponse +{ +private: + std::string serial_; +public: + SerialNumberResponse(const unsigned char *data, int length) + { + char *c = new char[length / 2]; + + for(int i = 0, j = 0; i < length; i += 2, ++j) + { + c[j] = (char)data[i]; + if(c[j] == 0) break; + } + + serial_.assign(c); + + delete[] c; + } + + std::string toString() + { + return serial_; + } +}; + +class FirmwareVersionResponse +{ +private: + struct FWSubsystemVersion + { + uint16_t minor; + uint16_t major; + uint16_t build; + uint16_t revision; + uint16_t reserved0[4]; + + FWSubsystemVersion() + { + major = 0; + minor = 0; + build = 0; + revision = 0; + } + }; + + std::vector versions_; +public: + FirmwareVersionResponse(const unsigned char *data, int length) + { + int n = length / sizeof(FWSubsystemVersion); + const FWSubsystemVersion *sv = reinterpret_cast(data); + + for(int i = 0; i < n && sv->major > 0; ++i, ++sv) + { + versions_.push_back(*sv); + } + } + + std::string toString() + { + FWSubsystemVersion max; + for(int i = 0; i < versions_.size(); ++i) + { + max.major = std::max(max.major, versions_[i].major); + max.minor = std::max(max.minor, versions_[i].minor); + max.build = std::max(max.build, versions_[i].build); + max.revision = std::max(max.revision, versions_[i].revision); + } + std::stringstream version_string; + version_string << max.major << "." << max.minor << "." << max.build << "." << max.revision << "." << versions_.size(); + + return version_string.str(); + } +}; + +class GenericResponse +{ +private: + std::string dump_; +public: + GenericResponse(const unsigned char *data, int length) + { + std::stringstream dump; + dump << length << " bytes of raw data" << std::endl; + + int lines = length >> 4; + if (length % 16 != 0) lines += 1; + + for (int i = 0; i < lines; i++) + { + dump << "0x" << std::hex << std::setfill('0') << std::setw(4) << (i*16) << ": "; + for (int j = 0; j < 16; j++) + { + if (j < length) dump << std::hex << std::setfill('0') << std::setw(2) << int(data[i*16+j]) << " "; + else dump << " "; + } + dump << " "; + for (int j = 0; (j < 16) && (j < length); j++) + { + char c = data[i*16+j]; + dump << (((c<32)||(c>128))?'.':c); + } + dump << std::endl; + length -= 16; + } + + dump_ = dump.str(); + } + + std::string toString() + { + return dump_; + } +}; + +// probably some combination of color camera intrinsics + depth coefficient tables +LIBFREENECT2_PACK(struct RgbCameraParamsResponse +{ + // unknown, always seen as 1 so far + uint8_t table_id; + + // color -> depth mapping parameters + float color_f; + float color_cx; + float color_cy; + + float shift_d; + float shift_m; + + float mx_x3y0; // xxx + float mx_x0y3; // yyy + float mx_x2y1; // xxy + float mx_x1y2; // yyx + float mx_x2y0; // xx + float mx_x0y2; // yy + float mx_x1y1; // xy + float mx_x1y0; // x + float mx_x0y1; // y + float mx_x0y0; // 1 + + float my_x3y0; // xxx + float my_x0y3; // yyy + float my_x2y1; // xxy + float my_x1y2; // yyx + float my_x2y0; // xx + float my_x0y2; // yy + float my_x1y1; // xy + float my_x1y0; // x + float my_x0y1; // y + float my_x0y0; // 1 + + // perhaps related to xtable/ztable in the deconvolution code. + // data seems to be arranged into two tables of 28*23, which + // matches the depth image aspect ratio of 512*424 very closely + float table1[28 * 23 * 4]; + float table2[28 * 23]; +}); + + +// depth camera intrinsic & distortion parameters +LIBFREENECT2_PACK(struct DepthCameraParamsResponse +{ + // intrinsics (this is pretty certain) + float fx; + float fy; + float unknown0; // assumed to be always zero + float cx; + float cy; + + // radial distortion (educated guess based on calibration data from Kinect SDK) + float k1; + float k2; + float p1; // always seen as zero so far, so purely a guess + float p2; // always seen as zero so far, so purely a guess + float k3; + + float unknown1[13]; // assumed to be always zero +}); + +// "P0" coefficient tables, input to the deconvolution code +LIBFREENECT2_PACK(struct P0TablesResponse +{ + uint32_t headersize; + uint32_t unknown1; + uint32_t unknown2; + uint32_t tablesize; + uint32_t unknown3; + uint32_t unknown4; + uint32_t unknown5; + uint32_t unknown6; + + uint16_t unknown7; + uint16_t p0table0[512*424]; // row[0] == row[511] == 0x2c9a + uint16_t unknown8; + + uint16_t unknown9; + uint16_t p0table1[512*424]; // row[0] == row[511] == 0x08ec + uint16_t unknownA; + + uint16_t unknownB; + uint16_t p0table2[512*424]; // row[0] == row[511] == 0x42e8 + uint16_t unknownC; + + uint8_t unknownD[]; +}); + +} /* namespace protocol */ +} /* namespace libfreenect2 */ +#endif /* RESPONSE_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/protocol/usb_control.h b/examples/k22v4l/include/libfreenect2/protocol/usb_control.h new file mode 100644 index 000000000..f42cafed0 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/protocol/usb_control.h @@ -0,0 +1,108 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef USB_CONTROL_H_ +#define USB_CONTROL_H_ + +#include + +namespace libfreenect2 +{ +namespace protocol +{ +/** + * The Kinect2 device defines 2 USB interface associations (=device functions) + * + * 1. Interface Association: video transfer + * 2. Interface Association: audio transfer + * + * The first interface association is enabled/disabled by setting the feature FUNCTION_SUSPEND. + * + * The following describes the interfaces in the video transfer interface association. + * + * It contains 2 USB interfaces + * + * 1. Interface: control communication, RGB transfer + * 2. Interface: IR transfer + * + * Each interface has different endpoints + * + * 1. Interface + * - 0x81 (bulk) control communication IN + * - 0x02 (bulk) control communication OUT + * - 0x83 (bulk) RGB transfer IN + * - 0x82 (interrupt) unknown IN + * + * 2. Interface + * - 0x84 (isochronous) IR transfer IN + * + * The 2. interface can be enabled/disabled by changing its alternate setting to 1/0 + */ +class UsbControl +{ +public: + UsbControl(libusb_device_handle *handle); + virtual ~UsbControl(); + + enum State + { + Enabled, + Disabled + }; + + enum ResultCode + { + Success, + Error + }; + + ResultCode getIrMaxIsoPacketSize(int &size); + + ResultCode setConfiguration(); + ResultCode claimInterfaces(); + ResultCode releaseInterfaces(); + + ResultCode setIsochronousDelay(); + ResultCode setPowerStateLatencies(); + ResultCode enablePowerStates(); + + // enable/suspend 1. Interface Association + ResultCode setVideoTransferFunctionState(State state); + + // enable/disable 2. Interface using alternate setting + ResultCode setIrInterfaceState(State state); + +private: + static const int ControlAndRgbInterfaceId = 0; + static const int IrInterfaceId = 1; + + libusb_device_handle* handle_; + int timeout_; +}; + +} /* namespace protocol */ +} /* namespace libfreenect2 */ +#endif /* USB_CONTROL_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/resource.h b/examples/k22v4l/include/libfreenect2/resource.h new file mode 100644 index 000000000..a8dc38262 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/resource.h @@ -0,0 +1,38 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef RESOURCE_H_ +#define RESOURCE_H_ + +#include + +namespace libfreenect2 +{ + +bool loadResource(const std::string &name, unsigned char const**data, size_t *length); + +} /* namespace libfreenect2 */ +#endif /* RESOURCE_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/rgb_packet_processor.h b/examples/k22v4l/include/libfreenect2/rgb_packet_processor.h new file mode 100644 index 000000000..e3a389dfd --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/rgb_packet_processor.h @@ -0,0 +1,86 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef RGB_PACKET_PROCESSOR_H_ +#define RGB_PACKET_PROCESSOR_H_ + +#include +#include + +#include +#include +#include + +namespace libfreenect2 +{ + +struct LIBFREENECT2_API RgbPacket +{ + uint32_t sequence; + + unsigned char *jpeg_buffer; + size_t jpeg_buffer_length; +}; + +// explicit instantiation and export to make vsc++ happy +template class LIBFREENECT2_API PacketProcessor; +typedef PacketProcessor BaseRgbPacketProcessor; + +class LIBFREENECT2_API RgbPacketProcessor : public BaseRgbPacketProcessor +{ +public: + RgbPacketProcessor(); + virtual ~RgbPacketProcessor(); + + virtual void setFrameListener(libfreenect2::FrameListener *listener); +protected: + libfreenect2::FrameListener *listener_; +}; + +class LIBFREENECT2_API DumpRgbPacketProcessor : public RgbPacketProcessor +{ +public: + DumpRgbPacketProcessor(); + virtual ~DumpRgbPacketProcessor(); +protected: + virtual void process(const libfreenect2::RgbPacket &packet); +}; + +class TurboJpegRgbPacketProcessorImpl; + +class LIBFREENECT2_API TurboJpegRgbPacketProcessor : public RgbPacketProcessor +{ +public: + TurboJpegRgbPacketProcessor(); + virtual ~TurboJpegRgbPacketProcessor(); +protected: + virtual void process(const libfreenect2::RgbPacket &packet); +private: + TurboJpegRgbPacketProcessorImpl *impl_; +}; + +} /* namespace libfreenect2 */ +#endif /* RGB_PACKET_PROCESSOR_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/rgb_packet_stream_parser.h b/examples/k22v4l/include/libfreenect2/rgb_packet_stream_parser.h new file mode 100644 index 000000000..ac1cd0caf --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/rgb_packet_stream_parser.h @@ -0,0 +1,56 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef RGB_PACKET_STREAM_PARSER_H_ +#define RGB_PACKET_STREAM_PARSER_H_ + +#include + +#include +#include +#include + +#include + +namespace libfreenect2 +{ + +class LIBFREENECT2_API RgbPacketStreamParser : public DataCallback +{ +public: + RgbPacketStreamParser(); + virtual ~RgbPacketStreamParser(); + + void setPacketProcessor(BaseRgbPacketProcessor *processor); + + virtual void onDataReceived(unsigned char* buffer, size_t length); +private: + libfreenect2::DoubleBuffer buffer_; + BaseRgbPacketProcessor *processor_; +}; + +} /* namespace libfreenect2 */ +#endif /* RGB_PACKET_STREAM_PARSER_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/threading.h b/examples/k22v4l/include/libfreenect2/threading.h new file mode 100644 index 000000000..02b9e4a73 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/threading.h @@ -0,0 +1,96 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef THREADING_H_ +#define THREADING_H_ + +#include + +#ifdef LIBFREENECT2_THREADING_STDLIB + +#include +#include +#include +#include + +#define WAIT_CONDITION(var, mutex, lock) var.wait(lock); + +namespace libfreenect2 +{ + +typedef std::thread thread; +typedef std::mutex mutex; +typedef std::lock_guard lock_guard; +typedef std::unique_lock unique_lock; +typedef std::condition_variable condition_variable; + +namespace chrono +{ +using namespace std::chrono; +} + +namespace this_thread +{ +using namespace std::this_thread; +} + +} /* libfreenect2 */ + +#endif + +#ifdef LIBFREENECT2_THREADING_TINYTHREAD + +#include + +// TODO: work around for tinythread incompatibility +#define WAIT_CONDITION(var, mutex, lock) var.wait(mutex); + +namespace libfreenect2 +{ + +typedef tthread::thread thread; +typedef tthread::mutex mutex; +typedef tthread::lock_guard lock_guard; +// TODO: this is not optimal +typedef tthread::lock_guard unique_lock; +typedef tthread::condition_variable condition_variable; + +namespace chrono +{ +using namespace tthread::chrono; +} + +namespace this_thread +{ +using namespace tthread::this_thread; +} + +} /* libfreenect2 */ + +#endif + + +#endif /* THREADING_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/usb/event_loop.h b/examples/k22v4l/include/libfreenect2/usb/event_loop.h new file mode 100644 index 000000000..61c298b7e --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/usb/event_loop.h @@ -0,0 +1,57 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef EVENT_LOOP_H_ +#define EVENT_LOOP_H_ + +#include + +namespace libfreenect2 +{ +namespace usb +{ + +class EventLoop +{ +public: + EventLoop(); + virtual ~EventLoop(); + + void start(void *usb_context); + + void stop(); +private: + bool shutdown_; + libfreenect2::thread *thread_; + void *usb_context_; + + static void static_execute(void *cookie); + void execute(); +}; + +} /* namespace usb */ +} /* namespace libfreenect2 */ +#endif /* EVENT_LOOP_H_ */ diff --git a/examples/k22v4l/include/libfreenect2/usb/transfer_pool.h b/examples/k22v4l/include/libfreenect2/usb/transfer_pool.h new file mode 100644 index 000000000..3a0dbef56 --- /dev/null +++ b/examples/k22v4l/include/libfreenect2/usb/transfer_pool.h @@ -0,0 +1,118 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef TRANSFER_POOL_H_ +#define TRANSFER_POOL_H_ + +#include +#include + +#include + +namespace libfreenect2 +{ + +namespace usb +{ + +class TransferPool +{ +public: + TransferPool(libusb_device_handle *device_handle, unsigned char device_endpoint); + virtual ~TransferPool(); + + void deallocate(); + + void enableSubmission(); + + void disableSubmission(); + + void submit(size_t num_parallel_transfers); + + void cancel(); + + void setCallback(DataCallback *callback); +protected: + void allocateTransfers(size_t num_transfers, size_t transfer_size); + + virtual libusb_transfer *allocateTransfer() = 0; + virtual void fillTransfer(libusb_transfer *transfer) = 0; + + virtual void processTransfer(libusb_transfer *transfer) = 0; + + DataCallback *callback_; +private: + typedef std::deque TransferQueue; + + libusb_device_handle *device_handle_; + unsigned char device_endpoint_; + + TransferQueue idle_transfers_, pending_transfers_; + unsigned char *buffer_; + size_t buffer_size_; + + bool enable_submit_; + + static void onTransferCompleteStatic(libusb_transfer *transfer); + + void onTransferComplete(libusb_transfer *transfer); +}; + +class BulkTransferPool : public TransferPool +{ +public: + BulkTransferPool(libusb_device_handle *device_handle, unsigned char device_endpoint); + virtual ~BulkTransferPool(); + + void allocate(size_t num_transfers, size_t transfer_size); + +protected: + virtual libusb_transfer *allocateTransfer(); + virtual void fillTransfer(libusb_transfer *transfer); + virtual void processTransfer(libusb_transfer *transfer); +}; + +class IsoTransferPool : public TransferPool +{ +public: + IsoTransferPool(libusb_device_handle *device_handle, unsigned char device_endpoint); + virtual ~IsoTransferPool(); + + void allocate(size_t num_transfers, size_t num_packets, size_t packet_size); + +protected: + virtual libusb_transfer *allocateTransfer(); + virtual void fillTransfer(libusb_transfer *transfer); + virtual void processTransfer(libusb_transfer *transfer); + +private: + size_t num_packets_; + size_t packet_size_; +}; + +} /* namespace usb */ +} /* namespace libfreenect2 */ +#endif /* TRANSFER_POOL_H_ */ diff --git a/examples/k22v4l/k22v4l.cpp b/examples/k22v4l/k22v4l.cpp new file mode 100644 index 000000000..35ec3e1de --- /dev/null +++ b/examples/k22v4l/k22v4l.cpp @@ -0,0 +1,207 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#define VIDEO_DEVICE_RGB "/dev/video0" +#define VIDEO_DEVICE_IR "/dev/video1" +#define VIDEO_DEVICE_DEPTH "/dev/video2" + +bool k22v4l_shutdown = false; + +void sigint_handler(int s) +{ + k22v4l_shutdown = true; +} + +int main(int argc, char *argv[]) +{ + std::string program_path(argv[0]); + size_t executable_name_idx = program_path.rfind("k22v4l"); + + std::string binpath = "/"; + + if(executable_name_idx != std::string::npos) + { + binpath = program_path.substr(0, executable_name_idx); + } + + + libfreenect2::Freenect2 freenect2; + libfreenect2::Freenect2Device *dev = freenect2.openDefaultDevice(); + + if(dev == 0) + { + std::cout << "no device connected or failure opening the default one!" << std::endl; + return -1; + } + + signal(SIGINT,sigint_handler); + k22v4l_shutdown = false; + + libfreenect2::SyncMultiFrameListener listener(libfreenect2::Frame::Color | libfreenect2::Frame::Ir | libfreenect2::Frame::Depth); + libfreenect2::FrameMap frames; + + dev->setColorFrameListener(&listener); + dev->setIrAndDepthFrameListener(&listener); + dev->start(); + + std::cout << "device serial: " << dev->getSerialNumber() << std::endl; + std::cout << "device firmware: " << dev->getFirmwareVersion() << std::endl; + + // don't do that at home, one int to retrieve various return code + int ret_code; + + // init V4L loopback output for RGB + int fd_rgb = open(VIDEO_DEVICE_RGB, O_RDWR); + assert(fd_rgb >= 0); + // what should handle + struct v4l2_capability vid_caps; + ret_code = ioctl(fd_rgb, VIDIOC_QUERYCAP, &vid_caps); + assert(ret_code != -1); + + // init V4L loopback output for IR + int fd_ir = open(VIDEO_DEVICE_IR, O_RDWR); + assert(fd_ir >= 0); + ret_code = ioctl(fd_ir, VIDIOC_QUERYCAP, &vid_caps); + assert(ret_code != -1); + + // init V4L loopback output for DEPTH + int fd_depth = open(VIDEO_DEVICE_DEPTH, O_RDWR); + assert(fd_depth >= 0); + ret_code = ioctl(fd_depth, VIDIOC_QUERYCAP, &vid_caps); + assert(ret_code != -1); + + std::cout << "init feeds" << std::endl; + // first run to get pointer to frame + listener.waitForNewFrame(frames); + libfreenect2::Frame *rgb = frames[libfreenect2::Frame::Color]; + libfreenect2::Frame *ir = frames[libfreenect2::Frame::Ir]; + libfreenect2::Frame *depth = frames[libfreenect2::Frame::Depth]; + + // configure for our RBG device + std::cout << "configure v4l loopback for RGB" << std::endl; + struct v4l2_format vid_format_rgb; + vid_format_rgb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + vid_format_rgb.fmt.pix.width = rgb->width; + vid_format_rgb.fmt.pix.height = rgb->height; + vid_format_rgb.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24; + vid_format_rgb.fmt.pix.sizeimage = rgb->width * rgb->height * 3; + vid_format_rgb.fmt.pix.field = V4L2_FIELD_NONE; + vid_format_rgb.fmt.pix.bytesperline = rgb->width * 3; + vid_format_rgb.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + ret_code = ioctl(fd_rgb, VIDIOC_S_FMT, &vid_format_rgb); + assert(ret_code != -1); + + // configure for our IR device + std::cout << "configure v4l loopback for IR" << std::endl; + struct v4l2_format vid_format_ir; + vid_format_ir.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + vid_format_ir.fmt.pix.width = ir->width; + vid_format_ir.fmt.pix.height = ir->height; + vid_format_ir.fmt.pix.pixelformat = V4L2_PIX_FMT_Y16; // black and white 16bits + vid_format_ir.fmt.pix.sizeimage = ir->width * ir->height * 2; + vid_format_ir.fmt.pix.field = V4L2_FIELD_NONE; + vid_format_ir.fmt.pix.bytesperline = rgb->width * 2; + vid_format_ir.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + ret_code = ioctl(fd_ir, VIDIOC_S_FMT, &vid_format_ir); + assert(ret_code != -1); + + // configure for our DEPTH device + std::cout << "configure v4l loopback for DEPTH" << std::endl; + struct v4l2_format vid_format_depth; + vid_format_depth.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + vid_format_depth.fmt.pix.width = ir->width; + vid_format_depth.fmt.pix.height = ir->height; + vid_format_depth.fmt.pix.pixelformat = V4L2_PIX_FMT_Y16; // black and white 16bits + vid_format_depth.fmt.pix.sizeimage = ir->width * ir->height * 2; + vid_format_depth.fmt.pix.field = V4L2_FIELD_NONE; + vid_format_depth.fmt.pix.bytesperline = rgb->width * 2; + vid_format_depth.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; + ret_code = ioctl(fd_depth, VIDIOC_S_FMT, &vid_format_depth); + assert(ret_code != -1); + + std::cout << "start loop" << std::endl; + + // use opencv to confert pixel format (float to int), need some matrix + cv::Mat mat_ir, tmp_ir; + cv::Mat mat_depth, tmp_depth; + + // dummy image for dummy frame + cv::Mat mat_dummy(240,320, CV_8UC1,128); + + while(!k22v4l_shutdown) + { + + listener.waitForNewFrame(frames); + rgb = frames[libfreenect2::Frame::Color]; + ir = frames[libfreenect2::Frame::Ir]; + depth = frames[libfreenect2::Frame::Depth]; + + // could write directly RGB image as it's 3xint8 + ret_code = write(fd_rgb, rgb->data, rgb->width * rgb->height * 3); + + // IR: use a matrix to convert from float32 to int16 and normalize data to adjust brightness + mat_ir = cv::Mat(ir->height, ir->width, CV_32FC1, ir->data) ; + cv::normalize(mat_ir, tmp_ir, 0, 255*255, cv::NORM_MINMAX, CV_16UC1); // 255*255 for color depth... + ret_code = write(fd_ir, tmp_ir.data, ir->width * ir->height * 2); + + // same with depth + mat_depth = cv::Mat(depth->height, depth->width, CV_32FC1, depth->data) ; + cv::normalize(mat_depth, tmp_depth, 0, 255*255, cv::NORM_MINMAX, CV_16UC1); + ret_code = write(fd_depth, tmp_depth.data, depth->width * depth->height * 2); + + // one hell of a GUI + cv::imshow("esc to quit", mat_dummy); + + int key = cv::waitKey(1); + k22v4l_shutdown = k22v4l_shutdown || (key > 0 && ((key & 0xFF) == 27)); // shutdown on escape + + listener.release(frames); + //libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(100)); + } + + // TODO: restarting ir stream doesn't work! + // TODO: bad things will happen, if frame listeners are freed before dev->stop() :( + dev->stop(); + dev->close(); + + close(fd_rgb); + + return 0; +} diff --git a/examples/k22v4l/src/command_transaction.cpp b/examples/k22v4l/src/command_transaction.cpp new file mode 100644 index 000000000..b1b6efe84 --- /dev/null +++ b/examples/k22v4l/src/command_transaction.cpp @@ -0,0 +1,189 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include + +#include +#include + +namespace libfreenect2 +{ +namespace protocol +{ +CommandTransaction::Result::Result() : + code(Error), data(NULL), capacity(0), length(0) +{ +} + +CommandTransaction::Result::~Result() +{ + deallocate(); +} + +void CommandTransaction::Result::allocate(size_t size) +{ + if (capacity < size) + { + deallocate(); + data = new unsigned char[size]; + capacity = size; + } + length = 0; +} + +void CommandTransaction::Result::deallocate() +{ + if (data != NULL) + { + delete[] data; + } + length = 0; + capacity = 0; +} + +bool CommandTransaction::Result::notSuccessfulThenDeallocate() +{ + bool not_successful = (code != Success); + + if (not_successful) + { + deallocate(); + } + + return not_successful; +} + +CommandTransaction::CommandTransaction(libusb_device_handle *handle, int inbound_endpoint, int outbound_endpoint) : + handle_(handle), + inbound_endpoint_(inbound_endpoint), + outbound_endpoint_(outbound_endpoint), + timeout_(1000) +{ + response_complete_result_.allocate(ResponseCompleteLength); +} + +CommandTransaction::~CommandTransaction() {} + +void CommandTransaction::execute(const CommandBase& command, Result& result) +{ + result.allocate(command.maxResponseLength()); + + // send command + result.code = send(command); + + if(result.notSuccessfulThenDeallocate()) return; + + bool complete = false; + + // receive response data + if(command.maxResponseLength() > 0) + { + receive(result); + complete = isResponseCompleteResult(result, command.sequence()); + + if(complete) + { + std::cerr << "[CommandTransaction::execute] received premature response complete!" << std::endl; + result.code = Error; + } + + if(result.notSuccessfulThenDeallocate()) return; + } + + // receive response complete + receive(response_complete_result_); + complete = isResponseCompleteResult(response_complete_result_, command.sequence()); + + if(!complete) + { + std::cerr << "[CommandTransaction::execute] missing response complete!" << std::endl; + result.code = Error; + } + + result.notSuccessfulThenDeallocate(); +} + +CommandTransaction::ResultCode CommandTransaction::send(const CommandBase& command) +{ + ResultCode code = Success; + + int transferred_bytes = 0; + int r = libusb_bulk_transfer(handle_, outbound_endpoint_, const_cast(command.data()), command.size(), &transferred_bytes, timeout_); + + if(r != LIBUSB_SUCCESS) + { + std::cerr << "[CommandTransaction::send] bulk transfer failed! libusb error " << r << ": " << libusb_error_name(r) << std::endl; + code = Error; + } + + if(transferred_bytes != command.size()) + { + std::cerr << "[CommandTransaction::send] sent number of bytes differs from expected number! expected: " << command.size() << " got: " << transferred_bytes << std::endl; + code = Error; + } + + return code; +} + +void CommandTransaction::receive(CommandTransaction::Result& result) +{ + result.code = Success; + result.length = 0; + + int r = libusb_bulk_transfer(handle_, inbound_endpoint_, result.data, result.capacity, &result.length, timeout_); + + if(r != LIBUSB_SUCCESS) + { + std::cerr << "[CommandTransaction::receive] bulk transfer failed! libusb error " << r << ": " << libusb_error_name(r) << std::endl; + result.code = Error; + } +} + +bool CommandTransaction::isResponseCompleteResult(CommandTransaction::Result& result, uint32_t sequence) +{ + bool complete = false; + + if(result.code == Success && result.length == ResponseCompleteLength) + { + uint32_t *data = reinterpret_cast(result.data); + + if(data[0] == ResponseCompleteMagic) + { + complete = true; + + if(data[1] != sequence) + { + std::cerr << "[CommandTransaction::isResponseCompleteResult] response complete with wrong sequence number! expected: " << sequence << " got: " << data[1]<< std::endl; + } + } + } + + return complete; +} + + +} /* namespace protocol */ +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/cpu_depth_packet_processor.cpp b/examples/k22v4l/src/cpu_depth_packet_processor.cpp new file mode 100644 index 000000000..269d39811 --- /dev/null +++ b/examples/k22v4l/src/cpu_depth_packet_processor.cpp @@ -0,0 +1,826 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include + +#include +#include +#include + +#if defined(WIN32) +#define _USE_MATH_DEFINES +#include +#endif + +namespace libfreenect2 +{ + +bool loadBufferFromFile2(const std::string& filename, unsigned char *buffer, size_t n) +{ + bool success = true; + std::ifstream in(filename.c_str()); + + in.read(reinterpret_cast(buffer), n); + success = in.gcount() == n; + + in.close(); + + return success; +} + +inline int bfi(int width, int offset, int src2, int src3) +{ + int bitmask = (((1 << width)-1) << offset) & 0xffffffff; + return ((src2 << offset) & bitmask) | (src3 & ~bitmask); +} + +class CpuDepthPacketProcessorImpl +{ +public: + cv::Mat p0_table0, p0_table1, p0_table2, x_table, z_table; + + int16_t lut11to16[2048]; + + float trig_table0[512*424][6]; + float trig_table1[512*424][6]; + float trig_table2[512*424][6]; + + double timing_acc; + double timing_acc_n; + + double timing_current_start; + + bool enable_bilateral_filter, enable_edge_filter; + DepthPacketProcessor::Parameters params; + + Frame *ir_frame, *depth_frame; + + bool flip_ptables; + + CpuDepthPacketProcessorImpl() + { + newIrFrame(); + newDepthFrame(); + + timing_acc = 0.0; + timing_acc_n = 0.0; + timing_current_start = 0.0; + + enable_bilateral_filter = true; + enable_edge_filter = true; + + flip_ptables = true; + } + + void startTiming() + { + timing_current_start = cv::getTickCount(); + } + + void stopTiming() + { + timing_acc += (cv::getTickCount() - timing_current_start) / cv::getTickFrequency(); + timing_acc_n += 1.0; + + if(timing_acc_n >= 100.0) + { + double avg = (timing_acc / timing_acc_n); + std::cout << "[CpuDepthPacketProcessor] avg. time: " << (avg * 1000) << "ms -> ~" << (1.0/avg) << "Hz" << std::endl; + timing_acc = 0.0; + timing_acc_n = 0.0; + } + } + + void newIrFrame() + { + ir_frame = new Frame(512, 424, 4); + //ir_frame = new Frame(512, 424, 12); + } + + void newDepthFrame() + { + depth_frame = new Frame(512, 424, 4); + } + + int32_t decodePixelMeasurement(unsigned char* data, int sub, int x, int y) + { + // 298496 = 512 * 424 * 11 / 8 = number of bytes per sub image + uint16_t *ptr = reinterpret_cast(data + 298496 * sub); + int i = y < 212 ? y + 212 : 423 - y; + ptr += 352*i; + + /** + r1.yz = r2.xxyx < l(0, 1, 0, 0) // ilt + r1.y = r1.z | r1.y // or + */ + bool r1y = x < 1 || y < 0; + /* + r1.zw = l(0, 0, 510, 423) < r2.xxxy // ilt + r1.z = r1.w | r1.z // or + */ + bool r1z = 510 < x || 423 < y; + /* + r1.y = r1.z | r1.y // or + */ + r1y = r1y || r1z; + /* + r1.y = r1.y & l(0x1fffffff) // and + */ + int r1yi = r1y ? 0xffffffff : 0x0; + r1yi &= 0x1fffffff; + + /* + bfi r1.z, l(2), l(7), r2.x, l(0) + ushr r1.w, r2.x, l(2) + r1.z = r1.w + r1.z // iadd + */ + int r1zi = bfi(2, 7, x, 0); + int r1wi = x >> 2; + r1zi = r1wi + r1zi; + + /* + imul null, r1.z, r1.z, l(11) + ushr r1.w, r1.z, l(4) + r1.y = r1.w + r1.y // iadd + r1.w = r1.y + l(1) // iadd + r1.z = r1.z & l(15) // and + r4.w = -r1.z + l(16) // iadd + */ + r1zi = (r1zi * 11L) & 0xffffffff; + r1wi = r1zi >> 4; + r1yi = r1yi + r1wi; + r1zi = r1zi & 15; + int r4wi = -r1zi + 16; + + if(r1yi > 352) + { + return lut11to16[0]; + } + + int i1 = ptr[r1yi]; + int i2 = ptr[r1yi + 1]; + i1 = i1 >> r1zi; + i2 = i2 << r4wi; + + return lut11to16[((i1 | i2) & 2047)]; + } + + void fill_trig_tables(cv::Mat& p0table, float trig_table[512*424][6]) + { + for (int i = 0; i < 512*424; i++) + { + float p0 = -((float)p0table.at(i)) * 0.000031 * M_PI; + + float tmp0 = p0 + params.phase_in_rad[0]; + float tmp1 = p0 + params.phase_in_rad[1]; + float tmp2 = p0 + params.phase_in_rad[2]; + + trig_table[i][0] = std::cos(tmp0); + trig_table[i][1] = std::cos(tmp1); + trig_table[i][2] = std::cos(tmp2); + + trig_table[i][3] = std::sin(-tmp0); + trig_table[i][4] = std::sin(-tmp1); + trig_table[i][5] = std::sin(-tmp2); + } + } + + void processMeasurementTriple(float trig_table[512*424][6], float abMultiplierPerFrq, int x, int y, const int32_t* m, float* m_out) + { + int offset = y * 512 + x; + float cos_tmp0 = trig_table[offset][0]; + float cos_tmp1 = trig_table[offset][1]; + float cos_tmp2 = trig_table[offset][2]; + + float sin_negtmp0 = trig_table[offset][3]; + float sin_negtmp1 = trig_table[offset][4]; + float sin_negtmp2 = trig_table[offset][5]; + + float zmultiplier = z_table.at(y, x); + bool cond0 = 0 < zmultiplier; + bool cond1 = (m[0] == 32767 || m[1] == 32767 || m[2] == 32767) && cond0; + + // formula given in Patent US 8,587,771 B2 + float tmp3 = cos_tmp0 * m[0] + cos_tmp1 * m[1] + cos_tmp2 * m[2]; + float tmp4 = sin_negtmp0 * m[0] + sin_negtmp1 * m[1] + sin_negtmp2 * m[2]; + + // only if modeMask & 32 != 0; + if(true)//(modeMask & 32) != 0) + { + tmp3 *= abMultiplierPerFrq; + tmp4 *= abMultiplierPerFrq; + } + float tmp5 = std::sqrt(tmp3 * tmp3 + tmp4 * tmp4) * params.ab_multiplier; + + // invalid pixel because zmultiplier < 0 ?? + tmp3 = cond0 ? tmp3 : 0; + tmp4 = cond0 ? tmp4 : 0; + tmp5 = cond0 ? tmp5 : 0; + + // invalid pixel because saturated? + tmp3 = !cond1 ? tmp3 : 0; + tmp4 = !cond1 ? tmp4 : 0; + tmp5 = !cond1 ? tmp5 : 65535.0; // some kind of norm calculated from tmp3 and tmp4 + + m_out[0] = tmp3; // ir image a + m_out[1] = tmp4; // ir image b + m_out[2] = tmp5; // ir amplitude + } + + void transformMeasurements(float* m) + { + float tmp0 = std::atan2((m[1]), (m[0])); + tmp0 = tmp0 < 0 ? tmp0 + M_PI * 2.0f : tmp0; + tmp0 = (tmp0 != tmp0) ? 0 : tmp0; + + float tmp1 = std::sqrt(m[0] * m[0] + m[1] * m[1]) * params.ab_multiplier; + + m[0] = tmp0; // phase + m[1] = tmp1; // ir amplitude - (possibly bilateral filtered) + } + + void processPixelStage1(int x, int y, unsigned char* data, float *m0_out, float *m1_out, float *m2_out) + { + int32_t m0_raw[3], m1_raw[3], m2_raw[3]; + + m0_raw[0] = decodePixelMeasurement(data, 0, x, y); + m0_raw[1] = decodePixelMeasurement(data, 1, x, y); + m0_raw[2] = decodePixelMeasurement(data, 2, x, y); + m1_raw[0] = decodePixelMeasurement(data, 3, x, y); + m1_raw[1] = decodePixelMeasurement(data, 4, x, y); + m1_raw[2] = decodePixelMeasurement(data, 5, x, y); + m2_raw[0] = decodePixelMeasurement(data, 6, x, y); + m2_raw[1] = decodePixelMeasurement(data, 7, x, y); + m2_raw[2] = decodePixelMeasurement(data, 8, x, y); + + processMeasurementTriple(trig_table0, params.ab_multiplier_per_frq[0], x, y, m0_raw, m0_out); + processMeasurementTriple(trig_table1, params.ab_multiplier_per_frq[1], x, y, m1_raw, m1_out); + processMeasurementTriple(trig_table2, params.ab_multiplier_per_frq[2], x, y, m2_raw, m2_out); + } + + void filterPixelStage1(int x, int y, const cv::Mat& m, float* m_out, bool& bilateral_max_edge_test) + { + const float *m_ptr = m.ptr(y, x); + bilateral_max_edge_test = true; + + if(x < 1 || y < 1 || x > 510 || y > 422) + { + for(int i = 0; i < 9; ++i) + m_out[i] = m_ptr[i]; + } + else + { + float m_normalized[2]; + float other_m_normalized[2]; + + int offset = 0; + + for(int i = 0; i < 3; ++i, m_ptr += 3, m_out += 3, offset += 3) + { + float norm2 = m_ptr[0] * m_ptr[0] + m_ptr[1] * m_ptr[1]; + float inv_norm = 1.0f / std::sqrt(norm2); + inv_norm = (inv_norm == inv_norm) ? inv_norm : std::numeric_limits::infinity(); + + m_normalized[0] = m_ptr[0] * inv_norm; + m_normalized[1] = m_ptr[1] * inv_norm; + + int j = 0; + + float weight_acc = 0.0f; + float weighted_m_acc[2] = {0.0f, 0.0f}; + + float threshold = (params.joint_bilateral_ab_threshold * params.joint_bilateral_ab_threshold) / (params.ab_multiplier * params.ab_multiplier); + float joint_bilateral_exp = params.joint_bilateral_exp; + + if(norm2 < threshold) + { + threshold = 0.0f; + joint_bilateral_exp = 0.0f; + } + + float dist_acc = 0.0f; + + for(int yi = -1; yi < 2; ++yi) + { + for(int xi = -1; xi < 2; ++xi, ++j) + { + if(yi == 0 && xi == 0) + { + weight_acc += params.gaussian_kernel[j]; + + weighted_m_acc[0] += params.gaussian_kernel[j] * m_ptr[0]; + weighted_m_acc[1] += params.gaussian_kernel[j] * m_ptr[1]; + continue; + } + + const float *other_m_ptr = m.ptr(y + yi, x + xi) + offset; + float other_norm2 = other_m_ptr[0] * other_m_ptr[0] + other_m_ptr[1] * other_m_ptr[1]; + // TODO: maybe fix numeric problems when norm = 0 - original code uses reciprocal square root, which returns +inf for +0 + float other_inv_norm = 1.0f / std::sqrt(other_norm2); + other_inv_norm = (other_inv_norm == other_inv_norm) ? other_inv_norm : std::numeric_limits::infinity(); + + other_m_normalized[0] = other_m_ptr[0] * other_inv_norm; + other_m_normalized[1] = other_m_ptr[1] * other_inv_norm; + + float dist = -(other_m_normalized[0] * m_normalized[0] + other_m_normalized[1] * m_normalized[1]); + dist += 1.0f; + dist *= 0.5f; + + float weight = 0.0f; + + if(other_norm2 >= threshold) + { + weight = (params.gaussian_kernel[j] * std::exp(-1.442695f * joint_bilateral_exp * dist)); + dist_acc += dist; + } + + weighted_m_acc[0] += weight * other_m_ptr[0]; + weighted_m_acc[1] += weight * other_m_ptr[1]; + + weight_acc += weight; + } + } + + bilateral_max_edge_test = bilateral_max_edge_test && dist_acc < params.joint_bilateral_max_edge; + + m_out[0] = 0.0f < weight_acc ? weighted_m_acc[0] / weight_acc : 0.0f; + m_out[1] = 0.0f < weight_acc ? weighted_m_acc[1] / weight_acc : 0.0f; + m_out[2] = m_ptr[2]; + } + } + } + + void processPixelStage2(int x, int y, float *m0, float *m1, float *m2, float *ir_out, float *depth_out, float *ir_sum_out) + { + //// 10th measurement + //float m9 = 1; // decodePixelMeasurement(data, 9, x, y); + // + //// WTF? + //bool cond0 = zmultiplier == 0 || (m9 >= 0 && m9 < 32767); + //m9 = std::max(-m9, m9); + //// if m9 is positive or pixel is invalid (zmultiplier) we set it to 0 otherwise to its absolute value O.o + //m9 = cond0 ? 0 : m9; + + transformMeasurements(m0); + transformMeasurements(m1); + transformMeasurements(m2); + + float ir_sum = m0[1] + m1[1] + m2[1]; + + float phase; + // if(DISABLE_DISAMBIGUATION) + if(false) + { + //r0.yz = r3.zx + r4.zx // add + //r0.yz = r5.xz + r0.zy // add + float phase = m0[0] + m1[0] + m2[0]; // r0.y + float tmp1 = m0[2] + m1[2] + m2[2]; // r0.z + + //r7.xyz = r3.zxy + r4.zxy // add + //r4.xyz = r5.zyx + r7.xzy // add + float tmp2 = m0[0] + m1[0] + m2[0]; // r4.z + //r3.zw = r4.xy // mov + float tmp3 = m0[2] + m1[2] + m2[2]; // r3.z + float tmp4 = m0[1] + m1[1] + m2[1]; // r3.w + } + else + { + float ir_min = std::min(std::min(m0[1], m1[1]), m2[1]); + + if (ir_min < params.individual_ab_threshold || ir_sum < params.ab_threshold) + { + phase = 0; + } + else + { + float t0 = m0[0] / (2.0f * M_PI) * 3.0f; + float t1 = m1[0] / (2.0f * M_PI) * 15.0f; + float t2 = m2[0] / (2.0f * M_PI) * 2.0f; + + float t5 = (std::floor((t1 - t0) * 0.333333f + 0.5f) * 3.0f + t0); + float t3 = (-t2 + t5); + float t4 = t3 * 2.0f; + + bool c1 = t4 >= -t4; // true if t4 positive + + float f1 = c1 ? 2.0f : -2.0f; + float f2 = c1 ? 0.5f : -0.5f; + t3 *= f2; + t3 = (t3 - std::floor(t3)) * f1; + + bool c2 = 0.5f < std::abs(t3) && std::abs(t3) < 1.5f; + + float t6 = c2 ? t5 + 15.0f : t5; + float t7 = c2 ? t1 + 15.0f : t1; + + float t8 = (std::floor((-t2 + t6) * 0.5f + 0.5f) * 2.0f + t2) * 0.5f; + + t6 *= 0.333333f; // = / 3 + t7 *= 0.066667f; // = / 15 + + float t9 = (t8 + t6 + t7); // transformed phase measurements (they are transformed and divided by the values the original values were multiplied with) + float t10 = t9 * 0.333333f; // some avg + + t6 *= 2.0f * M_PI; + t7 *= 2.0f * M_PI; + t8 *= 2.0f * M_PI; + + // some cross product + float t8_new = t7 * 0.826977f - t8 * 0.110264f; + float t6_new = t8 * 0.551318f - t6 * 0.826977f; + float t7_new = t6 * 0.110264f - t7 * 0.551318f; + + t8 = t8_new; + t6 = t6_new; + t7 = t7_new; + + float norm = t8 * t8 + t6 * t6 + t7 * t7; + float mask = t9 >= 0.0f ? 1.0f : 0.0f; + t10 *= mask; + + bool slope_positive = 0 < params.ab_confidence_slope; + + float ir_min_ = std::min(std::min(m0[1], m1[1]), m2[1]); + float ir_max_ = std::max(std::max(m0[1], m1[1]), m2[1]); + + float ir_x = slope_positive ? ir_min_ : ir_max_; + + ir_x = std::log(ir_x); + ir_x = (ir_x * params.ab_confidence_slope * 0.301030f + params.ab_confidence_offset) * 3.321928f; + ir_x = std::exp(ir_x); + ir_x = std::min(params.max_dealias_confidence, std::max(params.min_dealias_confidence, ir_x)); + ir_x *= ir_x; + + float mask2 = ir_x >= norm ? 1.0f : 0.0f; + + float t11 = t10 * mask2; + + float mask3 = params.max_dealias_confidence * params.max_dealias_confidence >= norm ? 1.0f : 0.0f; + t10 *= mask3; + phase = true/*(modeMask & 2) != 0*/ ? t11 : t10; + } + } + + // this seems to be the phase to depth mapping :) + float zmultiplier = z_table.at(y, x); + float xmultiplier = x_table.at(y, x); + + phase = 0 < phase ? phase + params.phase_offset : phase; + + float depth_linear = zmultiplier * phase; + float max_depth = phase * params.unambigious_dist * 2; + + bool cond1 = /*(modeMask & 32) != 0*/ true && 0 < depth_linear && 0 < max_depth; + + xmultiplier = (xmultiplier * 90) / (max_depth * max_depth * 8192.0); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + + depth_fit = depth_fit < 0 ? 0 : depth_fit; + float depth = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + + // depth + *depth_out = depth; + if(ir_sum_out != 0) + { + *ir_sum_out = ir_sum; + } + + // ir + //*ir_out = std::min((m1[2]) * ab_output_multiplier, 65535.0f); + // ir avg + *ir_out = std::min((m0[2] + m1[2] + m2[2]) * 0.3333333f * params.ab_output_multiplier, 65535.0f); + //ir_out[0] = std::min(m0[2] * ab_output_multiplier, 65535.0f); + //ir_out[1] = std::min(m1[2] * ab_output_multiplier, 65535.0f); + //ir_out[2] = std::min(m2[2] * ab_output_multiplier, 65535.0f); + } + + void filterPixelStage2(int x, int y, cv::Mat &m, bool max_edge_test_ok, float *depth_out) + { + cv::Vec3f &depth_and_ir_sum = m.at(y, x); + float &raw_depth = depth_and_ir_sum.val[0], &ir_sum = depth_and_ir_sum.val[2]; + + if(raw_depth >= params.min_depth && raw_depth <= params.max_depth) + { + if(x < 1 || y < 1 || x > 510 || y > 422) + { + *depth_out = raw_depth; + } + else + { + float ir_sum_acc = ir_sum, squared_ir_sum_acc = ir_sum * ir_sum, min_depth = raw_depth, max_depth = raw_depth; + + for(int yi = -1; yi < 2; ++yi) + { + for(int xi = -1; xi < 2; ++xi) + { + if(yi == 0 && xi == 0) continue; + + cv::Vec3f &other = m.at(y + yi, x + xi); + + ir_sum_acc += other.val[2]; + squared_ir_sum_acc += other.val[2] * other.val[2]; + + if(0.0f < other.val[1]) + { + min_depth = std::min(min_depth, other.val[1]); + max_depth = std::max(max_depth, other.val[1]); + } + } + } + + float tmp0 = std::sqrt(squared_ir_sum_acc * 9.0f - ir_sum_acc * ir_sum_acc) / 9.0f; + float edge_avg = std::max(ir_sum_acc / 9.0f, params.edge_ab_avg_min_value); + tmp0 /= edge_avg; + + float abs_min_diff = std::abs(raw_depth - min_depth); + float abs_max_diff = std::abs(raw_depth - max_depth); + + float avg_diff = (abs_min_diff + abs_max_diff) * 0.5f; + float max_abs_diff = std::max(abs_min_diff, abs_max_diff); + + bool cond0 = + 0.0f < raw_depth && + tmp0 >= params.edge_ab_std_dev_threshold && + params.edge_close_delta_threshold < abs_min_diff && + params.edge_far_delta_threshold < abs_max_diff && + params.edge_max_delta_threshold < max_abs_diff && + params.edge_avg_delta_threshold < avg_diff; + + *depth_out = cond0 ? 0.0f : raw_depth; + + if(!cond0) + { + if(max_edge_test_ok) + { + float tmp1 = 1500.0f > raw_depth ? 30.0f : 0.02f * raw_depth; + float edge_count = 0.0f; + + *depth_out = edge_count > params.max_edge_count ? 0.0f : raw_depth; + } + else + { + *depth_out = !max_edge_test_ok ? 0.0f : raw_depth; + *depth_out = true ? *depth_out : raw_depth; + } + } + } + } + else + { + *depth_out = 0.0f; + } + + // override raw depth + depth_and_ir_sum.val[0] = depth_and_ir_sum.val[1]; + } +}; + +CpuDepthPacketProcessor::CpuDepthPacketProcessor() : + impl_(new CpuDepthPacketProcessorImpl()) +{ +} + +CpuDepthPacketProcessor::~CpuDepthPacketProcessor() +{ + delete impl_; +} + +void CpuDepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + + impl_->params.min_depth = config.MinDepth * 1000.0f; + impl_->params.max_depth = config.MaxDepth * 1000.0f; + impl_->enable_bilateral_filter = config.EnableBilateralFilter; + impl_->enable_edge_filter = config.EnableEdgeAwareFilter; +} + +void CpuDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length) +{ + // TODO: check known header fields (headersize, tablesize) + libfreenect2::protocol::P0TablesResponse* p0table = (libfreenect2::protocol::P0TablesResponse*)buffer; + + if(buffer_length < sizeof(libfreenect2::protocol::P0TablesResponse)) + { + std::cerr << "[CpuDepthPacketProcessor::loadP0TablesFromCommandResponse] P0Table response too short!" << std::endl; + return; + } + + if(impl_->flip_ptables) + { + cv::flip(cv::Mat(424, 512, CV_16UC1, p0table->p0table0), impl_->p0_table0, 0); + cv::flip(cv::Mat(424, 512, CV_16UC1, p0table->p0table1), impl_->p0_table1, 0); + cv::flip(cv::Mat(424, 512, CV_16UC1, p0table->p0table2), impl_->p0_table2, 0); + + impl_->fill_trig_tables(impl_->p0_table0, impl_->trig_table0); + impl_->fill_trig_tables(impl_->p0_table1, impl_->trig_table1); + impl_->fill_trig_tables(impl_->p0_table2, impl_->trig_table2); + } + else + { + cv::Mat(424, 512, CV_16UC1, p0table->p0table0).copyTo(impl_->p0_table0); + cv::Mat(424, 512, CV_16UC1, p0table->p0table1).copyTo(impl_->p0_table1); + cv::Mat(424, 512, CV_16UC1, p0table->p0table2).copyTo(impl_->p0_table2); + } +} +void CpuDepthPacketProcessor::loadP0TablesFromFiles(const char* p0_filename, const char* p1_filename, const char* p2_filename) +{ + cv::Mat p0_table0(424, 512, CV_16UC1); + if(!loadBufferFromFile2(p0_filename, p0_table0.data, p0_table0.total() * p0_table0.elemSize())) + { + std::cerr << "[CpuDepthPacketProcessor::loadP0TablesFromFiles] Loading p0table 0 from '" << p0_filename << "' failed!" << std::endl; + } + + cv::Mat p0_table1(424, 512, CV_16UC1); + if(!loadBufferFromFile2(p1_filename, p0_table1.data, p0_table1.total() * p0_table1.elemSize())) + { + std::cerr << "[CpuDepthPacketProcessor::loadP0TablesFromFiles] Loading p0table 1 from '" << p1_filename << "' failed!" << std::endl; + } + + cv::Mat p0_table2(424, 512, CV_16UC1); + if(!loadBufferFromFile2(p2_filename, p0_table2.data, p0_table2.total() * p0_table2.elemSize())) + { + std::cerr << "[CpuDepthPacketProcessor::loadP0TablesFromFiles] Loading p0table 2 from '" << p2_filename << "' failed!" << std::endl; + } + + if(impl_->flip_ptables) + { + cv::flip(p0_table0, impl_->p0_table0, 0); + cv::flip(p0_table1, impl_->p0_table1, 0); + cv::flip(p0_table2, impl_->p0_table2, 0); + + impl_->fill_trig_tables(impl_->p0_table0, impl_->trig_table0); + impl_->fill_trig_tables(impl_->p0_table1, impl_->trig_table1); + impl_->fill_trig_tables(impl_->p0_table2, impl_->trig_table2); + } + else + { + impl_->fill_trig_tables(p0_table0, impl_->trig_table0); + impl_->fill_trig_tables(p0_table1, impl_->trig_table1); + impl_->fill_trig_tables(p0_table2, impl_->trig_table2); + } +} + +void CpuDepthPacketProcessor::loadXTableFromFile(const char* filename) +{ + impl_->x_table.create(424, 512, CV_32FC1); + const unsigned char *data; + size_t length; + + if(loadResource("xTable.bin", &data, &length)) + { + std::copy(data, data + length, impl_->x_table.data); + } + else + { + std::cerr << "[CpuDepthPacketProcessor::loadXTableFromFile] Loading xtable from resource 'xTable.bin' failed!" << std::endl; + } +} + +void CpuDepthPacketProcessor::loadZTableFromFile(const char* filename) +{ + impl_->z_table.create(424, 512, CV_32FC1); + + const unsigned char *data; + size_t length; + + if(loadResource("zTable.bin", &data, &length)) + { + std::copy(data, data + length, impl_->z_table.data); + } + else + { + std::cerr << "[CpuDepthPacketProcessor::loadZTableFromFile] Loading ztable from resource 'zTable.bin' failed!" << std::endl; + } +} + +void CpuDepthPacketProcessor::load11To16LutFromFile(const char* filename) +{ + const unsigned char *data; + size_t length; + + if(loadResource("11to16.bin", &data, &length)) + { + std::copy(data, data + length, reinterpret_cast(impl_->lut11to16)); + } + else + { + std::cerr << "[CpuDepthPacketProcessor::load11To16LutFromFile] Loading 11to16 lut from resource '11to16.bin' failed!" << std::endl; + } +} + +void CpuDepthPacketProcessor::process(const DepthPacket &packet) +{ + if(listener_ == 0) return; + + impl_->startTiming(); + + cv::Mat m = cv::Mat::zeros(424, 512, CV_32FC(9)), m_filtered = cv::Mat::zeros(424, 512, CV_32FC(9)), m_max_edge_test = cv::Mat::ones(424, 512, CV_8UC1); + + float *m_ptr = m.ptr(); + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, m_ptr += 9) + { + impl_->processPixelStage1(x, y, packet.buffer, m_ptr + 0, m_ptr + 3, m_ptr + 6); + } + + // bilateral filtering + if(impl_->enable_bilateral_filter) + { + float *m_filtered_ptr = m_filtered.ptr(); + unsigned char *m_max_edge_test_ptr = m_max_edge_test.ptr(); + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, m_filtered_ptr += 9, ++m_max_edge_test_ptr) + { + bool max_edge_test_val = true; + impl_->filterPixelStage1(x, y, m, m_filtered_ptr, max_edge_test_val); + *m_max_edge_test_ptr = max_edge_test_val ? 1 : 0; + } + + m_ptr = m_filtered.ptr(); + } + else + { + m_ptr = m.ptr(); + } + + cv::Mat out_ir(424, 512, CV_32FC1, impl_->ir_frame->data), out_depth(424, 512, CV_32FC1, impl_->depth_frame->data); + + if(impl_->enable_edge_filter) + { + cv::Mat depth_ir_sum(424, 512, CV_32FC3); + cv::Vec3f *depth_ir_sum_ptr = depth_ir_sum.ptr(); + unsigned char *m_max_edge_test_ptr = m_max_edge_test.ptr(); + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, m_ptr += 9, ++m_max_edge_test_ptr, ++depth_ir_sum_ptr) + { + float raw_depth, ir_sum; + + impl_->processPixelStage2(x, y, m_ptr + 0, m_ptr + 3, m_ptr + 6, out_ir.ptr(423 - y, x), &raw_depth, &ir_sum); + + depth_ir_sum_ptr->val[0] = raw_depth; + depth_ir_sum_ptr->val[1] = *m_max_edge_test_ptr == 1 ? raw_depth : 0; + depth_ir_sum_ptr->val[2] = ir_sum; + } + + m_max_edge_test_ptr = m_max_edge_test.ptr(); + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, ++m_max_edge_test_ptr) + { + impl_->filterPixelStage2(x, y, depth_ir_sum, *m_max_edge_test_ptr == 1, out_depth.ptr(423 - y, x)); + } + } + else + { + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, m_ptr += 9) + { + impl_->processPixelStage2(x, y, m_ptr + 0, m_ptr + 3, m_ptr + 6, out_ir.ptr(423 - y, x), out_depth.ptr(423 - y, x), 0); + } + } + + if(listener_->onNewFrame(Frame::Ir, impl_->ir_frame)) + { + impl_->newIrFrame(); + } + + if(listener_->onNewFrame(Frame::Depth, impl_->depth_frame)) + { + impl_->newDepthFrame(); + } + + impl_->stopTiming(); +} + +} /* namespace libfreenect2 */ + diff --git a/examples/k22v4l/src/depth_packet_processor.cpp b/examples/k22v4l/src/depth_packet_processor.cpp new file mode 100644 index 000000000..b37e0059e --- /dev/null +++ b/examples/k22v4l/src/depth_packet_processor.cpp @@ -0,0 +1,108 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include + +namespace libfreenect2 +{ + +DepthPacketProcessor::Config::Config() : + MinDepth(0.5f), + MaxDepth(4.5f), + EnableBilateralFilter(true), + EnableEdgeAwareFilter(true) +{ + +} + +DepthPacketProcessor::Parameters::Parameters() +{ + ab_multiplier = 0.6666667f; + ab_multiplier_per_frq[0] = 1.322581f; + ab_multiplier_per_frq[1] = 1.0f; + ab_multiplier_per_frq[2] = 1.612903f; + ab_output_multiplier = 16.0f; + + phase_in_rad[0] = 0.0f; + phase_in_rad[1] = 2.094395f; + phase_in_rad[2] = 4.18879f; + + joint_bilateral_ab_threshold = 3.0f; + joint_bilateral_max_edge = 2.5f; + joint_bilateral_exp = 5.0f; + + gaussian_kernel[0] = 0.1069973f; + gaussian_kernel[1] = 0.1131098f; + gaussian_kernel[2] = 0.1069973f; + gaussian_kernel[3] = 0.1131098f; + gaussian_kernel[4] = 0.1195715f; + gaussian_kernel[5] = 0.1131098f; + gaussian_kernel[6] = 0.1069973f; + gaussian_kernel[7] = 0.1131098f; + gaussian_kernel[8] = 0.1069973f; + + phase_offset = 0.0f; + unambigious_dist = 2083.333f; + individual_ab_threshold = 3.0f; + ab_threshold = 10.0f; + ab_confidence_slope = -0.5330578f; + ab_confidence_offset = 0.7694894f; + min_dealias_confidence = 0.3490659f; + max_dealias_confidence = 0.6108653f; + + edge_ab_avg_min_value = 50.0f; + edge_ab_std_dev_threshold = 0.05f; + edge_close_delta_threshold = 50.0f; + edge_far_delta_threshold = 30.0f; + edge_max_delta_threshold = 100.0f; + edge_avg_delta_threshold = 0.0f; + max_edge_count = 5.0f; + + min_depth = 500.0f; + max_depth = 4500.0f; +} + +DepthPacketProcessor::DepthPacketProcessor() : + listener_(0) +{ +} + +DepthPacketProcessor::~DepthPacketProcessor() +{ +} + +void DepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + config_ = config; +} + +void DepthPacketProcessor::setFrameListener(libfreenect2::FrameListener *listener) +{ + listener_ = listener; +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/depth_packet_stream_parser.cpp b/examples/k22v4l/src/depth_packet_stream_parser.cpp new file mode 100644 index 000000000..5c648abf7 --- /dev/null +++ b/examples/k22v4l/src/depth_packet_stream_parser.cpp @@ -0,0 +1,180 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include +#include + +namespace libfreenect2 +{ + +DepthPacketStreamParser::DepthPacketStreamParser() : + processor_(noopProcessor()), + current_sequence_(0), + current_subsequence_(0) +{ + size_t single_image = 512*424*11/8; + + buffer_.allocate((single_image) * 10); + buffer_.front().length = buffer_.front().capacity; + buffer_.back().length = buffer_.back().capacity; + + work_buffer_.data = new unsigned char[single_image * 2]; + work_buffer_.capacity = single_image * 2; + work_buffer_.length = 0; +} + +DepthPacketStreamParser::~DepthPacketStreamParser() +{ +} + +void DepthPacketStreamParser::setPacketProcessor(libfreenect2::BaseDepthPacketProcessor *processor) +{ + processor_ = (processor != 0) ? processor : noopProcessor(); +} + +void DepthPacketStreamParser::onDataReceived(unsigned char* buffer, size_t in_length) +{ + // TODO: simplify this crap (so code, such unreadable, wow ;) + Buffer &wb = work_buffer_; + + size_t in_offset = 0; + + while(in_offset < in_length) + { + unsigned char *ptr_in = buffer + in_offset, *ptr_out = wb.data + wb.length; + DepthSubPacketFooter *footer = 0; + bool footer_found = false; + + size_t max_length = std::min(wb.capacity - wb.length, in_length - 8); + + for(; in_offset < max_length; ++in_offset) + { + footer = reinterpret_cast(ptr_in); + + if(footer->magic0 == 0x0 && footer->magic1 == 0x9) + { + footer_found = true; + break; + } + + *ptr_out = *ptr_in; + ++ptr_in; + ++ptr_out; + } + + wb.length = ptr_out - wb.data; + + if(footer_found) + { + if((in_length - in_offset) < sizeof(DepthSubPacketFooter)) + { + std::cerr << "[DepthPacketStreamParser::handleNewData] incomplete footer detected!" << std::endl; + } + else if(footer->length > wb.length) + { + std::cerr << "[DepthPacketStreamParser::handleNewData] image data too short!" << std::endl; + } + else + { + if(current_sequence_ != footer->sequence) + { + if(current_subsequence_ == 0x3ff) + { + if(processor_->ready()) + { + buffer_.swap(); + + DepthPacket packet; + packet.sequence = current_sequence_; + packet.buffer = buffer_.back().data; + packet.buffer_length = buffer_.back().length; + + processor_->process(packet); + } + else + { + //std::cerr << "[DepthPacketStreamParser::handleNewData] skipping depth packet!" << std::endl; + } + } + else + { + std::cerr << "[DepthPacketStreamParser::handleNewData] not all subsequences received " << current_subsequence_ << std::endl; + } + + current_sequence_ = footer->sequence; + current_subsequence_ = 0; + } + + Buffer &fb = buffer_.front(); + + // set the bit corresponding to the subsequence number to 1 + current_subsequence_ |= 1 << footer->subsequence; + + if(footer->subsequence * footer->length > fb.length) + { + std::cerr << "[DepthPacketStreamParser::handleNewData] front buffer too short! subsequence number is " << footer->subsequence << std::endl; + } + else + { + memcpy(fb.data + (footer->subsequence * footer->length), wb.data + (wb.length - footer->length), footer->length); + } + } + + // reset working buffer + wb.length = 0; + // skip header + in_offset += sizeof(DepthSubPacketFooter); + } + else + { + if((wb.length + 8) >= wb.capacity) + { + std::cerr << "[DepthPacketStreamParser::handleNewData] working buffer full, resetting it!" << std::endl; + wb.length = 0; + ptr_out = wb.data; + } + + // copy remaining 8 bytes + if((in_length - in_offset) != 8) + { + std::cerr << "[DepthPacketStreamParser::handleNewData] remaining data should be 8 bytes, but is " << (in_length - in_offset) << std::endl; + } + + for(; in_offset < in_length; ++in_offset) + { + *ptr_out = *ptr_in; + ++ptr_in; + ++ptr_out; + } + + wb.length = ptr_out - wb.data; + } + } +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/double_buffer.cpp b/examples/k22v4l/src/double_buffer.cpp new file mode 100644 index 000000000..c1948b49a --- /dev/null +++ b/examples/k22v4l/src/double_buffer.cpp @@ -0,0 +1,77 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include + +namespace libfreenect2 +{ + +DoubleBuffer::DoubleBuffer() : + front_buffer_index_(0), + buffer_data_(0) +{ +} + +DoubleBuffer::~DoubleBuffer() +{ + if(buffer_data_ != 0) + { + buffer_[0].data = 0; + buffer_[1].data = 0; + delete[] buffer_data_; + } +} + +void DoubleBuffer::allocate(size_t buffer_size) +{ + size_t total_buffer_size = 2 * buffer_size; + buffer_data_ = new unsigned char[total_buffer_size]; + + buffer_[0].capacity = buffer_size; + buffer_[0].length = 0; + buffer_[0].data = buffer_data_; + + buffer_[1].capacity = buffer_size; + buffer_[1].length = 0; + buffer_[1].data = buffer_data_ + buffer_size; +} + +void DoubleBuffer::swap() +{ + front_buffer_index_ = (front_buffer_index_ + 1) & 1; +} + +Buffer& DoubleBuffer::front() +{ + return buffer_[front_buffer_index_ & 1]; +} + +Buffer& DoubleBuffer::back() +{ + return buffer_[(front_buffer_index_ + 1) & 1]; +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/event_loop.cpp b/examples/k22v4l/src/event_loop.cpp new file mode 100644 index 000000000..bd89ce8ce --- /dev/null +++ b/examples/k22v4l/src/event_loop.cpp @@ -0,0 +1,93 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include + +#include +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace libfreenect2 +{ +namespace usb +{ + +void EventLoop::static_execute(void *cookie) +{ + static_cast(cookie)->execute(); +} + +EventLoop::EventLoop() : + shutdown_(false), + thread_(0), + usb_context_(0) +{ +} + +EventLoop::~EventLoop() +{ + stop(); +} + +void EventLoop::start(void *usb_context) +{ + if(thread_ == 0) + { + shutdown_ = false; + usb_context_ = usb_context; + thread_ = new libfreenect2::thread(&EventLoop::static_execute, this); + } +} + +void EventLoop::stop() +{ + if(thread_ != 0) + { + shutdown_ = true; + thread_->join(); + delete thread_; + thread_ = 0; + usb_context_ = 0; + } +} + +void EventLoop::execute() +{ + timeval t; + t.tv_sec = 0; + t.tv_usec = 100000; + + while(!shutdown_) + { + libusb_handle_events_timeout_completed(reinterpret_cast(usb_context_), &t, 0); + } +} + +} /* namespace usb */ +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/flextGL.c b/examples/k22v4l/src/flextGL.c new file mode 100644 index 000000000..a462628b3 --- /dev/null +++ b/examples/k22v4l/src/flextGL.c @@ -0,0 +1,367 @@ +/* WARNING: This file was automatically generated */ +/* Do not edit. */ + +#include "flextGL.h" +#include "GLFW/glfw3.h" + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +void flextLoadOpenGLFunctions(OpenGLBindings *bindings); + +int flextInit(GLFWwindow* window, OpenGLBindings *bindings) +{ + + int major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR); + int minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR); + + flextLoadOpenGLFunctions(bindings); + + /* --- Check for minimal version and profile --- */ + + if (major * 10 + minor < 33) { + fprintf(stderr, "Error: OpenGL version 3.3 not supported.\n"); + fprintf(stderr, " Your version is %d.%d.\n", major, minor); + fprintf(stderr, " Try updating your graphics driver.\n"); + return GL_FALSE; + } + + + /* --- Check for extensions --- */ + + + return GL_TRUE; +} + + + +void flextLoadOpenGLFunctions(OpenGLBindings *bindings) +{ + /* --- Function pointer loading --- */ + + + /* GL_VERSION_1_2 */ + + bindings->glDrawRangeElements = (PFNGLDRAWRANGEELEMENTS_PROC*)glfwGetProcAddress("glDrawRangeElements"); + bindings->glTexImage3D = (PFNGLTEXIMAGE3D_PROC*)glfwGetProcAddress("glTexImage3D"); + bindings->glTexSubImage3D = (PFNGLTEXSUBIMAGE3D_PROC*)glfwGetProcAddress("glTexSubImage3D"); + bindings->glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3D_PROC*)glfwGetProcAddress("glCopyTexSubImage3D"); + + /* GL_VERSION_1_3 */ + + bindings->glActiveTexture = (PFNGLACTIVETEXTURE_PROC*)glfwGetProcAddress("glActiveTexture"); + bindings->glSampleCoverage = (PFNGLSAMPLECOVERAGE_PROC*)glfwGetProcAddress("glSampleCoverage"); + bindings->glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3D_PROC*)glfwGetProcAddress("glCompressedTexImage3D"); + bindings->glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2D_PROC*)glfwGetProcAddress("glCompressedTexImage2D"); + bindings->glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1D_PROC*)glfwGetProcAddress("glCompressedTexImage1D"); + bindings->glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC*)glfwGetProcAddress("glCompressedTexSubImage3D"); + bindings->glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC*)glfwGetProcAddress("glCompressedTexSubImage2D"); + bindings->glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC*)glfwGetProcAddress("glCompressedTexSubImage1D"); + bindings->glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGE_PROC*)glfwGetProcAddress("glGetCompressedTexImage"); + + /* GL_VERSION_1_4 */ + + bindings->glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATE_PROC*)glfwGetProcAddress("glBlendFuncSeparate"); + bindings->glMultiDrawArrays = (PFNGLMULTIDRAWARRAYS_PROC*)glfwGetProcAddress("glMultiDrawArrays"); + bindings->glMultiDrawElements = (PFNGLMULTIDRAWELEMENTS_PROC*)glfwGetProcAddress("glMultiDrawElements"); + bindings->glPointParameterf = (PFNGLPOINTPARAMETERF_PROC*)glfwGetProcAddress("glPointParameterf"); + bindings->glPointParameterfv = (PFNGLPOINTPARAMETERFV_PROC*)glfwGetProcAddress("glPointParameterfv"); + bindings->glPointParameteri = (PFNGLPOINTPARAMETERI_PROC*)glfwGetProcAddress("glPointParameteri"); + bindings->glPointParameteriv = (PFNGLPOINTPARAMETERIV_PROC*)glfwGetProcAddress("glPointParameteriv"); + bindings->glBlendColor = (PFNGLBLENDCOLOR_PROC*)glfwGetProcAddress("glBlendColor"); + bindings->glBlendEquation = (PFNGLBLENDEQUATION_PROC*)glfwGetProcAddress("glBlendEquation"); + + /* GL_VERSION_1_5 */ + + bindings->glGenQueries = (PFNGLGENQUERIES_PROC*)glfwGetProcAddress("glGenQueries"); + bindings->glDeleteQueries = (PFNGLDELETEQUERIES_PROC*)glfwGetProcAddress("glDeleteQueries"); + bindings->glIsQuery = (PFNGLISQUERY_PROC*)glfwGetProcAddress("glIsQuery"); + bindings->glBeginQuery = (PFNGLBEGINQUERY_PROC*)glfwGetProcAddress("glBeginQuery"); + bindings->glEndQuery = (PFNGLENDQUERY_PROC*)glfwGetProcAddress("glEndQuery"); + bindings->glGetQueryiv = (PFNGLGETQUERYIV_PROC*)glfwGetProcAddress("glGetQueryiv"); + bindings->glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIV_PROC*)glfwGetProcAddress("glGetQueryObjectiv"); + bindings->glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIV_PROC*)glfwGetProcAddress("glGetQueryObjectuiv"); + bindings->glBindBuffer = (PFNGLBINDBUFFER_PROC*)glfwGetProcAddress("glBindBuffer"); + bindings->glDeleteBuffers = (PFNGLDELETEBUFFERS_PROC*)glfwGetProcAddress("glDeleteBuffers"); + bindings->glGenBuffers = (PFNGLGENBUFFERS_PROC*)glfwGetProcAddress("glGenBuffers"); + bindings->glIsBuffer = (PFNGLISBUFFER_PROC*)glfwGetProcAddress("glIsBuffer"); + bindings->glBufferData = (PFNGLBUFFERDATA_PROC*)glfwGetProcAddress("glBufferData"); + bindings->glBufferSubData = (PFNGLBUFFERSUBDATA_PROC*)glfwGetProcAddress("glBufferSubData"); + bindings->glGetBufferSubData = (PFNGLGETBUFFERSUBDATA_PROC*)glfwGetProcAddress("glGetBufferSubData"); + bindings->glMapBuffer = (PFNGLMAPBUFFER_PROC*)glfwGetProcAddress("glMapBuffer"); + bindings->glUnmapBuffer = (PFNGLUNMAPBUFFER_PROC*)glfwGetProcAddress("glUnmapBuffer"); + bindings->glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIV_PROC*)glfwGetProcAddress("glGetBufferParameteriv"); + bindings->glGetBufferPointerv = (PFNGLGETBUFFERPOINTERV_PROC*)glfwGetProcAddress("glGetBufferPointerv"); + + /* GL_VERSION_2_0 */ + + bindings->glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATE_PROC*)glfwGetProcAddress("glBlendEquationSeparate"); + bindings->glDrawBuffers = (PFNGLDRAWBUFFERS_PROC*)glfwGetProcAddress("glDrawBuffers"); + bindings->glStencilOpSeparate = (PFNGLSTENCILOPSEPARATE_PROC*)glfwGetProcAddress("glStencilOpSeparate"); + bindings->glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATE_PROC*)glfwGetProcAddress("glStencilFuncSeparate"); + bindings->glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATE_PROC*)glfwGetProcAddress("glStencilMaskSeparate"); + bindings->glAttachShader = (PFNGLATTACHSHADER_PROC*)glfwGetProcAddress("glAttachShader"); + bindings->glBindAttribLocation = (PFNGLBINDATTRIBLOCATION_PROC*)glfwGetProcAddress("glBindAttribLocation"); + bindings->glCompileShader = (PFNGLCOMPILESHADER_PROC*)glfwGetProcAddress("glCompileShader"); + bindings->glCreateProgram = (PFNGLCREATEPROGRAM_PROC*)glfwGetProcAddress("glCreateProgram"); + bindings->glCreateShader = (PFNGLCREATESHADER_PROC*)glfwGetProcAddress("glCreateShader"); + bindings->glDeleteProgram = (PFNGLDELETEPROGRAM_PROC*)glfwGetProcAddress("glDeleteProgram"); + bindings->glDeleteShader = (PFNGLDELETESHADER_PROC*)glfwGetProcAddress("glDeleteShader"); + bindings->glDetachShader = (PFNGLDETACHSHADER_PROC*)glfwGetProcAddress("glDetachShader"); + bindings->glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAY_PROC*)glfwGetProcAddress("glDisableVertexAttribArray"); + bindings->glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAY_PROC*)glfwGetProcAddress("glEnableVertexAttribArray"); + bindings->glGetActiveAttrib = (PFNGLGETACTIVEATTRIB_PROC*)glfwGetProcAddress("glGetActiveAttrib"); + bindings->glGetActiveUniform = (PFNGLGETACTIVEUNIFORM_PROC*)glfwGetProcAddress("glGetActiveUniform"); + bindings->glGetAttachedShaders = (PFNGLGETATTACHEDSHADERS_PROC*)glfwGetProcAddress("glGetAttachedShaders"); + bindings->glGetAttribLocation = (PFNGLGETATTRIBLOCATION_PROC*)glfwGetProcAddress("glGetAttribLocation"); + bindings->glGetProgramiv = (PFNGLGETPROGRAMIV_PROC*)glfwGetProcAddress("glGetProgramiv"); + bindings->glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOG_PROC*)glfwGetProcAddress("glGetProgramInfoLog"); + bindings->glGetShaderiv = (PFNGLGETSHADERIV_PROC*)glfwGetProcAddress("glGetShaderiv"); + bindings->glGetShaderInfoLog = (PFNGLGETSHADERINFOLOG_PROC*)glfwGetProcAddress("glGetShaderInfoLog"); + bindings->glGetShaderSource = (PFNGLGETSHADERSOURCE_PROC*)glfwGetProcAddress("glGetShaderSource"); + bindings->glGetUniformLocation = (PFNGLGETUNIFORMLOCATION_PROC*)glfwGetProcAddress("glGetUniformLocation"); + bindings->glGetUniformfv = (PFNGLGETUNIFORMFV_PROC*)glfwGetProcAddress("glGetUniformfv"); + bindings->glGetUniformiv = (PFNGLGETUNIFORMIV_PROC*)glfwGetProcAddress("glGetUniformiv"); + bindings->glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDV_PROC*)glfwGetProcAddress("glGetVertexAttribdv"); + bindings->glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFV_PROC*)glfwGetProcAddress("glGetVertexAttribfv"); + bindings->glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIV_PROC*)glfwGetProcAddress("glGetVertexAttribiv"); + bindings->glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERV_PROC*)glfwGetProcAddress("glGetVertexAttribPointerv"); + bindings->glIsProgram = (PFNGLISPROGRAM_PROC*)glfwGetProcAddress("glIsProgram"); + bindings->glIsShader = (PFNGLISSHADER_PROC*)glfwGetProcAddress("glIsShader"); + bindings->glLinkProgram = (PFNGLLINKPROGRAM_PROC*)glfwGetProcAddress("glLinkProgram"); + bindings->glShaderSource = (PFNGLSHADERSOURCE_PROC*)glfwGetProcAddress("glShaderSource"); + bindings->glUseProgram = (PFNGLUSEPROGRAM_PROC*)glfwGetProcAddress("glUseProgram"); + bindings->glUniform1f = (PFNGLUNIFORM1F_PROC*)glfwGetProcAddress("glUniform1f"); + bindings->glUniform2f = (PFNGLUNIFORM2F_PROC*)glfwGetProcAddress("glUniform2f"); + bindings->glUniform3f = (PFNGLUNIFORM3F_PROC*)glfwGetProcAddress("glUniform3f"); + bindings->glUniform4f = (PFNGLUNIFORM4F_PROC*)glfwGetProcAddress("glUniform4f"); + bindings->glUniform1i = (PFNGLUNIFORM1I_PROC*)glfwGetProcAddress("glUniform1i"); + bindings->glUniform2i = (PFNGLUNIFORM2I_PROC*)glfwGetProcAddress("glUniform2i"); + bindings->glUniform3i = (PFNGLUNIFORM3I_PROC*)glfwGetProcAddress("glUniform3i"); + bindings->glUniform4i = (PFNGLUNIFORM4I_PROC*)glfwGetProcAddress("glUniform4i"); + bindings->glUniform1fv = (PFNGLUNIFORM1FV_PROC*)glfwGetProcAddress("glUniform1fv"); + bindings->glUniform2fv = (PFNGLUNIFORM2FV_PROC*)glfwGetProcAddress("glUniform2fv"); + bindings->glUniform3fv = (PFNGLUNIFORM3FV_PROC*)glfwGetProcAddress("glUniform3fv"); + bindings->glUniform4fv = (PFNGLUNIFORM4FV_PROC*)glfwGetProcAddress("glUniform4fv"); + bindings->glUniform1iv = (PFNGLUNIFORM1IV_PROC*)glfwGetProcAddress("glUniform1iv"); + bindings->glUniform2iv = (PFNGLUNIFORM2IV_PROC*)glfwGetProcAddress("glUniform2iv"); + bindings->glUniform3iv = (PFNGLUNIFORM3IV_PROC*)glfwGetProcAddress("glUniform3iv"); + bindings->glUniform4iv = (PFNGLUNIFORM4IV_PROC*)glfwGetProcAddress("glUniform4iv"); + bindings->glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FV_PROC*)glfwGetProcAddress("glUniformMatrix2fv"); + bindings->glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FV_PROC*)glfwGetProcAddress("glUniformMatrix3fv"); + bindings->glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FV_PROC*)glfwGetProcAddress("glUniformMatrix4fv"); + bindings->glValidateProgram = (PFNGLVALIDATEPROGRAM_PROC*)glfwGetProcAddress("glValidateProgram"); + bindings->glVertexAttrib1d = (PFNGLVERTEXATTRIB1D_PROC*)glfwGetProcAddress("glVertexAttrib1d"); + bindings->glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DV_PROC*)glfwGetProcAddress("glVertexAttrib1dv"); + bindings->glVertexAttrib1f = (PFNGLVERTEXATTRIB1F_PROC*)glfwGetProcAddress("glVertexAttrib1f"); + bindings->glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FV_PROC*)glfwGetProcAddress("glVertexAttrib1fv"); + bindings->glVertexAttrib1s = (PFNGLVERTEXATTRIB1S_PROC*)glfwGetProcAddress("glVertexAttrib1s"); + bindings->glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SV_PROC*)glfwGetProcAddress("glVertexAttrib1sv"); + bindings->glVertexAttrib2d = (PFNGLVERTEXATTRIB2D_PROC*)glfwGetProcAddress("glVertexAttrib2d"); + bindings->glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DV_PROC*)glfwGetProcAddress("glVertexAttrib2dv"); + bindings->glVertexAttrib2f = (PFNGLVERTEXATTRIB2F_PROC*)glfwGetProcAddress("glVertexAttrib2f"); + bindings->glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FV_PROC*)glfwGetProcAddress("glVertexAttrib2fv"); + bindings->glVertexAttrib2s = (PFNGLVERTEXATTRIB2S_PROC*)glfwGetProcAddress("glVertexAttrib2s"); + bindings->glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SV_PROC*)glfwGetProcAddress("glVertexAttrib2sv"); + bindings->glVertexAttrib3d = (PFNGLVERTEXATTRIB3D_PROC*)glfwGetProcAddress("glVertexAttrib3d"); + bindings->glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DV_PROC*)glfwGetProcAddress("glVertexAttrib3dv"); + bindings->glVertexAttrib3f = (PFNGLVERTEXATTRIB3F_PROC*)glfwGetProcAddress("glVertexAttrib3f"); + bindings->glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FV_PROC*)glfwGetProcAddress("glVertexAttrib3fv"); + bindings->glVertexAttrib3s = (PFNGLVERTEXATTRIB3S_PROC*)glfwGetProcAddress("glVertexAttrib3s"); + bindings->glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SV_PROC*)glfwGetProcAddress("glVertexAttrib3sv"); + bindings->glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBV_PROC*)glfwGetProcAddress("glVertexAttrib4Nbv"); + bindings->glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIV_PROC*)glfwGetProcAddress("glVertexAttrib4Niv"); + bindings->glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSV_PROC*)glfwGetProcAddress("glVertexAttrib4Nsv"); + bindings->glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUB_PROC*)glfwGetProcAddress("glVertexAttrib4Nub"); + bindings->glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBV_PROC*)glfwGetProcAddress("glVertexAttrib4Nubv"); + bindings->glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIV_PROC*)glfwGetProcAddress("glVertexAttrib4Nuiv"); + bindings->glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSV_PROC*)glfwGetProcAddress("glVertexAttrib4Nusv"); + bindings->glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BV_PROC*)glfwGetProcAddress("glVertexAttrib4bv"); + bindings->glVertexAttrib4d = (PFNGLVERTEXATTRIB4D_PROC*)glfwGetProcAddress("glVertexAttrib4d"); + bindings->glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DV_PROC*)glfwGetProcAddress("glVertexAttrib4dv"); + bindings->glVertexAttrib4f = (PFNGLVERTEXATTRIB4F_PROC*)glfwGetProcAddress("glVertexAttrib4f"); + bindings->glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FV_PROC*)glfwGetProcAddress("glVertexAttrib4fv"); + bindings->glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IV_PROC*)glfwGetProcAddress("glVertexAttrib4iv"); + bindings->glVertexAttrib4s = (PFNGLVERTEXATTRIB4S_PROC*)glfwGetProcAddress("glVertexAttrib4s"); + bindings->glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SV_PROC*)glfwGetProcAddress("glVertexAttrib4sv"); + bindings->glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBV_PROC*)glfwGetProcAddress("glVertexAttrib4ubv"); + bindings->glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIV_PROC*)glfwGetProcAddress("glVertexAttrib4uiv"); + bindings->glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USV_PROC*)glfwGetProcAddress("glVertexAttrib4usv"); + bindings->glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTER_PROC*)glfwGetProcAddress("glVertexAttribPointer"); + + /* GL_VERSION_2_1 */ + + bindings->glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FV_PROC*)glfwGetProcAddress("glUniformMatrix2x3fv"); + bindings->glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FV_PROC*)glfwGetProcAddress("glUniformMatrix3x2fv"); + bindings->glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FV_PROC*)glfwGetProcAddress("glUniformMatrix2x4fv"); + bindings->glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FV_PROC*)glfwGetProcAddress("glUniformMatrix4x2fv"); + bindings->glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FV_PROC*)glfwGetProcAddress("glUniformMatrix3x4fv"); + bindings->glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FV_PROC*)glfwGetProcAddress("glUniformMatrix4x3fv"); + + /* GL_VERSION_3_0 */ + + bindings->glColorMaski = (PFNGLCOLORMASKI_PROC*)glfwGetProcAddress("glColorMaski"); + bindings->glGetBooleani_v = (PFNGLGETBOOLEANI_V_PROC*)glfwGetProcAddress("glGetBooleani_v"); + bindings->glGetIntegeri_v = (PFNGLGETINTEGERI_V_PROC*)glfwGetProcAddress("glGetIntegeri_v"); + bindings->glEnablei = (PFNGLENABLEI_PROC*)glfwGetProcAddress("glEnablei"); + bindings->glDisablei = (PFNGLDISABLEI_PROC*)glfwGetProcAddress("glDisablei"); + bindings->glIsEnabledi = (PFNGLISENABLEDI_PROC*)glfwGetProcAddress("glIsEnabledi"); + bindings->glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACK_PROC*)glfwGetProcAddress("glBeginTransformFeedback"); + bindings->glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACK_PROC*)glfwGetProcAddress("glEndTransformFeedback"); + bindings->glBindBufferRange = (PFNGLBINDBUFFERRANGE_PROC*)glfwGetProcAddress("glBindBufferRange"); + bindings->glBindBufferBase = (PFNGLBINDBUFFERBASE_PROC*)glfwGetProcAddress("glBindBufferBase"); + bindings->glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGS_PROC*)glfwGetProcAddress("glTransformFeedbackVaryings"); + bindings->glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYING_PROC*)glfwGetProcAddress("glGetTransformFeedbackVarying"); + bindings->glClampColor = (PFNGLCLAMPCOLOR_PROC*)glfwGetProcAddress("glClampColor"); + bindings->glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDER_PROC*)glfwGetProcAddress("glBeginConditionalRender"); + bindings->glEndConditionalRender = (PFNGLENDCONDITIONALRENDER_PROC*)glfwGetProcAddress("glEndConditionalRender"); + bindings->glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTER_PROC*)glfwGetProcAddress("glVertexAttribIPointer"); + bindings->glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIV_PROC*)glfwGetProcAddress("glGetVertexAttribIiv"); + bindings->glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIV_PROC*)glfwGetProcAddress("glGetVertexAttribIuiv"); + bindings->glVertexAttribI1i = (PFNGLVERTEXATTRIBI1I_PROC*)glfwGetProcAddress("glVertexAttribI1i"); + bindings->glVertexAttribI2i = (PFNGLVERTEXATTRIBI2I_PROC*)glfwGetProcAddress("glVertexAttribI2i"); + bindings->glVertexAttribI3i = (PFNGLVERTEXATTRIBI3I_PROC*)glfwGetProcAddress("glVertexAttribI3i"); + bindings->glVertexAttribI4i = (PFNGLVERTEXATTRIBI4I_PROC*)glfwGetProcAddress("glVertexAttribI4i"); + bindings->glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UI_PROC*)glfwGetProcAddress("glVertexAttribI1ui"); + bindings->glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UI_PROC*)glfwGetProcAddress("glVertexAttribI2ui"); + bindings->glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UI_PROC*)glfwGetProcAddress("glVertexAttribI3ui"); + bindings->glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UI_PROC*)glfwGetProcAddress("glVertexAttribI4ui"); + bindings->glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IV_PROC*)glfwGetProcAddress("glVertexAttribI1iv"); + bindings->glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IV_PROC*)glfwGetProcAddress("glVertexAttribI2iv"); + bindings->glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IV_PROC*)glfwGetProcAddress("glVertexAttribI3iv"); + bindings->glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IV_PROC*)glfwGetProcAddress("glVertexAttribI4iv"); + bindings->glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIV_PROC*)glfwGetProcAddress("glVertexAttribI1uiv"); + bindings->glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIV_PROC*)glfwGetProcAddress("glVertexAttribI2uiv"); + bindings->glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIV_PROC*)glfwGetProcAddress("glVertexAttribI3uiv"); + bindings->glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIV_PROC*)glfwGetProcAddress("glVertexAttribI4uiv"); + bindings->glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BV_PROC*)glfwGetProcAddress("glVertexAttribI4bv"); + bindings->glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SV_PROC*)glfwGetProcAddress("glVertexAttribI4sv"); + bindings->glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBV_PROC*)glfwGetProcAddress("glVertexAttribI4ubv"); + bindings->glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USV_PROC*)glfwGetProcAddress("glVertexAttribI4usv"); + bindings->glGetUniformuiv = (PFNGLGETUNIFORMUIV_PROC*)glfwGetProcAddress("glGetUniformuiv"); + bindings->glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATION_PROC*)glfwGetProcAddress("glBindFragDataLocation"); + bindings->glGetFragDataLocation = (PFNGLGETFRAGDATALOCATION_PROC*)glfwGetProcAddress("glGetFragDataLocation"); + bindings->glUniform1ui = (PFNGLUNIFORM1UI_PROC*)glfwGetProcAddress("glUniform1ui"); + bindings->glUniform2ui = (PFNGLUNIFORM2UI_PROC*)glfwGetProcAddress("glUniform2ui"); + bindings->glUniform3ui = (PFNGLUNIFORM3UI_PROC*)glfwGetProcAddress("glUniform3ui"); + bindings->glUniform4ui = (PFNGLUNIFORM4UI_PROC*)glfwGetProcAddress("glUniform4ui"); + bindings->glUniform1uiv = (PFNGLUNIFORM1UIV_PROC*)glfwGetProcAddress("glUniform1uiv"); + bindings->glUniform2uiv = (PFNGLUNIFORM2UIV_PROC*)glfwGetProcAddress("glUniform2uiv"); + bindings->glUniform3uiv = (PFNGLUNIFORM3UIV_PROC*)glfwGetProcAddress("glUniform3uiv"); + bindings->glUniform4uiv = (PFNGLUNIFORM4UIV_PROC*)glfwGetProcAddress("glUniform4uiv"); + bindings->glTexParameterIiv = (PFNGLTEXPARAMETERIIV_PROC*)glfwGetProcAddress("glTexParameterIiv"); + bindings->glTexParameterIuiv = (PFNGLTEXPARAMETERIUIV_PROC*)glfwGetProcAddress("glTexParameterIuiv"); + bindings->glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIV_PROC*)glfwGetProcAddress("glGetTexParameterIiv"); + bindings->glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIV_PROC*)glfwGetProcAddress("glGetTexParameterIuiv"); + bindings->glClearBufferiv = (PFNGLCLEARBUFFERIV_PROC*)glfwGetProcAddress("glClearBufferiv"); + bindings->glClearBufferuiv = (PFNGLCLEARBUFFERUIV_PROC*)glfwGetProcAddress("glClearBufferuiv"); + bindings->glClearBufferfv = (PFNGLCLEARBUFFERFV_PROC*)glfwGetProcAddress("glClearBufferfv"); + bindings->glClearBufferfi = (PFNGLCLEARBUFFERFI_PROC*)glfwGetProcAddress("glClearBufferfi"); + bindings->glGetStringi = (PFNGLGETSTRINGI_PROC*)glfwGetProcAddress("glGetStringi"); + bindings->glIsRenderbuffer = (PFNGLISRENDERBUFFER_PROC*)glfwGetProcAddress("glIsRenderbuffer"); + bindings->glBindRenderbuffer = (PFNGLBINDRENDERBUFFER_PROC*)glfwGetProcAddress("glBindRenderbuffer"); + bindings->glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERS_PROC*)glfwGetProcAddress("glDeleteRenderbuffers"); + bindings->glGenRenderbuffers = (PFNGLGENRENDERBUFFERS_PROC*)glfwGetProcAddress("glGenRenderbuffers"); + bindings->glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGE_PROC*)glfwGetProcAddress("glRenderbufferStorage"); + bindings->glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIV_PROC*)glfwGetProcAddress("glGetRenderbufferParameteriv"); + bindings->glIsFramebuffer = (PFNGLISFRAMEBUFFER_PROC*)glfwGetProcAddress("glIsFramebuffer"); + bindings->glBindFramebuffer = (PFNGLBINDFRAMEBUFFER_PROC*)glfwGetProcAddress("glBindFramebuffer"); + bindings->glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERS_PROC*)glfwGetProcAddress("glDeleteFramebuffers"); + bindings->glGenFramebuffers = (PFNGLGENFRAMEBUFFERS_PROC*)glfwGetProcAddress("glGenFramebuffers"); + bindings->glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUS_PROC*)glfwGetProcAddress("glCheckFramebufferStatus"); + bindings->glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1D_PROC*)glfwGetProcAddress("glFramebufferTexture1D"); + bindings->glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2D_PROC*)glfwGetProcAddress("glFramebufferTexture2D"); + bindings->glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3D_PROC*)glfwGetProcAddress("glFramebufferTexture3D"); + bindings->glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFER_PROC*)glfwGetProcAddress("glFramebufferRenderbuffer"); + bindings->glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC*)glfwGetProcAddress("glGetFramebufferAttachmentParameteriv"); + bindings->glGenerateMipmap = (PFNGLGENERATEMIPMAP_PROC*)glfwGetProcAddress("glGenerateMipmap"); + bindings->glBlitFramebuffer = (PFNGLBLITFRAMEBUFFER_PROC*)glfwGetProcAddress("glBlitFramebuffer"); + bindings->glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC*)glfwGetProcAddress("glRenderbufferStorageMultisample"); + bindings->glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYER_PROC*)glfwGetProcAddress("glFramebufferTextureLayer"); + bindings->glMapBufferRange = (PFNGLMAPBUFFERRANGE_PROC*)glfwGetProcAddress("glMapBufferRange"); + bindings->glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGE_PROC*)glfwGetProcAddress("glFlushMappedBufferRange"); + bindings->glBindVertexArray = (PFNGLBINDVERTEXARRAY_PROC*)glfwGetProcAddress("glBindVertexArray"); + bindings->glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYS_PROC*)glfwGetProcAddress("glDeleteVertexArrays"); + bindings->glGenVertexArrays = (PFNGLGENVERTEXARRAYS_PROC*)glfwGetProcAddress("glGenVertexArrays"); + bindings->glIsVertexArray = (PFNGLISVERTEXARRAY_PROC*)glfwGetProcAddress("glIsVertexArray"); + + /* GL_VERSION_3_1 */ + + bindings->glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCED_PROC*)glfwGetProcAddress("glDrawArraysInstanced"); + bindings->glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCED_PROC*)glfwGetProcAddress("glDrawElementsInstanced"); + bindings->glTexBuffer = (PFNGLTEXBUFFER_PROC*)glfwGetProcAddress("glTexBuffer"); + bindings->glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEX_PROC*)glfwGetProcAddress("glPrimitiveRestartIndex"); + bindings->glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATA_PROC*)glfwGetProcAddress("glCopyBufferSubData"); + bindings->glGetUniformIndices = (PFNGLGETUNIFORMINDICES_PROC*)glfwGetProcAddress("glGetUniformIndices"); + bindings->glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIV_PROC*)glfwGetProcAddress("glGetActiveUniformsiv"); + bindings->glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAME_PROC*)glfwGetProcAddress("glGetActiveUniformName"); + bindings->glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEX_PROC*)glfwGetProcAddress("glGetUniformBlockIndex"); + bindings->glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIV_PROC*)glfwGetProcAddress("glGetActiveUniformBlockiv"); + bindings->glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC*)glfwGetProcAddress("glGetActiveUniformBlockName"); + bindings->glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDING_PROC*)glfwGetProcAddress("glUniformBlockBinding"); + + /* GL_VERSION_3_2 */ + + bindings->glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEX_PROC*)glfwGetProcAddress("glDrawElementsBaseVertex"); + bindings->glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEX_PROC*)glfwGetProcAddress("glDrawRangeElementsBaseVertex"); + bindings->glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEX_PROC*)glfwGetProcAddress("glDrawElementsInstancedBaseVertex"); + bindings->glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEX_PROC*)glfwGetProcAddress("glMultiDrawElementsBaseVertex"); + bindings->glProvokingVertex = (PFNGLPROVOKINGVERTEX_PROC*)glfwGetProcAddress("glProvokingVertex"); + bindings->glFenceSync = (PFNGLFENCESYNC_PROC*)glfwGetProcAddress("glFenceSync"); + bindings->glIsSync = (PFNGLISSYNC_PROC*)glfwGetProcAddress("glIsSync"); + bindings->glDeleteSync = (PFNGLDELETESYNC_PROC*)glfwGetProcAddress("glDeleteSync"); + bindings->glClientWaitSync = (PFNGLCLIENTWAITSYNC_PROC*)glfwGetProcAddress("glClientWaitSync"); + bindings->glWaitSync = (PFNGLWAITSYNC_PROC*)glfwGetProcAddress("glWaitSync"); + bindings->glGetInteger64v = (PFNGLGETINTEGER64V_PROC*)glfwGetProcAddress("glGetInteger64v"); + bindings->glGetSynciv = (PFNGLGETSYNCIV_PROC*)glfwGetProcAddress("glGetSynciv"); + bindings->glGetInteger64i_v = (PFNGLGETINTEGER64I_V_PROC*)glfwGetProcAddress("glGetInteger64i_v"); + bindings->glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64V_PROC*)glfwGetProcAddress("glGetBufferParameteri64v"); + bindings->glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTURE_PROC*)glfwGetProcAddress("glFramebufferTexture"); + bindings->glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLE_PROC*)glfwGetProcAddress("glTexImage2DMultisample"); + bindings->glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLE_PROC*)glfwGetProcAddress("glTexImage3DMultisample"); + bindings->glGetMultisamplefv = (PFNGLGETMULTISAMPLEFV_PROC*)glfwGetProcAddress("glGetMultisamplefv"); + bindings->glSampleMaski = (PFNGLSAMPLEMASKI_PROC*)glfwGetProcAddress("glSampleMaski"); + + /* GL_VERSION_3_3 */ + + bindings->glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXED_PROC*)glfwGetProcAddress("glBindFragDataLocationIndexed"); + bindings->glGetFragDataIndex = (PFNGLGETFRAGDATAINDEX_PROC*)glfwGetProcAddress("glGetFragDataIndex"); + bindings->glGenSamplers = (PFNGLGENSAMPLERS_PROC*)glfwGetProcAddress("glGenSamplers"); + bindings->glDeleteSamplers = (PFNGLDELETESAMPLERS_PROC*)glfwGetProcAddress("glDeleteSamplers"); + bindings->glIsSampler = (PFNGLISSAMPLER_PROC*)glfwGetProcAddress("glIsSampler"); + bindings->glBindSampler = (PFNGLBINDSAMPLER_PROC*)glfwGetProcAddress("glBindSampler"); + bindings->glSamplerParameteri = (PFNGLSAMPLERPARAMETERI_PROC*)glfwGetProcAddress("glSamplerParameteri"); + bindings->glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIV_PROC*)glfwGetProcAddress("glSamplerParameteriv"); + bindings->glSamplerParameterf = (PFNGLSAMPLERPARAMETERF_PROC*)glfwGetProcAddress("glSamplerParameterf"); + bindings->glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFV_PROC*)glfwGetProcAddress("glSamplerParameterfv"); + bindings->glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIV_PROC*)glfwGetProcAddress("glSamplerParameterIiv"); + bindings->glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIV_PROC*)glfwGetProcAddress("glSamplerParameterIuiv"); + bindings->glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIV_PROC*)glfwGetProcAddress("glGetSamplerParameteriv"); + bindings->glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIV_PROC*)glfwGetProcAddress("glGetSamplerParameterIiv"); + bindings->glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFV_PROC*)glfwGetProcAddress("glGetSamplerParameterfv"); + bindings->glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIV_PROC*)glfwGetProcAddress("glGetSamplerParameterIuiv"); + bindings->glQueryCounter = (PFNGLQUERYCOUNTER_PROC*)glfwGetProcAddress("glQueryCounter"); + bindings->glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64V_PROC*)glfwGetProcAddress("glGetQueryObjecti64v"); + bindings->glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64V_PROC*)glfwGetProcAddress("glGetQueryObjectui64v"); + bindings->glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISOR_PROC*)glfwGetProcAddress("glVertexAttribDivisor"); + bindings->glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UI_PROC*)glfwGetProcAddress("glVertexAttribP1ui"); + bindings->glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIV_PROC*)glfwGetProcAddress("glVertexAttribP1uiv"); + bindings->glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UI_PROC*)glfwGetProcAddress("glVertexAttribP2ui"); + bindings->glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIV_PROC*)glfwGetProcAddress("glVertexAttribP2uiv"); + bindings->glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UI_PROC*)glfwGetProcAddress("glVertexAttribP3ui"); + bindings->glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIV_PROC*)glfwGetProcAddress("glVertexAttribP3uiv"); + bindings->glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UI_PROC*)glfwGetProcAddress("glVertexAttribP4ui"); + bindings->glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIV_PROC*)glfwGetProcAddress("glVertexAttribP4uiv"); + +} + +/* ----------------------- Extension flag definitions ---------------------- */ + +#ifdef __cplusplus +} +#endif diff --git a/examples/k22v4l/src/flextGL.h b/examples/k22v4l/src/flextGL.h new file mode 100644 index 000000000..3da3d1c9c --- /dev/null +++ b/examples/k22v4l/src/flextGL.h @@ -0,0 +1,1664 @@ +/* WARNING: This file was automatically generated */ +/* Do not edit. */ + +#ifndef __gl_h_ +#define __gl_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Function declaration macros - to move into glplatform.h */ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#ifndef WINAPI +#define WINAPI __stdcall +#endif +#define APIENTRY WINAPI +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/* -------------------------------- DATA TYPES ------------------------------- */ + +#include +#ifndef GLEXT_64_TYPES_DEFINED +/* This code block is duplicated in glxext.h, so must be protected */ +#define GLEXT_64_TYPES_DEFINED +/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ +/* (as used in the GL_EXT_timer_query extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(__sun__) || defined(__digital__) +#include +#if defined(__STDC__) +#if defined(__arch64__) || defined(_LP64) +typedef long int int64_t; +typedef unsigned long int uint64_t; +#else +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#endif /* __arch64__ */ +#endif /* __STDC__ */ +#elif defined( __VMS ) || defined(__sgi) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ +#include +#endif +#endif +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef signed char GLbyte; +typedef short GLshort; +typedef int GLint; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef int GLsizei; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef char GLchar; +typedef unsigned short GLhalf; +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; +typedef int64_t GLint64; +typedef uint64_t GLuint64; +typedef struct __GLsync *GLsync; + +/* ----------------------------------- ENUMS --------------------------------- */ + +/* GL_VERSION_1_1 */ + +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_NONE 0 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_VIEWPORT 0x0BA2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_DOUBLE 0x140A +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_REPEAT 0x2901 +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B + +/* GL_VERSION_1_2 */ + +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +/* GL_VERSION_1_3 */ + +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D + +/* GL_VERSION_1_4 */ + +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 + +/* GL_VERSION_1_5 */ + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SRC1_ALPHA 0x8589 + +/* GL_VERSION_2_0 */ + +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +/* GL_VERSION_2_1 */ + +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 + +/* GL_VERSION_3_0 */ + +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 + +/* GL_VERSION_3_1 */ + +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu + +/* GL_VERSION_3_2 */ + +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_DEPTH_CLAMP 0x864F +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 + +/* GL_VERSION_3_3 */ + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_TIME_ELAPSED 0x88BF +#define GL_TIMESTAMP 0x8E28 +#define GL_INT_2_10_10_10_REV 0x8D9F + +/* --------------------------- FUNCTION PROTOTYPES --------------------------- */ + + +/* GL_VERSION_1_0 */ + +GLAPI void APIENTRY glCullFace (GLenum mode); +GLAPI void APIENTRY glFrontFace (GLenum mode); +GLAPI void APIENTRY glHint (GLenum target, GLenum mode); +GLAPI void APIENTRY glLineWidth (GLfloat width); +GLAPI void APIENTRY glPointSize (GLfloat size); +GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode); +GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat * params); +GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint * params); +GLAPI void APIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glDrawBuffer (GLenum buf); +GLAPI void APIENTRY glClear (GLbitfield mask); +GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void APIENTRY glClearStencil (GLint s); +GLAPI void APIENTRY glClearDepth (GLdouble depth); +GLAPI void APIENTRY glStencilMask (GLuint mask); +GLAPI void APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI void APIENTRY glDepthMask (GLboolean flag); +GLAPI void APIENTRY glDisable (GLenum cap); +GLAPI void APIENTRY glEnable (GLenum cap); +GLAPI void APIENTRY glFinish (void); +GLAPI void APIENTRY glFlush (void); +GLAPI void APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GLAPI void APIENTRY glLogicOp (GLenum opcode); +GLAPI void APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GLAPI void APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GLAPI void APIENTRY glDepthFunc (GLenum func); +GLAPI void APIENTRY glPixelStoref (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); +GLAPI void APIENTRY glReadBuffer (GLenum src); +GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); +GLAPI void APIENTRY glGetBooleanv (GLenum pname, GLboolean * data); +GLAPI void APIENTRY glGetDoublev (GLenum pname, GLdouble * data); +GLAPI GLenum APIENTRY glGetError (void); +GLAPI void APIENTRY glGetFloatv (GLenum pname, GLfloat * data); +GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint * data); +GLAPI const GLubyte * APIENTRY glGetString (GLenum name); +GLAPI void APIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +GLAPI void APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat * params); +GLAPI void APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint * params); +GLAPI void APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat * params); +GLAPI void APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint * params); +GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap); +GLAPI void APIENTRY glDepthRange (GLdouble near, GLdouble far); +GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +/* GL_VERSION_1_1 */ + +GLAPI void APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void * indices); +GLAPI void APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GLAPI void APIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture); +GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint * textures); +GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint * textures); +GLAPI GLboolean APIENTRY glIsTexture (GLuint texture); + + +/* GL_VERSION_1_2 */ + +typedef void (APIENTRY PFNGLDRAWRANGEELEMENTS_PROC (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices)); +typedef void (APIENTRY PFNGLTEXIMAGE3D_PROC (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels)); +typedef void (APIENTRY PFNGLTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels)); +typedef void (APIENTRY PFNGLCOPYTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)); + +/* GL_VERSION_1_3 */ + +typedef void (APIENTRY PFNGLACTIVETEXTURE_PROC (GLenum texture)); +typedef void (APIENTRY PFNGLSAMPLECOVERAGE_PROC (GLfloat value, GLboolean invert)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE3D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE2D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE1D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLGETCOMPRESSEDTEXIMAGE_PROC (GLenum target, GLint level, void * img)); + +/* GL_VERSION_1_4 */ + +typedef void (APIENTRY PFNGLBLENDFUNCSEPARATE_PROC (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)); +typedef void (APIENTRY PFNGLMULTIDRAWARRAYS_PROC (GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount)); +typedef void (APIENTRY PFNGLMULTIDRAWELEMENTS_PROC (GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount)); +typedef void (APIENTRY PFNGLPOINTPARAMETERF_PROC (GLenum pname, GLfloat param)); +typedef void (APIENTRY PFNGLPOINTPARAMETERFV_PROC (GLenum pname, const GLfloat * params)); +typedef void (APIENTRY PFNGLPOINTPARAMETERI_PROC (GLenum pname, GLint param)); +typedef void (APIENTRY PFNGLPOINTPARAMETERIV_PROC (GLenum pname, const GLint * params)); +typedef void (APIENTRY PFNGLBLENDCOLOR_PROC (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)); +typedef void (APIENTRY PFNGLBLENDEQUATION_PROC (GLenum mode)); + +/* GL_VERSION_1_5 */ + +typedef void (APIENTRY PFNGLGENQUERIES_PROC (GLsizei n, GLuint * ids)); +typedef void (APIENTRY PFNGLDELETEQUERIES_PROC (GLsizei n, const GLuint * ids)); +typedef GLboolean (APIENTRY PFNGLISQUERY_PROC (GLuint id)); +typedef void (APIENTRY PFNGLBEGINQUERY_PROC (GLenum target, GLuint id)); +typedef void (APIENTRY PFNGLENDQUERY_PROC (GLenum target)); +typedef void (APIENTRY PFNGLGETQUERYIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTIV_PROC (GLuint id, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTUIV_PROC (GLuint id, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLBINDBUFFER_PROC (GLenum target, GLuint buffer)); +typedef void (APIENTRY PFNGLDELETEBUFFERS_PROC (GLsizei n, const GLuint * buffers)); +typedef void (APIENTRY PFNGLGENBUFFERS_PROC (GLsizei n, GLuint * buffers)); +typedef GLboolean (APIENTRY PFNGLISBUFFER_PROC (GLuint buffer)); +typedef void (APIENTRY PFNGLBUFFERDATA_PROC (GLenum target, GLsizeiptr size, const void * data, GLenum usage)); +typedef void (APIENTRY PFNGLBUFFERSUBDATA_PROC (GLenum target, GLintptr offset, GLsizeiptr size, const void * data)); +typedef void (APIENTRY PFNGLGETBUFFERSUBDATA_PROC (GLenum target, GLintptr offset, GLsizeiptr size, void * data)); +typedef void * (APIENTRY PFNGLMAPBUFFER_PROC (GLenum target, GLenum access)); +typedef GLboolean (APIENTRY PFNGLUNMAPBUFFER_PROC (GLenum target)); +typedef void (APIENTRY PFNGLGETBUFFERPARAMETERIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETBUFFERPOINTERV_PROC (GLenum target, GLenum pname, void ** params)); + +/* GL_VERSION_2_0 */ + +typedef void (APIENTRY PFNGLBLENDEQUATIONSEPARATE_PROC (GLenum modeRGB, GLenum modeAlpha)); +typedef void (APIENTRY PFNGLDRAWBUFFERS_PROC (GLsizei n, const GLenum * bufs)); +typedef void (APIENTRY PFNGLSTENCILOPSEPARATE_PROC (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)); +typedef void (APIENTRY PFNGLSTENCILFUNCSEPARATE_PROC (GLenum face, GLenum func, GLint ref, GLuint mask)); +typedef void (APIENTRY PFNGLSTENCILMASKSEPARATE_PROC (GLenum face, GLuint mask)); +typedef void (APIENTRY PFNGLATTACHSHADER_PROC (GLuint program, GLuint shader)); +typedef void (APIENTRY PFNGLBINDATTRIBLOCATION_PROC (GLuint program, GLuint index, const GLchar * name)); +typedef void (APIENTRY PFNGLCOMPILESHADER_PROC (GLuint shader)); +typedef GLuint (APIENTRY PFNGLCREATEPROGRAM_PROC (void)); +typedef GLuint (APIENTRY PFNGLCREATESHADER_PROC (GLenum type)); +typedef void (APIENTRY PFNGLDELETEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLDELETESHADER_PROC (GLuint shader)); +typedef void (APIENTRY PFNGLDETACHSHADER_PROC (GLuint program, GLuint shader)); +typedef void (APIENTRY PFNGLDISABLEVERTEXATTRIBARRAY_PROC (GLuint index)); +typedef void (APIENTRY PFNGLENABLEVERTEXATTRIBARRAY_PROC (GLuint index)); +typedef void (APIENTRY PFNGLGETACTIVEATTRIB_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORM_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLGETATTACHEDSHADERS_PROC (GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders)); +typedef GLint (APIENTRY PFNGLGETATTRIBLOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLGETPROGRAMIV_PROC (GLuint program, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETPROGRAMINFOLOG_PROC (GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog)); +typedef void (APIENTRY PFNGLGETSHADERIV_PROC (GLuint shader, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETSHADERINFOLOG_PROC (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog)); +typedef void (APIENTRY PFNGLGETSHADERSOURCE_PROC (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source)); +typedef GLint (APIENTRY PFNGLGETUNIFORMLOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLGETUNIFORMFV_PROC (GLuint program, GLint location, GLfloat * params)); +typedef void (APIENTRY PFNGLGETUNIFORMIV_PROC (GLuint program, GLint location, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBDV_PROC (GLuint index, GLenum pname, GLdouble * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBFV_PROC (GLuint index, GLenum pname, GLfloat * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIV_PROC (GLuint index, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBPOINTERV_PROC (GLuint index, GLenum pname, void ** pointer)); +typedef GLboolean (APIENTRY PFNGLISPROGRAM_PROC (GLuint program)); +typedef GLboolean (APIENTRY PFNGLISSHADER_PROC (GLuint shader)); +typedef void (APIENTRY PFNGLLINKPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLSHADERSOURCE_PROC (GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length)); +typedef void (APIENTRY PFNGLUSEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLUNIFORM1F_PROC (GLint location, GLfloat v0)); +typedef void (APIENTRY PFNGLUNIFORM2F_PROC (GLint location, GLfloat v0, GLfloat v1)); +typedef void (APIENTRY PFNGLUNIFORM3F_PROC (GLint location, GLfloat v0, GLfloat v1, GLfloat v2)); +typedef void (APIENTRY PFNGLUNIFORM4F_PROC (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)); +typedef void (APIENTRY PFNGLUNIFORM1I_PROC (GLint location, GLint v0)); +typedef void (APIENTRY PFNGLUNIFORM2I_PROC (GLint location, GLint v0, GLint v1)); +typedef void (APIENTRY PFNGLUNIFORM3I_PROC (GLint location, GLint v0, GLint v1, GLint v2)); +typedef void (APIENTRY PFNGLUNIFORM4I_PROC (GLint location, GLint v0, GLint v1, GLint v2, GLint v3)); +typedef void (APIENTRY PFNGLUNIFORM1FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM2FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM3FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM4FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM1IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM2IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM3IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM4IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLVALIDATEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1D_PROC (GLuint index, GLdouble x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1F_PROC (GLuint index, GLfloat x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1S_PROC (GLuint index, GLshort x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2D_PROC (GLuint index, GLdouble x, GLdouble y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2F_PROC (GLuint index, GLfloat x, GLfloat y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2S_PROC (GLuint index, GLshort x, GLshort y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3D_PROC (GLuint index, GLdouble x, GLdouble y, GLdouble z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3F_PROC (GLuint index, GLfloat x, GLfloat y, GLfloat z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3S_PROC (GLuint index, GLshort x, GLshort y, GLshort z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NBV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NIV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NSV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUB_PROC (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUSV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4BV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4D_PROC (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4F_PROC (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4S_PROC (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4UBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4USV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBPOINTER_PROC (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)); + +/* GL_VERSION_2_1 */ + +typedef void (APIENTRY PFNGLUNIFORMMATRIX2X3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3X2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX2X4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4X2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3X4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4X3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); + +/* GL_VERSION_3_0 */ + +typedef void (APIENTRY PFNGLCOLORMASKI_PROC (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)); +typedef void (APIENTRY PFNGLGETBOOLEANI_V_PROC (GLenum target, GLuint index, GLboolean * data)); +typedef void (APIENTRY PFNGLGETINTEGERI_V_PROC (GLenum target, GLuint index, GLint * data)); +typedef void (APIENTRY PFNGLENABLEI_PROC (GLenum target, GLuint index)); +typedef void (APIENTRY PFNGLDISABLEI_PROC (GLenum target, GLuint index)); +typedef GLboolean (APIENTRY PFNGLISENABLEDI_PROC (GLenum target, GLuint index)); +typedef void (APIENTRY PFNGLBEGINTRANSFORMFEEDBACK_PROC (GLenum primitiveMode)); +typedef void (APIENTRY PFNGLENDTRANSFORMFEEDBACK_PROC (void)); +typedef void (APIENTRY PFNGLBINDBUFFERRANGE_PROC (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)); +typedef void (APIENTRY PFNGLBINDBUFFERBASE_PROC (GLenum target, GLuint index, GLuint buffer)); +typedef void (APIENTRY PFNGLTRANSFORMFEEDBACKVARYINGS_PROC (GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode)); +typedef void (APIENTRY PFNGLGETTRANSFORMFEEDBACKVARYING_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLCLAMPCOLOR_PROC (GLenum target, GLenum clamp)); +typedef void (APIENTRY PFNGLBEGINCONDITIONALRENDER_PROC (GLuint id, GLenum mode)); +typedef void (APIENTRY PFNGLENDCONDITIONALRENDER_PROC (void)); +typedef void (APIENTRY PFNGLVERTEXATTRIBIPOINTER_PROC (GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIIV_PROC (GLuint index, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIUIV_PROC (GLuint index, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1I_PROC (GLuint index, GLint x)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2I_PROC (GLuint index, GLint x, GLint y)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3I_PROC (GLuint index, GLint x, GLint y, GLint z)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4I_PROC (GLuint index, GLint x, GLint y, GLint z, GLint w)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1UI_PROC (GLuint index, GLuint x)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2UI_PROC (GLuint index, GLuint x, GLuint y)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3UI_PROC (GLuint index, GLuint x, GLuint y, GLuint z)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UI_PROC (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4BV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4USV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLGETUNIFORMUIV_PROC (GLuint program, GLint location, GLuint * params)); +typedef void (APIENTRY PFNGLBINDFRAGDATALOCATION_PROC (GLuint program, GLuint color, const GLchar * name)); +typedef GLint (APIENTRY PFNGLGETFRAGDATALOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLUNIFORM1UI_PROC (GLint location, GLuint v0)); +typedef void (APIENTRY PFNGLUNIFORM2UI_PROC (GLint location, GLuint v0, GLuint v1)); +typedef void (APIENTRY PFNGLUNIFORM3UI_PROC (GLint location, GLuint v0, GLuint v1, GLuint v2)); +typedef void (APIENTRY PFNGLUNIFORM4UI_PROC (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)); +typedef void (APIENTRY PFNGLUNIFORM1UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM2UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM3UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM4UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLTEXPARAMETERIIV_PROC (GLenum target, GLenum pname, const GLint * params)); +typedef void (APIENTRY PFNGLTEXPARAMETERIUIV_PROC (GLenum target, GLenum pname, const GLuint * params)); +typedef void (APIENTRY PFNGLGETTEXPARAMETERIIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETTEXPARAMETERIUIV_PROC (GLenum target, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLCLEARBUFFERIV_PROC (GLenum buffer, GLint drawbuffer, const GLint * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERUIV_PROC (GLenum buffer, GLint drawbuffer, const GLuint * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERFV_PROC (GLenum buffer, GLint drawbuffer, const GLfloat * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERFI_PROC (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)); +typedef const GLubyte * (APIENTRY PFNGLGETSTRINGI_PROC (GLenum name, GLuint index)); +typedef GLboolean (APIENTRY PFNGLISRENDERBUFFER_PROC (GLuint renderbuffer)); +typedef void (APIENTRY PFNGLBINDRENDERBUFFER_PROC (GLenum target, GLuint renderbuffer)); +typedef void (APIENTRY PFNGLDELETERENDERBUFFERS_PROC (GLsizei n, const GLuint * renderbuffers)); +typedef void (APIENTRY PFNGLGENRENDERBUFFERS_PROC (GLsizei n, GLuint * renderbuffers)); +typedef void (APIENTRY PFNGLRENDERBUFFERSTORAGE_PROC (GLenum target, GLenum internalformat, GLsizei width, GLsizei height)); +typedef void (APIENTRY PFNGLGETRENDERBUFFERPARAMETERIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef GLboolean (APIENTRY PFNGLISFRAMEBUFFER_PROC (GLuint framebuffer)); +typedef void (APIENTRY PFNGLBINDFRAMEBUFFER_PROC (GLenum target, GLuint framebuffer)); +typedef void (APIENTRY PFNGLDELETEFRAMEBUFFERS_PROC (GLsizei n, const GLuint * framebuffers)); +typedef void (APIENTRY PFNGLGENFRAMEBUFFERS_PROC (GLsizei n, GLuint * framebuffers)); +typedef GLenum (APIENTRY PFNGLCHECKFRAMEBUFFERSTATUS_PROC (GLenum target)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE1D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE2D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE3D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)); +typedef void (APIENTRY PFNGLFRAMEBUFFERRENDERBUFFER_PROC (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)); +typedef void (APIENTRY PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC (GLenum target, GLenum attachment, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGENERATEMIPMAP_PROC (GLenum target)); +typedef void (APIENTRY PFNGLBLITFRAMEBUFFER_PROC (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)); +typedef void (APIENTRY PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURELAYER_PROC (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)); +typedef void * (APIENTRY PFNGLMAPBUFFERRANGE_PROC (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)); +typedef void (APIENTRY PFNGLFLUSHMAPPEDBUFFERRANGE_PROC (GLenum target, GLintptr offset, GLsizeiptr length)); +typedef void (APIENTRY PFNGLBINDVERTEXARRAY_PROC (GLuint array)); +typedef void (APIENTRY PFNGLDELETEVERTEXARRAYS_PROC (GLsizei n, const GLuint * arrays)); +typedef void (APIENTRY PFNGLGENVERTEXARRAYS_PROC (GLsizei n, GLuint * arrays)); +typedef GLboolean (APIENTRY PFNGLISVERTEXARRAY_PROC (GLuint array)); + +/* GL_VERSION_3_1 */ + +typedef void (APIENTRY PFNGLDRAWARRAYSINSTANCED_PROC (GLenum mode, GLint first, GLsizei count, GLsizei instancecount)); +typedef void (APIENTRY PFNGLDRAWELEMENTSINSTANCED_PROC (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount)); +typedef void (APIENTRY PFNGLTEXBUFFER_PROC (GLenum target, GLenum internalformat, GLuint buffer)); +typedef void (APIENTRY PFNGLPRIMITIVERESTARTINDEX_PROC (GLuint index)); +typedef void (APIENTRY PFNGLCOPYBUFFERSUBDATA_PROC (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)); +typedef void (APIENTRY PFNGLGETUNIFORMINDICES_PROC (GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMSIV_PROC (GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMNAME_PROC (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName)); +typedef GLuint (APIENTRY PFNGLGETUNIFORMBLOCKINDEX_PROC (GLuint program, const GLchar * uniformBlockName)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMBLOCKIV_PROC (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName)); +typedef void (APIENTRY PFNGLUNIFORMBLOCKBINDING_PROC (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)); + +/* GL_VERSION_3_2 */ + +typedef void (APIENTRY PFNGLDRAWELEMENTSBASEVERTEX_PROC (GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex)); +typedef void (APIENTRY PFNGLDRAWRANGEELEMENTSBASEVERTEX_PROC (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex)); +typedef void (APIENTRY PFNGLDRAWELEMENTSINSTANCEDBASEVERTEX_PROC (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex)); +typedef void (APIENTRY PFNGLMULTIDRAWELEMENTSBASEVERTEX_PROC (GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex)); +typedef void (APIENTRY PFNGLPROVOKINGVERTEX_PROC (GLenum mode)); +typedef GLsync (APIENTRY PFNGLFENCESYNC_PROC (GLenum condition, GLbitfield flags)); +typedef GLboolean (APIENTRY PFNGLISSYNC_PROC (GLsync sync)); +typedef void (APIENTRY PFNGLDELETESYNC_PROC (GLsync sync)); +typedef GLenum (APIENTRY PFNGLCLIENTWAITSYNC_PROC (GLsync sync, GLbitfield flags, GLuint64 timeout)); +typedef void (APIENTRY PFNGLWAITSYNC_PROC (GLsync sync, GLbitfield flags, GLuint64 timeout)); +typedef void (APIENTRY PFNGLGETINTEGER64V_PROC (GLenum pname, GLint64 * data)); +typedef void (APIENTRY PFNGLGETSYNCIV_PROC (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values)); +typedef void (APIENTRY PFNGLGETINTEGER64I_V_PROC (GLenum target, GLuint index, GLint64 * data)); +typedef void (APIENTRY PFNGLGETBUFFERPARAMETERI64V_PROC (GLenum target, GLenum pname, GLint64 * params)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE_PROC (GLenum target, GLenum attachment, GLuint texture, GLint level)); +typedef void (APIENTRY PFNGLTEXIMAGE2DMULTISAMPLE_PROC (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations)); +typedef void (APIENTRY PFNGLTEXIMAGE3DMULTISAMPLE_PROC (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)); +typedef void (APIENTRY PFNGLGETMULTISAMPLEFV_PROC (GLenum pname, GLuint index, GLfloat * val)); +typedef void (APIENTRY PFNGLSAMPLEMASKI_PROC (GLuint maskNumber, GLbitfield mask)); + +/* GL_VERSION_3_3 */ + +typedef void (APIENTRY PFNGLBINDFRAGDATALOCATIONINDEXED_PROC (GLuint program, GLuint colorNumber, GLuint index, const GLchar * name)); +typedef GLint (APIENTRY PFNGLGETFRAGDATAINDEX_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLGENSAMPLERS_PROC (GLsizei count, GLuint * samplers)); +typedef void (APIENTRY PFNGLDELETESAMPLERS_PROC (GLsizei count, const GLuint * samplers)); +typedef GLboolean (APIENTRY PFNGLISSAMPLER_PROC (GLuint sampler)); +typedef void (APIENTRY PFNGLBINDSAMPLER_PROC (GLuint unit, GLuint sampler)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERI_PROC (GLuint sampler, GLenum pname, GLint param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERIV_PROC (GLuint sampler, GLenum pname, const GLint * param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERF_PROC (GLuint sampler, GLenum pname, GLfloat param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERFV_PROC (GLuint sampler, GLenum pname, const GLfloat * param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERIIV_PROC (GLuint sampler, GLenum pname, const GLint * param)); +typedef void (APIENTRY PFNGLSAMPLERPARAMETERIUIV_PROC (GLuint sampler, GLenum pname, const GLuint * param)); +typedef void (APIENTRY PFNGLGETSAMPLERPARAMETERIV_PROC (GLuint sampler, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETSAMPLERPARAMETERIIV_PROC (GLuint sampler, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETSAMPLERPARAMETERFV_PROC (GLuint sampler, GLenum pname, GLfloat * params)); +typedef void (APIENTRY PFNGLGETSAMPLERPARAMETERIUIV_PROC (GLuint sampler, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLQUERYCOUNTER_PROC (GLuint id, GLenum target)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTI64V_PROC (GLuint id, GLenum pname, GLint64 * params)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTUI64V_PROC (GLuint id, GLenum pname, GLuint64 * params)); +typedef void (APIENTRY PFNGLVERTEXATTRIBDIVISOR_PROC (GLuint index, GLuint divisor)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP1UI_PROC (GLuint index, GLenum type, GLboolean normalized, GLuint value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP1UIV_PROC (GLuint index, GLenum type, GLboolean normalized, const GLuint * value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP2UI_PROC (GLuint index, GLenum type, GLboolean normalized, GLuint value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP2UIV_PROC (GLuint index, GLenum type, GLboolean normalized, const GLuint * value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP3UI_PROC (GLuint index, GLenum type, GLboolean normalized, GLuint value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP3UIV_PROC (GLuint index, GLenum type, GLboolean normalized, const GLuint * value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP4UI_PROC (GLuint index, GLenum type, GLboolean normalized, GLuint value)); +typedef void (APIENTRY PFNGLVERTEXATTRIBP4UIV_PROC (GLuint index, GLenum type, GLboolean normalized, const GLuint * value)); + +struct OpenGLBindings +{ + + /* GL_VERSION_1_2 */ + + PFNGLDRAWRANGEELEMENTS_PROC* glDrawRangeElements; + PFNGLTEXIMAGE3D_PROC* glTexImage3D; + PFNGLTEXSUBIMAGE3D_PROC* glTexSubImage3D; + PFNGLCOPYTEXSUBIMAGE3D_PROC* glCopyTexSubImage3D; + + /* GL_VERSION_1_3 */ + + PFNGLACTIVETEXTURE_PROC* glActiveTexture; + PFNGLSAMPLECOVERAGE_PROC* glSampleCoverage; + PFNGLCOMPRESSEDTEXIMAGE3D_PROC* glCompressedTexImage3D; + PFNGLCOMPRESSEDTEXIMAGE2D_PROC* glCompressedTexImage2D; + PFNGLCOMPRESSEDTEXIMAGE1D_PROC* glCompressedTexImage1D; + PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC* glCompressedTexSubImage3D; + PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC* glCompressedTexSubImage2D; + PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC* glCompressedTexSubImage1D; + PFNGLGETCOMPRESSEDTEXIMAGE_PROC* glGetCompressedTexImage; + + /* GL_VERSION_1_4 */ + + PFNGLBLENDFUNCSEPARATE_PROC* glBlendFuncSeparate; + PFNGLMULTIDRAWARRAYS_PROC* glMultiDrawArrays; + PFNGLMULTIDRAWELEMENTS_PROC* glMultiDrawElements; + PFNGLPOINTPARAMETERF_PROC* glPointParameterf; + PFNGLPOINTPARAMETERFV_PROC* glPointParameterfv; + PFNGLPOINTPARAMETERI_PROC* glPointParameteri; + PFNGLPOINTPARAMETERIV_PROC* glPointParameteriv; + PFNGLBLENDCOLOR_PROC* glBlendColor; + PFNGLBLENDEQUATION_PROC* glBlendEquation; + + /* GL_VERSION_1_5 */ + + PFNGLGENQUERIES_PROC* glGenQueries; + PFNGLDELETEQUERIES_PROC* glDeleteQueries; + PFNGLISQUERY_PROC* glIsQuery; + PFNGLBEGINQUERY_PROC* glBeginQuery; + PFNGLENDQUERY_PROC* glEndQuery; + PFNGLGETQUERYIV_PROC* glGetQueryiv; + PFNGLGETQUERYOBJECTIV_PROC* glGetQueryObjectiv; + PFNGLGETQUERYOBJECTUIV_PROC* glGetQueryObjectuiv; + PFNGLBINDBUFFER_PROC* glBindBuffer; + PFNGLDELETEBUFFERS_PROC* glDeleteBuffers; + PFNGLGENBUFFERS_PROC* glGenBuffers; + PFNGLISBUFFER_PROC* glIsBuffer; + PFNGLBUFFERDATA_PROC* glBufferData; + PFNGLBUFFERSUBDATA_PROC* glBufferSubData; + PFNGLGETBUFFERSUBDATA_PROC* glGetBufferSubData; + PFNGLMAPBUFFER_PROC* glMapBuffer; + PFNGLUNMAPBUFFER_PROC* glUnmapBuffer; + PFNGLGETBUFFERPARAMETERIV_PROC* glGetBufferParameteriv; + PFNGLGETBUFFERPOINTERV_PROC* glGetBufferPointerv; + + /* GL_VERSION_2_0 */ + + PFNGLBLENDEQUATIONSEPARATE_PROC* glBlendEquationSeparate; + PFNGLDRAWBUFFERS_PROC* glDrawBuffers; + PFNGLSTENCILOPSEPARATE_PROC* glStencilOpSeparate; + PFNGLSTENCILFUNCSEPARATE_PROC* glStencilFuncSeparate; + PFNGLSTENCILMASKSEPARATE_PROC* glStencilMaskSeparate; + PFNGLATTACHSHADER_PROC* glAttachShader; + PFNGLBINDATTRIBLOCATION_PROC* glBindAttribLocation; + PFNGLCOMPILESHADER_PROC* glCompileShader; + PFNGLCREATEPROGRAM_PROC* glCreateProgram; + PFNGLCREATESHADER_PROC* glCreateShader; + PFNGLDELETEPROGRAM_PROC* glDeleteProgram; + PFNGLDELETESHADER_PROC* glDeleteShader; + PFNGLDETACHSHADER_PROC* glDetachShader; + PFNGLDISABLEVERTEXATTRIBARRAY_PROC* glDisableVertexAttribArray; + PFNGLENABLEVERTEXATTRIBARRAY_PROC* glEnableVertexAttribArray; + PFNGLGETACTIVEATTRIB_PROC* glGetActiveAttrib; + PFNGLGETACTIVEUNIFORM_PROC* glGetActiveUniform; + PFNGLGETATTACHEDSHADERS_PROC* glGetAttachedShaders; + PFNGLGETATTRIBLOCATION_PROC* glGetAttribLocation; + PFNGLGETPROGRAMIV_PROC* glGetProgramiv; + PFNGLGETPROGRAMINFOLOG_PROC* glGetProgramInfoLog; + PFNGLGETSHADERIV_PROC* glGetShaderiv; + PFNGLGETSHADERINFOLOG_PROC* glGetShaderInfoLog; + PFNGLGETSHADERSOURCE_PROC* glGetShaderSource; + PFNGLGETUNIFORMLOCATION_PROC* glGetUniformLocation; + PFNGLGETUNIFORMFV_PROC* glGetUniformfv; + PFNGLGETUNIFORMIV_PROC* glGetUniformiv; + PFNGLGETVERTEXATTRIBDV_PROC* glGetVertexAttribdv; + PFNGLGETVERTEXATTRIBFV_PROC* glGetVertexAttribfv; + PFNGLGETVERTEXATTRIBIV_PROC* glGetVertexAttribiv; + PFNGLGETVERTEXATTRIBPOINTERV_PROC* glGetVertexAttribPointerv; + PFNGLISPROGRAM_PROC* glIsProgram; + PFNGLISSHADER_PROC* glIsShader; + PFNGLLINKPROGRAM_PROC* glLinkProgram; + PFNGLSHADERSOURCE_PROC* glShaderSource; + PFNGLUSEPROGRAM_PROC* glUseProgram; + PFNGLUNIFORM1F_PROC* glUniform1f; + PFNGLUNIFORM2F_PROC* glUniform2f; + PFNGLUNIFORM3F_PROC* glUniform3f; + PFNGLUNIFORM4F_PROC* glUniform4f; + PFNGLUNIFORM1I_PROC* glUniform1i; + PFNGLUNIFORM2I_PROC* glUniform2i; + PFNGLUNIFORM3I_PROC* glUniform3i; + PFNGLUNIFORM4I_PROC* glUniform4i; + PFNGLUNIFORM1FV_PROC* glUniform1fv; + PFNGLUNIFORM2FV_PROC* glUniform2fv; + PFNGLUNIFORM3FV_PROC* glUniform3fv; + PFNGLUNIFORM4FV_PROC* glUniform4fv; + PFNGLUNIFORM1IV_PROC* glUniform1iv; + PFNGLUNIFORM2IV_PROC* glUniform2iv; + PFNGLUNIFORM3IV_PROC* glUniform3iv; + PFNGLUNIFORM4IV_PROC* glUniform4iv; + PFNGLUNIFORMMATRIX2FV_PROC* glUniformMatrix2fv; + PFNGLUNIFORMMATRIX3FV_PROC* glUniformMatrix3fv; + PFNGLUNIFORMMATRIX4FV_PROC* glUniformMatrix4fv; + PFNGLVALIDATEPROGRAM_PROC* glValidateProgram; + PFNGLVERTEXATTRIB1D_PROC* glVertexAttrib1d; + PFNGLVERTEXATTRIB1DV_PROC* glVertexAttrib1dv; + PFNGLVERTEXATTRIB1F_PROC* glVertexAttrib1f; + PFNGLVERTEXATTRIB1FV_PROC* glVertexAttrib1fv; + PFNGLVERTEXATTRIB1S_PROC* glVertexAttrib1s; + PFNGLVERTEXATTRIB1SV_PROC* glVertexAttrib1sv; + PFNGLVERTEXATTRIB2D_PROC* glVertexAttrib2d; + PFNGLVERTEXATTRIB2DV_PROC* glVertexAttrib2dv; + PFNGLVERTEXATTRIB2F_PROC* glVertexAttrib2f; + PFNGLVERTEXATTRIB2FV_PROC* glVertexAttrib2fv; + PFNGLVERTEXATTRIB2S_PROC* glVertexAttrib2s; + PFNGLVERTEXATTRIB2SV_PROC* glVertexAttrib2sv; + PFNGLVERTEXATTRIB3D_PROC* glVertexAttrib3d; + PFNGLVERTEXATTRIB3DV_PROC* glVertexAttrib3dv; + PFNGLVERTEXATTRIB3F_PROC* glVertexAttrib3f; + PFNGLVERTEXATTRIB3FV_PROC* glVertexAttrib3fv; + PFNGLVERTEXATTRIB3S_PROC* glVertexAttrib3s; + PFNGLVERTEXATTRIB3SV_PROC* glVertexAttrib3sv; + PFNGLVERTEXATTRIB4NBV_PROC* glVertexAttrib4Nbv; + PFNGLVERTEXATTRIB4NIV_PROC* glVertexAttrib4Niv; + PFNGLVERTEXATTRIB4NSV_PROC* glVertexAttrib4Nsv; + PFNGLVERTEXATTRIB4NUB_PROC* glVertexAttrib4Nub; + PFNGLVERTEXATTRIB4NUBV_PROC* glVertexAttrib4Nubv; + PFNGLVERTEXATTRIB4NUIV_PROC* glVertexAttrib4Nuiv; + PFNGLVERTEXATTRIB4NUSV_PROC* glVertexAttrib4Nusv; + PFNGLVERTEXATTRIB4BV_PROC* glVertexAttrib4bv; + PFNGLVERTEXATTRIB4D_PROC* glVertexAttrib4d; + PFNGLVERTEXATTRIB4DV_PROC* glVertexAttrib4dv; + PFNGLVERTEXATTRIB4F_PROC* glVertexAttrib4f; + PFNGLVERTEXATTRIB4FV_PROC* glVertexAttrib4fv; + PFNGLVERTEXATTRIB4IV_PROC* glVertexAttrib4iv; + PFNGLVERTEXATTRIB4S_PROC* glVertexAttrib4s; + PFNGLVERTEXATTRIB4SV_PROC* glVertexAttrib4sv; + PFNGLVERTEXATTRIB4UBV_PROC* glVertexAttrib4ubv; + PFNGLVERTEXATTRIB4UIV_PROC* glVertexAttrib4uiv; + PFNGLVERTEXATTRIB4USV_PROC* glVertexAttrib4usv; + PFNGLVERTEXATTRIBPOINTER_PROC* glVertexAttribPointer; + + /* GL_VERSION_2_1 */ + + PFNGLUNIFORMMATRIX2X3FV_PROC* glUniformMatrix2x3fv; + PFNGLUNIFORMMATRIX3X2FV_PROC* glUniformMatrix3x2fv; + PFNGLUNIFORMMATRIX2X4FV_PROC* glUniformMatrix2x4fv; + PFNGLUNIFORMMATRIX4X2FV_PROC* glUniformMatrix4x2fv; + PFNGLUNIFORMMATRIX3X4FV_PROC* glUniformMatrix3x4fv; + PFNGLUNIFORMMATRIX4X3FV_PROC* glUniformMatrix4x3fv; + + /* GL_VERSION_3_0 */ + + PFNGLCOLORMASKI_PROC* glColorMaski; + PFNGLGETBOOLEANI_V_PROC* glGetBooleani_v; + PFNGLGETINTEGERI_V_PROC* glGetIntegeri_v; + PFNGLENABLEI_PROC* glEnablei; + PFNGLDISABLEI_PROC* glDisablei; + PFNGLISENABLEDI_PROC* glIsEnabledi; + PFNGLBEGINTRANSFORMFEEDBACK_PROC* glBeginTransformFeedback; + PFNGLENDTRANSFORMFEEDBACK_PROC* glEndTransformFeedback; + PFNGLBINDBUFFERRANGE_PROC* glBindBufferRange; + PFNGLBINDBUFFERBASE_PROC* glBindBufferBase; + PFNGLTRANSFORMFEEDBACKVARYINGS_PROC* glTransformFeedbackVaryings; + PFNGLGETTRANSFORMFEEDBACKVARYING_PROC* glGetTransformFeedbackVarying; + PFNGLCLAMPCOLOR_PROC* glClampColor; + PFNGLBEGINCONDITIONALRENDER_PROC* glBeginConditionalRender; + PFNGLENDCONDITIONALRENDER_PROC* glEndConditionalRender; + PFNGLVERTEXATTRIBIPOINTER_PROC* glVertexAttribIPointer; + PFNGLGETVERTEXATTRIBIIV_PROC* glGetVertexAttribIiv; + PFNGLGETVERTEXATTRIBIUIV_PROC* glGetVertexAttribIuiv; + PFNGLVERTEXATTRIBI1I_PROC* glVertexAttribI1i; + PFNGLVERTEXATTRIBI2I_PROC* glVertexAttribI2i; + PFNGLVERTEXATTRIBI3I_PROC* glVertexAttribI3i; + PFNGLVERTEXATTRIBI4I_PROC* glVertexAttribI4i; + PFNGLVERTEXATTRIBI1UI_PROC* glVertexAttribI1ui; + PFNGLVERTEXATTRIBI2UI_PROC* glVertexAttribI2ui; + PFNGLVERTEXATTRIBI3UI_PROC* glVertexAttribI3ui; + PFNGLVERTEXATTRIBI4UI_PROC* glVertexAttribI4ui; + PFNGLVERTEXATTRIBI1IV_PROC* glVertexAttribI1iv; + PFNGLVERTEXATTRIBI2IV_PROC* glVertexAttribI2iv; + PFNGLVERTEXATTRIBI3IV_PROC* glVertexAttribI3iv; + PFNGLVERTEXATTRIBI4IV_PROC* glVertexAttribI4iv; + PFNGLVERTEXATTRIBI1UIV_PROC* glVertexAttribI1uiv; + PFNGLVERTEXATTRIBI2UIV_PROC* glVertexAttribI2uiv; + PFNGLVERTEXATTRIBI3UIV_PROC* glVertexAttribI3uiv; + PFNGLVERTEXATTRIBI4UIV_PROC* glVertexAttribI4uiv; + PFNGLVERTEXATTRIBI4BV_PROC* glVertexAttribI4bv; + PFNGLVERTEXATTRIBI4SV_PROC* glVertexAttribI4sv; + PFNGLVERTEXATTRIBI4UBV_PROC* glVertexAttribI4ubv; + PFNGLVERTEXATTRIBI4USV_PROC* glVertexAttribI4usv; + PFNGLGETUNIFORMUIV_PROC* glGetUniformuiv; + PFNGLBINDFRAGDATALOCATION_PROC* glBindFragDataLocation; + PFNGLGETFRAGDATALOCATION_PROC* glGetFragDataLocation; + PFNGLUNIFORM1UI_PROC* glUniform1ui; + PFNGLUNIFORM2UI_PROC* glUniform2ui; + PFNGLUNIFORM3UI_PROC* glUniform3ui; + PFNGLUNIFORM4UI_PROC* glUniform4ui; + PFNGLUNIFORM1UIV_PROC* glUniform1uiv; + PFNGLUNIFORM2UIV_PROC* glUniform2uiv; + PFNGLUNIFORM3UIV_PROC* glUniform3uiv; + PFNGLUNIFORM4UIV_PROC* glUniform4uiv; + PFNGLTEXPARAMETERIIV_PROC* glTexParameterIiv; + PFNGLTEXPARAMETERIUIV_PROC* glTexParameterIuiv; + PFNGLGETTEXPARAMETERIIV_PROC* glGetTexParameterIiv; + PFNGLGETTEXPARAMETERIUIV_PROC* glGetTexParameterIuiv; + PFNGLCLEARBUFFERIV_PROC* glClearBufferiv; + PFNGLCLEARBUFFERUIV_PROC* glClearBufferuiv; + PFNGLCLEARBUFFERFV_PROC* glClearBufferfv; + PFNGLCLEARBUFFERFI_PROC* glClearBufferfi; + PFNGLGETSTRINGI_PROC* glGetStringi; + PFNGLISRENDERBUFFER_PROC* glIsRenderbuffer; + PFNGLBINDRENDERBUFFER_PROC* glBindRenderbuffer; + PFNGLDELETERENDERBUFFERS_PROC* glDeleteRenderbuffers; + PFNGLGENRENDERBUFFERS_PROC* glGenRenderbuffers; + PFNGLRENDERBUFFERSTORAGE_PROC* glRenderbufferStorage; + PFNGLGETRENDERBUFFERPARAMETERIV_PROC* glGetRenderbufferParameteriv; + PFNGLISFRAMEBUFFER_PROC* glIsFramebuffer; + PFNGLBINDFRAMEBUFFER_PROC* glBindFramebuffer; + PFNGLDELETEFRAMEBUFFERS_PROC* glDeleteFramebuffers; + PFNGLGENFRAMEBUFFERS_PROC* glGenFramebuffers; + PFNGLCHECKFRAMEBUFFERSTATUS_PROC* glCheckFramebufferStatus; + PFNGLFRAMEBUFFERTEXTURE1D_PROC* glFramebufferTexture1D; + PFNGLFRAMEBUFFERTEXTURE2D_PROC* glFramebufferTexture2D; + PFNGLFRAMEBUFFERTEXTURE3D_PROC* glFramebufferTexture3D; + PFNGLFRAMEBUFFERRENDERBUFFER_PROC* glFramebufferRenderbuffer; + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC* glGetFramebufferAttachmentParameteriv; + PFNGLGENERATEMIPMAP_PROC* glGenerateMipmap; + PFNGLBLITFRAMEBUFFER_PROC* glBlitFramebuffer; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC* glRenderbufferStorageMultisample; + PFNGLFRAMEBUFFERTEXTURELAYER_PROC* glFramebufferTextureLayer; + PFNGLMAPBUFFERRANGE_PROC* glMapBufferRange; + PFNGLFLUSHMAPPEDBUFFERRANGE_PROC* glFlushMappedBufferRange; + PFNGLBINDVERTEXARRAY_PROC* glBindVertexArray; + PFNGLDELETEVERTEXARRAYS_PROC* glDeleteVertexArrays; + PFNGLGENVERTEXARRAYS_PROC* glGenVertexArrays; + PFNGLISVERTEXARRAY_PROC* glIsVertexArray; + + /* GL_VERSION_3_1 */ + + PFNGLDRAWARRAYSINSTANCED_PROC* glDrawArraysInstanced; + PFNGLDRAWELEMENTSINSTANCED_PROC* glDrawElementsInstanced; + PFNGLTEXBUFFER_PROC* glTexBuffer; + PFNGLPRIMITIVERESTARTINDEX_PROC* glPrimitiveRestartIndex; + PFNGLCOPYBUFFERSUBDATA_PROC* glCopyBufferSubData; + PFNGLGETUNIFORMINDICES_PROC* glGetUniformIndices; + PFNGLGETACTIVEUNIFORMSIV_PROC* glGetActiveUniformsiv; + PFNGLGETACTIVEUNIFORMNAME_PROC* glGetActiveUniformName; + PFNGLGETUNIFORMBLOCKINDEX_PROC* glGetUniformBlockIndex; + PFNGLGETACTIVEUNIFORMBLOCKIV_PROC* glGetActiveUniformBlockiv; + PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC* glGetActiveUniformBlockName; + PFNGLUNIFORMBLOCKBINDING_PROC* glUniformBlockBinding; + + /* GL_VERSION_3_2 */ + + PFNGLDRAWELEMENTSBASEVERTEX_PROC* glDrawElementsBaseVertex; + PFNGLDRAWRANGEELEMENTSBASEVERTEX_PROC* glDrawRangeElementsBaseVertex; + PFNGLDRAWELEMENTSINSTANCEDBASEVERTEX_PROC* glDrawElementsInstancedBaseVertex; + PFNGLMULTIDRAWELEMENTSBASEVERTEX_PROC* glMultiDrawElementsBaseVertex; + PFNGLPROVOKINGVERTEX_PROC* glProvokingVertex; + PFNGLFENCESYNC_PROC* glFenceSync; + PFNGLISSYNC_PROC* glIsSync; + PFNGLDELETESYNC_PROC* glDeleteSync; + PFNGLCLIENTWAITSYNC_PROC* glClientWaitSync; + PFNGLWAITSYNC_PROC* glWaitSync; + PFNGLGETINTEGER64V_PROC* glGetInteger64v; + PFNGLGETSYNCIV_PROC* glGetSynciv; + PFNGLGETINTEGER64I_V_PROC* glGetInteger64i_v; + PFNGLGETBUFFERPARAMETERI64V_PROC* glGetBufferParameteri64v; + PFNGLFRAMEBUFFERTEXTURE_PROC* glFramebufferTexture; + PFNGLTEXIMAGE2DMULTISAMPLE_PROC* glTexImage2DMultisample; + PFNGLTEXIMAGE3DMULTISAMPLE_PROC* glTexImage3DMultisample; + PFNGLGETMULTISAMPLEFV_PROC* glGetMultisamplefv; + PFNGLSAMPLEMASKI_PROC* glSampleMaski; + + /* GL_VERSION_3_3 */ + + PFNGLBINDFRAGDATALOCATIONINDEXED_PROC* glBindFragDataLocationIndexed; + PFNGLGETFRAGDATAINDEX_PROC* glGetFragDataIndex; + PFNGLGENSAMPLERS_PROC* glGenSamplers; + PFNGLDELETESAMPLERS_PROC* glDeleteSamplers; + PFNGLISSAMPLER_PROC* glIsSampler; + PFNGLBINDSAMPLER_PROC* glBindSampler; + PFNGLSAMPLERPARAMETERI_PROC* glSamplerParameteri; + PFNGLSAMPLERPARAMETERIV_PROC* glSamplerParameteriv; + PFNGLSAMPLERPARAMETERF_PROC* glSamplerParameterf; + PFNGLSAMPLERPARAMETERFV_PROC* glSamplerParameterfv; + PFNGLSAMPLERPARAMETERIIV_PROC* glSamplerParameterIiv; + PFNGLSAMPLERPARAMETERIUIV_PROC* glSamplerParameterIuiv; + PFNGLGETSAMPLERPARAMETERIV_PROC* glGetSamplerParameteriv; + PFNGLGETSAMPLERPARAMETERIIV_PROC* glGetSamplerParameterIiv; + PFNGLGETSAMPLERPARAMETERFV_PROC* glGetSamplerParameterfv; + PFNGLGETSAMPLERPARAMETERIUIV_PROC* glGetSamplerParameterIuiv; + PFNGLQUERYCOUNTER_PROC* glQueryCounter; + PFNGLGETQUERYOBJECTI64V_PROC* glGetQueryObjecti64v; + PFNGLGETQUERYOBJECTUI64V_PROC* glGetQueryObjectui64v; + PFNGLVERTEXATTRIBDIVISOR_PROC* glVertexAttribDivisor; + PFNGLVERTEXATTRIBP1UI_PROC* glVertexAttribP1ui; + PFNGLVERTEXATTRIBP1UIV_PROC* glVertexAttribP1uiv; + PFNGLVERTEXATTRIBP2UI_PROC* glVertexAttribP2ui; + PFNGLVERTEXATTRIBP2UIV_PROC* glVertexAttribP2uiv; + PFNGLVERTEXATTRIBP3UI_PROC* glVertexAttribP3ui; + PFNGLVERTEXATTRIBP3UIV_PROC* glVertexAttribP3uiv; + PFNGLVERTEXATTRIBP4UI_PROC* glVertexAttribP4ui; + PFNGLVERTEXATTRIBP4UIV_PROC* glVertexAttribP4uiv; +}; + +typedef struct OpenGLBindings OpenGLBindings; + +/* --------------------------- CATEGORY DEFINES ------------------------------ */ + +#define GL_VERSION_1_0 +#define GL_VERSION_1_1 +#define GL_VERSION_1_2 +#define GL_VERSION_1_3 +#define GL_VERSION_1_4 +#define GL_VERSION_1_5 +#define GL_VERSION_2_0 +#define GL_VERSION_2_1 +#define GL_VERSION_3_0 +#define GL_VERSION_3_1 +#define GL_VERSION_3_2 +#define GL_VERSION_3_3 + +/* ---------------------- Flags for optional extensions ---------------------- */ + + + +struct GLFWwindow; +typedef struct GLFWwindow GLFWwindow; + +int flextInit(GLFWwindow* window, OpenGLBindings *bindings); + +#define FLEXT_MAJOR_VERSION 3 +#define FLEXT_MINOR_VERSION 3 +#define FLEXT_CORE_PROFILE 1 + +#ifdef __cplusplus +} +#endif + +#endif /* _gl_h_ */ diff --git a/examples/k22v4l/src/frame_listener_impl.cpp b/examples/k22v4l/src/frame_listener_impl.cpp new file mode 100644 index 000000000..b16503be7 --- /dev/null +++ b/examples/k22v4l/src/frame_listener_impl.cpp @@ -0,0 +1,149 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include + +namespace libfreenect2 +{ + +FrameListener::~FrameListener() {} + +class SyncMultiFrameListenerImpl +{ +public: + libfreenect2::mutex mutex_; + libfreenect2::condition_variable condition_; + FrameMap next_frame_; + + const unsigned int subscribed_frame_types_; + unsigned int ready_frame_types_; + + SyncMultiFrameListenerImpl(unsigned int frame_types) : + subscribed_frame_types_(frame_types), + ready_frame_types_(0) + { + } + + bool hasNewFrame() const + { + return ready_frame_types_ == subscribed_frame_types_; + } +}; + +SyncMultiFrameListener::SyncMultiFrameListener(unsigned int frame_types) : + impl_(new SyncMultiFrameListenerImpl(frame_types)) +{ +} + +SyncMultiFrameListener::~SyncMultiFrameListener() +{ + delete impl_; +} + +bool SyncMultiFrameListener::hasNewFrame() const +{ + libfreenect2::unique_lock l(impl_->mutex_); + + return impl_->hasNewFrame(); +} + +#ifdef LIBFREENECT2_THREADING_STDLIB +bool SyncMultiFrameListener::waitForNewFrame(FrameMap &frame, int milliseconds) +{ + libfreenect2::unique_lock l(impl_->mutex_); + + auto predicate = std::bind(&SyncMultiFrameListenerImpl::hasNewFrame, impl_); + + if(impl_->condition_.wait_for(l, std::chrono::milliseconds(milliseconds), predicate)) + { + frame = impl_->next_frame_; + impl_->next_frame_.clear(); + impl_->ready_frame_types_ = 0; + + return true; + } + else + { + return false; + } +} +#endif // LIBFREENECT2_THREADING_STDLIB + +void SyncMultiFrameListener::waitForNewFrame(FrameMap &frame) +{ + libfreenect2::unique_lock l(impl_->mutex_); + + while(!impl_->hasNewFrame()) + { + WAIT_CONDITION(impl_->condition_, impl_->mutex_, l) + } + + frame = impl_->next_frame_; + impl_->next_frame_.clear(); + impl_->ready_frame_types_ = 0; +} + +void SyncMultiFrameListener::release(FrameMap &frame) +{ + for(FrameMap::iterator it = frame.begin(); it != frame.end(); ++it) + { + delete it->second; + it->second = 0; + } + + frame.clear(); +} + +bool SyncMultiFrameListener::onNewFrame(Frame::Type type, Frame *frame) +{ + if((impl_->subscribed_frame_types_ & type) == 0) return false; + + { + libfreenect2::lock_guard l(impl_->mutex_); + + FrameMap::iterator it = impl_->next_frame_.find(type); + + if(it != impl_->next_frame_.end()) + { + // replace frame + delete it->second; + it->second = frame; + } + else + { + impl_->next_frame_[type] = frame; + } + + impl_->ready_frame_types_ |= type; + } + + impl_->condition_.notify_one(); + + return true; +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/generate_resources.cpp b/examples/k22v4l/src/generate_resources.cpp new file mode 100644 index 000000000..475479309 --- /dev/null +++ b/examples/k22v4l/src/generate_resources.cpp @@ -0,0 +1,83 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include +#include + +void dumpFile(const std::string& filename) +{ + using namespace std; + + ifstream f(filename.c_str(), ios::binary); + + unsigned char buffer[1024]; + + while(!f.eof()) + { + f.read(reinterpret_cast(buffer), sizeof(buffer)); + size_t n = f.gcount(); + + if(n == 0) break; + + cout << hex << setw(2) << setfill('0') << " "; + for(size_t i = 0; i < n; ++i) + { + cout << "0x" << int(buffer[i]) << ", "; + } + cout << endl; + } + cout << dec; +} + +int main(int argc, char **argv) +{ + if(argc < 2) return -1; + + using namespace std; + + string basefolder(argv[1]); + + for(int i = 2; i < argc; ++i) + { + cout << "unsigned char resource" << (i - 2) << "[] = {" << endl; + dumpFile(basefolder + "/" + argv[i]); + cout << "};" << endl; + } + + cout << "ResourceDescriptor resource_descriptors[] = {" << endl; + + for(int i = 2; i < argc; ++i) + { + cout << " { \"" << argv[i] << "\", resource" << (i - 2) << ", " << "sizeof(resource" << (i - 2) << ") }," << endl; + } + + cout << "};" << endl; + cout << "int resource_descriptors_length = " << (argc - 2) << ";" << endl; + + return 0; +} diff --git a/examples/k22v4l/src/libfreenect2.cpp b/examples/k22v4l/src/libfreenect2.cpp new file mode 100644 index 000000000..ba57cf9a0 --- /dev/null +++ b/examples/k22v4l/src/libfreenect2.cpp @@ -0,0 +1,765 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace libfreenect2 +{ +using namespace libfreenect2; +using namespace libfreenect2::usb; +using namespace libfreenect2::protocol; + +class Freenect2DeviceImpl : public Freenect2Device +{ +private: + enum State + { + Created, + Open, + Streaming, + Closed + }; + + State state_; + bool has_usb_interfaces_; + + Freenect2Impl *context_; + libusb_device *usb_device_; + libusb_device_handle *usb_device_handle_; + + BulkTransferPool rgb_transfer_pool_; + IsoTransferPool ir_transfer_pool_; + + UsbControl usb_control_; + CommandTransaction command_tx_; + int command_seq_; + + const PacketPipeline *pipeline_; + std::string serial_, firmware_; + Freenect2Device::IrCameraParams ir_camera_params_; + Freenect2Device::ColorCameraParams rgb_camera_params_; +public: + Freenect2DeviceImpl(Freenect2Impl *context, const PacketPipeline *pipeline, libusb_device *usb_device, libusb_device_handle *usb_device_handle, const std::string &serial); + virtual ~Freenect2DeviceImpl(); + + bool isSameUsbDevice(libusb_device* other); + + virtual std::string getSerialNumber(); + virtual std::string getFirmwareVersion(); + + virtual Freenect2Device::ColorCameraParams getColorCameraParams(); + virtual Freenect2Device::IrCameraParams getIrCameraParams(); + + int nextCommandSeq(); + + bool open(); + + virtual void setColorFrameListener(libfreenect2::FrameListener* rgb_frame_listener); + virtual void setIrAndDepthFrameListener(libfreenect2::FrameListener* ir_frame_listener); + virtual void start(); + virtual void stop(); + virtual void close(); +}; + +struct PrintBusAndDevice +{ + libusb_device *dev_; + + PrintBusAndDevice(libusb_device *dev) : dev_(dev) {} +}; + +std::ostream &operator<<(std::ostream &out, const PrintBusAndDevice& dev) +{ + out << "@" << int(libusb_get_bus_number(dev.dev_)) << ":" << int(libusb_get_device_address(dev.dev_)); + return out; +} + +class Freenect2Impl +{ +private: + bool managed_usb_context_; + libusb_context *usb_context_; + EventLoop usb_event_loop_; +public: + struct UsbDeviceWithSerial + { + libusb_device *dev; + std::string serial; + }; + typedef std::vector UsbDeviceVector; + typedef std::vector DeviceVector; + + bool has_device_enumeration_; + UsbDeviceVector enumerated_devices_; + DeviceVector devices_; + + Freenect2Impl(void *usb_context) : + managed_usb_context_(usb_context == 0), + usb_context_(reinterpret_cast(usb_context)), + has_device_enumeration_(false) + { + if(managed_usb_context_) + { + int r = libusb_init(&usb_context_); + // TODO: error handling + if(r != 0) + { + std::cout << "[Freenect2Impl] failed to create usb context!" << std::endl; + } + } + + usb_event_loop_.start(usb_context_); + } + + ~Freenect2Impl() + { + clearDevices(); + clearDeviceEnumeration(); + + usb_event_loop_.stop(); + + if(managed_usb_context_ && usb_context_ != 0) + { + libusb_exit(usb_context_); + usb_context_ = 0; + } + } + + void addDevice(Freenect2DeviceImpl *device) + { + devices_.push_back(device); + } + + void removeDevice(Freenect2DeviceImpl *device) + { + DeviceVector::iterator it = std::find(devices_.begin(), devices_.end(), device); + + if(it != devices_.end()) + { + devices_.erase(it); + } + else + { + std::cout << "[Freenect2Impl] tried to remove device, which is not in the internal device list!" << std::endl; + } + } + + bool tryGetDevice(libusb_device *usb_device, Freenect2DeviceImpl **device) + { + for(DeviceVector::iterator it = devices_.begin(); it != devices_.end(); ++it) + { + if((*it)->isSameUsbDevice(usb_device)) + { + *device = *it; + return true; + } + } + + return false; + } + + void clearDevices() + { + DeviceVector devices(devices_.begin(), devices_.end()); + + for(DeviceVector::iterator it = devices.begin(); it != devices.end(); ++it) + { + delete (*it); + } + + if(!devices_.empty()) + { + std::cout << "[Freenect2Impl] after deleting all devices the internal device list should be empty!" << std::endl; + } + } + + void clearDeviceEnumeration() + { + // free enumerated device pointers, this should not affect opened devices + for(UsbDeviceVector::iterator it = enumerated_devices_.begin(); it != enumerated_devices_.end(); ++it) + { + libusb_unref_device(it->dev); + } + + enumerated_devices_.clear(); + has_device_enumeration_ = false; + } + + void enumerateDevices() + { + std::cout << "[Freenect2Impl] enumerating devices..." << std::endl; + libusb_device **device_list; + int num_devices = libusb_get_device_list(usb_context_, &device_list); + + std::cout << "[Freenect2Impl] " << num_devices << " usb devices connected" << std::endl; + + if(num_devices > 0) + { + for(int idx = 0; idx < num_devices; ++idx) + { + libusb_device *dev = device_list[idx]; + libusb_device_descriptor dev_desc; + + int r = libusb_get_device_descriptor(dev, &dev_desc); // this is always successful + + if(dev_desc.idVendor == Freenect2Device::VendorId && (dev_desc.idProduct == Freenect2Device::ProductId || dev_desc.idProduct == Freenect2Device::ProductIdPreview)) + { + Freenect2DeviceImpl *freenect2_dev; + + // prevent error if device is already open + if(tryGetDevice(dev, &freenect2_dev)) + { + UsbDeviceWithSerial dev_with_serial; + dev_with_serial.dev = dev; + dev_with_serial.serial = freenect2_dev->getSerialNumber(); + + enumerated_devices_.push_back(dev_with_serial); + continue; + } + else + { + libusb_device_handle *dev_handle; + r = libusb_open(dev, &dev_handle); + + if(r == LIBUSB_SUCCESS) + { + unsigned char buffer[1024]; + r = libusb_get_string_descriptor_ascii(dev_handle, dev_desc.iSerialNumber, buffer, sizeof(buffer)); + + if(r > LIBUSB_SUCCESS) + { + UsbDeviceWithSerial dev_with_serial; + dev_with_serial.dev = dev; + dev_with_serial.serial = std::string(reinterpret_cast(buffer), size_t(r)); + + std::cout << "[Freenect2Impl] found valid Kinect v2 " << PrintBusAndDevice(dev) << " with serial " << dev_with_serial.serial << std::endl; + // valid Kinect v2 + enumerated_devices_.push_back(dev_with_serial); + continue; + } + else + { + std::cout << "[Freenect2Impl] failed to get serial number of Kinect v2 " << PrintBusAndDevice(dev) << "!" << std::endl; + } + + libusb_close(dev_handle); + } + else + { + std::cout << "[Freenect2Impl] failed to open Kinect v2 " << PrintBusAndDevice(dev) << "!" << std::endl; + } + } + } + libusb_unref_device(dev); + } + } + + libusb_free_device_list(device_list, 0); + has_device_enumeration_ = true; + + std::cout << "[Freenect2Impl] found " << enumerated_devices_.size() << " devices" << std::endl; + } + + int getNumDevices() + { + if(!has_device_enumeration_) + { + enumerateDevices(); + } + return enumerated_devices_.size(); + } +}; + + +Freenect2Device::~Freenect2Device() +{ +} + +Freenect2DeviceImpl::Freenect2DeviceImpl(Freenect2Impl *context, const PacketPipeline *pipeline, libusb_device *usb_device, libusb_device_handle *usb_device_handle, const std::string &serial) : + state_(Created), + has_usb_interfaces_(false), + context_(context), + usb_device_(usb_device), + usb_device_handle_(usb_device_handle), + rgb_transfer_pool_(usb_device_handle, 0x83), + ir_transfer_pool_(usb_device_handle, 0x84), + usb_control_(usb_device_handle_), + command_tx_(usb_device_handle_, 0x81, 0x02), + command_seq_(0), + pipeline_(pipeline), + serial_(serial), + firmware_("") +{ + rgb_transfer_pool_.setCallback(pipeline_->getRgbPacketParser()); + ir_transfer_pool_.setCallback(pipeline_->getIrPacketParser()); +} + +Freenect2DeviceImpl::~Freenect2DeviceImpl() +{ + close(); + context_->removeDevice(this); + + delete pipeline_; +} + +int Freenect2DeviceImpl::nextCommandSeq() +{ + return command_seq_++; +} + +bool Freenect2DeviceImpl::isSameUsbDevice(libusb_device* other) +{ + bool result = false; + + if(state_ != Closed && usb_device_ != 0) + { + unsigned char bus = libusb_get_bus_number(usb_device_); + unsigned char address = libusb_get_device_address(usb_device_); + + unsigned char other_bus = libusb_get_bus_number(other); + unsigned char other_address = libusb_get_device_address(other); + + result = (bus == other_bus) && (address == other_address); + } + + return result; +} + +std::string Freenect2DeviceImpl::getSerialNumber() +{ + return serial_; +} + +std::string Freenect2DeviceImpl::getFirmwareVersion() +{ + return firmware_; +} + +Freenect2Device::ColorCameraParams Freenect2DeviceImpl::getColorCameraParams() +{ + return rgb_camera_params_; +} + + +Freenect2Device::IrCameraParams Freenect2DeviceImpl::getIrCameraParams() +{ + return ir_camera_params_; +} +void Freenect2DeviceImpl::setColorFrameListener(libfreenect2::FrameListener* rgb_frame_listener) +{ + // TODO: should only be possible, if not started + if(pipeline_->getRgbPacketProcessor() != 0) + pipeline_->getRgbPacketProcessor()->setFrameListener(rgb_frame_listener); +} + +void Freenect2DeviceImpl::setIrAndDepthFrameListener(libfreenect2::FrameListener* ir_frame_listener) +{ + // TODO: should only be possible, if not started + if(pipeline_->getDepthPacketProcessor() != 0) + pipeline_->getDepthPacketProcessor()->setFrameListener(ir_frame_listener); +} + +bool Freenect2DeviceImpl::open() +{ + std::cout << "[Freenect2DeviceImpl] opening..." << std::endl; + + if(state_ != Created) return false; + + if(usb_control_.setConfiguration() != UsbControl::Success) return false; + if(!has_usb_interfaces_ && usb_control_.claimInterfaces() != UsbControl::Success) return false; + has_usb_interfaces_ = true; + + if(usb_control_.setIsochronousDelay() != UsbControl::Success) return false; + // TODO: always fails right now with error 6 - TRANSFER_OVERFLOW! + //if(usb_control_.setPowerStateLatencies() != UsbControl::Success) return false; + if(usb_control_.setIrInterfaceState(UsbControl::Disabled) != UsbControl::Success) return false; + if(usb_control_.enablePowerStates() != UsbControl::Success) return false; + if(usb_control_.setVideoTransferFunctionState(UsbControl::Disabled) != UsbControl::Success) return false; + + int max_iso_packet_size; + if(usb_control_.getIrMaxIsoPacketSize(max_iso_packet_size) != UsbControl::Success) return false; + + if(max_iso_packet_size < 0x8400) + { + std::cout << "[Freenect2DeviceImpl] max iso packet size for endpoint 0x84 too small! (expected: " << 0x8400 << " got: " << max_iso_packet_size << ")" << std::endl; + return false; + } + + rgb_transfer_pool_.allocate(50, 0x4000); + ir_transfer_pool_.allocate(80, 8, max_iso_packet_size); + + state_ = Open; + + std::cout << "[Freenect2DeviceImpl] opened" << std::endl; + + return true; +} + +void Freenect2DeviceImpl::start() +{ + std::cout << "[Freenect2DeviceImpl] starting..." << std::endl; + if(state_ != Open) return; + + CommandTransaction::Result serial_result, firmware_result, result; + + usb_control_.setVideoTransferFunctionState(UsbControl::Enabled); + + command_tx_.execute(ReadFirmwareVersionsCommand(nextCommandSeq()), firmware_result); + firmware_ = FirmwareVersionResponse(firmware_result.data, firmware_result.length).toString(); + + command_tx_.execute(ReadData0x14Command(nextCommandSeq()), result); + std::cout << "[Freenect2DeviceImpl] ReadData0x14 response" << std::endl; + std::cout << GenericResponse(result.data, result.length).toString() << std::endl; + + command_tx_.execute(ReadSerialNumberCommand(nextCommandSeq()), serial_result); + std::string new_serial = SerialNumberResponse(serial_result.data, serial_result.length).toString(); + + if(serial_ != new_serial) + { + std::cout << "[Freenect2DeviceImpl] serial number reported by libusb " << serial_ << " differs from serial number " << new_serial << " in device protocol! " << std::endl; + } + + command_tx_.execute(ReadDepthCameraParametersCommand(nextCommandSeq()), result); + DepthCameraParamsResponse *ir_p = reinterpret_cast(result.data); + + ir_camera_params_.fx = ir_p->fx; + ir_camera_params_.fy = ir_p->fy; + ir_camera_params_.cx = ir_p->cx; + ir_camera_params_.cy = ir_p->cy; + ir_camera_params_.k1 = ir_p->k1; + ir_camera_params_.k2 = ir_p->k2; + ir_camera_params_.k3 = ir_p->k3; + ir_camera_params_.p1 = ir_p->p1; + ir_camera_params_.p2 = ir_p->p2; + + command_tx_.execute(ReadP0TablesCommand(nextCommandSeq()), result); + if(pipeline_->getDepthPacketProcessor() != 0) + pipeline_->getDepthPacketProcessor()->loadP0TablesFromCommandResponse(result.data, result.length); + + command_tx_.execute(ReadRgbCameraParametersCommand(nextCommandSeq()), result); + RgbCameraParamsResponse *rgb_p = reinterpret_cast(result.data); + + rgb_camera_params_.fx = rgb_p->color_f; + rgb_camera_params_.fy = rgb_p->color_f; + rgb_camera_params_.cx = rgb_p->color_cx; + rgb_camera_params_.cy = rgb_p->color_cy; + + command_tx_.execute(ReadStatus0x090000Command(nextCommandSeq()), result); + std::cout << "[Freenect2DeviceImpl] ReadStatus0x090000 response" << std::endl; + std::cout << GenericResponse(result.data, result.length).toString() << std::endl; + + command_tx_.execute(InitStreamsCommand(nextCommandSeq()), result); + + usb_control_.setIrInterfaceState(UsbControl::Enabled); + + command_tx_.execute(ReadStatus0x090000Command(nextCommandSeq()), result); + std::cout << "[Freenect2DeviceImpl] ReadStatus0x090000 response" << std::endl; + std::cout << GenericResponse(result.data, result.length).toString() << std::endl; + + command_tx_.execute(SetStreamEnabledCommand(nextCommandSeq()), result); + + //command_tx_.execute(Unknown0x47Command(nextCommandSeq()), result); + //command_tx_.execute(Unknown0x46Command(nextCommandSeq()), result); +/* + command_tx_.execute(SetModeEnabledCommand(nextCommandSeq()), result); + command_tx_.execute(SetModeDisabledCommand(nextCommandSeq()), result); + + usb_control_.setIrInterfaceState(UsbControl::Enabled); + + command_tx_.execute(SetModeEnabledWith0x00640064Command(nextCommandSeq()), result); + command_tx_.execute(ReadData0x26Command(nextCommandSeq()), result); + command_tx_.execute(ReadStatus0x100007Command(nextCommandSeq()), result); + command_tx_.execute(SetModeEnabledWith0x00500050Command(nextCommandSeq()), result); + command_tx_.execute(ReadData0x26Command(nextCommandSeq()), result); + command_tx_.execute(ReadStatus0x100007Command(nextCommandSeq()), result); + command_tx_.execute(ReadData0x26Command(nextCommandSeq()), result); + command_tx_.execute(ReadData0x26Command(nextCommandSeq()), result); +*/ + std::cout << "[Freenect2DeviceImpl] enabling usb transfer submission..." << std::endl; + rgb_transfer_pool_.enableSubmission(); + ir_transfer_pool_.enableSubmission(); + + std::cout << "[Freenect2DeviceImpl] submitting usb transfers..." << std::endl; + rgb_transfer_pool_.submit(20); + ir_transfer_pool_.submit(60); + + state_ = Streaming; + std::cout << "[Freenect2DeviceImpl] started" << std::endl; +} + +void Freenect2DeviceImpl::stop() +{ + std::cout << "[Freenect2DeviceImpl] stopping..." << std::endl; + + if(state_ != Streaming) + { + std::cout << "[Freenect2DeviceImpl] already stopped, doing nothing" << std::endl; + return; + } + + std::cout << "[Freenect2DeviceImpl] disabling usb transfer submission..." << std::endl; + rgb_transfer_pool_.disableSubmission(); + ir_transfer_pool_.disableSubmission(); + + std::cout << "[Freenect2DeviceImpl] canceling usb transfers..." << std::endl; + rgb_transfer_pool_.cancel(); + ir_transfer_pool_.cancel(); + + // wait for completion of transfer cancelation + // TODO: better implementation + libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(1500)); + + usb_control_.setIrInterfaceState(UsbControl::Disabled); + + CommandTransaction::Result result; + command_tx_.execute(Unknown0x0ACommand(nextCommandSeq()), result); + command_tx_.execute(SetStreamDisabledCommand(nextCommandSeq()), result); + + usb_control_.setVideoTransferFunctionState(UsbControl::Disabled); + + state_ = Open; + std::cout << "[Freenect2DeviceImpl] stopped" << std::endl; +} + +void Freenect2DeviceImpl::close() +{ + std::cout << "[Freenect2DeviceImpl] closing..." << std::endl; + + if(state_ == Closed) + { + std::cout << "[Freenect2DeviceImpl] already closed, doing nothing" << std::endl; + return; + } + + if(state_ == Streaming) + { + stop(); + } + + if(pipeline_->getRgbPacketProcessor() != 0) + pipeline_->getRgbPacketProcessor()->setFrameListener(0); + + if(pipeline_->getDepthPacketProcessor() != 0) + pipeline_->getDepthPacketProcessor()->setFrameListener(0); + + if(has_usb_interfaces_) + { + std::cout << "[Freenect2DeviceImpl] releasing usb interfaces..." << std::endl; + + usb_control_.releaseInterfaces(); + has_usb_interfaces_ = false; + } + + std::cout << "[Freenect2DeviceImpl] deallocating usb transfer pools..." << std::endl; + rgb_transfer_pool_.deallocate(); + ir_transfer_pool_.deallocate(); + + std::cout << "[Freenect2DeviceImpl] closing usb device..." << std::endl; + + libusb_close(usb_device_handle_); + usb_device_handle_ = 0; + usb_device_ = 0; + + state_ = Closed; + std::cout << "[Freenect2DeviceImpl] closed" << std::endl; +} + +PacketPipeline *createDefaultPacketPipeline() +{ +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT + return new OpenGLPacketPipeline(); +#else + #ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + return new OpenCLPacketPipeline(); + #else + return new CpuPacketPipeline(); + #endif +#endif +} + +Freenect2::Freenect2(void *usb_context) : + impl_(new Freenect2Impl(usb_context)) +{ +} + +Freenect2::~Freenect2() +{ + delete impl_; +} + +int Freenect2::enumerateDevices() +{ + impl_->clearDeviceEnumeration(); + return impl_->getNumDevices(); +} + +std::string Freenect2::getDeviceSerialNumber(int idx) +{ + return impl_->enumerated_devices_[idx].serial; +} + +std::string Freenect2::getDefaultDeviceSerialNumber() +{ + return getDeviceSerialNumber(0); +} + +Freenect2Device *Freenect2::openDevice(int idx) +{ + return openDevice(idx, createDefaultPacketPipeline()); +} + +Freenect2Device *Freenect2::openDevice(int idx, const PacketPipeline *pipeline) +{ + return openDevice(idx, pipeline, true); +} + +Freenect2Device *Freenect2::openDevice(int idx, const PacketPipeline *pipeline, bool attempting_reset) +{ + int num_devices = impl_->getNumDevices(); + Freenect2DeviceImpl *device = 0; + + if(idx >= num_devices) + { + std::cout << "[Freenect2Impl] requested device " << idx << " is not connected!" << std::endl; + return device; + } + + Freenect2Impl::UsbDeviceWithSerial &dev = impl_->enumerated_devices_[idx]; + libusb_device_handle *dev_handle; + + if(impl_->tryGetDevice(dev.dev, &device)) + { + std::cout << "[Freenect2Impl] failed to get device " << PrintBusAndDevice(dev.dev) + << " (the device may already be open)" << std::endl; + return device; + } + + int r = libusb_open(dev.dev, &dev_handle); + + if(r != LIBUSB_SUCCESS) + { + std::cout << "[Freenect2Impl] failed to open Kinect v2 " << PrintBusAndDevice(dev.dev) << "!" << std::endl; + return device; + } + + if(attempting_reset) + { + r = libusb_reset_device(dev_handle); + + if(r == LIBUSB_ERROR_NOT_FOUND) + { + // From libusb documentation: + // "If the reset fails, the descriptors change, or the previous state + // cannot be restored, the device will appear to be disconnected and + // reconnected. This means that the device handle is no longer valid (you + // should close it) and rediscover the device. A return code of + // LIBUSB_ERROR_NOT_FOUND indicates when this is the case." + + // be a good citizen + libusb_close(dev_handle); + + // HACK: wait for the planets to align... (When the reset fails it may + // take a short while for the device to show up on the bus again. In the + // absence of hotplug support, we just wait a little. If this code path + // is followed there will already be a delay opening the device fully so + // adding a little more is tolerable.) + libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(1000)); + + // reenumerate devices + std::cout << "[Freenect2Impl] re-enumerating devices after reset" << std::endl; + impl_->clearDeviceEnumeration(); + impl_->enumerateDevices(); + + // re-open without reset + return openDevice(idx, pipeline, false); + } + else if(r != LIBUSB_SUCCESS) + { + std::cout << "[Freenect2Impl] failed to reset Kinect v2 " << PrintBusAndDevice(dev.dev) << "!" << std::endl; + return device; + } + } + + device = new Freenect2DeviceImpl(impl_, pipeline, dev.dev, dev_handle, dev.serial); + impl_->addDevice(device); + + if(!device->open()) + { + delete device; + device = 0; + + std::cout << "[Freenect2DeviceImpl] failed to open Kinect v2 " << PrintBusAndDevice(dev.dev) << "!" << std::endl; + } + + return device; +} + +Freenect2Device *Freenect2::openDevice(const std::string &serial) +{ + return openDevice(serial, createDefaultPacketPipeline()); +} + +Freenect2Device *Freenect2::openDevice(const std::string &serial, const PacketPipeline *pipeline) +{ + Freenect2Device *device = 0; + int num_devices = impl_->getNumDevices(); + + for(int idx = 0; idx < num_devices; ++idx) + { + if(impl_->enumerated_devices_[idx].serial == serial) + { + device = openDevice(idx, pipeline); + break; + } + } + + return device; +} + +Freenect2Device *Freenect2::openDefaultDevice() +{ + return openDevice(0); +} + +Freenect2Device *Freenect2::openDefaultDevice(const PacketPipeline *pipeline) +{ + return openDevice(0, pipeline); +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/opencl_depth_packet_processor.cl b/examples/k22v4l/src/opencl_depth_packet_processor.cl new file mode 100644 index 000000000..cdcc04559 --- /dev/null +++ b/examples/k22v4l/src/opencl_depth_packet_processor.cl @@ -0,0 +1,380 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/******************************************************************************* + * Process pixel stage 1 + ******************************************************************************/ + +float decodePixelMeasurement(global const ushort *data, global const short *lut11to16, const uint sub, const uint x, const uint y) +{ + uint row_idx = (424 * sub + (y < 212 ? y + 212 : 423 - y)) * 352; + uint idx = (((x >> 2) + ((x << 7) & BFI_BITMASK)) * 11) & (uint)0xffffffff; + + uint col_idx = idx >> 4; + uint upper_bytes = idx & 15; + uint lower_bytes = 16 - upper_bytes; + + uint data_idx0 = row_idx + col_idx; + uint data_idx1 = row_idx + col_idx + 1; + + return (float)lut11to16[(x < 1 || 510 < x || col_idx > 352) ? 0 : ((data[data_idx0] >> upper_bytes) | (data[data_idx1] << lower_bytes)) & 2047]; +} + +float2 processMeasurementTriple(const float ab_multiplier_per_frq, const float p0, const float3 v, int *invalid) +{ + float3 p0vec = (float3)(p0 + PHASE_IN_RAD0, p0 + PHASE_IN_RAD1, p0 + PHASE_IN_RAD2); + float3 p0cos = cos(p0vec); + float3 p0sin = sin(-p0vec); + + *invalid = *invalid && any(isequal(v, (float3)(32767.0f))); + + return (float2)(dot(v, p0cos), dot(v, p0sin)) * ab_multiplier_per_frq; +} + +void kernel processPixelStage1(global const short *lut11to16, global const float *z_table, global const float3 *p0_table, global const ushort *data, + global float3 *a_out, global float3 *b_out, global float3 *n_out, global float *ir_out) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const uint y_in = (423 - y); + + const float zmultiplier = z_table[i]; + int valid = (int)(0.0f < zmultiplier); + int saturatedX = valid; + int saturatedY = valid; + int saturatedZ = valid; + int3 invalid_pixel = (int3)((int)(!valid)); + const float3 p0 = p0_table[i]; + + const float3 v0 = (float3)(decodePixelMeasurement(data, lut11to16, 0, x, y_in), + decodePixelMeasurement(data, lut11to16, 1, x, y_in), + decodePixelMeasurement(data, lut11to16, 2, x, y_in)); + const float2 ab0 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ0, p0.x, v0, &saturatedX); + + const float3 v1 = (float3)(decodePixelMeasurement(data, lut11to16, 3, x, y_in), + decodePixelMeasurement(data, lut11to16, 4, x, y_in), + decodePixelMeasurement(data, lut11to16, 5, x, y_in)); + const float2 ab1 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ1, p0.y, v1, &saturatedY); + + const float3 v2 = (float3)(decodePixelMeasurement(data, lut11to16, 6, x, y_in), + decodePixelMeasurement(data, lut11to16, 7, x, y_in), + decodePixelMeasurement(data, lut11to16, 8, x, y_in)); + const float2 ab2 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ2, p0.z, v2, &saturatedZ); + + float3 a = select((float3)(ab0.x, ab1.x, ab2.x), (float3)(0.0f), invalid_pixel); + float3 b = select((float3)(ab0.y, ab1.y, ab2.y), (float3)(0.0f), invalid_pixel); + float3 n = sqrt(a * a + b * b); + + int3 saturated = (int3)(saturatedX, saturatedY, saturatedZ); + a = select(a, (float3)(0.0f), saturated); + b = select(b, (float3)(0.0f), saturated); + + a_out[i] = a; + b_out[i] = b; + n_out[i] = n; + ir_out[i] = min(dot(select(n, (float3)(65535.0f), saturated), (float3)(0.333333333f * AB_MULTIPLIER * AB_OUTPUT_MULTIPLIER)), 65535.0f); +} + +/******************************************************************************* + * Filter pixel stage 1 + ******************************************************************************/ +void kernel filterPixelStage1(global const float3 *a, global const float3 *b, global const float3 *n, + global float3 *a_out, global float3 *b_out, global uchar *max_edge_test) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const float3 self_a = a[i]; + const float3 self_b = b[i]; + + const float gaussian[9] = {GAUSSIAN_KERNEL_0, GAUSSIAN_KERNEL_1, GAUSSIAN_KERNEL_2, GAUSSIAN_KERNEL_3, GAUSSIAN_KERNEL_4, GAUSSIAN_KERNEL_5, GAUSSIAN_KERNEL_6, GAUSSIAN_KERNEL_7, GAUSSIAN_KERNEL_8}; + + if(x < 1 || y < 1 || x > 510 || y > 422) + { + a_out[i] = self_a; + b_out[i] = self_b; + max_edge_test[i] = 1; + } + else + { + float3 threshold = (float3)(JOINT_BILATERAL_THRESHOLD); + float3 joint_bilateral_exp = (float3)(JOINT_BILATERAL_EXP); + + const float3 self_norm = n[i]; + const float3 self_normalized_a = self_a / self_norm; + const float3 self_normalized_b = self_b / self_norm; + + float3 weight_acc = (float3)(0.0f); + float3 weighted_a_acc = (float3)(0.0f); + float3 weighted_b_acc = (float3)(0.0f); + float3 dist_acc = (float3)(0.0f); + + const int3 c0 = isless(self_norm * self_norm, threshold); + + threshold = select(threshold, (float3)(0.0f), c0); + joint_bilateral_exp = select(joint_bilateral_exp, (float3)(0.0f), c0); + + for(int yi = -1, j = 0; yi < 2; ++yi) + { + uint i_other = (y + yi) * 512 + x - 1; + + for(int xi = -1; xi < 2; ++xi, ++j, ++i_other) + { + const float3 other_a = a[i_other]; + const float3 other_b = b[i_other]; + const float3 other_norm = n[i_other]; + const float3 other_normalized_a = other_a / other_norm; + const float3 other_normalized_b = other_b / other_norm; + + const int3 c1 = isless(other_norm * other_norm, threshold); + + const float3 dist = 0.5f * (1.0f - (self_normalized_a * other_normalized_a + self_normalized_b * other_normalized_b)); + const float3 weight = select(gaussian[j] * exp(-1.442695f * joint_bilateral_exp * dist), (float3)(0.0f), c1); + + weighted_a_acc += weight * other_a; + weighted_b_acc += weight * other_b; + weight_acc += weight; + dist_acc += select((float3)(0.0f), dist, c1); + } + } + + const int3 c2 = isless((float3)(0.0f), weight_acc.xyz); + a_out[i] = select((float3)(0.0f), weighted_a_acc / weight_acc, c2); + b_out[i] = select((float3)(0.0f), weighted_b_acc / weight_acc, c2); + + max_edge_test[i] = all(isless(dist_acc, (float3)(JOINT_BILATERAL_MAX_EDGE))); + } +} + +/******************************************************************************* + * Process pixel stage 2 + ******************************************************************************/ +void kernel processPixelStage2(global const float3 *a_in, global const float3 *b_in, global const float *x_table, global const float *z_table, + global float *depth, global float *ir_sums) +{ + const uint i = get_global_id(0); + float3 a = a_in[i]; + float3 b = b_in[i]; + + float3 phase = atan2(b, a); + phase = select(phase, phase + 2.0f * M_PI_F, isless(phase, (float3)(0.0f))); + phase = select(phase, (float3)(0.0f), isnan(phase)); + float3 ir = sqrt(a * a + b * b) * AB_MULTIPLIER; + + float ir_sum = ir.x + ir.y + ir.z; + float ir_min = min(ir.x, min(ir.y, ir.z)); + float ir_max = max(ir.x, max(ir.y, ir.z)); + + float phase_final = 0; + + if(ir_min >= INDIVIDUAL_AB_THRESHOLD && ir_sum >= AB_THRESHOLD) + { + float3 t = phase / (2.0f * M_PI_F) * (float3)(3.0f, 15.0f, 2.0f); + + float t0 = t.x; + float t1 = t.y; + float t2 = t.z; + + float t5 = (floor((t1 - t0) * 0.333333f + 0.5f) * 3.0f + t0); + float t3 = (-t2 + t5); + float t4 = t3 * 2.0f; + + bool c1 = t4 >= -t4; // true if t4 positive + + float f1 = c1 ? 2.0f : -2.0f; + float f2 = c1 ? 0.5f : -0.5f; + t3 *= f2; + t3 = (t3 - floor(t3)) * f1; + + bool c2 = 0.5f < fabs(t3) && fabs(t3) < 1.5f; + + float t6 = c2 ? t5 + 15.0f : t5; + float t7 = c2 ? t1 + 15.0f : t1; + + float t8 = (floor((-t2 + t6) * 0.5f + 0.5f) * 2.0f + t2) * 0.5f; + + t6 *= 0.333333f; // = / 3 + t7 *= 0.066667f; // = / 15 + + float t9 = (t8 + t6 + t7); // transformed phase measurements (they are transformed and divided by the values the original values were multiplied with) + float t10 = t9 * 0.333333f; // some avg + + t6 *= 2.0f * M_PI_F; + t7 *= 2.0f * M_PI_F; + t8 *= 2.0f * M_PI_F; + + // some cross product + float t8_new = t7 * 0.826977f - t8 * 0.110264f; + float t6_new = t8 * 0.551318f - t6 * 0.826977f; + float t7_new = t6 * 0.110264f - t7 * 0.551318f; + + t8 = t8_new; + t6 = t6_new; + t7 = t7_new; + + float norm = t8 * t8 + t6 * t6 + t7 * t7; + float mask = t9 >= 0.0f ? 1.0f : 0.0f; + t10 *= mask; + + bool slope_positive = 0 < AB_CONFIDENCE_SLOPE; + + float ir_x = slope_positive ? ir_min : ir_max; + + ir_x = log(ir_x); + ir_x = (ir_x * AB_CONFIDENCE_SLOPE * 0.301030f + AB_CONFIDENCE_OFFSET) * 3.321928f; + ir_x = exp(ir_x); + ir_x = clamp(ir_x, MIN_DEALIAS_CONFIDENCE, MAX_DEALIAS_CONFIDENCE); + ir_x *= ir_x; + + float mask2 = ir_x >= norm ? 1.0f : 0.0f; + + float t11 = t10 * mask2; + + float mask3 = MAX_DEALIAS_CONFIDENCE * MAX_DEALIAS_CONFIDENCE >= norm ? 1.0f : 0.0f; + t10 *= mask3; + phase_final = true/*(modeMask & 2) != 0*/ ? t11 : t10; + } + + float zmultiplier = z_table[i]; + float xmultiplier = x_table[i]; + + phase_final = 0.0f < phase_final ? phase_final + PHASE_OFFSET : phase_final; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * UNAMBIGIOUS_DIST * 2.0; + + bool cond1 = /*(modeMask & 32) != 0*/ true && 0.0f < depth_linear && 0.0f < max_depth; + + xmultiplier = (xmultiplier * 90.0) / (max_depth * max_depth * 8192.0); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0f ? 0.0f : depth_fit; + + float d = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + depth[i] = d; + ir_sums[i] = ir_sum; +} + +/******************************************************************************* + * Filter pixel stage 2 + ******************************************************************************/ +void kernel filterPixelStage2(global const float *depth, global const float *ir_sums, global const uchar *max_edge_test, global float *filtered) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const float raw_depth = depth[i]; + const float ir_sum = ir_sums[i]; + const uchar edge_test = max_edge_test[i]; + + if(raw_depth >= MIN_DEPTH && raw_depth <= MAX_DEPTH) + { + if(x < 1 || y < 1 || x > 510 || y > 422) + { + filtered[i] = raw_depth; + } + else + { + float ir_sum_acc = ir_sum; + float squared_ir_sum_acc = ir_sum * ir_sum; + float min_depth = raw_depth; + float max_depth = raw_depth; + + for(int yi = -1; yi < 2; ++yi) + { + uint i_other = (y + yi) * 512 + x - 1; + + for(int xi = -1; xi < 2; ++xi, ++i_other) + { + if(i_other == i) + { + continue; + } + + const float raw_depth_other = depth[i_other]; + const float ir_sum_other = ir_sums[i_other]; + + ir_sum_acc += ir_sum_other; + squared_ir_sum_acc += ir_sum_other * ir_sum_other; + + if(0.0f < raw_depth_other) + { + min_depth = min(min_depth, raw_depth_other); + max_depth = max(max_depth, raw_depth_other); + } + } + } + + float tmp0 = sqrt(squared_ir_sum_acc * 9.0f - ir_sum_acc * ir_sum_acc) / 9.0f; + float edge_avg = max(ir_sum_acc / 9.0f, EDGE_AB_AVG_MIN_VALUE); + tmp0 /= edge_avg; + + float abs_min_diff = fabs(raw_depth - min_depth); + float abs_max_diff = fabs(raw_depth - max_depth); + + float avg_diff = (abs_min_diff + abs_max_diff) * 0.5f; + float max_abs_diff = max(abs_min_diff, abs_max_diff); + + bool cond0 = + 0.0f < raw_depth && + tmp0 >= EDGE_AB_STD_DEV_THRESHOLD && + EDGE_CLOSE_DELTA_THRESHOLD < abs_min_diff && + EDGE_FAR_DELTA_THRESHOLD < abs_max_diff && + EDGE_MAX_DELTA_THRESHOLD < max_abs_diff && + EDGE_AVG_DELTA_THRESHOLD < avg_diff; + + if(!cond0) + { + if(edge_test != 0) + { + float tmp1 = 1500.0f > raw_depth ? 30.0f : 0.02f * raw_depth; + float edge_count = 0.0f; + + filtered[i] = edge_count > MAX_EDGE_COUNT ? 0.0f : raw_depth; + } + else + { + filtered[i] = 0.0f; + } + } + else + { + filtered[i] = 0.0f; + } + } + } + else + { + filtered[i] = 0.0f; + } +} diff --git a/examples/k22v4l/src/opencl_depth_packet_processor.cpp b/examples/k22v4l/src/opencl_depth_packet_processor.cpp new file mode 100644 index 000000000..edda413af --- /dev/null +++ b/examples/k22v4l/src/opencl_depth_packet_processor.cpp @@ -0,0 +1,672 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#if defined(WIN32) +#define _USE_MATH_DEFINES +#include +#endif + +#define __CL_ENABLE_EXCEPTIONS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#ifndef REG_OPENCL_FILE +#define REG_OPENCL_FILE "" +#endif + +#define OUT_NAME(FUNCTION) "[OpenCLDepthPacketProcessor::" FUNCTION "] " + +namespace libfreenect2 +{ + +bool loadBufferFromResources(const std::string &filename, unsigned char *buffer, const size_t n) +{ + size_t length = 0; + const unsigned char *data = NULL; + + if(!loadResource(filename, &data, &length)) + { + std::cerr << OUT_NAME("loadBufferFromResources") "failed to load resource: " << filename << std::endl; + return false; + } + + if(length != n) + { + std::cerr << OUT_NAME("loadBufferFromResources") "wrong size of resource: " << filename << std::endl; + return false; + } + + memcpy(buffer, data, length); + return true; +} + +std::string loadCLSource(const std::string &filename) +{ + const unsigned char *data; + size_t length = 0; + + if(!loadResource(filename, &data, &length)) + { + std::cerr << OUT_NAME("loadCLSource") "failed to load cl source!" << std::endl; + return ""; + } + + return std::string(reinterpret_cast(data), length); +} + +class OpenCLDepthPacketProcessorImpl +{ +public: + cl_short lut11to16[2048]; + cl_float x_table[512 * 424]; + cl_float z_table[512 * 424]; + cl_float3 p0_table[512 * 424]; + libfreenect2::DepthPacketProcessor::Config config; + DepthPacketProcessor::Parameters params; + + double timing_acc; + double timing_acc_n; + + double timing_current_start; + + Frame *ir_frame, *depth_frame; + + cl::Context context; + cl::Device device; + + cl::Program program; + cl::CommandQueue queue; + + cl::Kernel kernel_processPixelStage1; + cl::Kernel kernel_filterPixelStage1; + cl::Kernel kernel_processPixelStage2; + cl::Kernel kernel_filterPixelStage2; + + size_t image_size; + + // Read only buffers + size_t buf_lut11to16_size; + size_t buf_p0_table_size; + size_t buf_x_table_size; + size_t buf_z_table_size; + size_t buf_packet_size; + + cl::Buffer buf_lut11to16; + cl::Buffer buf_p0_table; + cl::Buffer buf_x_table; + cl::Buffer buf_z_table; + cl::Buffer buf_packet; + + // Read-Write buffers + size_t buf_a_size; + size_t buf_b_size; + size_t buf_n_size; + size_t buf_ir_size; + size_t buf_a_filtered_size; + size_t buf_b_filtered_size; + size_t buf_edge_test_size; + size_t buf_depth_size; + size_t buf_ir_sum_size; + size_t buf_filtered_size; + + cl::Buffer buf_a; + cl::Buffer buf_b; + cl::Buffer buf_n; + cl::Buffer buf_ir; + cl::Buffer buf_a_filtered; + cl::Buffer buf_b_filtered; + cl::Buffer buf_edge_test; + cl::Buffer buf_depth; + cl::Buffer buf_ir_sum; + cl::Buffer buf_filtered; + + bool deviceInitialized; + bool programInitialized; + std::string sourceCode; + + OpenCLDepthPacketProcessorImpl(const int deviceId = -1) : deviceInitialized(false), programInitialized(false) + { + newIrFrame(); + newDepthFrame(); + + timing_acc = 0.0; + timing_acc_n = 0.0; + timing_current_start = 0.0; + image_size = 512 * 424; + + deviceInitialized = initDevice(deviceId); + } + + void generateOptions(std::string &options) const + { + std::ostringstream oss; + oss.precision(16); + oss << std::scientific; + oss << " -D BFI_BITMASK=" << "0x180"; + + oss << " -D AB_MULTIPLIER=" << params.ab_multiplier << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ0=" << params.ab_multiplier_per_frq[0] << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ1=" << params.ab_multiplier_per_frq[1] << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ2=" << params.ab_multiplier_per_frq[2] << "f"; + oss << " -D AB_OUTPUT_MULTIPLIER=" << params.ab_output_multiplier << "f"; + + oss << " -D PHASE_IN_RAD0=" << params.phase_in_rad[0] << "f"; + oss << " -D PHASE_IN_RAD1=" << params.phase_in_rad[1] << "f"; + oss << " -D PHASE_IN_RAD2=" << params.phase_in_rad[2] << "f"; + + oss << " -D JOINT_BILATERAL_AB_THRESHOLD=" << params.joint_bilateral_ab_threshold << "f"; + oss << " -D JOINT_BILATERAL_MAX_EDGE=" << params.joint_bilateral_max_edge << "f"; + oss << " -D JOINT_BILATERAL_EXP=" << params.joint_bilateral_exp << "f"; + oss << " -D JOINT_BILATERAL_THRESHOLD=" << (params.joint_bilateral_ab_threshold * params.joint_bilateral_ab_threshold) / (params.ab_multiplier * params.ab_multiplier) << "f"; + oss << " -D GAUSSIAN_KERNEL_0=" << params.gaussian_kernel[0] << "f"; + oss << " -D GAUSSIAN_KERNEL_1=" << params.gaussian_kernel[1] << "f"; + oss << " -D GAUSSIAN_KERNEL_2=" << params.gaussian_kernel[2] << "f"; + oss << " -D GAUSSIAN_KERNEL_3=" << params.gaussian_kernel[3] << "f"; + oss << " -D GAUSSIAN_KERNEL_4=" << params.gaussian_kernel[4] << "f"; + oss << " -D GAUSSIAN_KERNEL_5=" << params.gaussian_kernel[5] << "f"; + oss << " -D GAUSSIAN_KERNEL_6=" << params.gaussian_kernel[6] << "f"; + oss << " -D GAUSSIAN_KERNEL_7=" << params.gaussian_kernel[7] << "f"; + oss << " -D GAUSSIAN_KERNEL_8=" << params.gaussian_kernel[8] << "f"; + + oss << " -D PHASE_OFFSET=" << params.phase_offset << "f"; + oss << " -D UNAMBIGIOUS_DIST=" << params.unambigious_dist << "f"; + oss << " -D INDIVIDUAL_AB_THRESHOLD=" << params.individual_ab_threshold << "f"; + oss << " -D AB_THRESHOLD=" << params.ab_threshold << "f"; + oss << " -D AB_CONFIDENCE_SLOPE=" << params.ab_confidence_slope << "f"; + oss << " -D AB_CONFIDENCE_OFFSET=" << params.ab_confidence_offset << "f"; + oss << " -D MIN_DEALIAS_CONFIDENCE=" << params.min_dealias_confidence << "f"; + oss << " -D MAX_DEALIAS_CONFIDENCE=" << params.max_dealias_confidence << "f"; + + oss << " -D EDGE_AB_AVG_MIN_VALUE=" << params.edge_ab_avg_min_value << "f"; + oss << " -D EDGE_AB_STD_DEV_THRESHOLD=" << params.edge_ab_std_dev_threshold << "f"; + oss << " -D EDGE_CLOSE_DELTA_THRESHOLD=" << params.edge_close_delta_threshold << "f"; + oss << " -D EDGE_FAR_DELTA_THRESHOLD=" << params.edge_far_delta_threshold << "f"; + oss << " -D EDGE_MAX_DELTA_THRESHOLD=" << params.edge_max_delta_threshold << "f"; + oss << " -D EDGE_AVG_DELTA_THRESHOLD=" << params.edge_avg_delta_threshold << "f"; + oss << " -D MAX_EDGE_COUNT=" << params.max_edge_count << "f"; + + oss << " -D MIN_DEPTH=" << config.MinDepth * 1000.0f << "f"; + oss << " -D MAX_DEPTH=" << config.MaxDepth * 1000.0f << "f"; + options = oss.str(); + } + + void getDevices(const std::vector &platforms, std::vector &devices) + { + devices.clear(); + for(size_t i = 0; i < platforms.size(); ++i) + { + const cl::Platform &platform = platforms[i]; + + std::vector devs; + if(platform.getDevices(CL_DEVICE_TYPE_ALL, &devs) != CL_SUCCESS) + { + continue; + } + + devices.insert(devices.end(), devs.begin(), devs.end()); + } + } + + void listDevice(std::vector &devices) + { + std::cout << OUT_NAME("listDevice") " devices:" << std::endl; + for(size_t i = 0; i < devices.size(); ++i) + { + cl::Device &dev = devices[i]; + std::string devName, devVendor, devType; + size_t devTypeID; + dev.getInfo(CL_DEVICE_NAME, &devName); + dev.getInfo(CL_DEVICE_VENDOR, &devVendor); + dev.getInfo(CL_DEVICE_TYPE, &devTypeID); + + switch(devTypeID) + { + case CL_DEVICE_TYPE_CPU: + devType = "CPU"; + break; + case CL_DEVICE_TYPE_GPU: + devType = "GPU"; + break; + case CL_DEVICE_TYPE_ACCELERATOR: + devType = "ACCELERATOR"; + break; + case CL_DEVICE_TYPE_CUSTOM: + devType = "CUSTOM"; + break; + default: + devType = "UNKNOWN"; + } + + std::cout << " " << i << ": " << devName << " (" << devType << ")[" << devVendor << ']' << std::endl; + } + } + + bool selectDevice(std::vector &devices, const int deviceId) + { + if(deviceId != -1 && devices.size() > (size_t)deviceId) + { + device = devices[deviceId]; + return true; + } + + bool selected = false; + size_t selectedType = 0; + + for(size_t i = 0; i < devices.size(); ++i) + { + cl::Device &dev = devices[i]; + size_t devTypeID; + dev.getInfo(CL_DEVICE_TYPE, &devTypeID); + + if(!selected || (selectedType != CL_DEVICE_TYPE_GPU && devTypeID == CL_DEVICE_TYPE_GPU)) + { + selectedType = devTypeID; + selected = true; + device = dev; + } + } + return selected; + } + + bool initDevice(const int deviceId) + { + if(!readProgram(sourceCode)) + { + return false; + } + + cl_int err = CL_SUCCESS; + try + { + std::vector platforms; + if(cl::Platform::get(&platforms) != CL_SUCCESS) + { + std::cerr << OUT_NAME("init") "error while getting opencl platforms." << std::endl; + return false; + } + if(platforms.empty()) + { + std::cerr << OUT_NAME("init") "no opencl platforms found." << std::endl; + return false; + } + + std::vector devices; + getDevices(platforms, devices); + listDevice(devices); + if(selectDevice(devices, deviceId)) + { + std::string devName, devVendor, devType; + size_t devTypeID; + device.getInfo(CL_DEVICE_NAME, &devName); + device.getInfo(CL_DEVICE_VENDOR, &devVendor); + device.getInfo(CL_DEVICE_TYPE, &devTypeID); + + switch(devTypeID) + { + case CL_DEVICE_TYPE_CPU: + devType = "CPU"; + break; + case CL_DEVICE_TYPE_GPU: + devType = "GPU"; + break; + case CL_DEVICE_TYPE_ACCELERATOR: + devType = "ACCELERATOR"; + break; + case CL_DEVICE_TYPE_CUSTOM: + devType = "CUSTOM"; + break; + default: + devType = "UNKNOWN"; + } + std::cout << OUT_NAME("init") " selected device: " << devName << " (" << devType << ")[" << devVendor << ']' << std::endl; + } + else + { + std::cerr << OUT_NAME("init") "could not find any suitable device" << std::endl; + return false; + } + + context = cl::Context(device); + } + catch(const cl::Error &err) + { + std::cerr << OUT_NAME("init") "ERROR: " << err.what() << "(" << err.err() << ")" << std::endl; + throw err; + } + return true; + } + + bool initProgram() + { + if(!deviceInitialized) + { + return false; + } + + cl_int err = CL_SUCCESS; + try + { + std::string options; + generateOptions(options); + + cl::Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length())); + program = cl::Program(context, source); + program.build(options.c_str()); + + queue = cl::CommandQueue(context, device, 0, &err); + + //Read only + buf_lut11to16_size = 2048 * sizeof(cl_short); + buf_p0_table_size = image_size * sizeof(cl_float3); + buf_x_table_size = image_size * sizeof(cl_float); + buf_z_table_size = image_size * sizeof(cl_float); + buf_packet_size = ((image_size * 11) / 16) * 10 * sizeof(cl_ushort); + + buf_lut11to16 = cl::Buffer(context, CL_READ_ONLY_CACHE, buf_lut11to16_size, NULL, &err); + buf_p0_table = cl::Buffer(context, CL_READ_ONLY_CACHE, buf_p0_table_size, NULL, &err); + buf_x_table = cl::Buffer(context, CL_READ_ONLY_CACHE, buf_x_table_size, NULL, &err); + buf_z_table = cl::Buffer(context, CL_READ_ONLY_CACHE, buf_z_table_size, NULL, &err); + buf_packet = cl::Buffer(context, CL_READ_ONLY_CACHE, buf_packet_size, NULL, &err); + + //Read-Write + buf_a_size = image_size * sizeof(cl_float3); + buf_b_size = image_size * sizeof(cl_float3); + buf_n_size = image_size * sizeof(cl_float3); + buf_ir_size = image_size * sizeof(cl_float); + buf_a_filtered_size = image_size * sizeof(cl_float3); + buf_b_filtered_size = image_size * sizeof(cl_float3); + buf_edge_test_size = image_size * sizeof(cl_uchar); + buf_depth_size = image_size * sizeof(cl_float); + buf_ir_sum_size = image_size * sizeof(cl_float); + buf_filtered_size = image_size * sizeof(cl_float); + + buf_a = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_a_size, NULL, &err); + buf_b = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_b_size, NULL, &err); + buf_n = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_n_size, NULL, &err); + buf_ir = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_ir_size, NULL, &err); + buf_a_filtered = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_a_filtered_size, NULL, &err); + buf_b_filtered = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_b_filtered_size, NULL, &err); + buf_edge_test = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_edge_test_size, NULL, &err); + buf_depth = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_depth_size, NULL, &err); + buf_ir_sum = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_ir_sum_size, NULL, &err); + buf_filtered = cl::Buffer(context, CL_READ_WRITE_CACHE, buf_filtered_size, NULL, &err); + + kernel_processPixelStage1 = cl::Kernel(program, "processPixelStage1", &err); + kernel_processPixelStage1.setArg(0, buf_lut11to16); + kernel_processPixelStage1.setArg(1, buf_z_table); + kernel_processPixelStage1.setArg(2, buf_p0_table); + kernel_processPixelStage1.setArg(3, buf_packet); + kernel_processPixelStage1.setArg(4, buf_a); + kernel_processPixelStage1.setArg(5, buf_b); + kernel_processPixelStage1.setArg(6, buf_n); + kernel_processPixelStage1.setArg(7, buf_ir); + + kernel_filterPixelStage1 = cl::Kernel(program, "filterPixelStage1", &err); + kernel_filterPixelStage1.setArg(0, buf_a); + kernel_filterPixelStage1.setArg(1, buf_b); + kernel_filterPixelStage1.setArg(2, buf_n); + kernel_filterPixelStage1.setArg(3, buf_a_filtered); + kernel_filterPixelStage1.setArg(4, buf_b_filtered); + kernel_filterPixelStage1.setArg(5, buf_edge_test); + + kernel_processPixelStage2 = cl::Kernel(program, "processPixelStage2", &err); + kernel_processPixelStage2.setArg(0, config.EnableBilateralFilter ? buf_a_filtered : buf_a); + kernel_processPixelStage2.setArg(1, config.EnableBilateralFilter ? buf_b_filtered : buf_b); + kernel_processPixelStage2.setArg(2, buf_x_table); + kernel_processPixelStage2.setArg(3, buf_z_table); + kernel_processPixelStage2.setArg(4, buf_depth); + kernel_processPixelStage2.setArg(5, buf_ir_sum); + + kernel_filterPixelStage2 = cl::Kernel(program, "filterPixelStage2", &err); + kernel_filterPixelStage2.setArg(0, buf_depth); + kernel_filterPixelStage2.setArg(1, buf_ir_sum); + kernel_filterPixelStage2.setArg(2, buf_edge_test); + kernel_filterPixelStage2.setArg(3, buf_filtered); + + cl::Event event0, event1, event2, event3; + queue.enqueueWriteBuffer(buf_lut11to16, CL_FALSE, 0, buf_lut11to16_size, lut11to16, NULL, &event0); + queue.enqueueWriteBuffer(buf_p0_table, CL_FALSE, 0, buf_p0_table_size, p0_table, NULL, &event1); + queue.enqueueWriteBuffer(buf_x_table, CL_FALSE, 0, buf_x_table_size, x_table, NULL, &event2); + queue.enqueueWriteBuffer(buf_z_table, CL_FALSE, 0, buf_z_table_size, z_table, NULL, &event3); + + event0.wait(); + event1.wait(); + event2.wait(); + event3.wait(); + } + catch(const cl::Error &err) + { + std::cerr << OUT_NAME("init") "ERROR: " << err.what() << "(" << err.err() << ")" << std::endl; + + if(err.err() == CL_BUILD_PROGRAM_FAILURE) + { + std::cout << OUT_NAME("init") "Build Status: " << program.getBuildInfo(device) << std::endl; + std::cout << OUT_NAME("init") "Build Options:\t" << program.getBuildInfo(device) << std::endl; + std::cout << OUT_NAME("init") "Build Log:\t " << program.getBuildInfo(device) << std::endl; + } + + throw err; + } + programInitialized = true; + return true; + } + + void run(const DepthPacket &packet) + { + try + { + std::vector eventWrite(1), eventPPS1(1), eventFPS1(1), eventPPS2(1), eventFPS2(1); + cl::Event event0, event1; + + queue.enqueueWriteBuffer(buf_packet, CL_FALSE, 0, buf_packet_size, packet.buffer, NULL, &eventWrite[0]); + + queue.enqueueNDRangeKernel(kernel_processPixelStage1, cl::NullRange, cl::NDRange(image_size), cl::NullRange, &eventWrite, &eventPPS1[0]); + queue.enqueueReadBuffer(buf_ir, CL_FALSE, 0, buf_ir_size, ir_frame->data, &eventPPS1, &event0); + + if(config.EnableBilateralFilter) + { + queue.enqueueNDRangeKernel(kernel_filterPixelStage1, cl::NullRange, cl::NDRange(image_size), cl::NullRange, &eventPPS1, &eventFPS1[0]); + } + else + { + eventFPS1[0] = eventPPS1[0]; + } + + queue.enqueueNDRangeKernel(kernel_processPixelStage2, cl::NullRange, cl::NDRange(image_size), cl::NullRange, &eventFPS1, &eventPPS2[0]); + + if(config.EnableEdgeAwareFilter) + { + queue.enqueueNDRangeKernel(kernel_filterPixelStage2, cl::NullRange, cl::NDRange(image_size), cl::NullRange, &eventPPS2, &eventFPS2[0]); + } + else + { + eventFPS2[0] = eventPPS2[0]; + } + + queue.enqueueReadBuffer(config.EnableEdgeAwareFilter ? buf_filtered : buf_depth, CL_FALSE, 0, buf_depth_size, depth_frame->data, &eventFPS2, &event1); + event0.wait(); + event1.wait(); + } + catch(const cl::Error &err) + { + std::cerr << OUT_NAME("run") "ERROR: " << err.what() << " (" << err.err() << ")" << std::endl; + throw err; + return; + } + } + + bool readProgram(std::string &source) const + { + source = loadCLSource("src/opencl_depth_packet_processor.cl"); + return !source.empty(); + } + + void startTiming() + { + timing_current_start = cv::getTickCount(); + } + + void stopTiming() + { + timing_acc += (cv::getTickCount() - timing_current_start) / cv::getTickFrequency(); + timing_acc_n += 1.0; + + if(timing_acc_n >= 100.0) + { + double avg = (timing_acc / timing_acc_n); + std::cout << "[OpenCLDepthPacketProcessor] avg. time: " << (avg * 1000) << "ms -> ~" << (1.0 / avg) << "Hz" << std::endl; + timing_acc = 0.0; + timing_acc_n = 0.0; + } + } + + void newIrFrame() + { + ir_frame = new Frame(512, 424, 4); + } + + void newDepthFrame() + { + depth_frame = new Frame(512, 424, 4); + } + + void fill_trig_table(const libfreenect2::protocol::P0TablesResponse *p0table) + { + for(int r = 0; r < 424; ++r) + { + cl_float3 *it = &p0_table[r * 512]; + const uint16_t *it0 = &p0table->p0table0[r * 512]; + const uint16_t *it1 = &p0table->p0table1[r * 512]; + const uint16_t *it2 = &p0table->p0table2[r * 512]; + for(int c = 0; c < 512; ++c, ++it, ++it0, ++it1, ++it2) + { + it->s[0] = -((float) * it0) * 0.000031 * M_PI; + it->s[1] = -((float) * it1) * 0.000031 * M_PI; + it->s[2] = -((float) * it2) * 0.000031 * M_PI; + it->s[3] = 0.0f; + } + } + } +}; + +OpenCLDepthPacketProcessor::OpenCLDepthPacketProcessor(const int deviceId) : + impl_(new OpenCLDepthPacketProcessorImpl(deviceId)) +{ +} + +OpenCLDepthPacketProcessor::~OpenCLDepthPacketProcessor() +{ + delete impl_; +} + +void OpenCLDepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + impl_->config = config; + impl_->programInitialized = false; +} + +void OpenCLDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char *buffer, size_t buffer_length) +{ + libfreenect2::protocol::P0TablesResponse *p0table = (libfreenect2::protocol::P0TablesResponse *)buffer; + + if(buffer_length < sizeof(libfreenect2::protocol::P0TablesResponse)) + { + std::cerr << OUT_NAME("loadP0TablesFromCommandResponse") "P0Table response too short!" << std::endl; + return; + } + + impl_->fill_trig_table(p0table); +} + +void OpenCLDepthPacketProcessor::loadXTableFromFile(const char *filename) +{ + if(!loadBufferFromResources(filename, (unsigned char *)impl_->x_table, impl_->image_size * sizeof(float))) + { + std::cerr << OUT_NAME("loadXTableFromFile") "could not load x table from: " << filename << std::endl; + } +} + +void OpenCLDepthPacketProcessor::loadZTableFromFile(const char *filename) +{ + if(!loadBufferFromResources(filename, (unsigned char *)impl_->z_table, impl_->image_size * sizeof(float))) + { + std::cerr << OUT_NAME("loadZTableFromFile") "could not load z table from: " << filename << std::endl; + } +} + +void OpenCLDepthPacketProcessor::load11To16LutFromFile(const char *filename) +{ + if(!loadBufferFromResources(filename, (unsigned char *)impl_->lut11to16, 2048 * sizeof(cl_ushort))) + { + std::cerr << OUT_NAME("load11To16LutFromFile") "could not load lut table from: " << filename << std::endl; + } +} + +void OpenCLDepthPacketProcessor::process(const DepthPacket &packet) +{ + bool has_listener = this->listener_ != 0; + + if(!impl_->programInitialized && !impl_->initProgram()) + { + std::cerr << OUT_NAME("process") "could not initialize OpenCLDepthPacketProcessor" << std::endl; + return; + } + + impl_->startTiming(); + + impl_->run(packet); + + impl_->stopTiming(); + + if(has_listener) + { + if(this->listener_->onNewFrame(Frame::Ir, impl_->ir_frame)) + { + impl_->newIrFrame(); + } + + if(this->listener_->onNewFrame(Frame::Depth, impl_->depth_frame)) + { + impl_->newDepthFrame(); + } + } +} + +} /* namespace libfreenect2 */ + diff --git a/examples/k22v4l/src/opengl_depth_packet_processor.cpp b/examples/k22v4l/src/opengl_depth_packet_processor.cpp new file mode 100644 index 000000000..567453e60 --- /dev/null +++ b/examples/k22v4l/src/opengl_depth_packet_processor.cpp @@ -0,0 +1,952 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include +#include "flextGL.h" +#include + +#include +#include + + +#include + +namespace libfreenect2 +{ + +struct ChangeCurrentOpenGLContext +{ + GLFWwindow *last_ctx; + + ChangeCurrentOpenGLContext(GLFWwindow *new_context); + ~ChangeCurrentOpenGLContext(); +}; + +ChangeCurrentOpenGLContext::ChangeCurrentOpenGLContext(GLFWwindow *new_context) +{ + last_ctx = glfwGetCurrentContext(); + glfwMakeContextCurrent(new_context); +} + +ChangeCurrentOpenGLContext::~ChangeCurrentOpenGLContext() +{ + //std::cerr << "[ChangeCurrentOpenGLContext] restoring context!" << std::endl; + if(last_ctx != 0) + { + glfwMakeContextCurrent(last_ctx); + } + else + { + glfwMakeContextCurrent(0); + } +} + +class WithOpenGLBindings +{ +private: + OpenGLBindings *bindings; +protected: + WithOpenGLBindings() : bindings(0) {} + virtual ~WithOpenGLBindings() {} + + virtual void onOpenGLBindingsChanged(OpenGLBindings *b) { } +public: + void gl(OpenGLBindings *bindings) + { + this->bindings = bindings; + onOpenGLBindingsChanged(this->bindings); + } + + OpenGLBindings *gl() + { + return bindings; + } +}; + +std::string loadShaderSource(const std::string& filename) +{ + const unsigned char* data; + size_t length = 0; + + if(!loadResource(filename, &data, &length)) + { + std::cerr << "failed to load shader source!" << std::endl; + return ""; + } + + return std::string(reinterpret_cast(data), length); +} + +bool loadBufferFromFile(const std::string& filename, unsigned char *buffer, size_t n) +{ + bool success = true; + std::ifstream in(filename.c_str()); + + in.read(reinterpret_cast(buffer), n); + success = in.gcount() == n; + + in.close(); + + return success; +} + +struct ShaderProgram : public WithOpenGLBindings +{ + GLuint program, vertex_shader, fragment_shader; + + char error_buffer[2048]; + + ShaderProgram() : + program(0), + vertex_shader(0), + fragment_shader(0) + { + } + + void setVertexShader(const std::string& src) + { + const char* src_ = src.c_str(); + int length_ = src.length(); + vertex_shader = gl()->glCreateShader(GL_VERTEX_SHADER); + gl()->glShaderSource(vertex_shader, 1, &src_, &length_); + } + + void setFragmentShader(const std::string& src) + { + const char* src_ = src.c_str(); + int length_ = src.length(); + fragment_shader = gl()->glCreateShader(GL_FRAGMENT_SHADER); + gl()->glShaderSource(fragment_shader, 1, &src_, &length_); + } + + void build() + { + GLint status; + + gl()->glCompileShader(vertex_shader); + gl()->glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status); + + if(status != GL_TRUE) + { + gl()->glGetShaderInfoLog(vertex_shader, sizeof(error_buffer), NULL, error_buffer); + + std::cerr << "[ShaderProgram::build] failed to compile vertex shader!" << std::endl; + std::cerr << error_buffer << std::endl; + } + + gl()->glCompileShader(fragment_shader); + + gl()->glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status); + if(status != GL_TRUE) + { + gl()->glGetShaderInfoLog(fragment_shader, sizeof(error_buffer), NULL, error_buffer); + + std::cerr << "[ShaderProgram::build] failed to compile fragment shader!" << std::endl; + std::cerr << error_buffer << std::endl; + } + + program = gl()->glCreateProgram(); + gl()->glAttachShader(program, vertex_shader); + gl()->glAttachShader(program, fragment_shader); + + gl()->glLinkProgram(program); + + gl()->glGetProgramiv(program, GL_LINK_STATUS, &status); + + if(status != GL_TRUE) + { + gl()->glGetProgramInfoLog(program, sizeof(error_buffer), NULL, error_buffer); + std::cerr << "[ShaderProgram::build] failed to link shader program!" << std::endl; + std::cerr << error_buffer << std::endl; + } + } + + GLint getAttributeLocation(const std::string& name) + { + return gl()->glGetAttribLocation(program, name.c_str()); + } + + void setUniform(const std::string& name, GLint value) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if(idx == -1) return; + + gl()->glUniform1i(idx, value); + } + + void setUniform(const std::string& name, GLfloat value) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if(idx == -1) return; + + gl()->glUniform1f(idx, value); + } + + void setUniformVector3(const std::string& name, GLfloat value[3]) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if(idx == -1) return; + + gl()->glUniform3fv(idx, 1, value); + } + + void setUniformMatrix3(const std::string& name, GLfloat value[9]) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if(idx == -1) return; + + gl()->glUniformMatrix3fv(idx, 1, false, value); + } + + void use() + { + gl()->glUseProgram(program); + } +}; + +template +struct ImageFormat +{ + static const size_t BytesPerPixel = TBytesPerPixel; + static const GLenum InternalFormat = TInternalFormat; + static const GLenum Format = TFormat; + static const GLenum Type = TType; +}; + +typedef ImageFormat<1, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE> U8C1; +typedef ImageFormat<2, GL_R16I, GL_RED_INTEGER, GL_SHORT> S16C1; +typedef ImageFormat<2, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT> U16C1; +typedef ImageFormat<4, GL_R32F, GL_RED, GL_FLOAT> F32C1; +typedef ImageFormat<8, GL_RG32F, GL_RG, GL_FLOAT> F32C2; +typedef ImageFormat<12, GL_RGB32F, GL_RGB, GL_FLOAT> F32C3; +typedef ImageFormat<16, GL_RGBA32F, GL_RGBA, GL_FLOAT> F32C4; + +template +struct Texture : public WithOpenGLBindings +{ +protected: + size_t bytes_per_pixel, height, width; + +public: + GLuint texture; + unsigned char *data; + size_t size; + + Texture() : texture(0), data(0), size(0), bytes_per_pixel(FormatT::BytesPerPixel), height(0), width(0) + { + } + + void bindToUnit(GLenum unit) + { + gl()->glActiveTexture(unit); + glBindTexture(GL_TEXTURE_RECTANGLE, texture); + } + + void allocate(size_t new_width, size_t new_height) + { + width = new_width; + height = new_height; + size = height * width * bytes_per_pixel; + data = new unsigned char[size]; + + glGenTextures(1, &texture); + bindToUnit(GL_TEXTURE0); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, FormatT::InternalFormat, width, height, 0, FormatT::Format, FormatT::Type, 0); + } + + void upload() + { + bindToUnit(GL_TEXTURE0); + glTexSubImage2D(GL_TEXTURE_RECTANGLE, /*level*/0, /*xoffset*/0, /*yoffset*/0, width, height, FormatT::Format, FormatT::Type, data); + } + + void download() + { + downloadToBuffer(data); + } + + void downloadToBuffer(unsigned char *data) + { + glReadPixels(0, 0, width, height, FormatT::Format, FormatT::Type, data); + } + + void flipY() + { + flipYBuffer(data); + } + + void flipYBuffer(unsigned char *data) + { + typedef unsigned char type; + + int linestep = width * bytes_per_pixel / sizeof(type); + + type *first_line = reinterpret_cast(data), *last_line = reinterpret_cast(data) + (height - 1) * linestep; + + for(int y = 0; y < height / 2; ++y) + { + for(int x = 0; x < linestep; ++x, ++first_line, ++last_line) + { + std::swap(*first_line, *last_line); + } + last_line -= 2 * linestep; + } + } + + Frame *downloadToNewFrame() + { + Frame *f = new Frame(width, height, bytes_per_pixel); + downloadToBuffer(f->data); + flipYBuffer(f->data); + + return f; + } +}; + +struct OpenGLDepthPacketProcessorImpl : public WithOpenGLBindings +{ + GLFWwindow *opengl_context_ptr; + std::string shader_folder; + libfreenect2::DepthPacketProcessor::Config config; + + GLuint square_vbo, square_vao, stage1_framebuffer, filter1_framebuffer, stage2_framebuffer, filter2_framebuffer; + Texture lut11to16; + Texture p0table[3]; + Texture x_table, z_table; + + Texture input_data; + + Texture stage1_debug; + Texture stage1_data[3]; + Texture stage1_infrared; + + Texture filter1_data[2]; + Texture filter1_max_edge_test; + Texture filter1_debug; + + Texture stage2_debug; + + Texture stage2_depth; + Texture stage2_depth_and_ir_sum; + + Texture filter2_debug; + Texture filter2_depth; + + ShaderProgram stage1, filter1, stage2, filter2, debug; + + DepthPacketProcessor::Parameters params; + bool params_need_update; + + double timing_acc; + double timing_acc_n; + + double timing_current_start; + + bool do_debug; + + struct Vertex + { + float x, y; + float u, v; + }; + + OpenGLDepthPacketProcessorImpl(GLFWwindow *new_opengl_context_ptr, bool debug) : + opengl_context_ptr(new_opengl_context_ptr), + shader_folder("src/shader/"), + square_vao(0), + square_vbo(0), + stage1_framebuffer(0), + filter1_framebuffer(0), + stage2_framebuffer(0), + filter2_framebuffer(0), + params_need_update(true), + timing_acc(0), + timing_acc_n(0), + timing_current_start(0), + do_debug(debug) + { + } + + virtual ~OpenGLDepthPacketProcessorImpl() + { + if(gl() != 0) + { + delete gl(); + gl(0); + } + glfwDestroyWindow(opengl_context_ptr); + opengl_context_ptr = 0; + } + + virtual void onOpenGLBindingsChanged(OpenGLBindings *b) + { + lut11to16.gl(b); + p0table[0].gl(b); + p0table[1].gl(b); + p0table[2].gl(b); + x_table.gl(b); + z_table.gl(b); + + input_data.gl(b); + + stage1_debug.gl(b); + stage1_data[0].gl(b); + stage1_data[1].gl(b); + stage1_data[2].gl(b); + stage1_infrared.gl(b); + + filter1_data[0].gl(b); + filter1_data[1].gl(b); + filter1_max_edge_test.gl(b); + filter1_debug.gl(b); + + stage2_debug.gl(b); + + stage2_depth.gl(b); + stage2_depth_and_ir_sum.gl(b); + + filter2_debug.gl(b); + filter2_depth.gl(b); + + stage1.gl(b); + filter1.gl(b); + stage2.gl(b); + filter2.gl(b); + debug.gl(b); + } + + void startTiming() + { + timing_current_start = glfwGetTime(); + } + + void stopTiming() + { + timing_acc += (glfwGetTime() - timing_current_start); + timing_acc_n += 1.0; + + if(timing_acc_n >= 100.0) + { + double avg = (timing_acc / timing_acc_n); + std::cout << "[OpenGLDepthPacketProcessor] avg. time: " << (avg * 1000) << "ms -> ~" << (1.0/avg) << "Hz" << std::endl; + timing_acc = 0.0; + timing_acc_n = 0.0; + } + } + + void initialize() + { + ChangeCurrentOpenGLContext ctx(opengl_context_ptr); + + OpenGLBindings *b = new OpenGLBindings(); + flextInit(opengl_context_ptr, b); + gl(b); + + input_data.allocate(352, 424 * 10); + + for(int i = 0; i < 3; ++i) + stage1_data[i].allocate(512, 424); + + if(do_debug) stage1_debug.allocate(512, 424); + stage1_infrared.allocate(512, 424); + + for(int i = 0; i < 2; ++i) + filter1_data[i].allocate(512, 424); + + filter1_max_edge_test.allocate(512, 424); + if(do_debug) filter1_debug.allocate(512, 424); + + if(do_debug) stage2_debug.allocate(512, 424); + stage2_depth.allocate(512, 424); + stage2_depth_and_ir_sum.allocate(512, 424); + + if(do_debug) filter2_debug.allocate(512, 424); + filter2_depth.allocate(512, 424); + + stage1.setVertexShader(loadShaderSource(shader_folder + "default.vs")); + stage1.setFragmentShader(loadShaderSource(shader_folder + "stage1.fs")); + stage1.build(); + + filter1.setVertexShader(loadShaderSource(shader_folder + "default.vs")); + filter1.setFragmentShader(loadShaderSource(shader_folder + "filter1.fs")); + filter1.build(); + + stage2.setVertexShader(loadShaderSource(shader_folder + "default.vs")); + stage2.setFragmentShader(loadShaderSource(shader_folder + "stage2.fs")); + stage2.build(); + + filter2.setVertexShader(loadShaderSource(shader_folder + "default.vs")); + filter2.setFragmentShader(loadShaderSource(shader_folder + "filter2.fs")); + filter2.build(); + + if(do_debug) + { + debug.setVertexShader(loadShaderSource(shader_folder + "default.vs")); + debug.setFragmentShader(loadShaderSource(shader_folder + "debug.fs")); + debug.build(); + } + + GLenum debug_attachment = do_debug ? GL_COLOR_ATTACHMENT0 : GL_NONE; + + gl()->glGenFramebuffers(1, &stage1_framebuffer); + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, stage1_framebuffer); + + const GLenum stage1_buffers[] = { debug_attachment, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4 }; + gl()->glDrawBuffers(5, stage1_buffers); + + if(do_debug) gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, stage1_debug.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, stage1_data[0].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_RECTANGLE, stage1_data[1].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_RECTANGLE, stage1_data[2].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_RECTANGLE, stage1_infrared.texture, 0); + + gl()->glGenFramebuffers(1, &filter1_framebuffer); + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, filter1_framebuffer); + + const GLenum filter1_buffers[] = { debug_attachment, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; + gl()->glDrawBuffers(4, filter1_buffers); + + if(do_debug) gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, filter1_debug.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, filter1_data[0].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_RECTANGLE, filter1_data[1].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_RECTANGLE, filter1_max_edge_test.texture, 0); + + gl()->glGenFramebuffers(1, &stage2_framebuffer); + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, stage2_framebuffer); + + const GLenum stage2_buffers[] = { debug_attachment, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; + gl()->glDrawBuffers(3, stage2_buffers); + + if(do_debug) gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, stage2_debug.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, stage2_depth.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_RECTANGLE, stage2_depth_and_ir_sum.texture, 0); + + gl()->glGenFramebuffers(1, &filter2_framebuffer); + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, filter2_framebuffer); + + const GLenum filter2_buffers[] = { debug_attachment, GL_COLOR_ATTACHMENT1 }; + gl()->glDrawBuffers(2, filter2_buffers); + + if(do_debug) gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, filter2_debug.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, filter2_depth.texture, 0); + + Vertex bl = {-1.0f, -1.0f, 0.0f, 0.0f }, br = { 1.0f, -1.0f, 512.0f, 0.0f }, tl = {-1.0f, 1.0f, 0.0f, 424.0f }, tr = { 1.0f, 1.0f, 512.0f, 424.0f }; + Vertex vertices[] = { + bl, tl, tr, tr, br, bl + }; + gl()->glGenBuffers(1, &square_vbo); + gl()->glGenVertexArrays(1, &square_vao); + + gl()->glBindVertexArray(square_vao); + gl()->glBindBuffer(GL_ARRAY_BUFFER, square_vbo); + gl()->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + GLint position_attr = stage1.getAttributeLocation("Position"); + gl()->glVertexAttribPointer(position_attr, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0); + gl()->glEnableVertexAttribArray(position_attr); + + GLint texcoord_attr = stage1.getAttributeLocation("TexCoord"); + gl()->glVertexAttribPointer(texcoord_attr, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(2 * sizeof(float))); + gl()->glEnableVertexAttribArray(texcoord_attr); + } + + void deinitialize() + { + } + + void updateShaderParametersForProgram(ShaderProgram &program) + { + if(!params_need_update) return; + + program.setUniform("Params.ab_multiplier", params.ab_multiplier); + program.setUniformVector3("Params.ab_multiplier_per_frq", params.ab_multiplier_per_frq); + program.setUniform("Params.ab_output_multiplier", params.ab_output_multiplier); + + program.setUniformVector3("Params.phase_in_rad", params.phase_in_rad); + + program.setUniform("Params.joint_bilateral_ab_threshold", params.joint_bilateral_ab_threshold); + program.setUniform("Params.joint_bilateral_max_edge", params.joint_bilateral_max_edge); + program.setUniform("Params.joint_bilateral_exp", params.joint_bilateral_exp); + program.setUniformMatrix3("Params.gaussian_kernel", params.gaussian_kernel); + + program.setUniform("Params.phase_offset", params.phase_offset); + program.setUniform("Params.unambigious_dist", params.unambigious_dist); + program.setUniform("Params.individual_ab_threshold", params.individual_ab_threshold); + program.setUniform("Params.ab_threshold", params.ab_threshold); + program.setUniform("Params.ab_confidence_slope", params.ab_confidence_slope); + program.setUniform("Params.ab_confidence_offset", params.ab_confidence_offset); + program.setUniform("Params.min_dealias_confidence", params.min_dealias_confidence); + program.setUniform("Params.max_dealias_confidence", params.max_dealias_confidence); + + program.setUniform("Params.edge_ab_avg_min_value", params.edge_ab_avg_min_value); + program.setUniform("Params.edge_ab_std_dev_threshold", params.edge_ab_std_dev_threshold); + program.setUniform("Params.edge_close_delta_threshold", params.edge_close_delta_threshold); + program.setUniform("Params.edge_far_delta_threshold", params.edge_far_delta_threshold); + program.setUniform("Params.edge_max_delta_threshold", params.edge_max_delta_threshold); + program.setUniform("Params.edge_avg_delta_threshold", params.edge_avg_delta_threshold); + program.setUniform("Params.max_edge_count", params.max_edge_count); + + program.setUniform("Params.min_depth", params.min_depth); + program.setUniform("Params.max_depth", params.max_depth); + } + + void run(Frame **ir, Frame **depth) + { + // data processing 1 + glViewport(0, 0, 512, 424); + stage1.use(); + updateShaderParametersForProgram(stage1); + + p0table[0].bindToUnit(GL_TEXTURE0); + stage1.setUniform("P0Table0", 0); + p0table[1].bindToUnit(GL_TEXTURE1); + stage1.setUniform("P0Table1", 1); + p0table[2].bindToUnit(GL_TEXTURE2); + stage1.setUniform("P0Table2", 2); + lut11to16.bindToUnit(GL_TEXTURE3); + stage1.setUniform("Lut11to16", 3); + input_data.bindToUnit(GL_TEXTURE4); + stage1.setUniform("Data", 4); + z_table.bindToUnit(GL_TEXTURE5); + stage1.setUniform("ZTable", 5); + + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, stage1_framebuffer); + glClear(GL_COLOR_BUFFER_BIT); + + gl()->glBindVertexArray(square_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + + if(ir != 0) + { + gl()->glBindFramebuffer(GL_READ_FRAMEBUFFER, stage1_framebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT4); + *ir = stage1_infrared.downloadToNewFrame(); + } + + if(config.EnableBilateralFilter) + { + // bilateral filter + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, filter1_framebuffer); + glClear(GL_COLOR_BUFFER_BIT); + + filter1.use(); + updateShaderParametersForProgram(filter1); + + stage1_data[0].bindToUnit(GL_TEXTURE0); + filter1.setUniform("A", 0); + stage1_data[1].bindToUnit(GL_TEXTURE1); + filter1.setUniform("B", 1); + stage1_data[2].bindToUnit(GL_TEXTURE2); + filter1.setUniform("Norm", 2); + + gl()->glBindVertexArray(square_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + } + // data processing 2 + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, stage2_framebuffer); + glClear(GL_COLOR_BUFFER_BIT); + + stage2.use(); + updateShaderParametersForProgram(stage2); + + if(config.EnableBilateralFilter) + { + filter1_data[0].bindToUnit(GL_TEXTURE0); + filter1_data[1].bindToUnit(GL_TEXTURE1); + } + else + { + stage1_data[0].bindToUnit(GL_TEXTURE0); + stage1_data[1].bindToUnit(GL_TEXTURE1); + } + stage2.setUniform("A", 0); + stage2.setUniform("B", 1); + x_table.bindToUnit(GL_TEXTURE2); + stage2.setUniform("XTable", 2); + z_table.bindToUnit(GL_TEXTURE3); + stage2.setUniform("ZTable", 3); + + gl()->glBindVertexArray(square_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + + if(config.EnableEdgeAwareFilter) + { + // edge aware filter + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, filter2_framebuffer); + glClear(GL_COLOR_BUFFER_BIT); + + filter2.use(); + updateShaderParametersForProgram(filter2); + + stage2_depth_and_ir_sum.bindToUnit(GL_TEXTURE0); + filter2.setUniform("DepthAndIrSum", 0); + filter1_max_edge_test.bindToUnit(GL_TEXTURE1); + filter2.setUniform("MaxEdgeTest", 1); + + gl()->glBindVertexArray(square_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + if(depth != 0) + { + gl()->glBindFramebuffer(GL_READ_FRAMEBUFFER, filter2_framebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT1); + *depth = filter2_depth.downloadToNewFrame(); + } + } + else + { + if(depth != 0) + { + gl()->glBindFramebuffer(GL_READ_FRAMEBUFFER, stage2_framebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT1); + *depth = stage2_depth.downloadToNewFrame(); + } + } + + if(do_debug) + { + // debug drawing + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT); + + gl()->glBindVertexArray(square_vao); + + debug.use(); + stage2_debug.bindToUnit(GL_TEXTURE0); + debug.setUniform("Debug", 0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + glViewport(512, 0, 512, 424); + filter2_debug.bindToUnit(GL_TEXTURE0); + debug.setUniform("Debug", 0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + glViewport(0, 424, 512, 424); + stage1_debug.bindToUnit(GL_TEXTURE0); + debug.setUniform("Debug", 0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + } + + params_need_update = false; + } +}; + +OpenGLDepthPacketProcessor::OpenGLDepthPacketProcessor(void *parent_opengl_context_ptr, bool debug) +{ + GLFWwindow* parent_window = (GLFWwindow *)parent_opengl_context_ptr; + + // init glfw - if already initialized nothing happens + glfwInit(); + + // setup context + glfwDefaultWindowHints(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + #ifdef __APPLE__ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + #endif + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_VISIBLE, debug ? GL_TRUE : GL_FALSE); + + GLFWwindow* window = glfwCreateWindow(1024, 848, "OpenGLDepthPacketProcessor", 0, parent_window); + + impl_ = new OpenGLDepthPacketProcessorImpl(window, debug); + impl_->initialize(); +} + +OpenGLDepthPacketProcessor::~OpenGLDepthPacketProcessor() +{ + delete impl_; +} + + +void OpenGLDepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + impl_->config = config; + + impl_->params.min_depth = impl_->config.MinDepth * 1000.0f; + impl_->params.max_depth = impl_->config.MaxDepth * 1000.0f; + + impl_->params_need_update = true; +} + +void OpenGLDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length) +{ + ChangeCurrentOpenGLContext ctx(impl_->opengl_context_ptr); + + size_t n = 512 * 424; + libfreenect2::protocol::P0TablesResponse* p0table = (libfreenect2::protocol::P0TablesResponse*)buffer; + + impl_->p0table[0].allocate(512, 424); + std::copy(reinterpret_cast(p0table->p0table0), reinterpret_cast(p0table->p0table0 + n), impl_->p0table[0].data); + impl_->p0table[0].flipY(); + impl_->p0table[0].upload(); + + impl_->p0table[1].allocate(512, 424); + std::copy(reinterpret_cast(p0table->p0table1), reinterpret_cast(p0table->p0table1 + n), impl_->p0table[1].data); + impl_->p0table[1].flipY(); + impl_->p0table[1].upload(); + + impl_->p0table[2].allocate(512, 424); + std::copy(reinterpret_cast(p0table->p0table2), reinterpret_cast(p0table->p0table2 + n), impl_->p0table[2].data); + impl_->p0table[2].flipY(); + impl_->p0table[2].upload(); + +} + +void OpenGLDepthPacketProcessor::loadP0TablesFromFiles(const char* p0_filename, const char* p1_filename, const char* p2_filename) +{ + ChangeCurrentOpenGLContext ctx(impl_->opengl_context_ptr); + + impl_->p0table[0].allocate(512, 424); + if(loadBufferFromFile(p0_filename, impl_->p0table[0].data, impl_->p0table[0].size)) + { + impl_->p0table[0].upload(); + } + else + { + std::cerr << "[OpenGLDepthPacketProcessor::loadP0TablesFromFiles] Loading p0table 0 from '" << p0_filename << "' failed!" << std::endl; + } + + impl_->p0table[1].allocate(512, 424); + if(loadBufferFromFile(p1_filename, impl_->p0table[1].data, impl_->p0table[1].size)) + { + impl_->p0table[1].upload(); + } + else + { + std::cerr << "[OpenGLDepthPacketProcessor::loadP0TablesFromFiles] Loading p0table 1 from '" << p1_filename << "' failed!" << std::endl; + } + + impl_->p0table[2].allocate(512, 424); + if(loadBufferFromFile(p2_filename, impl_->p0table[2].data, impl_->p0table[2].size)) + { + impl_->p0table[2].upload(); + } + else + { + std::cerr << "[OpenGLDepthPacketProcessor::loadP0TablesFromFiles] Loading p0table 2 from '" << p2_filename << "' failed!" << std::endl; + } +} + +void OpenGLDepthPacketProcessor::loadXTableFromFile(const char* filename) +{ + ChangeCurrentOpenGLContext ctx(impl_->opengl_context_ptr); + + impl_->x_table.allocate(512, 424); + const unsigned char *data; + size_t length; + + if(loadResource("xTable.bin", &data, &length)) + { + std::copy(data, data + length, impl_->x_table.data); + impl_->x_table.upload(); + } + else + { + std::cerr << "[OpenGLDepthPacketProcessor::loadXTableFromFile] Loading xtable from resource 'xTable.bin' failed!" << std::endl; + } +} + +void OpenGLDepthPacketProcessor::loadZTableFromFile(const char* filename) +{ + ChangeCurrentOpenGLContext ctx(impl_->opengl_context_ptr); + + impl_->z_table.allocate(512, 424); + + const unsigned char *data; + size_t length; + + if(loadResource("zTable.bin", &data, &length)) + { + std::copy(data, data + length, impl_->z_table.data); + impl_->z_table.upload(); + } + else + { + std::cerr << "[OpenGLDepthPacketProcessor::loadZTableFromFile] Loading ztable from resource 'zTable.bin' failed!" << std::endl; + } +} + +void OpenGLDepthPacketProcessor::load11To16LutFromFile(const char* filename) +{ + ChangeCurrentOpenGLContext ctx(impl_->opengl_context_ptr); + + impl_->lut11to16.allocate(2048, 1); + + const unsigned char *data; + size_t length; + + if(loadResource("11to16.bin", &data, &length)) + { + std::copy(data, data + length, impl_->lut11to16.data); + impl_->lut11to16.upload(); + } + else + { + std::cerr << "[OpenGLDepthPacketProcessor::load11To16LutFromFile] Loading 11to16 lut from resource '11to16.bin' failed!" << std::endl; + } +} + +void OpenGLDepthPacketProcessor::process(const DepthPacket &packet) +{ + bool has_listener = this->listener_ != 0; + Frame *ir = 0, *depth = 0; + + impl_->startTiming(); + + glfwMakeContextCurrent(impl_->opengl_context_ptr); + + std::copy(packet.buffer, packet.buffer + packet.buffer_length, impl_->input_data.data); + impl_->input_data.upload(); + impl_->run(has_listener ? &ir : 0, has_listener ? &depth : 0); + + if(impl_->do_debug) glfwSwapBuffers(impl_->opengl_context_ptr); + + impl_->stopTiming(); + + if(has_listener) + { + if(!this->listener_->onNewFrame(Frame::Ir, ir)) + { + delete ir; + } + + if(!this->listener_->onNewFrame(Frame::Depth, depth)) + { + delete depth; + } + } +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/packet_pipeline.cpp b/examples/k22v4l/src/packet_pipeline.cpp new file mode 100644 index 000000000..1c66f66b6 --- /dev/null +++ b/examples/k22v4l/src/packet_pipeline.cpp @@ -0,0 +1,139 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include + +namespace libfreenect2 +{ + +PacketPipeline::~PacketPipeline() +{ +} + +void BasePacketPipeline::initialize() +{ + rgb_parser_ = new RgbPacketStreamParser(); + depth_parser_ = new DepthPacketStreamParser(); + + rgb_processor_ = new TurboJpegRgbPacketProcessor(); + depth_processor_ = createDepthPacketProcessor(); + + async_rgb_processor_ = new AsyncPacketProcessor(rgb_processor_); + async_depth_processor_ = new AsyncPacketProcessor(depth_processor_); + + rgb_parser_->setPacketProcessor(async_rgb_processor_); + depth_parser_->setPacketProcessor(async_depth_processor_); +} + +BasePacketPipeline::~BasePacketPipeline() +{ + delete async_rgb_processor_; + delete async_depth_processor_; + delete rgb_processor_; + delete depth_processor_; + delete rgb_parser_; + delete depth_parser_; +} + +BasePacketPipeline::PacketParser *BasePacketPipeline::getRgbPacketParser() const +{ + return rgb_parser_; +} + +BasePacketPipeline::PacketParser *BasePacketPipeline::getIrPacketParser() const +{ + return depth_parser_; +} + +RgbPacketProcessor *BasePacketPipeline::getRgbPacketProcessor() const +{ + return rgb_processor_; +} + +DepthPacketProcessor *BasePacketPipeline::getDepthPacketProcessor() const +{ + return depth_processor_; +} + +CpuPacketPipeline::CpuPacketPipeline() +{ + initialize(); +} + +CpuPacketPipeline::~CpuPacketPipeline() { } + +DepthPacketProcessor *CpuPacketPipeline::createDepthPacketProcessor() +{ + CpuDepthPacketProcessor *depth_processor = new CpuDepthPacketProcessor(); + depth_processor->load11To16LutFromFile("11to16.bin"); + depth_processor->loadXTableFromFile("xTable.bin"); + depth_processor->loadZTableFromFile("zTable.bin"); + + return depth_processor; +} + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT +OpenGLPacketPipeline::OpenGLPacketPipeline(void *parent_opengl_context, bool debug) : parent_opengl_context_(parent_opengl_context), debug_(debug) +{ + initialize(); +} + +OpenGLPacketPipeline::~OpenGLPacketPipeline() { } + +DepthPacketProcessor *OpenGLPacketPipeline::createDepthPacketProcessor() +{ + OpenGLDepthPacketProcessor *depth_processor = new OpenGLDepthPacketProcessor(parent_opengl_context_, debug_); + depth_processor->load11To16LutFromFile("11to16.bin"); + depth_processor->loadXTableFromFile("xTable.bin"); + depth_processor->loadZTableFromFile("zTable.bin"); + + return depth_processor; +} +#endif // LIBFREENECT2_WITH_OPENGL_SUPPORT + + +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + +OpenCLPacketPipeline::OpenCLPacketPipeline(const int deviceId) : deviceId(deviceId) +{ + initialize(); +} + +OpenCLPacketPipeline::~OpenCLPacketPipeline() { } + +DepthPacketProcessor *OpenCLPacketPipeline::createDepthPacketProcessor() +{ + OpenCLDepthPacketProcessor *depth_processor = new OpenCLDepthPacketProcessor(deviceId); + depth_processor->load11To16LutFromFile("11to16.bin"); + depth_processor->loadXTableFromFile("xTable.bin"); + depth_processor->loadZTableFromFile("zTable.bin"); + + return depth_processor; +} +#endif // LIBFREENECT2_WITH_OPENCL_SUPPORT + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/resource.cpp b/examples/k22v4l/src/resource.cpp new file mode 100644 index 000000000..f3253de40 --- /dev/null +++ b/examples/k22v4l/src/resource.cpp @@ -0,0 +1,62 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include + +namespace libfreenect2 +{ + +struct ResourceDescriptor +{ + const char *filename; + const unsigned char *data; + size_t length; +}; + +#ifdef RESOURCES_INC +#include "resources.inc" +#else +ResourceDescriptor resource_descriptors[] = {}; +#endif + +bool loadResource(const std::string &name, unsigned char const**data, size_t *length) +{ + bool result = false; + + for(int i = 0; i < resource_descriptors_length; ++i) + { + if(name.compare(resource_descriptors[i].filename) == 0) + { + *data = resource_descriptors[i].data; + *length = resource_descriptors[i].length; + result = true; + break; + } + } + return result; +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/rgb_packet_processor.cpp b/examples/k22v4l/src/rgb_packet_processor.cpp new file mode 100644 index 000000000..2855b1658 --- /dev/null +++ b/examples/k22v4l/src/rgb_packet_processor.cpp @@ -0,0 +1,68 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include + +#include +#include + +namespace libfreenect2 +{ + +RgbPacketProcessor::RgbPacketProcessor() : + listener_(0) +{ +} + +RgbPacketProcessor::~RgbPacketProcessor() +{ +} + +void RgbPacketProcessor::setFrameListener(libfreenect2::FrameListener *listener) +{ + listener_ = listener; +} + +DumpRgbPacketProcessor::DumpRgbPacketProcessor() +{ +} + +DumpRgbPacketProcessor::~DumpRgbPacketProcessor() +{ +} + +void DumpRgbPacketProcessor::process(const RgbPacket &packet) +{ + //std::stringstream name; + //name << packet->sequence << "_" << packet->unknown0 << "_" << jpeg_buffer_length << ".jpeg"; + // + //std::ofstream file(name.str().c_str()); + //file.write(reinterpret_cast(packet->jpeg_buffer), jpeg_buffer_length); + //file.close(); +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/rgb_packet_stream_parser.cpp b/examples/k22v4l/src/rgb_packet_stream_parser.cpp new file mode 100644 index 000000000..fa69ac80f --- /dev/null +++ b/examples/k22v4l/src/rgb_packet_stream_parser.cpp @@ -0,0 +1,106 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include +#include + +namespace libfreenect2 +{ + + +LIBFREENECT2_PACK(struct RawRgbPacket +{ + uint32_t sequence; + uint32_t unknown0; + + unsigned char jpeg_buffer[0]; +}); + +RgbPacketStreamParser::RgbPacketStreamParser() : + processor_(noopProcessor()) +{ + buffer_.allocate(1920*1080*3+sizeof(RgbPacket)); +} + +RgbPacketStreamParser::~RgbPacketStreamParser() +{ +} + +void RgbPacketStreamParser::setPacketProcessor(BaseRgbPacketProcessor *processor) +{ + processor_ = (processor != 0) ? processor : noopProcessor(); +} + +void RgbPacketStreamParser::onDataReceived(unsigned char* buffer, size_t length) +{ + Buffer &fb = buffer_.front(); + + // package containing data + if(length > 0) + { + if(fb.length + length <= fb.capacity) + { + memcpy(fb.data + fb.length, buffer, length); + fb.length += length; + } + else + { + std::cerr << "[RgbPacketStreamParser::handleNewData] buffer overflow!" << std::endl; + } + + // not full transfer buffer and we already have some data -> signals end of rgb image packet + // TODO: better method, is unknown0 a magic? detect JPEG magic? + if(length < 0x4000 && fb.length > sizeof(RgbPacket)) + { + // can the processor handle the next image? + if(processor_->ready()) + { + buffer_.swap(); + Buffer &bb = buffer_.back(); + + RawRgbPacket *raw_packet = reinterpret_cast(bb.data); + RgbPacket rgb_packet; + rgb_packet.sequence = raw_packet->sequence; + rgb_packet.jpeg_buffer = raw_packet->jpeg_buffer; + rgb_packet.jpeg_buffer_length = bb.length - sizeof(RawRgbPacket); + + // call the processor + processor_->process(rgb_packet); + } + else + { + std::cerr << "[RgbPacketStreamParser::handleNewData] skipping rgb packet!" << std::endl; + } + + // reset front buffer + buffer_.front().length = 0; + } + } +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/shader/debug.fs b/examples/k22v4l/src/shader/debug.fs new file mode 100644 index 000000000..34dac1298 --- /dev/null +++ b/examples/k22v4l/src/shader/debug.fs @@ -0,0 +1,16 @@ +#version 330 + +uniform sampler2DRect Data; + +in VertexData { + vec2 TexCoord; +} FragmentIn; + +layout(location = 0) out vec4 Color; + +void main(void) +{ + ivec2 uv = ivec2(FragmentIn.TexCoord.x, FragmentIn.TexCoord.y); + + Color = texelFetch(Data, uv); +} \ No newline at end of file diff --git a/examples/k22v4l/src/shader/default.vs b/examples/k22v4l/src/shader/default.vs new file mode 100644 index 000000000..8cb838b5a --- /dev/null +++ b/examples/k22v4l/src/shader/default.vs @@ -0,0 +1,14 @@ +#version 330 + +in vec2 Position; +in vec2 TexCoord; + +out VertexData { + vec2 TexCoord; +} VertexOut; + +void main(void) +{ + gl_Position = vec4(Position, 0.0, 1.0); + VertexOut.TexCoord = TexCoord; +} \ No newline at end of file diff --git a/examples/k22v4l/src/shader/filter1.fs b/examples/k22v4l/src/shader/filter1.fs new file mode 100644 index 000000000..2fb526f6b --- /dev/null +++ b/examples/k22v4l/src/shader/filter1.fs @@ -0,0 +1,126 @@ +#version 330 + +struct Parameters +{ + float ab_multiplier; + vec3 ab_multiplier_per_frq; + float ab_output_multiplier; + + vec3 phase_in_rad; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + mat3 gaussian_kernel; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; +}; + +uniform sampler2DRect A; +uniform sampler2DRect B; +uniform sampler2DRect Norm; + +uniform Parameters Params; + +in VertexData { + vec2 TexCoord; +} FragmentIn; + +layout(location = 0) out vec4 Debug; +layout(location = 1) out vec3 FilterA; +layout(location = 2) out vec3 FilterB; +layout(location = 3) out uint MaxEdgeTest; + +void applyBilateralFilter(ivec2 uv) +{ + vec3 threshold = vec3((Params.joint_bilateral_ab_threshold * Params.joint_bilateral_ab_threshold) / (Params.ab_multiplier * Params.ab_multiplier)); + vec3 joint_bilateral_exp = vec3(Params.joint_bilateral_exp); + + vec3 self_a = texelFetch(A, uv).xyz; + vec3 self_b = texelFetch(B, uv).xyz; + vec3 self_norm = texelFetch(Norm, uv).xyz; + vec3 self_normalized_a = self_a / self_norm; + vec3 self_normalized_b = self_b / self_norm; + + vec4 weight_acc = vec4(0.0); + vec4 weighted_a_acc = vec4(0.0); + vec4 weighted_b_acc = vec4(0.0); + + bvec3 c0 = lessThan(self_norm * self_norm, threshold); + + threshold = mix(threshold, vec3(0.0), c0); + joint_bilateral_exp = mix(joint_bilateral_exp, vec3(0.0), c0); + + for(int y = 0; y < 3; ++y) + { + for(int x = 0; x < 3; ++x) + { + ivec2 ouv = uv + ivec2(x - 1, y - 1); + + vec3 other_a = texelFetch(A, ouv).xyz; + vec3 other_b = texelFetch(B, ouv).xyz; + vec3 other_norm = texelFetch(Norm, ouv).xyz; + + vec3 other_normalized_a = other_a / other_norm; + vec3 other_normalized_b = other_b / other_norm; + + bvec3 c1 = lessThan(other_norm * other_norm, threshold); + + vec3 dist = 0.5f * (1.0f - (self_normalized_a * other_normalized_a + self_normalized_b * other_normalized_b)); + vec3 weight = mix(Params.gaussian_kernel[x][y] * exp(-1.442695 * joint_bilateral_exp * dist), vec3(0.0), c1); + + weighted_a_acc.xyz += weight * other_a; + weighted_b_acc.xyz += weight * other_b; + weight_acc.xyz += weight; + + // TODO: this sucks, but otherwise opengl reports error: temporary registers exceeded :( + weighted_a_acc.w += mix(dist.x, 0, c1.x); + weighted_b_acc.w += mix(dist.y, 0, c1.y); + weight_acc.w += mix(dist.z, 0, c1.z); + } + } + + bvec3 c2 = lessThan(vec3(0.0), weight_acc.xyz); + FilterA = mix(vec3(0.0), weighted_a_acc.xyz / weight_acc.xyz, c2); + FilterB = mix(vec3(0.0), weighted_b_acc.xyz / weight_acc.xyz, c2); + + if(uv.x < 1 || uv.y < 1 || uv.x > 510 || uv.y > 422) + { + FilterA = self_a; + FilterB = self_b; + } + + vec3 dist_acc = vec3(weighted_a_acc.w, weighted_b_acc.w, weight_acc.w); + MaxEdgeTest = uint(all(lessThan(dist_acc, vec3(Params.joint_bilateral_max_edge)))); + //Debug = vec4(vec3(MaxEdgeTest), 1); +} + +void main(void) +{ + ivec2 uv = ivec2(FragmentIn.TexCoord.x, FragmentIn.TexCoord.y); + + applyBilateralFilter(uv); + + vec3 norm = sqrt(FilterA * FilterA + FilterB * FilterB); + float i = min(dot(norm, vec3(0.333333333 * Params.ab_multiplier * Params.ab_output_multiplier)), 65535.0); + + Debug = vec4(vec3(i, i, i) / 65535.0, 1); +} \ No newline at end of file diff --git a/examples/k22v4l/src/shader/filter2.fs b/examples/k22v4l/src/shader/filter2.fs new file mode 100644 index 000000000..03355e4a7 --- /dev/null +++ b/examples/k22v4l/src/shader/filter2.fs @@ -0,0 +1,134 @@ +#version 330 + +struct Parameters +{ + float ab_multiplier; + vec3 ab_multiplier_per_frq; + float ab_output_multiplier; + + vec3 phase_in_rad; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + mat3 gaussian_kernel; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; +}; + +uniform sampler2DRect DepthAndIrSum; +uniform usampler2DRect MaxEdgeTest; + +uniform Parameters Params; + +in VertexData { + vec2 TexCoord; +} FragmentIn; + +layout(location = 0) out vec4 Debug; +layout(location = 1) out float FilterDepth; + +void applyEdgeAwareFilter(ivec2 uv) +{ + vec2 v = texelFetch(DepthAndIrSum, uv).xy; + + if(v.x >= Params.min_depth && v.x <= Params.max_depth) + { + if(uv.x < 1 || uv.y < 1 || uv.x > 510 || uv.y > 422) + { + FilterDepth = v.x; + } + else + { + bool max_edge_test_ok = texelFetch(MaxEdgeTest, uv).x > 0u; + + float ir_sum_acc = v.y, squared_ir_sum_acc = v.y * v.y, min_depth = v.x, max_depth = v.x; + + for(int yi = -1; yi < 2; ++yi) + { + for(int xi = -1; xi < 2; ++xi) + { + if(yi == 0 && xi == 0) continue; + + vec2 other = texelFetch(DepthAndIrSum, uv + ivec2(xi, yi)).xy; + + ir_sum_acc += other.y; + squared_ir_sum_acc += other.y * other.y; + + if(0.0f < other.x) + { + min_depth = min(min_depth, other.x); + max_depth = max(max_depth, other.x); + } + } + } + + float tmp0 = sqrt(squared_ir_sum_acc * 9.0f - ir_sum_acc * ir_sum_acc) / 9.0f; + float edge_avg = max(ir_sum_acc / 9.0f, Params.edge_ab_avg_min_value); + tmp0 /= edge_avg; + + float abs_min_diff = abs(v.x - min_depth); + float abs_max_diff = abs(v.x - max_depth); + + float avg_diff = (abs_min_diff + abs_max_diff) * 0.5f; + float max_abs_diff = max(abs_min_diff, abs_max_diff); + + bool cond0 = + 0.0f < v.x && + tmp0 >= Params.edge_ab_std_dev_threshold && + Params.edge_close_delta_threshold < abs_min_diff && + Params.edge_far_delta_threshold < abs_max_diff && + Params.edge_max_delta_threshold < max_abs_diff && + Params.edge_avg_delta_threshold < avg_diff; + + FilterDepth = cond0 ? 0.0f : v.x; + + if(!cond0) + { + if(max_edge_test_ok) + { + float tmp1 = 1500.0f > v.x ? 30.0f : 0.02f * v.x; + float edge_count = 0.0f; + + FilterDepth = edge_count > Params.max_edge_count ? 0.0f : v.x; + } + else + { + FilterDepth = !max_edge_test_ok ? 0.0f : v.x; + //FilterDepth = true ? FilterDepth : v.x; + } + } + } + } + else + { + FilterDepth = 0.0f; + } +} + +void main(void) +{ + ivec2 uv = ivec2(FragmentIn.TexCoord.x, FragmentIn.TexCoord.y); + + applyEdgeAwareFilter(uv); + + Debug = vec4(vec3(FilterDepth / Params.max_depth), 1); +} diff --git a/examples/k22v4l/src/shader/stage1.fs b/examples/k22v4l/src/shader/stage1.fs new file mode 100644 index 000000000..d2fcd0e78 --- /dev/null +++ b/examples/k22v4l/src/shader/stage1.fs @@ -0,0 +1,121 @@ +#version 330 + +struct Parameters +{ + float ab_multiplier; + vec3 ab_multiplier_per_frq; + float ab_output_multiplier; + + vec3 phase_in_rad; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + mat3 gaussian_kernel; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; +}; + +uniform usampler2DRect P0Table0; +uniform usampler2DRect P0Table1; +uniform usampler2DRect P0Table2; +uniform isampler2DRect Lut11to16; +uniform usampler2DRect Data; +uniform sampler2DRect ZTable; + +uniform Parameters Params; + +in VertexData { + vec2 TexCoord; +} FragmentIn; + +layout(location = 0) out vec4 Debug; + +layout(location = 1) out vec3 A; +layout(location = 2) out vec3 B; +layout(location = 3) out vec3 Norm; +layout(location = 4) out float Infrared; + +#define M_PI 3.1415926535897932384626433832795 + +int data(ivec2 uv) +{ + return int(texelFetch(Data, uv).x); +} + +float decode_data(ivec2 uv, int sub) +{ + int row_idx = 424 * sub + (uv.y < 212 ? uv.y + 212 : 423 - uv.y); + + int m = int(0xffffffff); + int bitmask = (((1 << 2) - 1) << 7) & m; + int idx = (((uv.x >> 2) + ((uv.x << 7) & bitmask)) * 11) & m; + + int col_idx = idx >> 4; + int upper_bytes = idx & 15; + int lower_bytes = 16 - upper_bytes; + + ivec2 data_idx0 = ivec2(col_idx, row_idx); + ivec2 data_idx1 = ivec2(col_idx + 1, row_idx); + + int lut_idx = (uv.x < 1 || 510 < uv.x || col_idx > 352) ? 0 : ((data(data_idx0) >> upper_bytes) | (data(data_idx1) << lower_bytes)) & 2047; + + return float(texelFetch(Lut11to16, ivec2(int(lut_idx), 0)).x); +} + +vec2 processMeasurementTriple(in ivec2 uv, in usampler2DRect p0table, in int offset, in float ab_multiplier_per_frq, inout bool saturated) +{ + float p0 = -float(texelFetch(p0table, uv).x) * 0.000031 * M_PI; + + vec3 v = vec3(decode_data(uv, offset + 0), decode_data(uv, offset + 1), decode_data(uv, offset + 2)); + + saturated = saturated && any(equal(v, vec3(32767.0))); + + float a = dot(v, cos( p0 + Params.phase_in_rad)) * ab_multiplier_per_frq; + float b = dot(v, sin(-p0 - Params.phase_in_rad)) * ab_multiplier_per_frq; + + return vec2(a, b); +} + +void main(void) +{ + ivec2 uv = ivec2(FragmentIn.TexCoord.x, FragmentIn.TexCoord.y); + + bool valid_pixel = 0.0 < texelFetch(ZTable, uv).x; + bvec3 saturated = bvec3(valid_pixel); + + vec2 ab0 = processMeasurementTriple(uv, P0Table0, 0, Params.ab_multiplier_per_frq.x, saturated.x); + vec2 ab1 = processMeasurementTriple(uv, P0Table1, 3, Params.ab_multiplier_per_frq.y, saturated.y); + vec2 ab2 = processMeasurementTriple(uv, P0Table2, 6, Params.ab_multiplier_per_frq.z, saturated.z); + + bvec3 invalid_pixel = bvec3(!valid_pixel); + + A = mix(vec3(ab0.x, ab1.x, ab2.x), vec3(0.0), invalid_pixel); + B = mix(vec3(ab0.y, ab1.y, ab2.y), vec3(0.0), invalid_pixel); + Norm = sqrt(A * A + B * B); + + A = mix(A, vec3(0.0), saturated); + B = mix(B, vec3(0.0), saturated); + + Infrared = min(dot(mix(Norm, vec3(65535.0), saturated), vec3(0.333333333 * Params.ab_multiplier * Params.ab_output_multiplier)), 65535.0); + + Debug = vec4(sqrt(vec3(Infrared / 65535.0)), 1.0); +} diff --git a/examples/k22v4l/src/shader/stage2.fs b/examples/k22v4l/src/shader/stage2.fs new file mode 100644 index 000000000..a06c28f13 --- /dev/null +++ b/examples/k22v4l/src/shader/stage2.fs @@ -0,0 +1,159 @@ +#version 330 + +struct Parameters +{ + float ab_multiplier; + vec3 ab_multiplier_per_frq; + float ab_output_multiplier; + + vec3 phase_in_rad; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + mat3 gaussian_kernel; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; +}; + +uniform sampler2DRect A; +uniform sampler2DRect B; +uniform sampler2DRect XTable; +uniform sampler2DRect ZTable; + +uniform Parameters Params; + +in VertexData { + vec2 TexCoord; +} FragmentIn; + +layout(location = 0) out vec4 Debug; +layout(location = 1) out float Depth; +layout(location = 2) out vec2 DepthAndIrSum; + +#define M_PI 3.1415926535897932384626433832795 + +void main(void) +{ + ivec2 uv = ivec2(FragmentIn.TexCoord.x, FragmentIn.TexCoord.y); + + vec3 a = texelFetch(A, uv).xyz; + vec3 b = texelFetch(B, uv).xyz; + + vec3 phase = atan(b, a); + phase = mix(phase, phase + 2.0 * M_PI, lessThan(phase, vec3(0.0))); + phase = mix(phase, vec3(0.0), isnan(phase)); + vec3 ir = sqrt(a * a + b * b) * Params.ab_multiplier; + + float ir_sum = ir.x + ir.y + ir.z; + float ir_min = min(ir.x, min(ir.y, ir.z)); + float ir_max = max(ir.x, max(ir.y, ir.z)); + + float phase_final = 0; + + if(ir_min >= Params.individual_ab_threshold && ir_sum >= Params.ab_threshold) + { + vec3 t = phase / (2.0 * M_PI) * vec3(3.0, 15.0, 2.0); + + float t0 = t.x; + float t1 = t.y; + float t2 = t.z; + + float t5 = (floor((t1 - t0) * 0.333333f + 0.5f) * 3.0f + t0); + float t3 = (-t2 + t5); + float t4 = t3 * 2.0f; + + bool c1 = t4 >= -t4; // true if t4 positive + + float f1 = c1 ? 2.0f : -2.0f; + float f2 = c1 ? 0.5f : -0.5f; + t3 *= f2; + t3 = (t3 - floor(t3)) * f1; + + bool c2 = 0.5f < abs(t3) && abs(t3) < 1.5f; + + float t6 = c2 ? t5 + 15.0f : t5; + float t7 = c2 ? t1 + 15.0f : t1; + + float t8 = (floor((-t2 + t6) * 0.5f + 0.5f) * 2.0f + t2) * 0.5f; + + t6 *= 0.333333f; // = / 3 + t7 *= 0.066667f; // = / 15 + + float t9 = (t8 + t6 + t7); // transformed phase measurements (they are transformed and divided by the values the original values were multiplied with) + float t10 = t9 * 0.333333f; // some avg + + t6 *= 2.0f * M_PI; + t7 *= 2.0f * M_PI; + t8 *= 2.0f * M_PI; + + // some cross product + float t8_new = t7 * 0.826977f - t8 * 0.110264f; + float t6_new = t8 * 0.551318f - t6 * 0.826977f; + float t7_new = t6 * 0.110264f - t7 * 0.551318f; + + t8 = t8_new; + t6 = t6_new; + t7 = t7_new; + + float norm = t8 * t8 + t6 * t6 + t7 * t7; + float mask = t9 >= 0.0f ? 1.0f : 0.0f; + t10 *= mask; + + bool slope_positive = 0 < Params.ab_confidence_slope; + + float ir_x = slope_positive ? ir_min : ir_max; + + ir_x = log(ir_x); + ir_x = (ir_x * Params.ab_confidence_slope * 0.301030f + Params.ab_confidence_offset) * 3.321928f; + ir_x = exp(ir_x); + ir_x = min(Params.max_dealias_confidence, max(Params.min_dealias_confidence, ir_x)); + ir_x *= ir_x; + + float mask2 = ir_x >= norm ? 1.0f : 0.0f; + + float t11 = t10 * mask2; + + float mask3 = Params.max_dealias_confidence * Params.max_dealias_confidence >= norm ? 1.0f : 0.0f; + t10 *= mask3; + phase_final = true/*(modeMask & 2) != 0*/ ? t11 : t10; + } + + float zmultiplier = texelFetch(ZTable, uv).x; + float xmultiplier = texelFetch(XTable, uv).x; + + phase_final = 0.0 < phase_final ? phase_final + Params.phase_offset : phase_final; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * Params.unambigious_dist * 2.0; + + bool cond1 = /*(modeMask & 32) != 0*/ true && 0.0 < depth_linear && 0.0 < max_depth; + + xmultiplier = (xmultiplier * 90.0) / (max_depth * max_depth * 8192.0); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0 ? 0.0 : depth_fit; + + Depth = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + DepthAndIrSum = vec2(Depth, ir_sum); + + Debug = vec4(vec3(Depth / Params.max_depth), 1.0); +} \ No newline at end of file diff --git a/examples/k22v4l/src/test_opengl_depth_packet_processor.cpp b/examples/k22v4l/src/test_opengl_depth_packet_processor.cpp new file mode 100644 index 000000000..7c91d3fd7 --- /dev/null +++ b/examples/k22v4l/src/test_opengl_depth_packet_processor.cpp @@ -0,0 +1,148 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +void loadBufferFromFile(const std::string& filename, unsigned char *buffer, size_t n) +{ + std::ifstream in(filename.c_str()); + + in.read(reinterpret_cast(buffer), n); + if(in.gcount() != n) throw std::exception(); + + in.close(); +} + +int main(int argc, char **argv) { + std::string program_path(argv[0]); + size_t executable_name_idx = program_path.rfind("test_opengl"); + std::string binpath = "./"; + + if(executable_name_idx != std::string::npos) + { + binpath = program_path.substr(0, executable_name_idx); + } + + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + + GLFWwindow* window = glfwCreateWindow(1200, 600, "OpenGL", 0, 0); // Windowed + + libfreenect2::SyncMultiFrameListener fl(libfreenect2::Frame::Ir | libfreenect2::Frame::Depth); + libfreenect2::FrameMap frames; + + libfreenect2::DepthPacketProcessor::Config cfg; + cfg.EnableBilateralFilter = false; + cfg.EnableEdgeAwareFilter = false; + + libfreenect2::OpenGLDepthPacketProcessor processor(window, true); + processor.setConfiguration(cfg); + processor.setFrameListener(&fl); + processor.loadP0TablesFromFiles((binpath + "../p00.bin").c_str(), (binpath + "../p01.bin").c_str(), (binpath + "../p02.bin").c_str()); + processor.load11To16LutFromFile(""); + processor.loadXTableFromFile(""); + processor.loadZTableFromFile(""); + + libfreenect2::CpuDepthPacketProcessor ref_processor; + ref_processor.setConfiguration(cfg); + ref_processor.setFrameListener(&fl); + ref_processor.loadP0TablesFromFiles((binpath + "../p00.bin").c_str(), (binpath + "../p01.bin").c_str(), (binpath + "../p02.bin").c_str()); + ref_processor.load11To16LutFromFile(""); + ref_processor.loadXTableFromFile(""); + ref_processor.loadZTableFromFile(""); + + libfreenect2::AsyncPacketProcessor async(&processor); + + libfreenect2::DepthPacket p; + p.buffer_length = 352*424*10*2; + p.buffer = new unsigned char[p.buffer_length]; + + loadBufferFromFile(binpath + "../rawir/rawir_4599.bin", p.buffer, p.buffer_length); + + libfreenect2::Frame *ir, *depth; + cv::Mat cpu_ir, cpu_depth, ogl_ir, ogl_depth; + + ref_processor.process(p); + fl.waitForNewFrame(frames); + + ir = frames[libfreenect2::Frame::Ir]; + depth = frames[libfreenect2::Frame::Depth]; + cv::Mat(ir->height, ir->width, CV_32FC1, ir->data).copyTo(cpu_ir); + cv::Mat(depth->height, depth->width, CV_32FC1, depth->data).copyTo(cpu_depth); + + fl.release(frames); + + processor.process(p); + fl.waitForNewFrame(frames); + + ir = frames[libfreenect2::Frame::Ir]; + depth = frames[libfreenect2::Frame::Depth]; + cv::Mat(ir->height, ir->width, CV_32FC1, ir->data).copyTo(ogl_ir); + cv::Mat(depth->height, depth->width, CV_32FC1, depth->data).copyTo(ogl_depth); + + fl.release(frames); + + cv::Mat diff_ir = cv::abs(cpu_ir - ogl_ir); + cv::Mat diff_depth = cv::abs(cpu_depth - ogl_depth); + + cv::imshow("cpu_ir", cpu_ir / 65535.0f); + cv::imshow("cpu_depth", cpu_depth / 4500.0f); + + cv::imshow("diff_ir", diff_ir); + cv::imshow("diff_depth", diff_depth); + cv::waitKey(0); + + double mi, ma; + cv::minMaxIdx(diff_depth, &mi, &ma); + std::cout << "depth difference min: " << mi << " max: " << ma << std::endl; + + while(!glfwWindowShouldClose(window)) + { + if(async.ready()) + async.process(p); + //processor.process(p); + + glfwMakeContextCurrent(window); + glfwSwapBuffers(window); + //glfwSwapBuffers(window_background); + glfwPollEvents(); + } + + return 0; +} diff --git a/examples/k22v4l/src/tinythread/tinythread.cpp b/examples/k22v4l/src/tinythread/tinythread.cpp new file mode 100644 index 000000000..690eceea1 --- /dev/null +++ b/examples/k22v4l/src/tinythread/tinythread.cpp @@ -0,0 +1,303 @@ +/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- +Copyright (c) 2010-2012 Marcus Geelnard + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#include +#include "tinythread.h" + +#if defined(_TTHREAD_POSIX_) + #include + #include +#elif defined(_TTHREAD_WIN32_) + #include +#endif + + +namespace tthread { + +//------------------------------------------------------------------------------ +// condition_variable +//------------------------------------------------------------------------------ +// NOTE 1: The Win32 implementation of the condition_variable class is based on +// the corresponding implementation in GLFW, which in turn is based on a +// description by Douglas C. Schmidt and Irfan Pyarali: +// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html +// +// NOTE 2: Windows Vista actually has native support for condition variables +// (InitializeConditionVariable, WakeConditionVariable, etc), but we want to +// be portable with pre-Vista Windows versions, so TinyThread++ does not use +// Vista condition variables. +//------------------------------------------------------------------------------ + +#if defined(_TTHREAD_WIN32_) + #define _CONDITION_EVENT_ONE 0 + #define _CONDITION_EVENT_ALL 1 +#endif + +#if defined(_TTHREAD_WIN32_) +condition_variable::condition_variable() : mWaitersCount(0) +{ + mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL); + mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL); + InitializeCriticalSection(&mWaitersCountLock); +} +#endif + +#if defined(_TTHREAD_WIN32_) +condition_variable::~condition_variable() +{ + CloseHandle(mEvents[_CONDITION_EVENT_ONE]); + CloseHandle(mEvents[_CONDITION_EVENT_ALL]); + DeleteCriticalSection(&mWaitersCountLock); +} +#endif + +#if defined(_TTHREAD_WIN32_) +void condition_variable::_wait() +{ + // Wait for either event to become signaled due to notify_one() or + // notify_all() being called + int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE); + + // Check if we are the last waiter + EnterCriticalSection(&mWaitersCountLock); + -- mWaitersCount; + bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && + (mWaitersCount == 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we are the last waiter to be notified to stop waiting, reset the event + if(lastWaiter) + ResetEvent(mEvents[_CONDITION_EVENT_ALL]); +} +#endif + +#if defined(_TTHREAD_WIN32_) +void condition_variable::notify_one() +{ + // Are there any waiters? + EnterCriticalSection(&mWaitersCountLock); + bool haveWaiters = (mWaitersCount > 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we have any waiting threads, send them a signal + if(haveWaiters) + SetEvent(mEvents[_CONDITION_EVENT_ONE]); +} +#endif + +#if defined(_TTHREAD_WIN32_) +void condition_variable::notify_all() +{ + // Are there any waiters? + EnterCriticalSection(&mWaitersCountLock); + bool haveWaiters = (mWaitersCount > 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we have any waiting threads, send them a signal + if(haveWaiters) + SetEvent(mEvents[_CONDITION_EVENT_ALL]); +} +#endif + + +//------------------------------------------------------------------------------ +// POSIX pthread_t to unique thread::id mapping logic. +// Note: Here we use a global thread safe std::map to convert instances of +// pthread_t to small thread identifier numbers (unique within one process). +// This method should be portable across different POSIX implementations. +//------------------------------------------------------------------------------ + +#if defined(_TTHREAD_POSIX_) +static thread::id _pthread_t_to_ID(const pthread_t &aHandle) +{ + static mutex idMapLock; + static std::map idMap; + static unsigned long int idCount(1); + + lock_guard guard(idMapLock); + if(idMap.find(aHandle) == idMap.end()) + idMap[aHandle] = idCount ++; + return thread::id(idMap[aHandle]); +} +#endif // _TTHREAD_POSIX_ + + +//------------------------------------------------------------------------------ +// thread +//------------------------------------------------------------------------------ + +/// Information to pass to the new thread (what to run). +struct _thread_start_info { + void (*mFunction)(void *); ///< Pointer to the function to be executed. + void * mArg; ///< Function argument for the thread function. + thread * mThread; ///< Pointer to the thread object. +}; + +// Thread wrapper function. +#if defined(_TTHREAD_WIN32_) +unsigned WINAPI thread::wrapper_function(void * aArg) +#elif defined(_TTHREAD_POSIX_) +void * thread::wrapper_function(void * aArg) +#endif +{ + // Get thread startup information + _thread_start_info * ti = (_thread_start_info *) aArg; + + try + { + // Call the actual client thread function + ti->mFunction(ti->mArg); + } + catch(...) + { + // Uncaught exceptions will terminate the application (default behavior + // according to C++11) + std::terminate(); + } + + // The thread is no longer executing + lock_guard guard(ti->mThread->mDataMutex); + ti->mThread->mNotAThread = true; + + // The thread is responsible for freeing the startup information + delete ti; + + return 0; +} + +thread::thread(void (*aFunction)(void *), void * aArg) +{ + // Serialize access to this thread structure + lock_guard guard(mDataMutex); + + // Fill out the thread startup information (passed to the thread wrapper, + // which will eventually free it) + _thread_start_info * ti = new _thread_start_info; + ti->mFunction = aFunction; + ti->mArg = aArg; + ti->mThread = this; + + // The thread is now alive + mNotAThread = false; + + // Create the thread +#if defined(_TTHREAD_WIN32_) + mHandle = (HANDLE) _beginthreadex(0, 0, wrapper_function, (void *) ti, 0, &mWin32ThreadID); +#elif defined(_TTHREAD_POSIX_) + if(pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0) + mHandle = 0; +#endif + + // Did we fail to create the thread? + if(!mHandle) + { + mNotAThread = true; + delete ti; + } +} + +thread::~thread() +{ + if(joinable()) + std::terminate(); +} + +void thread::join() +{ + if(joinable()) + { +#if defined(_TTHREAD_WIN32_) + WaitForSingleObject(mHandle, INFINITE); + CloseHandle(mHandle); +#elif defined(_TTHREAD_POSIX_) + pthread_join(mHandle, NULL); +#endif + } +} + +bool thread::joinable() const +{ + mDataMutex.lock(); + bool result = !mNotAThread; + mDataMutex.unlock(); + return result; +} + +void thread::detach() +{ + mDataMutex.lock(); + if(!mNotAThread) + { +#if defined(_TTHREAD_WIN32_) + CloseHandle(mHandle); +#elif defined(_TTHREAD_POSIX_) + pthread_detach(mHandle); +#endif + mNotAThread = true; + } + mDataMutex.unlock(); +} + +thread::id thread::get_id() const +{ + if(!joinable()) + return id(); +#if defined(_TTHREAD_WIN32_) + return id((unsigned long int) mWin32ThreadID); +#elif defined(_TTHREAD_POSIX_) + return _pthread_t_to_ID(mHandle); +#endif +} + +unsigned thread::hardware_concurrency() +{ +#if defined(_TTHREAD_WIN32_) + SYSTEM_INFO si; + GetSystemInfo(&si); + return (int) si.dwNumberOfProcessors; +#elif defined(_SC_NPROCESSORS_ONLN) + return (int) sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(_SC_NPROC_ONLN) + return (int) sysconf(_SC_NPROC_ONLN); +#else + // The standard requires this function to return zero if the number of + // hardware cores could not be determined. + return 0; +#endif +} + + +//------------------------------------------------------------------------------ +// this_thread +//------------------------------------------------------------------------------ + +thread::id this_thread::get_id() +{ +#if defined(_TTHREAD_WIN32_) + return thread::id((unsigned long int) GetCurrentThreadId()); +#elif defined(_TTHREAD_POSIX_) + return _pthread_t_to_ID(pthread_self()); +#endif +} + +} diff --git a/examples/k22v4l/src/tinythread/tinythread.h b/examples/k22v4l/src/tinythread/tinythread.h new file mode 100644 index 000000000..566997a43 --- /dev/null +++ b/examples/k22v4l/src/tinythread/tinythread.h @@ -0,0 +1,716 @@ +/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- +Copyright (c) 2010-2012 Marcus Geelnard + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#ifndef _TINYTHREAD_H_ +#define _TINYTHREAD_H_ + +#include + +/// @file +/// @mainpage TinyThread++ API Reference +/// +/// @section intro_sec Introduction +/// TinyThread++ is a minimal, portable implementation of basic threading +/// classes for C++. +/// +/// They closely mimic the functionality and naming of the C++11 standard, and +/// should be easily replaceable with the corresponding std:: variants. +/// +/// @section port_sec Portability +/// The Win32 variant uses the native Win32 API for implementing the thread +/// classes, while for other systems, the POSIX threads API (pthread) is used. +/// +/// @section class_sec Classes +/// In order to mimic the threading API of the C++11 standard, subsets of +/// several classes are provided. The fundamental classes are: +/// @li tthread::thread +/// @li tthread::mutex +/// @li tthread::recursive_mutex +/// @li tthread::condition_variable +/// @li tthread::lock_guard +/// @li tthread::fast_mutex +/// +/// @section misc_sec Miscellaneous +/// The following special keywords are available: #thread_local. +/// +/// For more detailed information (including additional classes), browse the +/// different sections of this documentation. A good place to start is: +/// tinythread.h. + +// Which platform are we on? +#if !defined(_TTHREAD_PLATFORM_DEFINED_) + #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) + #define _TTHREAD_WIN32_ + #else + #define _TTHREAD_POSIX_ + #endif + #define _TTHREAD_PLATFORM_DEFINED_ +#endif + +// Platform specific includes +#if defined(_TTHREAD_WIN32_) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #define __UNDEF_LEAN_AND_MEAN + #endif + #include + #ifdef __UNDEF_LEAN_AND_MEAN + #undef WIN32_LEAN_AND_MEAN + #undef __UNDEF_LEAN_AND_MEAN + #endif +#else + #include + #include + #include + #include +#endif + +// Generic includes +#include + +/// TinyThread++ version (major number). +#define TINYTHREAD_VERSION_MAJOR 1 +/// TinyThread++ version (minor number). +#define TINYTHREAD_VERSION_MINOR 1 +/// TinyThread++ version (full version). +#define TINYTHREAD_VERSION (TINYTHREAD_VERSION_MAJOR * 100 + TINYTHREAD_VERSION_MINOR) + +// Do we have a fully featured C++11 compiler? +#if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L)) + #define _TTHREAD_CPP11_ +#endif + +// ...at least partial C++11? +#if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__) + #define _TTHREAD_CPP11_PARTIAL_ +#endif + +// Macro for disabling assignments of objects. +#ifdef _TTHREAD_CPP11_PARTIAL_ + #define _TTHREAD_DISABLE_ASSIGNMENT(name) \ + name(const name&) = delete; \ + name& operator=(const name&) = delete; +#else + #define _TTHREAD_DISABLE_ASSIGNMENT(name) \ + name(const name&); \ + name& operator=(const name&); +#endif + +/// @def thread_local +/// Thread local storage keyword. +/// A variable that is declared with the @c thread_local keyword makes the +/// value of the variable local to each thread (known as thread-local storage, +/// or TLS). Example usage: +/// @code +/// // This variable is local to each thread. +/// thread_local int variable; +/// @endcode +/// @note The @c thread_local keyword is a macro that maps to the corresponding +/// compiler directive (e.g. @c __declspec(thread)). While the C++11 standard +/// allows for non-trivial types (e.g. classes with constructors and +/// destructors) to be declared with the @c thread_local keyword, most pre-C++11 +/// compilers only allow for trivial types (e.g. @c int). So, to guarantee +/// portable code, only use trivial types for thread local storage. +/// @note This directive is currently not supported on Mac OS X (it will give +/// a compiler error), since compile-time TLS is not supported in the Mac OS X +/// executable format. Also, some older versions of MinGW (before GCC 4.x) do +/// not support this directive. +/// @hideinitializer + +#if !defined(_TTHREAD_CPP11_) && !defined(thread_local) + #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) + #define thread_local __thread + #else + #define thread_local __declspec(thread) + #endif +#endif + + +/// Main name space for TinyThread++. +/// This namespace is more or less equivalent to the @c std namespace for the +/// C++11 thread classes. For instance, the tthread::mutex class corresponds to +/// the std::mutex class. +namespace tthread { + +/// Mutex class. +/// This is a mutual exclusion object for synchronizing access to shared +/// memory areas for several threads. The mutex is non-recursive (i.e. a +/// program may deadlock if the thread that owns a mutex object calls lock() +/// on that object). +/// @see recursive_mutex +class LIBFREENECT2_API mutex { + public: + /// Constructor. + mutex() +#if defined(_TTHREAD_WIN32_) + : mAlreadyLocked(false) +#endif + { +#if defined(_TTHREAD_WIN32_) + InitializeCriticalSection(&mHandle); +#else + pthread_mutex_init(&mHandle, NULL); +#endif + } + + /// Destructor. + ~mutex() + { +#if defined(_TTHREAD_WIN32_) + DeleteCriticalSection(&mHandle); +#else + pthread_mutex_destroy(&mHandle); +#endif + } + + /// Lock the mutex. + /// The method will block the calling thread until a lock on the mutex can + /// be obtained. The mutex remains locked until @c unlock() is called. + /// @see lock_guard + inline void lock() + { +#if defined(_TTHREAD_WIN32_) + EnterCriticalSection(&mHandle); + while(mAlreadyLocked) Sleep(1000); // Simulate deadlock... + mAlreadyLocked = true; +#else + pthread_mutex_lock(&mHandle); +#endif + } + + /// Try to lock the mutex. + /// The method will try to lock the mutex. If it fails, the function will + /// return immediately (non-blocking). + /// @return @c true if the lock was acquired, or @c false if the lock could + /// not be acquired. + inline bool try_lock() + { +#if defined(_TTHREAD_WIN32_) + bool ret = (TryEnterCriticalSection(&mHandle) ? true : false); + if(ret && mAlreadyLocked) + { + LeaveCriticalSection(&mHandle); + ret = false; + } + return ret; +#else + return (pthread_mutex_trylock(&mHandle) == 0) ? true : false; +#endif + } + + /// Unlock the mutex. + /// If any threads are waiting for the lock on this mutex, one of them will + /// be unblocked. + inline void unlock() + { +#if defined(_TTHREAD_WIN32_) + mAlreadyLocked = false; + LeaveCriticalSection(&mHandle); +#else + pthread_mutex_unlock(&mHandle); +#endif + } + + _TTHREAD_DISABLE_ASSIGNMENT(mutex) + + private: +#if defined(_TTHREAD_WIN32_) + CRITICAL_SECTION mHandle; + bool mAlreadyLocked; +#else + pthread_mutex_t mHandle; +#endif + + friend class condition_variable; +}; + +/// Recursive mutex class. +/// This is a mutual exclusion object for synchronizing access to shared +/// memory areas for several threads. The mutex is recursive (i.e. a thread +/// may lock the mutex several times, as long as it unlocks the mutex the same +/// number of times). +/// @see mutex +class LIBFREENECT2_API recursive_mutex { + public: + /// Constructor. + recursive_mutex() + { +#if defined(_TTHREAD_WIN32_) + InitializeCriticalSection(&mHandle); +#else + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mHandle, &attr); +#endif + } + + /// Destructor. + ~recursive_mutex() + { +#if defined(_TTHREAD_WIN32_) + DeleteCriticalSection(&mHandle); +#else + pthread_mutex_destroy(&mHandle); +#endif + } + + /// Lock the mutex. + /// The method will block the calling thread until a lock on the mutex can + /// be obtained. The mutex remains locked until @c unlock() is called. + /// @see lock_guard + inline void lock() + { +#if defined(_TTHREAD_WIN32_) + EnterCriticalSection(&mHandle); +#else + pthread_mutex_lock(&mHandle); +#endif + } + + /// Try to lock the mutex. + /// The method will try to lock the mutex. If it fails, the function will + /// return immediately (non-blocking). + /// @return @c true if the lock was acquired, or @c false if the lock could + /// not be acquired. + inline bool try_lock() + { +#if defined(_TTHREAD_WIN32_) + return TryEnterCriticalSection(&mHandle) ? true : false; +#else + return (pthread_mutex_trylock(&mHandle) == 0) ? true : false; +#endif + } + + /// Unlock the mutex. + /// If any threads are waiting for the lock on this mutex, one of them will + /// be unblocked. + inline void unlock() + { +#if defined(_TTHREAD_WIN32_) + LeaveCriticalSection(&mHandle); +#else + pthread_mutex_unlock(&mHandle); +#endif + } + + _TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex) + + private: +#if defined(_TTHREAD_WIN32_) + CRITICAL_SECTION mHandle; +#else + pthread_mutex_t mHandle; +#endif + + friend class condition_variable; +}; + +/// Lock guard class. +/// The constructor locks the mutex, and the destructor unlocks the mutex, so +/// the mutex will automatically be unlocked when the lock guard goes out of +/// scope. Example usage: +/// @code +/// mutex m; +/// int counter; +/// +/// void increment() +/// { +/// lock_guard guard(m); +/// ++ counter; +/// } +/// @endcode + +template +class LIBFREENECT2_API lock_guard { + public: + typedef T mutex_type; + + lock_guard() : mMutex(0) {} + + /// The constructor locks the mutex. + explicit lock_guard(mutex_type &aMutex) + { + mMutex = &aMutex; + mMutex->lock(); + } + + /// The destructor unlocks the mutex. + ~lock_guard() + { + if(mMutex) + mMutex->unlock(); + } + + private: + mutex_type * mMutex; +}; + +/// Condition variable class. +/// This is a signalling object for synchronizing the execution flow for +/// several threads. Example usage: +/// @code +/// // Shared data and associated mutex and condition variable objects +/// int count; +/// mutex m; +/// condition_variable cond; +/// +/// // Wait for the counter to reach a certain number +/// void wait_counter(int targetCount) +/// { +/// lock_guard guard(m); +/// while(count < targetCount) +/// cond.wait(m); +/// } +/// +/// // Increment the counter, and notify waiting threads +/// void increment() +/// { +/// lock_guard guard(m); +/// ++ count; +/// cond.notify_all(); +/// } +/// @endcode +class LIBFREENECT2_API condition_variable { + public: + /// Constructor. +#if defined(_TTHREAD_WIN32_) + condition_variable(); +#else + condition_variable() + { + pthread_cond_init(&mHandle, NULL); + } +#endif + + /// Destructor. +#if defined(_TTHREAD_WIN32_) + ~condition_variable(); +#else + ~condition_variable() + { + pthread_cond_destroy(&mHandle); + } +#endif + + /// Wait for the condition. + /// The function will block the calling thread until the condition variable + /// is woken by @c notify_one(), @c notify_all() or a spurious wake up. + /// @param[in] aMutex A mutex that will be unlocked when the wait operation + /// starts, an locked again as soon as the wait operation is finished. + template + inline void wait(_mutexT &aMutex) + { +#if defined(_TTHREAD_WIN32_) + // Increment number of waiters + EnterCriticalSection(&mWaitersCountLock); + ++ mWaitersCount; + LeaveCriticalSection(&mWaitersCountLock); + + // Release the mutex while waiting for the condition (will decrease + // the number of waiters when done)... + aMutex.unlock(); + _wait(); + aMutex.lock(); +#else + pthread_cond_wait(&mHandle, &aMutex.mHandle); +#endif + } + + /// Notify one thread that is waiting for the condition. + /// If at least one thread is blocked waiting for this condition variable, + /// one will be woken up. + /// @note Only threads that started waiting prior to this call will be + /// woken up. +#if defined(_TTHREAD_WIN32_) + void notify_one(); +#else + inline void notify_one() + { + pthread_cond_signal(&mHandle); + } +#endif + + /// Notify all threads that are waiting for the condition. + /// All threads that are blocked waiting for this condition variable will + /// be woken up. + /// @note Only threads that started waiting prior to this call will be + /// woken up. +#if defined(_TTHREAD_WIN32_) + void notify_all(); +#else + inline void notify_all() + { + pthread_cond_broadcast(&mHandle); + } +#endif + + _TTHREAD_DISABLE_ASSIGNMENT(condition_variable) + + private: +#if defined(_TTHREAD_WIN32_) + void _wait(); + HANDLE mEvents[2]; ///< Signal and broadcast event HANDLEs. + unsigned int mWaitersCount; ///< Count of the number of waiters. + CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount. +#else + pthread_cond_t mHandle; +#endif +}; + + +/// Thread class. +class LIBFREENECT2_API thread { + public: +#if defined(_TTHREAD_WIN32_) + typedef HANDLE native_handle_type; +#else + typedef pthread_t native_handle_type; +#endif + + class id; + + /// Default constructor. + /// Construct a @c thread object without an associated thread of execution + /// (i.e. non-joinable). + thread() : mHandle(0), mNotAThread(true) +#if defined(_TTHREAD_WIN32_) + , mWin32ThreadID(0) +#endif + {} + + /// Thread starting constructor. + /// Construct a @c thread object with a new thread of execution. + /// @param[in] aFunction A function pointer to a function of type: + /// void fun(void * arg) + /// @param[in] aArg Argument to the thread function. + /// @note This constructor is not fully compatible with the standard C++ + /// thread class. It is more similar to the pthread_create() (POSIX) and + /// CreateThread() (Windows) functions. + thread(void (*aFunction)(void *), void * aArg); + + /// Destructor. + /// @note If the thread is joinable upon destruction, @c std::terminate() + /// will be called, which terminates the process. It is always wise to do + /// @c join() before deleting a thread object. + ~thread(); + + /// Wait for the thread to finish (join execution flows). + /// After calling @c join(), the thread object is no longer associated with + /// a thread of execution (i.e. it is not joinable, and you may not join + /// with it nor detach from it). + void join(); + + /// Check if the thread is joinable. + /// A thread object is joinable if it has an associated thread of execution. + bool joinable() const; + + /// Detach from the thread. + /// After calling @c detach(), the thread object is no longer assicated with + /// a thread of execution (i.e. it is not joinable). The thread continues + /// execution without the calling thread blocking, and when the thread + /// ends execution, any owned resources are released. + void detach(); + + /// Return the thread ID of a thread object. + id get_id() const; + + /// Get the native handle for this thread. + /// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this + /// is a @c pthread_t. + inline native_handle_type native_handle() + { + return mHandle; + } + + /// Determine the number of threads which can possibly execute concurrently. + /// This function is useful for determining the optimal number of threads to + /// use for a task. + /// @return The number of hardware thread contexts in the system. + /// @note If this value is not defined, the function returns zero (0). + static unsigned hardware_concurrency(); + + _TTHREAD_DISABLE_ASSIGNMENT(thread) + + private: + native_handle_type mHandle; ///< Thread handle. + mutable mutex mDataMutex; ///< Serializer for access to the thread private data. + bool mNotAThread; ///< True if this object is not a thread of execution. +#if defined(_TTHREAD_WIN32_) + unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex). +#endif + + // This is the internal thread wrapper function. +#if defined(_TTHREAD_WIN32_) + static unsigned WINAPI wrapper_function(void * aArg); +#else + static void * wrapper_function(void * aArg); +#endif +}; + +/// Thread ID. +/// The thread ID is a unique identifier for each thread. +/// @see thread::get_id() +class LIBFREENECT2_API thread::id { + public: + /// Default constructor. + /// The default constructed ID is that of thread without a thread of + /// execution. + id() : mId(0) {}; + + id(unsigned long int aId) : mId(aId) {}; + + id(const id& aId) : mId(aId.mId) {}; + + inline id & operator=(const id &aId) + { + mId = aId.mId; + return *this; + } + + inline friend bool operator==(const id &aId1, const id &aId2) + { + return (aId1.mId == aId2.mId); + } + + inline friend bool operator!=(const id &aId1, const id &aId2) + { + return (aId1.mId != aId2.mId); + } + + inline friend bool operator<=(const id &aId1, const id &aId2) + { + return (aId1.mId <= aId2.mId); + } + + inline friend bool operator<(const id &aId1, const id &aId2) + { + return (aId1.mId < aId2.mId); + } + + inline friend bool operator>=(const id &aId1, const id &aId2) + { + return (aId1.mId >= aId2.mId); + } + + inline friend bool operator>(const id &aId1, const id &aId2) + { + return (aId1.mId > aId2.mId); + } + + inline friend std::ostream& operator <<(std::ostream &os, const id &obj) + { + os << obj.mId; + return os; + } + + private: + unsigned long int mId; +}; + + +// Related to - minimal to be able to support chrono. +typedef long long __intmax_t; + +/// Minimal implementation of the @c ratio class. This class provides enough +/// functionality to implement some basic @c chrono classes. +template <__intmax_t N, __intmax_t D = 1> class ratio { + public: + static double _as_double() { return double(N) / double(D); } +}; + +/// Minimal implementation of the @c chrono namespace. +/// The @c chrono namespace provides types for specifying time intervals. +namespace chrono { + /// Duration template class. This class provides enough functionality to + /// implement @c this_thread::sleep_for(). + template > class duration { + private: + _Rep rep_; + public: + typedef _Rep rep; + typedef _Period period; + + /// Construct a duration object with the given duration. + template + explicit duration(const _Rep2& r) : rep_(r) {}; + + /// Return the value of the duration object. + rep count() const + { + return rep_; + } + }; + + // Standard duration types. + typedef duration<__intmax_t, ratio<1, 1000000000> > nanoseconds; ///< Duration with the unit nanoseconds. + typedef duration<__intmax_t, ratio<1, 1000000> > microseconds; ///< Duration with the unit microseconds. + typedef duration<__intmax_t, ratio<1, 1000> > milliseconds; ///< Duration with the unit milliseconds. + typedef duration<__intmax_t> seconds; ///< Duration with the unit seconds. + typedef duration<__intmax_t, ratio<60> > minutes; ///< Duration with the unit minutes. + typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours. +} + +/// The namespace @c this_thread provides methods for dealing with the +/// calling thread. +namespace this_thread { + /// Return the thread ID of the calling thread. + thread::id get_id(); + + /// Yield execution to another thread. + /// Offers the operating system the opportunity to schedule another thread + /// that is ready to run on the current processor. + inline void yield() + { +#if defined(_TTHREAD_WIN32_) + Sleep(0); +#else + sched_yield(); +#endif + } + + /// Blocks the calling thread for a period of time. + /// @param[in] aTime Minimum time to put the thread to sleep. + /// Example usage: + /// @code + /// // Sleep for 100 milliseconds + /// this_thread::sleep_for(chrono::milliseconds(100)); + /// @endcode + /// @note Supported duration types are: nanoseconds, microseconds, + /// milliseconds, seconds, minutes and hours. + template void sleep_for(const chrono::duration<_Rep, _Period>& aTime) + { +#if defined(_TTHREAD_WIN32_) + Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5)); +#else + usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5)); +#endif + } +} + +} + +// Define/macro cleanup +#undef _TTHREAD_DISABLE_ASSIGNMENT + +#endif // _TINYTHREAD_H_ diff --git a/examples/k22v4l/src/transfer_pool.cpp b/examples/k22v4l/src/transfer_pool.cpp new file mode 100644 index 000000000..60c4358b1 --- /dev/null +++ b/examples/k22v4l/src/transfer_pool.cpp @@ -0,0 +1,264 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include + +namespace libfreenect2 +{ +namespace usb +{ + +TransferPool::TransferPool(libusb_device_handle* device_handle, unsigned char device_endpoint) : + callback_(0), + device_handle_(device_handle), + device_endpoint_(device_endpoint), + buffer_(0), + buffer_size_(0), + enable_submit_(false) +{ +} + +TransferPool::~TransferPool() +{ + deallocate(); +} + +void TransferPool::enableSubmission() +{ + enable_submit_ = true; +} + +void TransferPool::disableSubmission() +{ + enable_submit_ = false; +} + +void TransferPool::deallocate() +{ + for(TransferQueue::iterator it = idle_transfers_.begin(); it != idle_transfers_.end(); ++it) + { + libusb_free_transfer(*it); + } + idle_transfers_.clear(); + + if(buffer_ != 0) + { + delete[] buffer_; + buffer_ = 0; + buffer_size_ = 0; + } +} + +void TransferPool::submit(size_t num_parallel_transfers) +{ + if(!enable_submit_) + { + std::cerr << "[TransferPool::submit] transfer submission disabled!" << std::endl; + return; + } + + if(idle_transfers_.size() < num_parallel_transfers) + { + std::cerr << "[TransferPool::submit] too few idle transfers!" << std::endl; + } + + for(size_t i = 0; i < num_parallel_transfers; ++i) + { + libusb_transfer *transfer = idle_transfers_.front(); + idle_transfers_.pop_front(); + + int r = libusb_submit_transfer(transfer); + + // put transfer in pending queue on success otherwise put it back in the idle queue + if(r == LIBUSB_SUCCESS) + { + pending_transfers_.push_back(transfer); + } + else + { + idle_transfers_.push_back(transfer); + std::cerr << "[TransferPool::submit] failed to submit transfer" << std::endl; + } + } +} + +void TransferPool::cancel() +{ + for(TransferQueue::iterator it = pending_transfers_.begin(); it != pending_transfers_.end(); ++it) + { + int r = libusb_cancel_transfer(*it); + + if(r != LIBUSB_SUCCESS) + { + // TODO: error reporting + } + } + + //idle_transfers_.insert(idle_transfers_.end(), pending_transfers_.begin(), pending_transfers_.end()); +} + +void TransferPool::setCallback(DataCallback *callback) +{ + callback_ = callback; +} + +void TransferPool::allocateTransfers(size_t num_transfers, size_t transfer_size) +{ + buffer_size_ = num_transfers * transfer_size; + buffer_ = new unsigned char[buffer_size_]; + + unsigned char *ptr = buffer_; + + for(size_t i = 0; i < num_transfers; ++i) + { + libusb_transfer *transfer = allocateTransfer(); + fillTransfer(transfer); + + transfer->dev_handle = device_handle_; + transfer->endpoint = device_endpoint_; + transfer->buffer = ptr; + transfer->length = transfer_size; + transfer->timeout = 1000; + transfer->callback = (libusb_transfer_cb_fn) &TransferPool::onTransferCompleteStatic; + transfer->user_data = this; + + idle_transfers_.push_back(transfer); + + ptr += transfer_size; + } +} + +void TransferPool::onTransferCompleteStatic(libusb_transfer* transfer) +{ + reinterpret_cast(transfer->user_data)->onTransferComplete(transfer); +} + +void TransferPool::onTransferComplete(libusb_transfer* transfer) +{ + // remove transfer from pending queue - should be fast as it is somewhere at the front + TransferQueue::iterator it = std::find(pending_transfers_.begin(), pending_transfers_.end(), transfer); + + if(it == pending_transfers_.end()) + { + // TODO: error reporting + } + + pending_transfers_.erase(it); + + // process data + processTransfer(transfer); + + // put transfer back in idle queue + idle_transfers_.push_back(transfer); + + // submit new transfer + submit(1); +} + +BulkTransferPool::BulkTransferPool(libusb_device_handle* device_handle, unsigned char device_endpoint) : + TransferPool(device_handle, device_endpoint) +{ +} + +BulkTransferPool::~BulkTransferPool() +{ +} + +void BulkTransferPool::allocate(size_t num_transfers, size_t transfer_size) +{ + allocateTransfers(num_transfers, transfer_size); +} + +libusb_transfer* BulkTransferPool::allocateTransfer() +{ + return libusb_alloc_transfer(0); +} + +void BulkTransferPool::fillTransfer(libusb_transfer* transfer) +{ + transfer->type = LIBUSB_TRANSFER_TYPE_BULK; +} + +void BulkTransferPool::processTransfer(libusb_transfer* transfer) +{ + if(transfer->status != LIBUSB_TRANSFER_COMPLETED) return; + + if(callback_) + callback_->onDataReceived(transfer->buffer, transfer->actual_length); +} + +IsoTransferPool::IsoTransferPool(libusb_device_handle* device_handle, unsigned char device_endpoint) : + TransferPool(device_handle, device_endpoint), + num_packets_(0), + packet_size_(0) +{ +} + +IsoTransferPool::~IsoTransferPool() +{ +} + +void IsoTransferPool::allocate(size_t num_transfers, size_t num_packets, size_t packet_size) +{ + num_packets_ = num_packets; + packet_size_ = packet_size; + + allocateTransfers(num_transfers, num_packets_ * packet_size_); +} + +libusb_transfer* IsoTransferPool::allocateTransfer() +{ + return libusb_alloc_transfer(num_packets_); +} + +void IsoTransferPool::fillTransfer(libusb_transfer* transfer) +{ + transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; + transfer->num_iso_packets = num_packets_; + + libusb_set_iso_packet_lengths(transfer, packet_size_); +} + +void IsoTransferPool::processTransfer(libusb_transfer* transfer) +{ + unsigned char *ptr = transfer->buffer; + + for(size_t i = 0; i < num_packets_; ++i) + { + if(transfer->iso_packet_desc[i].status != LIBUSB_TRANSFER_COMPLETED) continue; + + if(callback_) + callback_->onDataReceived(ptr, transfer->iso_packet_desc[i].actual_length); + + ptr += transfer->iso_packet_desc[i].length; + } +} + +} /* namespace usb */ +} /* namespace libfreenect2 */ + diff --git a/examples/k22v4l/src/turbo_jpeg_rgb_packet_processor.cpp b/examples/k22v4l/src/turbo_jpeg_rgb_packet_processor.cpp new file mode 100644 index 000000000..88f650c2b --- /dev/null +++ b/examples/k22v4l/src/turbo_jpeg_rgb_packet_processor.cpp @@ -0,0 +1,133 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include + +#include +#include + +namespace libfreenect2 +{ + +class TurboJpegRgbPacketProcessorImpl +{ +public: + + tjhandle decompressor; + + Frame *frame; + + double timing_acc; + double timing_acc_n; + + double timing_current_start; + + TurboJpegRgbPacketProcessorImpl() + { + decompressor = tjInitDecompress(); + if(decompressor == 0) + { + std::cerr << "[TurboJpegRgbPacketProcessor] Failed to initialize TurboJPEG decompressor! TurboJPEG error: '" << tjGetErrorStr() << "'" << std::endl; + } + + newFrame(); + + timing_acc = 0.0; + timing_acc_n = 0.0; + timing_current_start = 0.0; + } + + ~TurboJpegRgbPacketProcessorImpl() + { + if(decompressor != 0) + { + if(tjDestroy(decompressor) == -1) + { + std::cerr << "[TurboJpegRgbPacketProcessor] Failed to destroy TurboJPEG decompressor! TurboJPEG error: '" << tjGetErrorStr() << "'" << std::endl; + } + } + } + + void newFrame() + { + frame = new Frame(1920, 1080, tjPixelSize[TJPF_BGR]); + } + + void startTiming() + { + timing_current_start = cv::getTickCount(); + } + + void stopTiming() + { + timing_acc += (cv::getTickCount() - timing_current_start) / cv::getTickFrequency(); + timing_acc_n += 1.0; + + if(timing_acc_n >= 100.0) + { + double avg = (timing_acc / timing_acc_n); + std::cout << "[TurboJpegRgbPacketProcessor] avg. time: " << (avg * 1000) << "ms -> ~" << (1.0/avg) << "Hz" << std::endl; + timing_acc = 0.0; + timing_acc_n = 0.0; + } + } +}; + +TurboJpegRgbPacketProcessor::TurboJpegRgbPacketProcessor() : + impl_(new TurboJpegRgbPacketProcessorImpl()) +{ +} + +TurboJpegRgbPacketProcessor::~TurboJpegRgbPacketProcessor() +{ + delete impl_; +} + +void TurboJpegRgbPacketProcessor::process(const RgbPacket &packet) +{ + if(impl_->decompressor != 0 && listener_ != 0) + { + impl_->startTiming(); + + int r = tjDecompress2(impl_->decompressor, packet.jpeg_buffer, packet.jpeg_buffer_length, impl_->frame->data, 1920, 1920 * tjPixelSize[TJPF_BGR], 1080, TJPF_BGR, 0); + + if(r == 0) + { + if(listener_->onNewFrame(Frame::Color, impl_->frame)) + { + impl_->newFrame(); + } + } + else + { + std::cerr << "[TurboJpegRgbPacketProcessor::doProcess] Failed to decompress rgb image! TurboJPEG error: '" << tjGetErrorStr() << "'" << std::endl; + } + + impl_->stopTiming(); + } +} + +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/src/usb_control.cpp b/examples/k22v4l/src/usb_control.cpp new file mode 100644 index 000000000..360b96b09 --- /dev/null +++ b/examples/k22v4l/src/usb_control.cpp @@ -0,0 +1,323 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include + +#include +#include + +namespace libfreenect2 +{ +namespace protocol +{ + +namespace libusb_ext +{ + enum DeviceFeatureSelector + { + U1_ENABLE = 48, + U2_ENABLE = 49 + }; + + enum InterfaceFeatureSelector + { + FUNCTION_SUSPEND = 0, + }; + + template + struct FeatureSelectorRecipient + { + static uint8_t get(); + }; + + template<> + struct FeatureSelectorRecipient + { + static uint8_t get() { return LIBUSB_RECIPIENT_DEVICE; }; + }; + + template<> + struct FeatureSelectorRecipient + { + static uint8_t get() { return LIBUSB_RECIPIENT_INTERFACE; }; + }; + + int set_isochronous_delay(libusb_device_handle *handle, int timeout) + { + // for details see USB 3.1 r1 spec section 9.4.11 + + uint8_t bmRequestType = LIBUSB_RECIPIENT_DEVICE; + uint8_t bRequest = LIBUSB_SET_ISOCH_DELAY; + // if no super speed hubs in between, then it is equal to tTPTransmissionDelay(=40ns) + uint16_t wValue = 40; // 40 nanoseconds + uint16_t wIndex = 0; + uint16_t wLength = 0; + uint8_t *data = 0; + + return libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + } + + int set_sel(libusb_device_handle *handle, int timeout, uint8_t u1sel, uint8_t u1pel, uint8_t u2sel, uint8_t u2pel) + { + // for details see USB 3.1 r1 spec section 9.4.12 + + uint8_t bmRequestType = LIBUSB_RECIPIENT_DEVICE; + uint8_t bRequest = LIBUSB_REQUEST_SET_SEL; + uint16_t wValue = 0; + uint16_t wIndex = 0; + uint16_t wLength = 6; + unsigned char data[6] = { 0x55, 0, 0x55, 0, 0, 0 }; + + return libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + } + + template + int set_feature(libusb_device_handle *handle, int timeout, TFeatureSelector feature_selector) + { + // for details see USB 3.1 r1 spec section 9.4.9 + + uint8_t bmRequestType = FeatureSelectorRecipient::get(); + uint8_t bRequest = LIBUSB_REQUEST_SET_FEATURE; + uint16_t wValue = static_cast(feature_selector); + uint16_t wIndex = 0; + uint16_t wLength = 0; + uint8_t *data = 0; + + return libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + } + + int set_feature_function_suspend(libusb_device_handle *handle, int timeout, bool low_power_suspend, bool function_remote_wake) + { + uint8_t suspend_options = 0; + suspend_options |= low_power_suspend ? 1 : 0; + suspend_options |= function_remote_wake ? 2 : 0; + + // for details see USB 3.1 r1 spec section 9.4.9 + + InterfaceFeatureSelector feature_selector = FUNCTION_SUSPEND; + uint8_t bmRequestType = FeatureSelectorRecipient::get(); + uint8_t bRequest = LIBUSB_REQUEST_SET_FEATURE; + uint16_t wValue = static_cast(feature_selector); + uint16_t wIndex = suspend_options << 8 | 0; + uint16_t wLength = 0; + uint8_t *data = 0; + + return libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + } + + int get_max_iso_packet_size(libusb_device *device, int configuration, int alternate_setting, int endpoint) + { + libusb_config_descriptor *config_desc; + int r = LIBUSB_ERROR_NOT_FOUND; + + r = libusb_get_config_descriptor_by_value(device, configuration, &config_desc); + + if(r == LIBUSB_SUCCESS) + { + for(int interface_idx = 0; interface_idx < config_desc->bNumInterfaces; ++interface_idx) + { + const libusb_interface &interface = config_desc->interface[interface_idx]; + + if(interface.num_altsetting > alternate_setting) + { + const libusb_interface_descriptor &interface_desc = interface.altsetting[alternate_setting]; + const libusb_endpoint_descriptor *endpoint_desc = 0; + + for(int endpoint_idx = 0; endpoint_idx < interface_desc.bNumEndpoints; ++endpoint_idx) + { + if(interface_desc.endpoint[endpoint_idx].bEndpointAddress == endpoint && (interface_desc.endpoint[endpoint_idx].bmAttributes & 0x3) == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) + { + endpoint_desc = interface_desc.endpoint + endpoint_idx; + break; + } + } + + if(endpoint_desc != 0) + { + libusb_ss_endpoint_companion_descriptor *companion_desc; + // ctx is only used for error reporting, libusb should better ask for a libusb_device anyway... + r = libusb_get_ss_endpoint_companion_descriptor(NULL /* ctx */, endpoint_desc, &companion_desc); + + if(r != LIBUSB_SUCCESS) continue; + + r = companion_desc->wBytesPerInterval; + + libusb_free_ss_endpoint_companion_descriptor(companion_desc); + break; + } + } + } + } + libusb_free_config_descriptor(config_desc); + + return r; + } +} + +UsbControl::UsbControl(libusb_device_handle *handle) : + handle_(handle), + timeout_(1000) +{ +} + +UsbControl::~UsbControl() +{ +} + +static UsbControl::ResultCode checkLibusbResult(const char* method, int r) +{ + if(r != LIBUSB_SUCCESS) + { + std::cerr << "[UsbControl::" << method << "] failed! libusb error " << r << ": " << libusb_error_name(r) << std::endl; + return UsbControl::Error; + } + else + { + return UsbControl::Success; + } +} + +UsbControl::ResultCode UsbControl::setConfiguration() +{ + UsbControl::ResultCode code = Success; + int desired_config_id = 1; + int current_config_id = -1; + int r; + + r = libusb_get_configuration(handle_, ¤t_config_id); + code = checkLibusbResult("setConfiguration(initial get)", r); + + if(code == Success) + { + if(current_config_id != desired_config_id) + { + r = libusb_set_configuration(handle_, desired_config_id); + code = checkLibusbResult("setConfiguration(set)", r); + } + } + + return code; +} + +UsbControl::ResultCode UsbControl::claimInterfaces() +{ + UsbControl::ResultCode code = Success; + int r; + + r = libusb_claim_interface(handle_, ControlAndRgbInterfaceId); + code = checkLibusbResult("claimInterfaces(ControlAndRgbInterfaceId)", r); + + if(code == Success) + { + r = libusb_claim_interface(handle_, IrInterfaceId); + code = checkLibusbResult("claimInterfaces(IrInterfaceId)", r); + } + + return code; +} + +UsbControl::ResultCode UsbControl::releaseInterfaces() +{ + UsbControl::ResultCode code = Success; + int r; + + r = libusb_release_interface(handle_, ControlAndRgbInterfaceId); + code = checkLibusbResult("releaseInterfaces(ControlAndRgbInterfaceId)", r); + + if(code == Success) + { + r = libusb_release_interface(handle_, IrInterfaceId); + code = checkLibusbResult("releaseInterfaces(IrInterfaceId)", r); + } + + return code; +} + +UsbControl::ResultCode UsbControl::setIsochronousDelay() +{ + int r = libusb_ext::set_isochronous_delay(handle_, timeout_); + + return checkLibusbResult("setIsochronousDelay", r); +} + +UsbControl::ResultCode UsbControl::setPowerStateLatencies() +{ + int r = libusb_ext::set_sel(handle_, timeout_, 0x55, 0, 0x55, 0); + + return checkLibusbResult("setPowerStateLatencies", r); +} + +UsbControl::ResultCode UsbControl::enablePowerStates() +{ + UsbControl::ResultCode code; + int r; + + r = libusb_ext::set_feature(handle_, timeout_, libusb_ext::U1_ENABLE); + code = checkLibusbResult("enablePowerStates(U1)", r); + + if(code == Success) + { + r = libusb_ext::set_feature(handle_, timeout_, libusb_ext::U2_ENABLE); + code = checkLibusbResult("enablePowerStates(U2)", r); + } + + return code; +} + +UsbControl::ResultCode UsbControl::setVideoTransferFunctionState(UsbControl::State state) +{ + bool suspend = state == Enabled ? false : true; + int r = libusb_ext::set_feature_function_suspend(handle_, timeout_, suspend, suspend); + + return checkLibusbResult("setVideoTransferFunctionState", r); +} + +UsbControl::ResultCode UsbControl::setIrInterfaceState(UsbControl::State state) +{ + int alternate_setting = state == Enabled ? 1 : 0; + int r = libusb_set_interface_alt_setting(handle_, IrInterfaceId, alternate_setting); + + return checkLibusbResult("setIrInterfaceState", r); +} + + +UsbControl::ResultCode UsbControl::getIrMaxIsoPacketSize(int &size) +{ + size = 0; + libusb_device *dev = libusb_get_device(handle_); + int r = libusb_ext::get_max_iso_packet_size(dev, 1, 1, 0x84); + + if(r > LIBUSB_SUCCESS) + { + size = r; + r = LIBUSB_SUCCESS; + } + + return checkLibusbResult("getIrMaxIsoPacketSize", r); +} + +} /* namespace protocol */ +} /* namespace libfreenect2 */ diff --git a/examples/k22v4l/xTable.bin b/examples/k22v4l/xTable.bin new file mode 100644 index 000000000..f74842d36 Binary files /dev/null and b/examples/k22v4l/xTable.bin differ diff --git a/examples/k22v4l/zTable.bin b/examples/k22v4l/zTable.bin new file mode 100644 index 000000000..4504b6158 Binary files /dev/null and b/examples/k22v4l/zTable.bin differ