/******************************************************* * Copyright (c) 2014, ArrayFire * All rights reserved. * * This file is distributed under 3-clause BSD license. * The complete license agreement can be obtained at: * http://arrayfire.com/licenses/BSD-3-Clause ********************************************************/ #if defined(WITH_GRAPHICS) #include #include #include #include #include using namespace std; template GLenum getGLType() { return GL_FLOAT; } fg::MarkerType getFGMarker(const af_marker_type af_marker) { fg::MarkerType fg_marker; switch (af_marker) { case AF_MARKER_NONE: fg_marker = fg::FG_NONE; break; case AF_MARKER_POINT: fg_marker = fg::FG_POINT; break; case AF_MARKER_CIRCLE: fg_marker = fg::FG_CIRCLE; break; case AF_MARKER_SQUARE: fg_marker = fg::FG_SQUARE; break; case AF_MARKER_TRIANGLE: fg_marker = fg::FG_TRIANGLE; break; case AF_MARKER_CROSS: fg_marker = fg::FG_CROSS; break; case AF_MARKER_PLUS: fg_marker = fg::FG_PLUS; break; case AF_MARKER_STAR: fg_marker = fg::FG_STAR; break; default: fg_marker = fg::FG_NONE; break; } return fg_marker; } #define INSTANTIATE_GET_FG_TYPE(T, ForgeEnum)\ template<> fg::dtype getGLType() { return ForgeEnum; } INSTANTIATE_GET_FG_TYPE(float, fg::f32); INSTANTIATE_GET_FG_TYPE(int , fg::s32); INSTANTIATE_GET_FG_TYPE(unsigned, fg::u32); INSTANTIATE_GET_FG_TYPE(char, fg::s8); INSTANTIATE_GET_FG_TYPE(unsigned char, fg::u8); INSTANTIATE_GET_FG_TYPE(unsigned short, fg::u16); INSTANTIATE_GET_FG_TYPE(short, fg::s16); GLenum glErrorSkip(const char *msg, const char* file, int line) { #ifndef NDEBUG GLenum x = glGetError(); if (x != GL_NO_ERROR) { char buf[1024]; sprintf(buf, "GL Error Skipped at: %s:%d Message: %s Error Code: %d \"%s\"\n", file, line, msg, x, gluErrorString(x)); AF_ERROR(buf, AF_ERR_INTERNAL); } return x; #else return 0; #endif } GLenum glErrorCheck(const char *msg, const char* file, int line) { // Skipped in release mode #ifndef NDEBUG GLenum x = glGetError(); if (x != GL_NO_ERROR) { char buf[1024]; sprintf(buf, "GL Error at: %s:%d Message: %s Error Code: %d \"%s\"\n", file, line, msg, x, gluErrorString(x)); AF_ERROR(buf, AF_ERR_INTERNAL); } return x; #else return 0; #endif } GLenum glForceErrorCheck(const char *msg, const char* file, int line) { GLenum x = glGetError(); if (x != GL_NO_ERROR) { char buf[1024]; sprintf(buf, "GL Error at: %s:%d Message: %s Error Code: %d \"%s\"\n", file, line, msg, x, gluErrorString(x)); AF_ERROR(buf, AF_ERR_INTERNAL); } return x; } size_t getTypeSize(GLenum type) { switch(type) { case GL_FLOAT: return sizeof(float); case GL_INT: return sizeof(int ); case GL_UNSIGNED_INT: return sizeof(unsigned); case GL_SHORT: return sizeof(short); case GL_UNSIGNED_SHORT: return sizeof(unsigned short); case GL_BYTE: return sizeof(char ); case GL_UNSIGNED_BYTE: return sizeof(unsigned char); default: return sizeof(float); } } namespace graphics { ForgeManager& ForgeManager::getInstance() { static ForgeManager my_instance; return my_instance; } ForgeManager::~ForgeManager() { destroyResources(); } fg::Font* ForgeManager::getFont(const bool dontCreate) { static bool flag = true; static fg::Font* fnt = NULL; CheckGL("Begin ForgeManager::getFont"); if (flag && !dontCreate) { fnt = new fg::Font(); #if defined(_WIN32) || defined(_MSC_VER) fnt->loadSystemFont("Arial", 32); #else fnt->loadSystemFont("Vera", 32); #endif CheckGL("End ForgeManager::getFont"); flag = false; }; return fnt; } fg::Window* ForgeManager::getMainWindow(const bool dontCreate) { static bool flag = true; static fg::Window* wnd = NULL; // Define AF_DISABLE_GRAPHICS with any value to disable initialization std::string noGraphicsENV = getEnvVar("AF_DISABLE_GRAPHICS"); if(noGraphicsENV.empty()) { // If AF_DISABLE_GRAPHICS is not defined if (flag && !dontCreate) { wnd = new fg::Window(WIDTH, HEIGHT, "ArrayFire", NULL, true); CheckGL("End ForgeManager::getMainWindow"); flag = false; }; } return wnd; } fg::Image* ForgeManager::getImage(int w, int h, fg::ChannelFormat mode, fg::dtype type) { /* w, h needs to fall in the range of [0, 2^16] * for the ForgeManager to correctly retrieve * the necessary Forge Image object. So, this implementation * is a limitation on how big of an image can be rendered * using arrayfire graphics funtionality */ assert(w <= 2ll<<16); assert(h <= 2ll<<16); long long key = ((w & _16BIT) << 16) | (h & _16BIT); key = (((key << 16) | mode) << 16) | type; ImgMapIter iter = mImgMap.find(key); if (iter==mImgMap.end()) { fg::Image* temp = new fg::Image(w, h, mode, type); mImgMap[key] = temp; } return mImgMap[key]; } fg::Plot* ForgeManager::getPlot(int nPoints, fg::dtype dtype, fg::PlotType ptype, fg::MarkerType mtype) { /* nPoints needs to fall in the range of [0, 2^48] * for the ForgeManager to correctly retrieve * the necessary Forge Plot object. So, this implementation * is a limitation on how big of an plot graph can be rendered * using arrayfire graphics funtionality */ assert(nPoints <= 2ll<<48); long long key = ((nPoints & _48BIT) << 48); key |= (((((dtype & 0x000F) << 12) | (ptype & 0x000F)) << 8) | (mtype & 0x000F)); PltMapIter iter = mPltMap.find(key); if (iter==mPltMap.end()) { fg::Plot* temp = new fg::Plot(nPoints, dtype, ptype, mtype); mPltMap[key] = temp; } return mPltMap[key]; } fg::Plot3* ForgeManager::getPlot3(int nPoints, fg::dtype dtype, fg::PlotType ptype, fg::MarkerType mtype) { /* nPoints needs to fall in the range of [0, 2^48] * for the ForgeManager to correctly retrieve * the necessary Forge Plot object. So, this implementation * is a limitation on how big of an plot graph can be rendered * using arrayfire graphics funtionality */ assert(nPoints <= 2ll<<48); long long key = ((nPoints & _48BIT) << 48); key |= (((((dtype & 0x000F) << 12) | (ptype & 0x000F)) << 8) | (mtype & 0x000F)); Plt3MapIter iter = mPlt3Map.find(key); if (iter==mPlt3Map.end()) { fg::Plot3* temp = new fg::Plot3(nPoints, dtype, ptype, mtype); mPlt3Map[key] = temp; } return mPlt3Map[key]; } fg::Histogram* ForgeManager::getHistogram(int nBins, fg::dtype type) { /* nBins needs to fall in the range of [0, 2^48] * for the ForgeManager to correctly retrieve * the necessary Forge Histogram object. So, this implementation * is a limitation on how big of an histogram data can be rendered * using arrayfire graphics funtionality */ assert(nBins <= 2ll<<48); long long key = ((nBins & _48BIT) << 48) | (type & _16BIT); HstMapIter iter = mHstMap.find(key); if (iter==mHstMap.end()) { fg::Histogram* temp = new fg::Histogram(nBins, type); mHstMap[key] = temp; } return mHstMap[key]; } fg::Surface* ForgeManager::getSurface(int nX, int nY, fg::dtype type) { /* nX * nY needs to fall in the range of [0, 2^48] * for the ForgeManager to correctly retrieve * the necessary Forge Plot object. So, this implementation * is a limitation on how big of an plot graph can be rendered * using arrayfire graphics funtionality */ assert(nX * nY <= 2ll<<48); long long key = (((nX * nY) & _48BIT) << 48) | (type & _16BIT); SfcMapIter iter = mSfcMap.find(key); if (iter==mSfcMap.end()) { fg::Surface* temp = new fg::Surface(nX, nY, type); mSfcMap[key] = temp; } return mSfcMap[key]; } void ForgeManager::destroyResources() { /* clear all OpenGL resource objects (images, plots, histograms etc) first * and then delete the windows */ for(ImgMapIter iter = mImgMap.begin(); iter != mImgMap.end(); iter++) delete (iter->second); for(PltMapIter iter = mPltMap.begin(); iter != mPltMap.end(); iter++) delete (iter->second); for(HstMapIter iter = mHstMap.begin(); iter != mHstMap.end(); iter++) delete (iter->second); delete getFont(true); delete getMainWindow(true); } } #endif