From 31e518ebfde0f02c9bb72cdc10d8e768b3a07e3e Mon Sep 17 00:00:00 2001 From: tosh Date: Wed, 15 May 2013 14:21:32 +0200 Subject: [PATCH 1/4] moves dependency to new gl-program class to starfield/Config.h (where all the other dependencies to components outside the 'starfield' folder live) and removes dependency to obsolete OGlProgram.h --- interface/src/starfield/Config.h | 2 +- interface/src/starfield/renderer/Renderer.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/starfield/Config.h b/interface/src/starfield/Config.h index 92d4a05723..c11fe68e38 100644 --- a/interface/src/starfield/Config.h +++ b/interface/src/starfield/Config.h @@ -38,7 +38,7 @@ // #include "InterfaceConfig.h" -#include "OGlProgram.h" +#include "renderer/ProgramObject.h" #include "Log.h" #include diff --git a/interface/src/starfield/renderer/Renderer.h b/interface/src/starfield/renderer/Renderer.h index 8a7e4bd6de..b30a174d4f 100644 --- a/interface/src/starfield/renderer/Renderer.h +++ b/interface/src/starfield/renderer/Renderer.h @@ -13,8 +13,6 @@ #error "This is an implementation file - not intended for direct inclusion." #endif -#include "renderer/ProgramObject.h" - #include "starfield/Config.h" #include "starfield/data/InputVertex.h" #include "starfield/data/BrightnessLevel.h" From 9765ce7b9c57ba32cb052770fa8b9a4edd8a8ed5 Mon Sep 17 00:00:00 2001 From: tosh Date: Wed, 15 May 2013 14:25:40 +0200 Subject: [PATCH 2/4] removes obsolete OGlProgram.h, moves utility macro for logging gl errors to Log.h --- interface/src/Log.h | 19 ++++- interface/src/OGlProgram.h | 146 ------------------------------------- 2 files changed, 18 insertions(+), 147 deletions(-) delete mode 100644 interface/src/OGlProgram.h diff --git a/interface/src/Log.h b/interface/src/Log.h index 30f9098bc9..beaca0abf0 100644 --- a/interface/src/Log.h +++ b/interface/src/Log.h @@ -21,12 +21,29 @@ class Log; // int printLog(char const* fmt, ...); +// +// Macro to log OpenGl errors. +// Example: oglLog( glPushMatrix() ); +// +#define oGlLog(stmt) \ + stmt; \ + { \ + GLenum e = glGetError(); \ + if (e != GL_NO_ERROR) { \ + printLog(__FILE__ ":" oGlLog_stringize(__LINE__) \ + " [OpenGL] %s\n", gluErrorString(e)); \ + } \ + } \ + (void) 0 + +#define oGlLog_stringize(x) oGlLog_stringize_i(x) +#define oGlLog_stringize_i(x) # x + // // Global instance. // extern Log logger; - // // Logging subsystem. // diff --git a/interface/src/OGlProgram.h b/interface/src/OGlProgram.h deleted file mode 100644 index ac1ea019bd..0000000000 --- a/interface/src/OGlProgram.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef __interface__OpenGlSupport__ -#define __interface__OpenGlSupport__ - -#include "InterfaceConfig.h" -#include "Log.h" - -// -// Macro to log OpenGl errors. -// Example: oglLog( glPushMatrix() ); -// -#define oGlLog(stmt) \ - stmt; \ - { \ - GLenum e = glGetError(); \ - if (e != GL_NO_ERROR) { \ - printLog(__FILE__ ":" oGlLog_stringize(__LINE__) \ - " [OpenGL] %s\n", gluErrorString(e)); \ - } \ - } \ - (void) 0 - -#define oGlLog_stringize(x) oGlLog_stringize_i(x) -#define oGlLog_stringize_i(x) # x - -// -// Encapsulation of the otherwise lengthy call sequence to compile -// and link shading pipelines. -// -class OGlProgram { - - GLuint _hndProg; - -public: - - OGlProgram() : _hndProg(0) { } - - ~OGlProgram() { if (_hndProg != 0u) { glDeleteProgram(_hndProg); } } - - // no copy/assign - OGlProgram(OGlProgram const&); // = delete; - OGlProgram& operator=(OGlProgram const&); // = delete; - -#if 0 // let's keep this commented, for now (C++11) - - OGlProgram(OGlProgram&& disposable) : _hndProg(disposable._hndProg) { - - disposable._hndProg = 0; - } - - OGlProgram& operator=(OGlProgram&& disposable) { - - GLuint tmp = _hndProg; - _hndProg = disposable._hndProg; - disposable._hndProg = tmp; - } -#endif - - // - // Activates the executable for rendering. - // Shaders must be added and linked before this will work. - // - void activate() const { - - if (_hndProg != 0u) { - - oGlLog( glUseProgram(_hndProg) ); - } - } - - // - // Adds a shader to the program. - // - bool addShader(GLenum type, GLchar const* cString) { - - return addShader(type, 1, & cString); - } - - // - // Adds a shader to the program and logs to stderr. - // - bool addShader(GLenum type, GLsizei nStrings, GLchar const** strings) { - - if (! _hndProg && !! glCreateProgram) { - - _hndProg = glCreateProgram(); - } - if (! _hndProg) { return false; } - - GLuint s = glCreateShader(type); - glShaderSource(s, nStrings, strings, 0l); - glCompileShader(s); - GLint status; - glGetShaderiv(s, GL_COMPILE_STATUS, & status); - if (status != 0) - glAttachShader(_hndProg, s); -#ifdef NDEBUG // always fetch log in debug mode - else -#endif - fetchLog(s, glGetShaderiv, glGetShaderInfoLog); - glDeleteShader(s); - return !! status; - } - - // - // Links the program and logs to stderr. - // - bool link() { - - if (! _hndProg) { return false; } - - glLinkProgram(_hndProg); - GLint status; - glGetProgramiv(_hndProg, GL_LINK_STATUS, & status); -#ifndef NDEBUG // always fetch log in debug mode - fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog); -#endif - if (status == 0) { -#ifdef NDEBUG // only on error in release mode - fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog); -#endif - glDeleteProgram(_hndProg); - _hndProg = 0u; - return false; - - } else { - - return true; - } - } - -private: - - template< typename ParamFunc, typename GetLogFunc > - void fetchLog(GLint handle, ParamFunc getParam, GetLogFunc getLog) { - GLint logLength = 0; - getParam(handle, GL_INFO_LOG_LENGTH, &logLength); - if (!! logLength) { - GLchar* message = new GLchar[logLength]; - getLog(handle, logLength, 0l, message); - printLog("%s\n", message); - delete[] message; - } - } -}; - -#endif From 6a47db91dad8caa1a4c4a12118fa4be95f830148 Mon Sep 17 00:00:00 2001 From: tosh Date: Wed, 15 May 2013 15:29:02 +0200 Subject: [PATCH 3/4] tidies up UrlReader component --- libraries/shared/src/UrlReader.cpp | 154 +++++++++++++++++++---------- libraries/shared/src/UrlReader.h | 49 +++++---- 2 files changed, 129 insertions(+), 74 deletions(-) diff --git a/libraries/shared/src/UrlReader.cpp b/libraries/shared/src/UrlReader.cpp index 8814de899a..e069c0cb73 100644 --- a/libraries/shared/src/UrlReader.cpp +++ b/libraries/shared/src/UrlReader.cpp @@ -10,62 +10,83 @@ #include -#ifdef _WIN32 -#define NOCURL_IN_WINDOWS -#endif - #include #include -#ifndef NOCURL_IN_WINDOWS -#include -size_t const UrlReader::max_read_ahead = CURL_MAX_WRITE_SIZE; -#else -size_t const UrlReader::max_read_ahead = 0; -#endif +#include "shared_Log.h" +using shared_lib::printLog; -char const* const UrlReader::success = "UrlReader: Success!"; -char const* const UrlReader::success_cached = "UrlReader:: Using local file."; +#ifndef _WIN32 +// (Windows port is incomplete and the build files do not support CURL, yet) + +#include + + +// +// ATTENTION: A certain part of the implementation lives in inlined code +// (see the bottom of the header file). +// +// Why? Because it allows stream parsing without having to call around a +// lot (one static and one dynamic call per character if the parser just +// reads one character at a time). +// +// Here is an overview of the code structure: +// +// readUrl +// -> transferBegin (sets up state) +// -> perform (starts CURL transfer) +// -> (specialized, type-erased) callback_template +// -> getInfo (fetches HTTP header, eventually initiates caching) +// -> stream.begin (client code - called once) +// -> feedBuffered (the buffering logic) +// -> stream.transfer (client code - called repeatedly) +// -> stream.end (client code - called when the transfer is done) +// -> transferEnd (closes cache file, if used) +// +// "->" means "calls or inlines", here +// + +size_t const UrlReader::max_read_ahead = CURL_MAX_WRITE_SIZE; + +char const* const UrlReader::success = "UrlReader: Success!"; +char const* const UrlReader::success_cached = "UrlReader: Using local file."; char const* const UrlReader::error_init_failed = "UrlReader: Initialization failed."; char const* const UrlReader::error_aborted = "UrlReader: Processing error."; char const* const UrlReader::error_buffer_overflow = "UrlReader: Buffer overflow."; char const* const UrlReader::error_leftover_input = "UrlReader: Incomplete processing."; -#define hnd_curl static_cast(_ptrImpl) +#define _ptrCurl static_cast(_hndCurl) UrlReader::UrlReader() - : _ptrImpl(0l), _arrXtra(0l), _strError(0l), _arrCacheRdBuf(0l) { + : _hndCurl(0l), _arrXtra(0l), _strError(0l), _arrCacheRdBuf(0l) { _arrXtra = new(std::nothrow) char[max_read_ahead]; if (! _arrXtra) { _strError = error_init_failed; return; } -#ifndef NOCURL_IN_WINDOWS - _ptrImpl = curl_easy_init(); - if (! _ptrImpl) { _strError = error_init_failed; return; } - curl_easy_setopt(hnd_curl, CURLOPT_NOSIGNAL, 1l); - curl_easy_setopt(hnd_curl, CURLOPT_FAILONERROR, 1l); - curl_easy_setopt(hnd_curl, CURLOPT_FILETIME, 1l); - curl_easy_setopt(hnd_curl, CURLOPT_ENCODING, ""); -#endif + _hndCurl = curl_easy_init(); + if (! _hndCurl) { _strError = error_init_failed; return; } + curl_easy_setopt(_ptrCurl, CURLOPT_NOSIGNAL, 1l); + curl_easy_setopt(_ptrCurl, CURLOPT_FAILONERROR, 1l); + curl_easy_setopt(_ptrCurl, CURLOPT_FILETIME, 1l); + curl_easy_setopt(_ptrCurl, CURLOPT_ENCODING, ""); } UrlReader::~UrlReader() { delete[] _arrXtra; delete[] _arrCacheRdBuf; -#ifndef NOCURL_IN_WINDOWS - if (! hnd_curl) return; - curl_easy_cleanup(hnd_curl); -#endif + if (! _hndCurl) { + return; + } + curl_easy_cleanup(_ptrCurl); } -bool UrlReader::perform(char const* url, transfer_callback* cb) { -#ifndef NOCURL_IN_WINDOWS +void UrlReader::perform(char const* url, transfer_callback* cb) { - curl_easy_setopt(hnd_curl, CURLOPT_URL, url); - curl_easy_setopt(hnd_curl, CURLOPT_WRITEFUNCTION, cb); - curl_easy_setopt(hnd_curl, CURLOPT_WRITEDATA, this); + curl_easy_setopt(_ptrCurl, CURLOPT_URL, url); + curl_easy_setopt(_ptrCurl, CURLOPT_WRITEFUNCTION, cb); + curl_easy_setopt(_ptrCurl, CURLOPT_WRITEDATA, this); - CURLcode rc = curl_easy_perform(hnd_curl); + CURLcode rc = curl_easy_perform(_ptrCurl); if (rc == CURLE_OK) { @@ -74,20 +95,33 @@ bool UrlReader::perform(char const* url, transfer_callback* cb) { } else if (_strError == success) _strError = curl_easy_strerror(rc); - - return rc == CURLE_OK; -#else - return false; -#endif } -void UrlReader::getinfo(char const*& url, - char const*& type, int64_t& length, int64_t& stardate) { -#ifndef NOCURL_IN_WINDOWS +void UrlReader::transferBegin(void* stream, char const* cacheFile) { + _strError = success; + _ptrStream = stream; + _strCacheFile = cacheFile; + _ptrCacheFile = 0l; + _valCacheMode = no_cache; + _valXtraSize = ~size_t(0); +} + +void UrlReader::getInfo(char const*& url, + char const*& type, int64_t& length, int64_t& stardate) { + + // fetch information from HTTP header double clen; long time; - curl_easy_getinfo(hnd_curl, CURLINFO_FILETIME, & time); + curl_easy_getinfo(_ptrCurl, CURLINFO_FILETIME, & time); + curl_easy_getinfo(_ptrCurl, CURLINFO_EFFECTIVE_URL, & url); + curl_easy_getinfo(_ptrCurl, CURLINFO_CONTENT_TYPE, & type); + curl_easy_getinfo(_ptrCurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, & clen); + length = static_cast(clen); + curl_easy_getinfo(_ptrCurl, CURLINFO_FILETIME, & time); + stardate = time; + + printLog("UrlReader: Ready to transfer from URL '%s'\n", url); // check caching file time whether we actually want to download anything if (_strCacheFile != 0l) { @@ -96,7 +130,7 @@ void UrlReader::getinfo(char const*& url, if (time > s.st_mtime) { // file on server is newer -> update cache file _ptrCacheFile = fopen(_strCacheFile, "wb"); - printf("From URL: "); + printLog("UrlReader: Also writing content to cache file '%s'\n", _strCacheFile); if (_ptrCacheFile != 0l) { _valCacheMode = cache_write; } @@ -105,26 +139,38 @@ void UrlReader::getinfo(char const*& url, if (! _arrCacheRdBuf) { _arrCacheRdBuf = new (std::nothrow) char[max_read_ahead]; if (! _arrCacheRdBuf) { - _valCacheMode = no_cache; + // out of memory, no caching, have CURL catch it + return; } } _ptrCacheFile = fopen(_strCacheFile, "rb"); - printf("From file: "); + printLog("UrlReader: Delivering cached content from file '%s'\n", _strCacheFile); if (_ptrCacheFile != 0l) { _valCacheMode = cache_read; } + // override error code returned by CURL when we abort the download _strError = success_cached; } } - - curl_easy_getinfo(hnd_curl, CURLINFO_EFFECTIVE_URL, & url); - curl_easy_getinfo(hnd_curl, CURLINFO_CONTENT_TYPE, & type); - - curl_easy_getinfo(hnd_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, & clen); - length = static_cast(clen); - - curl_easy_getinfo(hnd_curl, CURLINFO_FILETIME, & time); - stardate = time; -#endif } +void UrlReader::transferEnd() { + + if (_ptrCacheFile != 0l) { + fclose(_ptrCacheFile); + } +} + +#else // no-op version for incomplete Windows build: + +UrlReader::UrlReader() : _ptrImpl(0l) { } +UrlReader::~UrlReader() { } +void UrlReader::perform(char const* url, transfer_callback* cb) { } +void UrlReader::transferBegin(void* stream, char const* cacheFile) { } +void UrlReader::getInfo(char const*& url, char const*& type, + int64_t& length, int64_t& stardate) { } +void UrlReader::transferEnd() { } + +#endif + + diff --git a/libraries/shared/src/UrlReader.h b/libraries/shared/src/UrlReader.h index 9ad77d27ff..ebd11a21ab 100644 --- a/libraries/shared/src/UrlReader.h +++ b/libraries/shared/src/UrlReader.h @@ -22,7 +22,7 @@ class UrlReader { enum CacheMode { no_cache, cache_write, cache_read }; - void* _ptrImpl; + void* _hndCurl; char* _arrXtra; char const* _strError; void* _ptrStream; @@ -145,13 +145,18 @@ class UrlReader { UrlReader(UrlReader const&); // = delete; UrlReader& operator=(UrlReader const&); // = delete; + inline bool isSuccess(); + // entrypoints to compiled code typedef size_t transfer_callback(char*, size_t, size_t, void*); - bool perform(char const* url, transfer_callback* transfer); + void transferBegin(void* stream, char const* cacheFile); + void transferEnd(); - void getinfo(char const*& url, + void perform(char const* url, transfer_callback* transfer); + + void getInfo(char const*& url, char const*& type, int64_t& length, int64_t& stardate); // synthesized callback @@ -163,33 +168,37 @@ class UrlReader { char* input, size_t size); }; -template< class ContentStream > -bool UrlReader::readUrl(char const* url, ContentStream& s, char const* cacheFile) { - if (! _ptrImpl) return false; - _strCacheFile = cacheFile; - _ptrCacheFile = 0l; - _valCacheMode = no_cache; // eventually set later - _strError = success; - _ptrStream = & s; - _valXtraSize = ~size_t(0); - this->perform(url, & callback_template); - s.end(_strError == success); - if (_ptrCacheFile != 0l) { - fclose(_ptrCacheFile); - } +inline char const* UrlReader::getError() const { + + return _strError; +} + +bool UrlReader::isSuccess() { + return _strError == success || _strError == success_cached; } -inline char const* UrlReader::getError() const { return this->_strError; } +template< class ContentStream > +bool UrlReader::readUrl(char const* url, ContentStream& s, char const* cacheFile) { + if (! _hndCurl) return false; + + this->transferBegin(& s, cacheFile); + this->perform(url, & callback_template); + this->transferEnd(); + bool ok = isSuccess(); + s.end(ok); + return ok; +} inline void UrlReader::setError(char const* staticCstring) { - if (this->_strError == success || this->_strError == success_cached) + if (this->isSuccess()) this->_strError = staticCstring; } template< class Stream > size_t UrlReader::feedBuffered(Stream* stream, char* input, size_t size) { + size_t inputOffset = 0u; while (true) { @@ -263,7 +272,7 @@ size_t UrlReader::callback_template(char *input, size_t size, size_t nmemb, void // extract meta information and call 'begin' char const* url, * type; int64_t length, stardate; - me->getinfo(url, type, length, stardate); + me->getInfo(url, type, length, stardate); if (me->_valCacheMode != cache_read) { stream->begin(url, type, length, stardate); } From 168bd24342070f08793d9c7eeffeb8d03085cceb Mon Sep 17 00:00:00 2001 From: tosh Date: Wed, 15 May 2013 16:16:53 +0200 Subject: [PATCH 4/4] comments out logging, after testing all is fine --- libraries/shared/src/UrlReader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/UrlReader.cpp b/libraries/shared/src/UrlReader.cpp index e069c0cb73..66a72a8c8a 100644 --- a/libraries/shared/src/UrlReader.cpp +++ b/libraries/shared/src/UrlReader.cpp @@ -121,7 +121,7 @@ void UrlReader::getInfo(char const*& url, curl_easy_getinfo(_ptrCurl, CURLINFO_FILETIME, & time); stardate = time; - printLog("UrlReader: Ready to transfer from URL '%s'\n", url); +// printLog("UrlReader: Ready to transfer from URL '%s'\n", url); // check caching file time whether we actually want to download anything if (_strCacheFile != 0l) { @@ -130,7 +130,7 @@ void UrlReader::getInfo(char const*& url, if (time > s.st_mtime) { // file on server is newer -> update cache file _ptrCacheFile = fopen(_strCacheFile, "wb"); - printLog("UrlReader: Also writing content to cache file '%s'\n", _strCacheFile); +// printLog("UrlReader: Also writing content to cache file '%s'\n", _strCacheFile); if (_ptrCacheFile != 0l) { _valCacheMode = cache_write; } @@ -144,7 +144,7 @@ void UrlReader::getInfo(char const*& url, } } _ptrCacheFile = fopen(_strCacheFile, "rb"); - printLog("UrlReader: Delivering cached content from file '%s'\n", _strCacheFile); +// printLog("UrlReader: Delivering cached content from file '%s'\n", _strCacheFile); if (_ptrCacheFile != 0l) { _valCacheMode = cache_read; }