Commit 6294701e authored by Nianchen Deng's avatar Nianchen Deng
Browse files

sync

parent 2824f796
//========= Copyright Valve Corporation ============//
#include "compat.h"
#include "strtools.h"
#include "pathtools.h"
#if defined( _WIN32)
#include <windows.h>
#include <direct.h>
#include <shobjidl.h>
#include <knownfolders.h>
#include <shlobj.h>
#include <share.h>
#undef GetEnvironmentVariable
#else
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#endif
#if defined OSX
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
#include <mach-o/dyld.h>
#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet
#endif
#include <sys/stat.h>
#include <algorithm>
/** Returns the path of the current working directory */
std::string Path_GetWorkingDirectory()
{
std::string sPath;
#if defined( _WIN32 )
wchar_t buf[MAX_UNICODE_PATH];
sPath = UTF16to8( _wgetcwd( buf, MAX_UNICODE_PATH ) );
#else
char buf[ 1024 ];
sPath = getcwd( buf, sizeof( buf ) );
#endif
return sPath;
}
/** Sets the path of the current working directory. Returns true if this was successful. */
bool Path_SetWorkingDirectory( const std::string & sPath )
{
bool bSuccess;
#if defined( _WIN32 )
std::wstring wsPath = UTF8to16( sPath.c_str() );
bSuccess = 0 == _wchdir( wsPath.c_str() );
#else
bSuccess = 0 == chdir( sPath.c_str() );
#endif
return bSuccess;
}
/** Returns the specified path without its filename */
std::string Path_StripFilename( const std::string & sPath, char slash )
{
if( slash == 0 )
slash = Path_GetSlash();
std::string::size_type n = sPath.find_last_of( slash );
if( n == std::string::npos )
return sPath;
else
return std::string( sPath.begin(), sPath.begin() + n );
}
/** returns just the filename from the provided full or relative path. */
std::string Path_StripDirectory( const std::string & sPath, char slash )
{
if( slash == 0 )
slash = Path_GetSlash();
std::string::size_type n = sPath.find_last_of( slash );
if( n == std::string::npos )
return sPath;
else
return std::string( sPath.begin() + n + 1, sPath.end() );
}
/** returns just the filename with no extension of the provided filename.
* If there is a path the path is left intact. */
std::string Path_StripExtension( const std::string & sPath )
{
for( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ )
{
if( *i == '.' )
{
return std::string( sPath.begin(), i.base() - 1 );
}
// if we find a slash there is no extension
if( *i == '\\' || *i == '/' )
break;
}
// we didn't find an extension
return sPath;
}
/** returns just extension of the provided filename (if any). */
std::string Path_GetExtension( const std::string & sPath )
{
for ( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ )
{
if ( *i == '.' )
{
return std::string( i.base(), sPath.end() );
}
// if we find a slash there is no extension
if ( *i == '\\' || *i == '/' )
break;
}
// we didn't find an extension
return "";
}
bool Path_IsAbsolute( const std::string & sPath )
{
if( sPath.empty() )
return false;
#if defined( WIN32 )
if ( sPath.size() < 3 ) // must be c:\x or \\x at least
return false;
if ( sPath[1] == ':' ) // drive letter plus slash, but must test both slash cases
{
if ( sPath[2] == '\\' || sPath[2] == '/' )
return true;
}
else if ( sPath[0] == '\\' && sPath[1] == '\\' ) // UNC path
return true;
#else
if( sPath[0] == '\\' || sPath[0] == '/' ) // any leading slash
return true;
#endif
return false;
}
/** Makes an absolute path from a relative path and a base path */
std::string Path_MakeAbsolute( const std::string & sRelativePath, const std::string & sBasePath )
{
if( Path_IsAbsolute( sRelativePath ) )
return sRelativePath;
else
{
if( !Path_IsAbsolute( sBasePath ) )
return "";
std::string sCompacted = Path_Compact( Path_Join( sBasePath, sRelativePath ) );
if( Path_IsAbsolute( sCompacted ) )
return sCompacted;
else
return "";
}
}
/** Fixes the directory separators for the current platform */
std::string Path_FixSlashes( const std::string & sPath, char slash )
{
if( slash == 0 )
slash = Path_GetSlash();
std::string sFixed = sPath;
for( std::string::iterator i = sFixed.begin(); i != sFixed.end(); i++ )
{
if( *i == '/' || *i == '\\' )
*i = slash;
}
return sFixed;
}
char Path_GetSlash()
{
#if defined(_WIN32)
return '\\';
#else
return '/';
#endif
}
/** Jams two paths together with the right kind of slash */
std::string Path_Join( const std::string & first, const std::string & second, char slash )
{
if( slash == 0 )
slash = Path_GetSlash();
// only insert a slash if we don't already have one
std::string::size_type nLen = first.length();
if( !nLen )
return second;
#if defined(_WIN32)
if( first.back() == '\\' || first.back() == '/' )
nLen--;
#else
char last_char = first[first.length()-1];
if (last_char == '\\' || last_char == '/')
nLen--;
#endif
return first.substr( 0, nLen ) + std::string( 1, slash ) + second;
}
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, char slash )
{
return Path_Join( Path_Join( first, second, slash ), third, slash );
}
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, const std::string &fourth, char slash )
{
return Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash );
}
std::string Path_Join(
const std::string & first,
const std::string & second,
const std::string & third,
const std::string & fourth,
const std::string & fifth,
char slash )
{
return Path_Join( Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash ), fifth, slash );
}
std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash )
{
if ( slash == 0 )
slash = Path_GetSlash();
std::string sPath = sRawPath;
std::string::size_type nCurrent = sRawPath.length();
if ( nCurrent == 0 )
return sPath;
int nLastFound = -1;
nCurrent--;
while( nCurrent != 0 )
{
if ( sRawPath[ nCurrent ] == slash )
{
nLastFound = (int)nCurrent;
nCurrent--;
}
else
{
break;
}
}
if ( nLastFound >= 0 )
{
sPath.erase( nLastFound, std::string::npos );
}
return sPath;
}
/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the
* specified path has a broken number of directories for its number of ..s */
std::string Path_Compact( const std::string & sRawPath, char slash )
{
if( slash == 0 )
slash = Path_GetSlash();
std::string sPath = Path_FixSlashes( sRawPath, slash );
std::string sSlashString( 1, slash );
// strip out all /./
for( std::string::size_type i = 0; (i + 3) < sPath.length(); )
{
if( sPath[ i ] == slash && sPath[ i+1 ] == '.' && sPath[ i+2 ] == slash )
{
sPath.replace( i, 3, sSlashString );
}
else
{
++i;
}
}
// get rid of trailing /. but leave the path separator
if( sPath.length() > 2 )
{
std::string::size_type len = sPath.length();
if( sPath[ len-1 ] == '.' && sPath[ len-2 ] == slash )
{
// sPath.pop_back();
sPath[len-1] = 0; // for now, at least
}
}
// get rid of leading ./
if( sPath.length() > 2 )
{
if( sPath[ 0 ] == '.' && sPath[ 1 ] == slash )
{
sPath.replace( 0, 2, "" );
}
}
// each time we encounter .. back up until we've found the previous directory name
// then get rid of both
std::string::size_type i = 0;
while( i < sPath.length() )
{
if( i > 0 && sPath.length() - i >= 2
&& sPath[i] == '.'
&& sPath[i+1] == '.'
&& ( i + 2 == sPath.length() || sPath[ i+2 ] == slash )
&& sPath[ i-1 ] == slash )
{
// check if we've hit the start of the string and have a bogus path
if( i == 1 )
return "";
// find the separator before i-1
std::string::size_type iDirStart = i-2;
while( iDirStart > 0 && sPath[ iDirStart - 1 ] != slash )
--iDirStart;
// remove everything from iDirStart to i+2
sPath.replace( iDirStart, (i - iDirStart) + 3, "" );
// start over
i = 0;
}
else
{
++i;
}
}
return sPath;
}
/** Returns the path to the current DLL or exe */
std::string Path_GetThisModulePath()
{
// gets the path of vrclient.dll itself
#ifdef WIN32
HMODULE hmodule = NULL;
::GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast<LPCTSTR>(Path_GetThisModulePath), &hmodule );
wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH];
char *pchPath = new char[ MAX_UNICODE_PATH_IN_UTF8 ];
::GetModuleFileNameW( hmodule, pwchPath, MAX_UNICODE_PATH );
WideCharToMultiByte( CP_UTF8, 0, pwchPath, -1, pchPath, MAX_UNICODE_PATH_IN_UTF8, NULL, NULL );
delete[] pwchPath;
std::string sPath = pchPath;
delete [] pchPath;
return sPath;
#elif defined( OSX ) || defined( LINUX )
// get the addr of a function in vrclient.so and then ask the dlopen system about it
Dl_info info;
dladdr( (void *)Path_GetThisModulePath, &info );
return info.dli_fname;
#endif
}
/** returns true if the specified path represents an app bundle */
bool Path_IsAppBundle( const std::string & sPath )
{
#if defined(OSX)
NSBundle *bundle = [ NSBundle bundleWithPath: [ NSString stringWithUTF8String:sPath.c_str() ] ];
bool bisAppBundle = ( nullptr != bundle );
[ bundle release ];
return bisAppBundle;
#else
return false;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: returns true if the the path exists
//-----------------------------------------------------------------------------
bool Path_Exists( const std::string & sPath )
{
std::string sFixedPath = Path_FixSlashes( sPath );
if( sFixedPath.empty() )
return false;
#if defined( WIN32 )
struct _stat buf;
std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() );
if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 )
{
return false;
}
#else
struct stat buf;
if ( stat ( sFixedPath.c_str(), &buf ) == -1)
{
return false;
}
#endif
return true;
}
//-----------------------------------------------------------------------------
// Purpose: helper to find a directory upstream from a given path
//-----------------------------------------------------------------------------
std::string Path_FindParentDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName )
{
std::string strFoundPath = "";
std::string strCurrentPath = Path_FixSlashes( strStartDirectory );
if ( strCurrentPath.length() == 0 )
return "";
bool bExists = Path_Exists( strCurrentPath );
std::string strCurrentDirectoryName = Path_StripDirectory( strCurrentPath );
if ( bExists && _stricmp( strCurrentDirectoryName.c_str(), strDirectoryName.c_str() ) == 0 )
return strCurrentPath;
while( bExists && strCurrentPath.length() != 0 )
{
strCurrentPath = Path_StripFilename( strCurrentPath );
strCurrentDirectoryName = Path_StripDirectory( strCurrentPath );
bExists = Path_Exists( strCurrentPath );
if ( bExists && _stricmp( strCurrentDirectoryName.c_str(), strDirectoryName.c_str() ) == 0 )
return strCurrentPath;
}
return "";
}
//-----------------------------------------------------------------------------
// Purpose: helper to find a subdirectory upstream from a given path
//-----------------------------------------------------------------------------
std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName )
{
std::string strFoundPath = "";
std::string strCurrentPath = Path_FixSlashes( strStartDirectory );
if ( strCurrentPath.length() == 0 )
return "";
bool bExists = Path_Exists( strCurrentPath );
while( bExists && strCurrentPath.length() != 0 )
{
strCurrentPath = Path_StripFilename( strCurrentPath );
bExists = Path_Exists( strCurrentPath );
if( Path_Exists( Path_Join( strCurrentPath, strDirectoryName ) ) )
{
strFoundPath = Path_Join( strCurrentPath, strDirectoryName );
break;
}
}
return strFoundPath;
}
#if defined(WIN32)
#define FILE_URL_PREFIX "file:///"
#else
#define FILE_URL_PREFIX "file://"
#endif
// ----------------------------------------------------------------------------------------------------------------------------
// Purpose: Turns a path to a file on disk into a URL (or just returns the value if it's already a URL)
// ----------------------------------------------------------------------------------------------------------------------------
std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath )
{
if ( !strncasecmp( sRelativePath.c_str(), "http://", 7 )
|| !strncasecmp( sRelativePath.c_str(), "https://", 8 )
|| !strncasecmp( sRelativePath.c_str(), "file://", 7 ) )
{
return sRelativePath;
}
else
{
std::string sAbsolute = Path_MakeAbsolute( sRelativePath, sBasePath );
if ( sAbsolute.empty() )
return sAbsolute;
sAbsolute = Path_FixSlashes( sAbsolute, '/' );
return std::string( FILE_URL_PREFIX ) + sAbsolute;
}
}
// -----------------------------------------------------------------------------------------------------
// Purpose: Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned
// -----------------------------------------------------------------------------------------------------
std::string Path_UrlToFilePath( const std::string & sFileUrl )
{
if ( !strncasecmp( sFileUrl.c_str(), FILE_URL_PREFIX, strlen( FILE_URL_PREFIX ) ) )
{
std::string sRet = sFileUrl.c_str() + strlen( FILE_URL_PREFIX );
sRet = Path_FixSlashes( sRet );
return sRet;
}
else
{
return "";
}
}
// -----------------------------------------------------------------------------------------------------
// Purpose: Returns the root of the directory the system wants us to store user documents in
// -----------------------------------------------------------------------------------------------------
std::string GetUserDocumentsPath()
{
#if defined( WIN32 )
WCHAR rwchPath[MAX_PATH];
if ( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) )
{
return "";
}
// Convert the path to UTF-8 and store in the output
std::string sUserPath = UTF16to8( rwchPath );
return sUserPath;
#elif defined( OSX )
@autoreleasepool {
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
if ( [paths count] == 0 )
{
return "";
}
return [[paths objectAtIndex:0] UTF8String];
}
#elif defined( LINUX )
// @todo: not solved/changed as part of OSX - still not real - just removed old class based steam cut and paste
const char *pchHome = getenv( "HOME" );
if ( pchHome == NULL )
{
return "";
}
return pchHome;
#endif
}
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <stdint.h>
/** Returns the path of the current working directory */
std::string Path_GetWorkingDirectory();
/** Sets the path of the current working directory. Returns true if this was successful. */
bool Path_SetWorkingDirectory( const std::string & sPath );
/** returns the path (including filename) of the current shared lib or DLL */
std::string Path_GetThisModulePath();
/** Returns the specified path without its filename.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_StripFilename( const std::string & sPath, char slash = 0 );
/** returns just the filename from the provided full or relative path. */
std::string Path_StripDirectory( const std::string & sPath, char slash = 0 );
/** returns just the filename with no extension of the provided filename.
* If there is a path the path is left intact. */
std::string Path_StripExtension( const std::string & sPath );
/** returns just extension of the provided filename (if any). */
std::string Path_GetExtension( const std::string & sPath );
/** Returns true if the path is absolute */
bool Path_IsAbsolute( const std::string & sPath );
/** Makes an absolute path from a relative path and a base path */
std::string Path_MakeAbsolute( const std::string & sRelativePath, const std::string & sBasePath );
/** Fixes the directory separators for the current platform.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_FixSlashes( const std::string & sPath, char slash = 0 );
/** Returns the path separator for the current platform */
char Path_GetSlash();
/** Jams two paths together with the right kind of slash */
std::string Path_Join( const std::string & first, const std::string & second, char slash = 0 );
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, char slash = 0 );
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, const std::string &fourth, char slash = 0 );
std::string Path_Join(
const std::string & first,
const std::string & second,
const std::string & third,
const std::string & fourth,
const std::string & fifth,
char slash = 0 );
/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the
* specified path has a broken number of directories for its number of ..s.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_Compact( const std::string & sRawPath, char slash = 0 );
//** Removed trailing slashes */
std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash = 0 );
/** returns true if the specified path represents an app bundle */
bool Path_IsAppBundle( const std::string & sPath );
/** returns true if the the path exists */
bool Path_Exists( const std::string & sPath );
/** Helper functions to find parent directories or subdirectories of parent directories */
std::string Path_FindParentDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
/** Returns a file:// url for paths, or an http or https url if that's what was provided */
std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath );
/** Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned */
std::string Path_UrlToFilePath( const std::string & sFileUrl );
/** Returns the root of the directory the system wants us to store user documents in */
std::string GetUserDocumentsPath();
#ifndef MAX_UNICODE_PATH
#define MAX_UNICODE_PATH 32767
#endif
#ifndef MAX_UNICODE_PATH_IN_UTF8
#define MAX_UNICODE_PATH_IN_UTF8 (MAX_UNICODE_PATH * 4)
#endif
//-----------------------------------------------------------------------------
#if defined(WIN32)
#define DYNAMIC_LIB_EXT ".dll"
#ifdef _WIN64
#define PLATSUBDIR "win64"
#else
#define PLATSUBDIR "win32"
#endif
#elif defined(OSX)
#define DYNAMIC_LIB_EXT ".dylib"
#define PLATSUBDIR "osx32"
#elif defined(LINUX)
#define DYNAMIC_LIB_EXT ".so"
#if defined( LINUX32 )
#define PLATSUBDIR "linux32"
#else
#define PLATSUBDIR "linux64"
#endif
#else
#warning "Unknown platform for PLATSUBDIR"
#define PLATSUBDIR "unknown_platform"
#endif
//========= Copyright Valve Corporation ============//
#include "strtools.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix )
{
return 0 == strncasecmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
}
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix )
{
return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
}
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix )
{
size_t cStrLen = sString.length();
size_t cSuffixLen = sSuffix.length();
if ( cSuffixLen > cStrLen )
return false;
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
return 0 == strcasecmp( sStringSuffix.c_str(), sSuffix.c_str() );
}
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix )
{
size_t cStrLen = sString.length();
size_t cSuffixLen = sSuffix.length();
if ( cSuffixLen > cStrLen )
return false;
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
return 0 == strcmp( sStringSuffix.c_str(), sSuffix.c_str() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
std::string UTF16to8(const wchar_t * in)
{
std::string out;
unsigned int codepoint = 0;
for ( ; in && *in != 0; ++in )
{
if (*in >= 0xd800 && *in <= 0xdbff)
codepoint = ((*in - 0xd800) << 10) + 0x10000;
else
{
if (*in >= 0xdc00 && *in <= 0xdfff)
codepoint |= *in - 0xdc00;
else
codepoint = *in;
if (codepoint <= 0x7f)
out.append(1, static_cast<char>(codepoint));
else if (codepoint <= 0x7ff)
{
out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else if (codepoint <= 0xffff)
{
out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else
{
out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
codepoint = 0;
}
}
return out;
}
std::wstring UTF8to16(const char * in)
{
std::wstring out;
unsigned int codepoint = 0;
int following = 0;
for ( ; in && *in != 0; ++in )
{
unsigned char ch = *in;
if (ch <= 0x7f)
{
codepoint = ch;
following = 0;
}
else if (ch <= 0xbf)
{
if (following > 0)
{
codepoint = (codepoint << 6) | (ch & 0x3f);
--following;
}
}
else if (ch <= 0xdf)
{
codepoint = ch & 0x1f;
following = 1;
}
else if (ch <= 0xef)
{
codepoint = ch & 0x0f;
following = 2;
}
else
{
codepoint = ch & 0x07;
following = 3;
}
if (following == 0)
{
if (codepoint > 0xffff)
{
out.append(1, static_cast<wchar_t>(0xd800 + (codepoint >> 10)));
out.append(1, static_cast<wchar_t>(0xdc00 + (codepoint & 0x03ff)));
}
else
out.append(1, static_cast<wchar_t>(codepoint));
codepoint = 0;
}
}
return out;
}
// --------------------------------------------------------------------
// Purpose: converts a string to upper case
// --------------------------------------------------------------------
std::string StringToUpper( const std::string & sString )
{
std::string sOut;
sOut.reserve( sString.size() + 1 );
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
{
sOut.push_back( (char)toupper( *i ) );
}
return sOut;
}
// --------------------------------------------------------------------
// Purpose: converts a string to lower case
// --------------------------------------------------------------------
std::string StringToLower( const std::string & sString )
{
std::string sOut;
sOut.reserve( sString.size() + 1 );
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
{
sOut.push_back( (char)tolower( *i ) );
}
return sOut;
}
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen )
{
uint32_t unLen = (uint32_t)sValue.length() + 1;
if( !pchBuffer || !unBufferLen )
return unLen;
if( unBufferLen < unLen )
{
pchBuffer[0] = '\0';
}
else
{
memcpy( pchBuffer, sValue.c_str(), unLen );
}
return unLen;
}
void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen )
{
sDest.resize( unBufferLen + 1 );
memcpy( const_cast< char* >( sDest.c_str() ), pchBuffer, unBufferLen );
const_cast< char* >( sDest.c_str() )[ unBufferLen ] = '\0';
}
/** Returns a std::string from a uint64_t */
std::string Uint64ToString( uint64_t ulValue )
{
char buf[ 22 ];
#if defined( _WIN32 )
sprintf_s( buf, "%llu", ulValue );
#else
snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue );
#endif
return buf;
}
/** returns a uint64_t from a string */
uint64_t StringToUint64( const std::string & sValue )
{
return strtoull( sValue.c_str(), NULL, 0 );
}
//-----------------------------------------------------------------------------
// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15.
//-----------------------------------------------------------------------------
char cIntToHexDigit( int nValue )
{
//Assert( nValue >= 0 && nValue <= 15 );
return "0123456789ABCDEF"[ nValue & 15 ];
}
//-----------------------------------------------------------------------------
// Purpose: Helper for converting a hex char value to numeric, return -1 if the char
// is not a valid hex digit.
//-----------------------------------------------------------------------------
int iHexCharToInt( char cValue )
{
int32_t iValue = cValue;
if ( (uint32_t)( iValue - '0' ) < 10 )
return iValue - '0';
iValue |= 0x20;
if ( (uint32_t)( iValue - 'a' ) < 6 )
return iValue - 'a' + 10;
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: Internal implementation of encode, works in the strict RFC manner, or
// with spaces turned to + like HTML form encoding.
//-----------------------------------------------------------------------------
void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, bool bUsePlusForSpace )
{
//AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" );
int iDestPos = 0;
for ( int i=0; i < nSourceLen; ++i )
{
// worst case we need 3 additional chars
if( (iDestPos+3) > nDestLen )
{
pchDest[0] = '\0';
// AssertMsg( false, "Target buffer too short\n" );
return;
}
// We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped.
// These are the characters allowed by both the original RFC 1738 and the latest RFC 3986.
// Current specs also allow '~', but that is forbidden under original RFC 1738.
if ( !( pchSource[i] >= 'a' && pchSource[i] <= 'z' ) && !( pchSource[i] >= 'A' && pchSource[i] <= 'Z' ) && !(pchSource[i] >= '0' && pchSource[i] <= '9' )
&& pchSource[i] != '-' && pchSource[i] != '_' && pchSource[i] != '.'
)
{
if ( bUsePlusForSpace && pchSource[i] == ' ' )
{
pchDest[iDestPos++] = '+';
}
else
{
pchDest[iDestPos++] = '%';
uint8_t iValue = pchSource[i];
if ( iValue == 0 )
{
pchDest[iDestPos++] = '0';
pchDest[iDestPos++] = '0';
}
else
{
char cHexDigit1 = cIntToHexDigit( iValue % 16 );
iValue /= 16;
char cHexDigit2 = cIntToHexDigit( iValue );
pchDest[iDestPos++] = cHexDigit2;
pchDest[iDestPos++] = cHexDigit1;
}
}
}
else
{
pchDest[iDestPos++] = pchSource[i];
}
}
if( (iDestPos+1) > nDestLen )
{
pchDest[0] = '\0';
//AssertMsg( false, "Target buffer too short to terminate\n" );
return;
}
// Null terminate
pchDest[iDestPos++] = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Internal implementation of decode, works in the strict RFC manner, or
// with spaces turned to + like HTML form encoding.
//
// Returns the amount of space used in the output buffer.
//-----------------------------------------------------------------------------
size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace )
{
if ( nDecodeDestLen < nEncodedSourceLen )
{
//AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" );
return 0;
}
int iDestPos = 0;
for( int i=0; i < nEncodedSourceLen; ++i )
{
if ( bUsePlusForSpace && pchEncodedSource[i] == '+' )
{
pchDecodeDest[ iDestPos++ ] = ' ';
}
else if ( pchEncodedSource[i] == '%' )
{
// Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that
// First make sure we have 2 more chars
if ( i < nEncodedSourceLen - 2 )
{
char cHexDigit1 = pchEncodedSource[i+1];
char cHexDigit2 = pchEncodedSource[i+2];
// Turn the chars into a hex value, if they are not valid, then we'll
// just place the % and the following two chars direct into the string,
// even though this really shouldn't happen, who knows what bad clients
// may do with encoding.
bool bValid = false;
int iValue = iHexCharToInt( cHexDigit1 );
if ( iValue != -1 )
{
iValue *= 16;
int iValue2 = iHexCharToInt( cHexDigit2 );
if ( iValue2 != -1 )
{
iValue += iValue2;
pchDecodeDest[ iDestPos++ ] = (char)iValue;
bValid = true;
}
}
if ( !bValid )
{
pchDecodeDest[ iDestPos++ ] = '%';
pchDecodeDest[ iDestPos++ ] = cHexDigit1;
pchDecodeDest[ iDestPos++ ] = cHexDigit2;
}
}
// Skip ahead
i += 2;
}
else
{
pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i];
}
}
// We may not have extra room to NULL terminate, since this can be used on raw data, but if we do
// go ahead and do it as this can avoid bugs.
if ( iDestPos < nDecodeDestLen )
{
pchDecodeDest[iDestPos] = 0;
}
return (size_t)iDestPos;
}
//-----------------------------------------------------------------------------
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
//-----------------------------------------------------------------------------
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
{
return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true );
}
//-----------------------------------------------------------------------------
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
//-----------------------------------------------------------------------------
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen )
{
return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true );
}
//-----------------------------------------------------------------------------
void V_StripExtension( std::string &in )
{
// Find the last dot. If it's followed by a dot or a slash, then it's part of a
// directory specifier like ../../somedir/./blah.
std::string::size_type test = in.rfind( '.' );
if ( test != std::string::npos )
{
// This handles things like ".\blah" or "c:\my@email.com\abc\def\geh"
// Which would otherwise wind up with "" and "c:\my@email", respectively.
if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test )
{
in.resize( test );
}
}
}
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <stdint.h>
#include <sys/types.h>
/** returns true if the string has the prefix */
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix );
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix );
/** returns if the string has the suffix */
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix );
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix );
/** converts a UTF-16 string to a UTF-8 string */
std::string UTF16to8(const wchar_t * in);
/** converts a UTF-8 string to a UTF-16 string */
std::wstring UTF8to16(const char * in);
#define Utf16FromUtf8 UTF8to16
/** safely copy a string into a buffer */
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource );
template< size_t bufferSize >
void strcpy_safe( char (& buffer) [ bufferSize ], const char *pchSource )
{
strcpy_safe( buffer, bufferSize, pchSource );
}
/** converts a string to upper case */
std::string StringToUpper( const std::string & sString );
/** converts a string to lower case */
std::string StringToLower( const std::string & sString );
// we stricmp (from WIN) but it isn't POSIX - OSX/LINUX have strcasecmp so just inline bridge to it
#if defined( OSX ) || defined( LINUX )
#ifndef __THROW // If __THROW is defined, these will clash with throw() versions on gcc
#include <strings.h>
inline int stricmp(const char *pStr1, const char *pStr2) { return strcasecmp(pStr1,pStr2); }
#ifndef _stricmp
#define _stricmp stricmp
#endif
inline int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen ) { return strncasecmp( pStr1,pStr2, unBufferLen ); }
#define _strnicmp strnicmp
#endif
#ifndef _vsnprintf_s
#define _vsnprintf_s vsnprintf
#endif
#define _TRUNCATE ((size_t)-1)
#endif // defined( OSX ) || defined( LINUX )
#if defined( OSX )
// behaviors ensure NULL-termination at least as well as _TRUNCATE does, but
// wcsncpy_s/strncpy_s can non-NULL-terminate, wcslcpy/strlcpy can not.
inline errno_t wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
{
return wcslcpy(strDest, strSource, numberOfElements);
}
inline errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
{
return strlcpy(strDest, strSource, numberOfElements);
}
#endif
#if defined( LINUX )
// this implementation does not return whether or not the destination was
// truncated, but that is straightforward to fix if anybody actually needs the
// return code.
#include "string.h"
inline void wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
{
wcsncpy(strDest, strSource, numberOfElements);
strDest[numberOfElements-1] = '\0';
}
inline void strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
{
strncpy(strDest, strSource, numberOfElements);
strDest[numberOfElements-1] = '\0';
}
#endif
#if defined( _WIN32 ) && _MSC_VER < 1800
inline uint64_t strtoull(const char *str, char **endptr, int base) { return _strtoui64( str, endptr, base ); }
#endif
/* Handles copying a std::string into a buffer as would be provided in an API */
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen );
/* Handles copying a buffer into an std::string and auto adds null terminator */
void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen );
/** Returns a std::string from a uint64_t */
std::string Uint64ToString( uint64_t ulValue );
/** returns a uint64_t from a string */
uint64_t StringToUint64( const std::string & sValue );
//-----------------------------------------------------------------------------
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
//-----------------------------------------------------------------------------
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen );
//-----------------------------------------------------------------------------
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
//-----------------------------------------------------------------------------
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen );
//-----------------------------------------------------------------------------
// Purpose: strip extension from a path
//-----------------------------------------------------------------------------
void V_StripExtension( std::string &in );
File mode changed from 100755 to 100644
OUTNAME_RELEASE = view_gl
OUTNAME_DEBUG = view_gl_debug
EXTRA_DIRECTORIES = ../utils ../fnr_core
.NOTPARALLEL:
MAKEFILE ?= ../Makefile.config
include $(MAKEFILE)
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <glm/glm.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/transform.hpp>
#include "../utils/Shader.h"
#include "../fnr_core/FoveatedSynthesis.h"
#include "../fnr_core/FoveatedBlend.h"
#include "../fnr_core/CrossRenderer.h"
#include "../fnr_core/BakedData.h"
#define STEREO_DISABLED 0
#define STEREO_OPTI 1
#define STEREO_NORMAL 2
bool prebake = false;
bool showPerf = true;
int stereo = STEREO_DISABLED;
glm::vec2 frameRes(1440.0f, 1600.0f);
float windowScale = 0.5f;
glm::mat4 trans = glm::mat4();
glm::vec2 fovea_pos = frameRes / 2.0f;
glm::vec2 fovea_pos_r = frameRes / 2.0f;
bool mouse_button_down[] = { false, false, false };
glm::vec2 mouse_pos;
static void error_callback(int error, const char* description) {
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
float speed = 0.005f;
switch (key) {
case GLFW_KEY_A:
trans = trans * glm::translate(glm::vec3(-speed, 0.0f, 0.0f));
break;
case GLFW_KEY_D:
trans = trans * glm::translate(glm::vec3(speed, 0.0f, 0.0f));
break;
case GLFW_KEY_W:
trans = trans * glm::translate(glm::vec3(0.0f, speed, 0.0f));
break;
case GLFW_KEY_S:
trans = trans * glm::translate(glm::vec3(0.0f, -speed, 0.0f));
break;
case GLFW_KEY_Q:
trans = trans * glm::translate(glm::vec3(0.0f, 0.0f, speed));
break;
case GLFW_KEY_E:
trans = trans * glm::translate(glm::vec3(0.0f, 0.0f, -speed));
break;
}
}
}
void setFoveaPos(glm::vec2 mousePos) {
if (stereo) {
mousePos /= windowScale;
if (mousePos.x >= frameRes.x)
fovea_pos_r = mousePos - glm::vec2(frameRes.x, 0.0f);
else
fovea_pos = mousePos;
}
else {
fovea_pos = mousePos / windowScale;
}
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
if (button <= 2)
mouse_button_down[button] = (action != GLFW_RELEASE);
if (mouse_button_down[0]) {
setFoveaPos(mouse_pos);
}
}
void cursor_position_callback(GLFWwindow* window, double x, double y) {
glm::vec2 cur_mouse_pos((float)x, (float)y);
if (mouse_button_down[1]) {
float speed = 0.1f;
auto dpos = cur_mouse_pos - mouse_pos;
trans =
trans * glm::eulerAngleXY(glm::radians(dpos.y * speed), glm::radians(dpos.x * speed));
}
if (mouse_button_down[0]) {
setFoveaPos(cur_mouse_pos);
}
mouse_pos = cur_mouse_pos;
}
GLFWwindow* initGl(glm::uvec2 windowRes) {
glfwSetErrorCallback(error_callback);
if (!glfwInit())
return nullptr;
/*
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_DEPTH_BITS, 0);
glfwWindowHint(GLFW_STENCIL_BITS, 0);
glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);
*/
GLFWwindow* window = glfwCreateWindow(windowRes.x, windowRes.y,
"Foveated Neueral Rendering", NULL, NULL);
if (!window) {
glfwTerminate();
return nullptr;
}
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glewInit();
glViewport(0, 0, windowRes.x, windowRes.y);
glClearColor(0.0f, 0.0f, 0.3f, 1.0f);
Logger::instance.info("OpenGL is initialized");
return window;
}
int main(void) {
Logger::instance.logLevel = 3;
glm::uvec2 windowRes = frameRes * windowScale;
if (stereo)
windowRes.x *= 2;
GLFWwindow* window = initGl(windowRes);
sptr<Camera> _cam;
std::vector<sptr<Camera>> _layerCams;
_layerCams.resize(3);
_layerCams[0].reset(new Camera(glm::uvec2(256, 256), 20)); // 406 -> 406
_layerCams[0]->loadMaskData("../nets/fovea.mask");
_layerCams[1].reset(new Camera(glm::uvec2(256, 256), 45)); // 784 -> 392
_layerCams[1]->loadMaskData("../nets/mid.mask");
_layerCams[2].reset(new Camera(glm::uvec2(230, 256), 110)); // 1600 -> 400
_cam.reset(new Camera(frameRes, 110));
sptr<CrossRenderer> crossRenderer(new CrossRenderer(frameRes, 10, { 0, 1, 0, 1 }));
sptr<FoveatedBlend> foveatedBlend(new FoveatedBlend(_cam, _layerCams, prebake));
if (prebake) {
sptr<BakedData> bakedData(new BakedData("../bakes/barbershop_0/"));
Logger::instance.info("Start main loop");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
switch (stereo)
{
case STEREO_OPTI:
{
GLuint glTexsL[] = {
bakedData->getStereoTexture(0, 0),
bakedData->getMonoTexture(1),
bakedData->getMonoTexture(2)
};
GLuint glTexsR[] = {
bakedData->getStereoTexture(1, 0),
bakedData->getMonoTexture(1),
bakedData->getMonoTexture(2)
};
float shift = (fovea_pos.x - fovea_pos_r.x) / 2.0f;
glViewport(0, 0, windowRes.x / 2, windowRes.y);
foveatedBlend->run(glTexsL, fovea_pos, -shift, 0.0f);
crossRenderer->render(fovea_pos, 0.0f);
glViewport(windowRes.x / 2, 0, windowRes.x / 2, windowRes.y);
foveatedBlend->run(glTexsR, fovea_pos_r, shift, 0.0f);
crossRenderer->render(fovea_pos_r, 0.0f);
}
break;
case STEREO_NORMAL:
{
GLuint glTexsL[] = {
bakedData->getStereoTexture(0, 0),
bakedData->getStereoTexture(0, 1),
bakedData->getStereoTexture(0, 2)
};
GLuint glTexsR[] = {
bakedData->getStereoTexture(1, 0),
bakedData->getStereoTexture(1, 1),
bakedData->getStereoTexture(1, 2)
};
glViewport(0, 0, windowRes.x / 2, windowRes.y);
foveatedBlend->run(glTexsL, fovea_pos, 0.0f, 0.0f);
crossRenderer->render(fovea_pos, 0.0f);
glViewport(windowRes.x / 2, 0, windowRes.x / 2, windowRes.y);
foveatedBlend->run(glTexsR, fovea_pos_r, 0.0f, 0.0f);
crossRenderer->render(fovea_pos_r, 0.0f);
}
break;
default:
{
GLuint glTexs[] = {
bakedData->getMonoTexture(0),
bakedData->getMonoTexture(1),
bakedData->getMonoTexture(2)
};
foveatedBlend->run(glTexs, fovea_pos, 0.0f, 0.0f);
crossRenderer->render(fovea_pos, 0.0f);
}
break;
}
glfwSwapBuffers(window);
glfwPollEvents();
}
}
else {
uint nSamples[] = { 64, 32 };
//sptr<FoveatedSynthesis> syn(new FoveatedSynthesis("../nets/stones", { 1.0f, 50.0f }, nSamples, 6, 2, _cam, _layerCams, stereo));
sptr<FoveatedSynthesis> syn(new FoveatedSynthesis("../nets/barbershop", { 1.2f, 6.0f }, nSamples, 6, 2, _cam, _layerCams, stereo));
//sptr<FoveatedSynthesis> syn(new FoveatedSynthesis("../nets/lobby", { 2.0f, 50.0f }, nSamples, 6, 2, _cam, _layerCams, stereo));
//sptr<FoveatedSynthesis> syn(new FoveatedSynthesis("../nets/classroom", { 1.0f, 7.0f }, nSamples, 6, 2, _cam, _layerCams, stereo));
Logger::instance.info("Start main loop");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
auto view = View(glm::vec3(trans[3]), glm::mat3(trans));
if (stereo == STEREO_NORMAL) {
{
auto view_l = view.getStereoEye(0.06, Eye_Left);
syn->run(view, fovea_pos, showPerf);
GLuint glTexs[] = {
syn->getGlResultTexture(0),
syn->getGlResultTexture(1),
syn->getGlResultTexture(2)
};
glViewport(0, 0, windowRes.x / 2, windowRes.y);
foveatedBlend->run(glTexs, fovea_pos, 0.0f, showPerf);
crossRenderer->render(fovea_pos, 0.0f);
}
{
auto view_r = view.getStereoEye(0.06, Eye_Right);
syn->run(view, fovea_pos_r, showPerf);
GLuint glTexs[] = {
syn->getGlResultTexture(0),
syn->getGlResultTexture(1),
syn->getGlResultTexture(2)
};
glViewport(windowRes.x / 2, 0, windowRes.x / 2, windowRes.y);
foveatedBlend->run(glTexs, fovea_pos_r, 0.0f, 0.0f, showPerf);
crossRenderer->render(fovea_pos, 0.0f);
}
} else {
syn->run(view, fovea_pos, showPerf, fovea_pos_r);
if (stereo == STEREO_DISABLED) {
GLuint glTexs[] = {
syn->getGlResultTexture(0),
syn->getGlResultTexture(1),
syn->getGlResultTexture(2)
};
foveatedBlend->run(glTexs, fovea_pos, 0.0f, 0.0f, showPerf);
crossRenderer->render(fovea_pos, 0.0f);
} else {
GLuint glTexsL[] = {
syn->getGlResultTexture(0),
syn->getGlResultTexture(1),
syn->getGlResultTexture(2)
};
GLuint glTexsR[] = {
syn->getGlResultTexture(3),
syn->getGlResultTexture(1),
syn->getGlResultTexture(2)
};
float shift = (fovea_pos.x - fovea_pos_r.x) / 2.0f;
glViewport(0, 0, windowRes.x / 2, windowRes.y);
foveatedBlend->run(glTexsL, fovea_pos, -shift, 0.0f, showPerf);
crossRenderer->render(fovea_pos, 0.0f);
glViewport(windowRes.x / 2, 0, windowRes.x / 2, windowRes.y);
foveatedBlend->run(glTexsR, fovea_pos_r, shift, 0.0f, showPerf);
crossRenderer->render(fovea_pos_r, 0.0f);
}
}
glfwSwapBuffers(window);
glfwPollEvents();
}
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
.SUFFIXES:
CUDA_TRIPLE ?= x86_64-linux
CUBLAS_TRIPLE ?= x86_64-linux-gnu
DLSW_TRIPLE ?= x86_64-linux-gnu
SAFE_PDK ?= 0
TARGET ?= $(shell uname -m)
ifeq ($(CUDA_INSTALL_DIR),)
CUDA_INSTALL_DIR ?= /usr/local/cuda
$(warning CUDA_INSTALL_DIR variable is not specified, using $(CUDA_INSTALL_DIR) by default, use CUDA_INSTALL_DIR=<cuda_directory> to change.)
endif
ifeq ($(CUDNN_INSTALL_DIR),)
CUDNN_INSTALL_DIR ?= $(CUDA_INSTALL_DIR)
$(warning CUDNN_INSTALL_DIR variable is not specified, using $(CUDA_INSTALL_DIR) by default, use CUDNN_INSTALL_DIR=<cudnn_directory> to change.)
endif
ifeq ($(ENABLE_DLA), 1)
ifeq ($(PDK_DIR),)
$(error DLA is enabled and PDK_DIR is not specified but it is required by some samples, use PDK_DIR=<pdk_directory> to specify.)
endif
PDK_LIB_DIR := $(PDK_DIR)/lib-target
PDK_INC_DIR := $(PDK_DIR)/include
endif
ifeq ($(TRT_LIB_DIR),)
TRT_LIB_DIR ?= ../../lib
$(warning TRT_LIB_DIR is not specified, searching $(TRT_LIB_DIR), ../../lib, ../lib by default, use TRT_LIB_DIR=<trt_lib_directory> to change.)
endif
CUDA_LIBDIR = lib
CUDNN_LIBDIR = lib64
ifeq ($(TARGET), aarch64)
ifeq ($(shell uname -m), aarch64)
CUDA_LIBDIR = lib64
CC = g++
else
CC = aarch64-linux-gnu-g++
endif
CUCC = $(CUDA_INSTALL_DIR)/bin/nvcc -m64 -ccbin $(CC)
else ifeq ($(TARGET), x86_64)
CUDA_LIBDIR = lib64
CC = g++
CUCC = $(CUDA_INSTALL_DIR)/bin/nvcc -m64
else ifeq ($(TARGET), ppc64le)
CUDA_LIBDIR = lib64
CC = g++
CUCC = $(CUDA_INSTALL_DIR)/bin/nvcc -m64
else ifeq ($(TARGET), qnx)
CC = ${QNX_HOST}/usr/bin/aarch64-unknown-nto-qnx7.0.0-g++
CUCC = $(CUDA_INSTALL_DIR)/bin/nvcc -m64 -ccbin $(CC)
else ifeq ($(TARGET), android64)
ifeq ($(ANDROID_CC),)
$(error ANDROID_CC must be set to the clang compiler to build for android 64bit, for example /path/to/utils-toolchain/bin/aarch64-linux-android-clang++)
endif
CUDA_LIBDIR = lib
ANDROID_FLAGS = -DANDROID -D_GLIBCXX_USE_C99=1 -Wno-sign-compare -D__aarch64__ -Wno-strict-aliasing -Werror -pie -fPIE -Wno-unused-command-line-argument
COMMON_FLAGS += $(ANDROID_FLAGS)
COMMON_LD_FLAGS += $(ANDROID_FLAGS)
CC = $(ANDROID_CC)
CUCC = $(CUDA_INSTALL_DIR)/bin/nvcc -m64 -ccbin $(CC) --compiler-options="-DANDROID -D_GLIBCXX_USE_C99=1 -Wno-sign-compare"
ANDROID = 1
else ########
$(error Auto-detection of platform failed. Please specify one of the following arguments to make: TARGET=[aarch64|x86_64|qnx|android64])
endif
ifdef VERBOSE
AT=
else
AT=@
endif
AR = ar cr
ECHO = @echo
SHELL = /bin/sh
ROOT_PATH = ..
ifeq ($(SAFE_PDK), 1)
OUT_PATH = $(ROOT_PATH)/bin/safety
else
OUT_PATH = $(ROOT_PATH)/bin
endif
OUTDIR = $(OUT_PATH)
define concat
$1$2$3$4$5$6$7$8
endef
ifneq ($(USE_QCC),1)
# Usage: $(call make-depend,source-file,object-file,depend-file)
define make-depend
$(AT)$(CC) -MM -MF $3 -MP -MT $2 $(COMMON_FLAGS) $1
endef
# Usage: $(call make-cuda-depend,source-file,object-file,depend-file,flags)
define make-cuda-depend
$(AT)$(CUCC) -M -MT $2 $4 $1 > $3
endef
endif
# When TRT_STATIC is set, pick the static libraries for all components. Samples are compiled with static libraries
ifeq ($(TRT_STATIC), 1)
CUDART_LIB = -lcudart_static
CUDNN_LIB = -lcudnn_static
CUBLAS_LIB = -lcublas_static
MYELIN_LIB = -lmyelin_compiler_static -lmyelin_executor_static -lmyelin_pattern_library_static -lmyelin_pattern_runtime_static
NVINFER_LIB = -Wl,-whole-archive -lnvinfer_static -Wl,-no-whole-archive
NVPARSERS_LIB = -lnvparsers_static
NVINFER_PLUGIN_LIB = -lnvinfer_plugin_static
NVONNXPARSERS_LIB = -lnvonnxparser_static
NVRTC_LIB = -lnvrtc_static
PROTO_LIB = -lprotobuf -lonnx_proto
STUBS_DIR = -L"$(TRT_LIB_DIR)/stubs" -Wl,-rpath-link="$(TRT_LIB_DIR)/stubs"
else
CUDART_LIB = -lcudart
CUDNN_LIB = -lcudnn
CUBLAS_LIB = -lcublas
MYELIN_LIB = -lmyelin
NVINFER_LIB = -lnvinfer
NVPARSERS_LIB = -lnvparsers
NVINFER_PLUGIN_LIB = -lnvinfer_plugin
NVONNXPARSERS_LIB = -lnvonnxparser
NVRTC_LIB = -lnvrtc
PROTO_LIBDIR =
STUBS_DIR =
endif
#########################
INCPATHS=
LIBPATHS=
COMMON_LIBS= -lGLEW -lglfw -lGL -lX11 -lpthread -lXrandr #-lXinerama -lXcursor -lXi -ldl
# Add extra libraries if TRT_STATIC is enabled
ifeq ($(TRT_STATIC), 1)
COMMON_LIBS += -lculibos -lcublasLt_static
endif
# add cross compile directories
ifneq ($(shell uname -m), $(TARGET))
INCPATHS += -I"/usr/include/$(DLSW_TRIPLE)" -I"/usr/include/$(CUBLAS_TRIPLE)"
LIBPATHS += -L"../lib/stubs" -L"../../lib/stubs" -L"/usr/lib/$(DLSW_TRIPLE)/stubs" -L"/usr/lib/$(DLSW_TRIPLE)" -L"/usr/lib/$(CUBLAS_TRIPLE)/stubs" -L"/usr/lib/$(CUBLAS_TRIPLE)"
LIBPATHS += -L"$(CUDA_INSTALL_DIR)/targets/$(CUDA_TRIPLE)/$(CUDA_LIBDIR)/stubs" -L"$(CUDA_INSTALL_DIR)/targets/$(CUDA_TRIPLE)/$(CUDA_LIBDIR)"
endif
INCPATHS += -I"../common" -I"$(CUDA_INSTALL_DIR)/include" -I"$(CUDNN_INSTALL_DIR)/include" -I"../include" -I"../../include" -I"../../parsers/onnxOpenSource"
LIBPATHS += -L"$(CUDA_INSTALL_DIR)/$(CUDA_LIBDIR)" -Wl,-rpath-link="$(CUDA_INSTALL_DIR)/$(CUDA_LIBDIR)"
LIBPATHS += -L"$(CUDNN_INSTALL_DIR)/$(CUDNN_LIBDIR)" -Wl,-rpath-link="$(CUDNN_INSTALL_DIR)/$(CUDNN_LIBDIR)"
LIBPATHS += -L"../lib" -L"../../lib" -L"$(TRT_LIB_DIR)" -Wl,-rpath-link="$(TRT_LIB_DIR)" $(STUBS_DIR)
# libnvinfer_safe.so links to neither standard nor safe PDK, while libnvinfer.so depends on standard PDK when DLA is enabled.
ifeq ($(SAFE_PDK), 0)
ifneq ($(ENABLE_DLA), 0)
LIBPATHS += -L"$(PDK_LIB_DIR)" -Wl,-rpath-link="$(PDK_LIB_DIR)"
endif
endif
# delimiter ; is to avoid the issue caused by the case that one keyword is the substr of another keyword
USE_PDK_LISTS := dla_safety_runtime; sample_nvmedia;
# add required PDK headers/libraries
ifeq ($(ENABLE_DLA), 1)
ifeq ($(TARGET), qnx)
LIBPATHS += -L"$(QNX_TARGET)/aarch64le/lib"
LIBPATHS += -L"$(QNX_TARGET)/aarch64le/lib/gcc/5.4.0"
LIBPATHS += -L"$(QNX_TARGET)/aarch64le/usr/lib"
INCPATHS += -I"$(QNX_TARGET)/usr/include"
endif
PDK_LISTS_FILTER := $(OUTNAME_RELEASE);
ifneq ($(findstring $(PDK_LISTS_FILTER),$(USE_PDK_LISTS)),)
HAS_NVSCIBUF_LIB=$(shell ls ${PDK_LIB_DIR}/libnvscibuf.so 2> /dev/null | wc -l)
ifeq ($(HAS_NVSCIBUF_LIB), 1)
LIBLIST += -lnvscibuf
endif
HAS_NVMEDIA_LIB=$(shell ls ${PDK_LIB_DIR}/libnvmedia.so 2> /dev/null | wc -l)
ifeq ($(HAS_NVMEDIA_LIB), 1)
LIBLIST += -lnvmedia
endif
HAS_NVMEDIA_CORE_LIB=$(shell ls ${PDK_LIB_DIR}/libnvmedia_core.so 2> /dev/null | wc -l)
ifeq ($(HAS_NVMEDIA_CORE_LIB), 1)
LIBLIST += -lnvmedia_core
endif
HAS_NVMEDIA_TENSOR_LIB=$(shell ls ${PDK_LIB_DIR}/libnvmedia_tensor.so 2> /dev/null | wc -l)
ifeq ($(HAS_NVMEDIA_TENSOR_LIB), 1)
LIBLIST += -lnvmedia_tensor
endif
HAS_NVMEDIA_DLA_LIB=$(shell ls ${PDK_LIB_DIR}/libnvmedia_dla.so 2> /dev/null | wc -l)
ifeq ($(HAS_NVMEDIA_DLA_LIB), 1)
LIBLIST += -lnvmedia_dla
endif
COMMON_LIBS += ${LIBLIST}
LIBPATHS += -L"$(PDK_LIB_DIR)" -Wl,-rpath-link=$(PDK_LIB_DIR) -Wl,--unresolved-symbols=ignore-in-shared-libs
INCPATHS += -I"$(PDK_INC_DIR)"
endif
endif
# Add myelin libraries if applicable
ENABLE_MYELIN := 0
ifeq ($(TARGET), x86_64)
ENABLE_MYELIN = 1
else ifeq ($(TARGET), ppc64le)
ifeq ($(CUDA), $(filter $(CUDA), cuda-10.2))
ENABLE_MYELIN = 1
endif
else ifeq ($(TARGET), aarch64)
ifeq ($(CUDA), $(filter $(CUDA), cuda-10.2))
ENABLE_MYELIN = 1
endif
endif
ifeq ($(ENABLE_MYELIN), 1)
#COMMON_LIBS += $(MYELIN_LIB) $(NVRTC_LIB)
endif
.SUFFIXES:
vpath %.h $(EXTRA_DIRECTORIES)
vpath %.cpp $(EXTRA_DIRECTORIES)
COMMON_FLAGS += -Wall -Wno-deprecated-declarations -std=c++11 $(INCPATHS)
ifneq ($(ANDROID),1)
COMMON_FLAGS += -D_REENTRANT
endif
ifeq ($(TARGET), qnx)
COMMON_FLAGS += -D_POSIX_C_SOURCE=200112L -D_QNX_SOURCE -D_FILE_OFFSET_BITS=64 -fpermissive
endif
COMMON_LD_FLAGS += $(LIBPATHS) -L$(OUTDIR)
OBJDIR = $(call concat,$(OUTDIR),/chobj)
DOBJDIR = $(call concat,$(OUTDIR),/dchobj)
COMMON_LIBS += $(CUDART_LIB)
ifneq ($(SAFE_PDK),1)
COMMON_LIBS += $(CUBLAS_LIB) $(CUDNN_LIB)
endif
ifneq ($(TARGET), qnx)
ifneq ($(ANDROID), 1)
COMMON_LIBS += -lrt -ldl -lpthread
endif
endif
ifeq ($(ANDROID),1)
COMMON_LIBS += -lculibos -llog
endif
COMMON_LIBS_FOR_EXECUTABLE := $(filter-out -lcudart_static ,$(COMMON_LIBS))
ifeq ($(USE_CUDART_STATIC), 1)
COMMON_LIBS_FOR_EXECUTABLE += $(CUDART_LIB)
endif
ifeq ($(SAFE_PDK),1)
LIBS = $(COMMON_LIBS_FOR_EXECUTABLE) $(PROTO_LIB)
DLIBS = $(COMMON_LIBS_FOR_EXECUTABLE) $(PROTO_LIB)
else
LIBS = $(NVINFER_LIB) $(NVPARSERS_LIB) $(NVINFER_PLUGIN_LIB) $(NVONNXPARSERS_LIB) $(COMMON_LIBS_FOR_EXECUTABLE) $(PROTO_LIB)
DLIBS = $(NVINFER_LIB) $(NVPARSERS_LIB) $(NVINFER_PLUGIN_LIB) $(NVONNXPARSERS_LIB) $(COMMON_LIBS_FOR_EXECUTABLE) $(PROTO_LIB)
endif
OBJS = $(patsubst %.cpp, $(OBJDIR)/%.o, $(wildcard *.cpp $(addsuffix /*.cpp, $(EXTRA_DIRECTORIES))))
DOBJS = $(patsubst %.cpp, $(DOBJDIR)/%.o, $(wildcard *.cpp $(addsuffix /*.cpp, $(EXTRA_DIRECTORIES))))
CUOBJS = $(patsubst %.cu, $(OBJDIR)/%.o, $(wildcard *.cu $(addsuffix /*.cu, $(EXTRA_DIRECTORIES))))
CUDOBJS = $(patsubst %.cu, $(DOBJDIR)/%.o, $(wildcard *.cu $(addsuffix /*.cu, $(EXTRA_DIRECTORIES))))
CFLAGS = $(COMMON_FLAGS)
CFLAGSD = $(COMMON_FLAGS) -g
LFLAGS = $(COMMON_LD_FLAGS)
LFLAGSD = $(COMMON_LD_FLAGS)
all: debug release
release : $(OUTDIR)/$(OUTNAME_RELEASE)
debug : $(OUTDIR)/$(OUTNAME_DEBUG)
test: test_debug test_release
test_debug:
$(AT)cd $(OUTDIR) && ./$(OUTNAME_DEBUG)
test_release:
$(AT)cd $(OUTDIR) && ./$(OUTNAME_RELEASE)
ifdef MAC
$(OUTDIR)/$(OUTNAME_RELEASE) : $(OBJS) $(CUOBJS)
$(ECHO) Linking: $@
$(AT)$(CC) -o $@ $^ $(LFLAGS) $(LIBS)
# Copy every EXTRA_FILE of this sample to bin dir
$(foreach EXTRA_FILE,$(EXTRA_FILES), cp -f $(EXTRA_FILE) $(OUTDIR)/$(EXTRA_FILE); )
$(OUTDIR)/$(OUTNAME_DEBUG) : $(DOBJS) $(CUDOBJS)
$(ECHO) Linking: $@
$(AT)$(CC) -o $@ $^ $(LFLAGSD) $(DLIBS)
else
$(OUTDIR)/$(OUTNAME_RELEASE) : $(OBJS) $(CUOBJS)
$(ECHO) Linking: $@
$(AT)$(CC) -o $@ $^ $(LFLAGS) -Wl,--start-group $(LIBS) -Wl,--end-group
# Copy every EXTRA_FILE of this sample to bin dir
$(foreach EXTRA_FILE,$(EXTRA_FILES), cp -f $(EXTRA_FILE) $(OUTDIR)/$(EXTRA_FILE); )
$(OUTDIR)/$(OUTNAME_DEBUG) : $(DOBJS) $(CUDOBJS)
$(ECHO) Linking: $@
$(AT)$(CC) -o $@ $^ $(LFLAGSD) -Wl,--start-group $(DLIBS) -Wl,--end-group
endif
$(OBJDIR)/%.o: %.cpp
$(AT)if [ ! -d $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi
$(foreach XDIR,$(EXTRA_DIRECTORIES), if [ ! -d $(OBJDIR)/$(XDIR) ]; then mkdir -p $(OBJDIR)/$(XDIR); fi;) :
$(call make-depend,$<,$@,$(subst .o,.d,$@))
$(ECHO) Compiling: $<
$(AT)$(CC) $(CFLAGS) -c -o $@ $<
$(DOBJDIR)/%.o: %.cpp
$(AT)if [ ! -d $(DOBJDIR) ]; then mkdir -p $(DOBJDIR); fi
$(foreach XDIR,$(EXTRA_DIRECTORIES), if [ ! -d $(OBJDIR)/$(XDIR) ]; then mkdir -p $(DOBJDIR)/$(XDIR); fi;) :
$(call make-depend,$<,$@,$(subst .o,.d,$@))
$(ECHO) Compiling: $<
$(AT)$(CC) $(CFLAGSD) -c -o $@ $<
######################################################################### CU
$(OBJDIR)/%.o: %.cu
$(AT)if [ ! -d $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi
$(foreach XDIR,$(EXTRA_DIRECTORIES), if [ ! -d $(OBJDIR)/$(XDIR) ]; then mkdir -p $(OBJDIR)/$(XDIR); fi;) :
$(call make-cuda-depend,$<,$@,$(subst .o,.d,$@))
$(ECHO) Compiling CUDA release: $<
$(AT)$(CUCC) $(CUFLAGS) -c -o $@ $<
$(DOBJDIR)/%.o: %.cu
$(AT)if [ ! -d $(DOBJDIR) ]; then mkdir -p $(DOBJDIR); fi
$(foreach XDIR,$(EXTRA_DIRECTORIES), if [ ! -d $(DOBJDIR)/$(XDIR) ]; then mkdir -p $(DOBJDIR)/$(XDIR); fi;) :
$(call make-cuda-depend,$<,$@,$(subst .o,.d,$@))
$(ECHO) Compiling CUDA debug: $<
$(AT)$(CUCC) $(CUFLAGSD) -c -o $@ $<
clean:
$(ECHO) Cleaning...
$(foreach XDIR,$(EXTRA_DIRECTORIES), if [ -d $(OBJDIR)/$(XDIR) ]; then rm -rf $(OBJDIR)/$(XDIR); fi;) :
$(foreach XDIR,$(EXTRA_DIRECTORIES), if [ -d $(DOBJDIR)/$(XDIR) ]; then rm -rf $(DOBJDIR)/$(XDIR); fi;) :
$(AT)rm -rf $(OBJDIR) $(DOBJDIR) $(OUTDIR)/$(OUTNAME_RELEASE) $(OUTDIR)/$(OUTNAME_DEBUG)
$(foreach EXTRA_FILE,$(EXTRA_FILES), if [ -f $(OUTDIR)/$(EXTRA_FILE) ]; then rm -f $(OUTDIR)/$(EXTRA_FILE); fi;) :
ifneq "$(MAKECMDGOALS)" "clean"
-include $(OBJDIR)/*.d $(DOBJDIR)/*.d
endif # ifneq "$(MAKECMDGOALS)" "clean"
#include "Enhancement.h"
#include "../utils/cuda.h"
#define max(__a__, __b__) (__a__ > __b__ ? __a__ : __b__)
#define min(__a__, __b__) (__a__ < __b__ ? __a__ : __b__)
__global__ void cu_boxFilter(glm::vec4 *o_filtered, glm::vec4 *imageData, glm::uvec2 res) {
glm::uvec2 idx2 = IDX2;
if (idx2.x >= res.x || idx2.y >= res.y)
return;
uint idx = idx2.x + idx2.y * res.x;
glm::vec4 c (0.0f, 0.0f, 0.0f, 0.0f);
float n = 0.0f;
for (int dy = -1; dy <= 1; ++dy) {
for (int dx = -1; dx <= 1; ++dx) {
glm::ivec2 idx2_ = (glm::ivec2)idx2 + glm::ivec2(dx, dy);
if (idx2_.x < 0 || idx2_.x >= res.x || idx2_.y < 0 || idx2_.y >= res.y)
continue;
int idx_ = idx2_.x + idx2_.y * res.x;
c += imageData[idx_];
n += 1.0f;
}
}
if (n < 0.5f)
o_filtered[idx] = glm::vec4();
else
o_filtered[idx] = c / n;
}
__global__ void cu_constrastEnhance(glm::vec4 *io_imageData, glm::vec4 *filtered, float cScale,
glm::uvec2 res) {
glm::uvec2 idx2 = IDX2;
if (idx2.x >= res.x || idx2.y >= res.y)
return;
uint idx = idx2.x + idx2.y * res.x;
glm::vec4 c = filtered[idx] + (io_imageData[idx] - filtered[idx]) * cScale;
io_imageData[idx].r = min(max(c.r, 0.0f), 1.0f);
io_imageData[idx].g = min(max(c.g, 0.0f), 1.0f);
io_imageData[idx].b = min(max(c.b, 0.0f), 1.0f);
}
Enhancement::Enhancement(glm::uvec2 res, glm::vec2 params)
: _res(res), _boxFiltered(new CudaArray<glm::vec4>(res.x * res.y)), _params(params) {}
void Enhancement::run(sptr<CudaArray<glm::vec4>> imageData) {
dim3 blkSize(32, 32);
dim3 grdSize(ceilDiv(_res.x, blkSize.x), ceilDiv(_res.y, blkSize.y));
CU_INVOKE(cu_boxFilter)(*_boxFiltered, *imageData, _res);
CU_INVOKE(cu_constrastEnhance)(*imageData, *_boxFiltered, 1.0f + _params[0] * _params[1], _res);
}
\ No newline at end of file
#include "ImageGen.h"
ImageGen::ImageGen(glm::uvec2 res) : _res(res) {
_glResultBuffer = _createGlResultBuffer(_res.x * _res.y);
_glResultTexture = _createGlResultTexture(_res);
}
void ImageGen::run(sptr<CudaArray<glm::vec4>> colors) {
// Copy result from Cuda array to OpenGL buffer
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _glResultBuffer);
void *bufferData = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
cudaMemcpy(bufferData, colors->getBuffer(), colors->size(), cudaMemcpyDeviceToHost);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
// Upload data from OpenGL buffer to texture
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _glResultBuffer);
glBindTexture(GL_TEXTURE_2D, _glResultTexture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _res.x, _res.y, GL_RGBA, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
GLuint ImageGen::_createGlResultTexture(glm::uvec2 res) {
GLuint textureID;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res.x, res.y, 0, GL_RGBA, GL_FLOAT, nullptr);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
return textureID;
}
GLuint ImageGen::_createGlResultBuffer(unsigned int elements) {
GLuint glBuffer;
glGenBuffers(1, &glBuffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBuffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, elements * sizeof(glm::vec4), nullptr, GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
return glBuffer;
}
\ No newline at end of file
#pragma once
#include "../utils/common.h"
#include "InferPipeline.h"
#include "View.h"
#include "Enhancement.h"
class ImageGen {
public:
ImageGen(glm::uvec2 res);
void run(sptr<CudaArray<glm::vec4>> colors);
GLuint getGlResultTexture() { return _glResultTexture; }
protected:
glm::uvec2 _res;
GLuint _glResultTexture;
GLuint _glResultBuffer;
GLuint _createGlResultTexture(glm::uvec2 res);
GLuint _createGlResultBuffer(unsigned int elements);
};
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment