ImageTransformsGPU.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00026 #include <iostream>
00027 #include <iomanip>
00028 
00029 #include <GL/glew.h>
00030 
00031 #include <string.h>
00032 #ifdef _WIN32
00033 // weird errors in accessor.hxx if DIFFERENCE is defined
00034   #undef DIFFERENCE
00035 #endif
00036 #include <vigra/diff2d.hxx>
00037 #include <vigra/utilities.hxx>
00038 #include <vigra/error.hxx>
00039 #include <vigra_ext/ImageTransformsGPU.h>
00040 
00041 #ifdef _WIN32
00042 #include <windows.h>
00043 long getms()
00044 {
00045     return GetTickCount();
00046 };
00047 #else
00048 #include <sys/time.h>
00049 long getms()
00050 {
00051     struct timeval tv;
00052     gettimeofday(&tv,NULL);
00053     return (long)(tv.tv_sec*1000+(tv.tv_usec/1000));
00054 };
00055 #endif
00056 #include <time.h>
00057 
00058 #include <vector>
00059 
00060 using std::cout;
00061 using std::cerr;
00062 using std::endl;
00063 using std::vector;
00064 
00065 using vigra::Rect2D;
00066 
00067 #define ___NCFILE___ ((char *) __FILE__)
00068 #define CHECK_GL() checkGLErrors(__LINE__, ___NCFILE___)
00069 
00070 
00071 static GLenum XGLMap[] = {
00072     // gltypes
00073     GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT,
00074     // Internalformats
00075     GL_RGBA8, GL_RGBA16, GL_RGBA32F_ARB, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA32F_ARB,
00076     GL_RGB8,  GL_RGB16,  GL_RGB32F_ARB,  GL_LUMINANCE8,        GL_LUMINANCE16,         GL_LUMINANCE32F_ARB,
00077     // formats
00078     GL_LUMINANCE, GL_RGB, GL_LUMINANCE_ALPHA, GL_RGBA
00079 };
00080 
00081 static const char* XGLStringMap[] = {
00082     // gltypes
00083     "GL_BYTE", "GL_UNSIGNED_BYTE", "GL_SHORT", "GL_UNSIGNED_SHORT", "GL_INT", "GL_UNSIGNED_INT", "GL_FLOAT",
00084     // Internalformats
00085     "GL_RGBA8", "GL_RGBA16", "GL_RGBA32F_ARB", "GL_LUMINANCE8_ALPHA8", "GL_LUMINANCE16_ALPHA16", "GL_LUMINANCE_ALPHA32F_ARB",
00086     "GL_RGB8",  "GL_RGB16",  "GL_RGB32F_ARB",  "GL_LUMINANCE8",        "GL_LUMINANCE16",         "GL_LUMINANCE32F_ARB",
00087     // formats
00088     "GL_LUMINANCE", "GL_RGB", "GL_LUMINANCE_ALPHA", "GL_RGBA"
00089 };
00090 
00091 static int BytesPerPixel[] = {
00092     1, 1, 2, 2, 4, 4, 4,
00093     4, 8, 16, 2, 4, 8,
00094     3, 6, 12, 1, 2, 4,
00095     0, 0, 0, 0
00096 };
00097 
00098 static const char* AlphaCompositeKernelSource = {
00099 "#version 110\n"
00100 "#extension GL_ARB_texture_rectangle : enable\n"
00101 "uniform sampler2DRect SrcAlphaTexture;\n"
00102 "void main(void)\n"
00103 "{\n"
00104 "   float alpha = texture2DRect(SrcAlphaTexture, gl_TexCoord[0].st).a;\n"
00105 "   if (alpha != 0.0) discard;\n"
00106 "   gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
00107 "}\n"
00108 };
00109 
00110 static void checkGLErrors(int line, char* file) {
00111     GLenum errCode = glGetError();
00112     if (errCode != GL_NO_ERROR)
00113     {
00114         while (errCode != GL_NO_ERROR)
00115         {
00116             const GLubyte* message = gluErrorString(errCode);
00117             std::cerr << "nona: GL error in " << file << ":" << line << std::endl;
00118             if (message)
00119             {
00120 #ifdef _WIN32
00121                 const char* messageChar = reinterpret_cast<const char*>(message);
00122                 size_t size = strlen(messageChar);
00123                 LPSTR OEMmessageBuffer = (LPSTR)LocalAlloc(LPTR, (size + 1)*sizeof(char));
00124                 if (OEMmessageBuffer)
00125                 {
00126                     if (CharToOemBuff(messageChar, OEMmessageBuffer, size))
00127                     {
00128                         std::cerr << OEMmessageBuffer << " (0x" << std::hex << errCode << ")" << std::endl;
00129                     }
00130                     else
00131                     {
00132                         std::cerr << message << " (0x" << std::hex << errCode << ")" << std::endl;
00133                     };
00134                 }
00135                 else
00136                 {
00137                     std::cerr << message << " (0x" << std::hex << errCode << ")" << std::endl;
00138                 };
00139                 LocalFree(OEMmessageBuffer);
00140 #else
00141                 std::cerr << message << " (0x" << std::hex << errCode << ")" << std::endl;
00142 #endif
00143             }
00144             else
00145             {
00146                 std::cerr << "Error code: 0x" << std::hex << errCode << std::endl;
00147             }
00148             errCode = glGetError();
00149         };
00150         exit(1);
00151     }
00152 }
00153 
00154 static void printInfoLog(GLhandleARB obj) {
00155     GLint infologLength = 0;
00156     GLint charsWritten = 0;
00157     glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
00158     if (infologLength > 1) {
00159         char* infoLog = new char[infologLength];
00160         glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
00161         cout << "nona: GL info log:" << endl << infoLog << endl << endl;
00162         delete[] infoLog;
00163     }
00164 }
00165 
00166 static bool printDebug=false;
00167 
00168 static bool checkFramebufferStatus(int line, char* file) {
00169     GLenum status;
00170     status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
00171     switch(status) {
00172         case GL_FRAMEBUFFER_COMPLETE_EXT:
00173             return true;
00174         case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
00175             cerr << "nona: GL error: Framebuffer incomplete, incomplete attachment in: " << file << ":" << line << endl;
00176             return false;
00177         case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
00178             cerr << "nona: Unsupported framebuffer format in: " << file << ":" << line << endl;
00179             return false;
00180         case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
00181             cerr << "nona: Framebuffer incomplete, missing attachment in: " << file << ":" << line << endl;
00182             return false;
00183         case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
00184             cerr << "nona: Framebuffer incomplete, attached images must have same dimensions in: " << file << ":" << line << endl;
00185             return false;
00186         case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
00187             cerr << "nona: Framebuffer incomplete, attached images must have same format in: " << file << ":" << line << endl;
00188             return false;
00189         case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
00190             cerr << "nona: Framebuffer incomplete, missing draw buffer in: " << file << ":" << line << endl;
00191             return false;
00192         case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
00193             cerr << "nona: Framebuffer incomplete, missing read buffer in: " << file << ":" << line << endl;
00194             return false;
00195     }
00196 
00197     return false;
00198 }
00199 
00200 static void compileGLSL(const char* programName,
00201                         GLhandleARB& programObject,
00202                         GLhandleARB& shaderObject,
00203                         const char** source)
00204 {
00205     GLint success;
00206 
00207     programObject = glCreateProgramObjectARB();
00208     shaderObject = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00209 
00210     glShaderSourceARB(shaderObject, 1, source, NULL);
00211     glCompileShaderARB(shaderObject);
00212 
00213     glGetObjectParameterivARB(shaderObject, GL_OBJECT_COMPILE_STATUS_ARB, &success);
00214     if (!success) {
00215         cerr << "nona: " << programName << " shader program could not be compiled." << endl;
00216         printInfoLog(shaderObject);
00217         exit(1);
00218     }
00219 
00220     if(printDebug)
00221         printInfoLog(shaderObject);
00222 
00223     glAttachObjectARB(programObject, shaderObject);
00224     glLinkProgramARB(programObject);
00225 
00226     glGetObjectParameterivARB(programObject, GL_OBJECT_LINK_STATUS_ARB, &success);
00227     if (!success) {
00228         cerr << "nona: " << programName << " shader program could not be linked." << endl;
00229         printInfoLog(programObject);
00230         exit(1);
00231     }
00232 
00233     if(printDebug)
00234         printInfoLog(programObject);
00235 }
00236 
00237 static void makeChunks(const int width,
00238                        const int height,
00239                        const int maxTextureSize,
00240                        const long long int maxPixels,
00241                        vector<Rect2D>& result)
00242 {
00243     int numXChunks = 1;
00244     int numYChunks = 1;
00245 
00246     // Make chunks small enough to fit into maxTextureSize
00247     while (ceil(static_cast<double>(width) / numXChunks) > maxTextureSize) numXChunks++;
00248     while (ceil(static_cast<double>(height) / numYChunks) > maxTextureSize) numYChunks++;
00249 
00250     // Make chunks small enough to fit into maxPixels limit
00251     while ((ceil(static_cast<double>(width) / numXChunks) * ceil(static_cast<double>(height) / numYChunks))
00252            > maxPixels) {
00253 
00254         if (ceil(static_cast<double>(width) / numXChunks) > ceil(static_cast<double>(height) / numYChunks)) {
00255             ++numXChunks;
00256         } else {
00257             ++numYChunks;
00258         }
00259     }
00260 
00261     // Make chunks small enough to fit in GL_PROXY_TEXTURE_2D of the biggest internalformat type.
00262     while (1) {
00263         glTexImage2D(GL_PROXY_TEXTURE_2D,
00264                      0,
00265                      GL_RGBA32F_ARB,
00266                      static_cast<int>(ceil(static_cast<double>(width) / numXChunks)),
00267                      static_cast<int>(ceil(static_cast<double>(height) / numYChunks)),
00268                      0,
00269                      GL_RGBA,
00270                      GL_FLOAT,
00271                      NULL);
00272         GLint returnedWidth;
00273         glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &returnedWidth);
00274 
00275         if (returnedWidth != 0) break;
00276 
00277         if (ceil(static_cast<double>(width) / numXChunks) > ceil(static_cast<double>(height) / numYChunks)) {
00278             ++numXChunks;
00279         } else {
00280             ++numYChunks;
00281         }
00282     }
00283 
00284     for (int yChunk = 0, y = 0; yChunk < numYChunks; yChunk++) {
00285         int yEnd = std::min<int>(height, static_cast<int>(ceil(static_cast<double>(height) / numYChunks)) + y);
00286         for (int xChunk = 0, x = 0; xChunk < numXChunks; xChunk++) {
00287             int xEnd = std::min<int>(width, static_cast<int>(ceil(static_cast<double>(width) / numXChunks)) + x);
00288             result.push_back(Rect2D(x, y, xEnd, yEnd));
00289             x = xEnd;
00290         }
00291         y = yEnd;
00292     }
00293 }
00294 
00295 
00296 namespace vigra_ext
00297 {
00298 
00299 void SetGPUDebugMessages(const bool doPrint)
00300 {
00301     printDebug=doPrint;
00302 };
00303 
00304 bool transformImageGPUIntern(const std::string& coordXformGLSL,
00305                              const std::string& interpolatorGLSL,
00306                              const int interpolatorSize,
00307                              const std::string& photometricGLSL,
00308                              const vector<double>& invLut,
00309                              const vector<double>& destLut,
00310                              const vigra::Diff2D srcSize,
00311                              const void* const srcBuffer,
00312                              const int srcGLInternalFormat, const int srcGLTransferFormat, const int srcGLFormat, const int srcGLType,
00313                              const void* const srcAlphaBuffer,
00314                              const int srcAlphaGLType,
00315                              const vigra::Diff2D destUL,
00316                              const vigra::Diff2D destSize,
00317                              void* const destBuffer,
00318                              const int destGLInternalFormat, const int destGLTransferFormat, const int destGLFormat, const int destGLType,
00319                              void* const destAlphaBuffer,
00320                              const int destAlphaGLType,
00321                              const bool warparound)
00322 {
00323     long t1, t3, t5, t6, t7, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t21;
00324 
00325     const int xstart = destUL.x;
00326     const int xend   = destUL.x + destSize.x;
00327     const int ystart = destUL.y;
00328     const int yend   = destUL.y + destSize.y;
00329 
00330     if(printDebug)
00331     {
00332         t1=getms();
00333         cout << "destStart=[" << xstart << ", " << ystart << "]" << endl
00334              << "destEnd=[" << xend << ", " << yend << "]" << endl
00335              << "destSize=[" << destSize << "]" << endl
00336              << "srcSize=[" << srcSize << "]" << endl
00337              << "srcBuffer=" << srcBuffer << endl
00338              << "srcAlphaBuffer=" << srcAlphaBuffer << endl
00339              << "destBuffer=" << destBuffer << endl
00340              << "destAlphaBuffer=" << destAlphaBuffer << endl
00341              << "destGLInternalFormat=" << XGLStringMap[destGLInternalFormat] << endl
00342              << "destGLFormat=" << XGLStringMap[destGLFormat] << endl
00343              << "destGLType=" << XGLStringMap[destGLType] << endl
00344              << "srcGLInternalFormat=" << XGLStringMap[srcGLInternalFormat] << endl
00345              << "srcGLFormat=" << XGLStringMap[srcGLFormat] << endl
00346              << "srcGLType=" << XGLStringMap[srcGLType] << endl
00347              << "srcAlphaGLType=" << XGLStringMap[srcAlphaGLType] << endl
00348              << "destAlphaGLType=" << XGLStringMap[destAlphaGLType] << endl
00349              << endl
00350              << "warparound=" << warparound << endl;
00351     };
00352 
00353     vigra_precondition((srcSize.x % 8) == 0, "src image width not a multiple of 8");
00354     vigra_precondition((destSize.x % 8) == 0, "dest image width not a multiple of 8");
00355 
00356     vigra_precondition((reinterpret_cast<const uintptr_t>(srcBuffer) & 0x7) == 0, "src image buffer not 8-byte aligned");
00357     vigra_precondition((reinterpret_cast<const uintptr_t>(srcAlphaBuffer) & 0x7) == 0, "src alpha image buffer not 8-byte aligned");
00358     vigra_precondition((reinterpret_cast<const uintptr_t>(destBuffer) & 0x7) == 0, "dest image buffer not 8-byte aligned");
00359     vigra_precondition((reinterpret_cast<const uintptr_t>(destAlphaBuffer) & 0x7) == 0, "dest alpha image buffer not 8-byte aligned");
00360 
00361     const char* const gpuVendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
00362     const bool needsAtanWorkaround = (strncmp(gpuVendor, "ATI", 3) == 0);
00363 
00364     if(printDebug)
00365         cout << "needsAtanWorkaround=" << needsAtanWorkaround << endl;
00366 
00367     GLint maxTextureSize;
00368     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
00369     if(printDebug)
00370         cout << "maxTextureSize=" << maxTextureSize << endl;
00371 
00372     // Artificial limit: binding big textures to fbos seems to be very slow.
00373     //maxTextureSize = 2048;
00374 
00375     long long int GpuMemoryInBytes = 512 << 20;
00376     // read memory size, not implemented on all graphic cards
00377     {
00378         // for nvidia cards
00379 #define GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX 0x9048
00380         GLint total_mem_kb = 0;
00381         glGetIntegerv(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX, &total_mem_kb);
00382         if (glGetError() == GL_NO_ERROR)
00383         {
00384             GpuMemoryInBytes = total_mem_kb * 1024ll;
00385         };
00386     };
00387     {
00388         //for amd/ati cards
00389 #define TEXTURE_FREE_MEMORY_ATI 0x87FC
00390         GLint param[4];
00391         glGetIntegerv(TEXTURE_FREE_MEMORY_ATI, param);
00392         if (glGetError() == GL_NO_ERROR)
00393         {
00394             GpuMemoryInBytes = param[0] * 1024ll;
00395         };
00396     }
00397     const double SourceAllocationRatio = 0.7;
00398 
00399     const int bytesPerSourcePixel = BytesPerPixel[srcGLInternalFormat]
00400                                     + ((srcGLInternalFormat != srcGLTransferFormat) ? BytesPerPixel[srcGLTransferFormat] : 0)
00401                                     + ((srcAlphaBuffer != NULL) ? 1 : 0);
00402     const long long int maxSourcePixels = static_cast<long long int>(GpuMemoryInBytes * SourceAllocationRatio) / bytesPerSourcePixel;
00403 
00404     vector<Rect2D> sourceChunks;
00405     makeChunks(srcSize.x, srcSize.y, maxTextureSize, maxSourcePixels, sourceChunks);
00406 
00407     const long long int actualSourcePixels = sourceChunks[0].area();
00408     const long long int gpuMemoryRemaining = GpuMemoryInBytes - (actualSourcePixels * bytesPerSourcePixel);
00409 
00410     // 16 bytes/pixel * 2 dest images for ping/pong multipass rendering
00411     //  8 bytes/pixel for coordinate texture
00412     //  destXfer + GL_ALPHA
00413     const int bytesPerDestPixel = 16 + 16 + 8
00414                                   + ((XGLMap[destGLTransferFormat] != GL_RGBA32F_ARB) ? BytesPerPixel[destGLTransferFormat] : 0)
00415                                   + ((destAlphaBuffer != NULL) ? 1 : 0);
00416     const long long int maxDestPixels = gpuMemoryRemaining / bytesPerDestPixel;
00417 
00418     vector<Rect2D> destChunks;
00419     makeChunks(destSize.x, destSize.y, maxTextureSize, maxDestPixels, destChunks);
00420 
00421     const long long int totalGpuMemoryUsed = (sourceChunks[0].area() * bytesPerSourcePixel) + (destChunks[0].area() * bytesPerDestPixel);
00422     vigra_assert(totalGpuMemoryUsed <= GpuMemoryInBytes,
00423                  "failed to subdivide source and dest images into pieces small enough to fit in gpu memory.");
00424 
00425     if(printDebug)
00426     {
00427         cout << "Source chunks:" << endl;
00428         for (vector<Rect2D>::iterator rI = sourceChunks.begin(); rI != sourceChunks.end(); ++rI) {
00429             cout << "    " << *rI << endl;
00430         }
00431         cout << "Dest chunks:" << endl;
00432         for (vector<Rect2D>::iterator rI = destChunks.begin(); rI != destChunks.end(); ++rI) {
00433             cout << "    " << *rI << endl;
00434         }
00435         cout << "Total GPU memory used: " << totalGpuMemoryUsed << endl;
00436     };
00437 
00438 
00439     const int TextureFetchesPerInterpolatorPass = 16;
00440     vector<Rect2D> interpolatorChunks;
00441     makeChunks(interpolatorSize, interpolatorSize, TextureFetchesPerInterpolatorPass, TextureFetchesPerInterpolatorPass, interpolatorChunks);
00442     if(printDebug)
00443     {
00444         cout << "Interpolator chunks:" << endl;
00445         for (vector<Rect2D>::iterator rI = interpolatorChunks.begin(); rI != interpolatorChunks.end(); ++rI) {
00446             cout << "    " << *rI << endl;
00447         }
00448     };
00449     bool allInterpolatorChunksAreEqual = true;
00450     const Rect2D& firstInterpolatorChunk = interpolatorChunks.front();
00451     for (vector<Rect2D>::iterator rI = ++(interpolatorChunks.begin()); rI != interpolatorChunks.end(); ++rI) {
00452         if (rI->width() != firstInterpolatorChunk.width()
00453             || rI->height() != firstInterpolatorChunk.height()) {
00454             allInterpolatorChunksAreEqual = false;
00455             break;
00456         }
00457     }
00458 
00459 
00460     // Prepare coord transform GLSL program
00461     std::ostringstream oss;
00462     oss << std::setprecision(20) << std::showpoint;
00463     oss << "#version 110" << endl
00464         << "#extension GL_ARB_texture_rectangle : enable" << endl
00465         << "uniform sampler2DRect SrcTexture;" << endl
00466         << "float sinh(in float x) { return (exp(x) - exp(-x)) / 2.0; }" << endl
00467         << "float cosh(in float x) { return (exp(x) + exp(-x)) / 2.0; }" << endl;
00468     // TODO: OpenGL Shader vers. 1.5 has built-in sinh and cosh function,
00469     // need to check is this functions are available and compile only when
00470     // this functions are not available
00471 
00472     if (needsAtanWorkaround) {
00473         oss << "float atan2_xge0(const in float y, const in float x) {" << endl
00474             << "    if (abs(y) > x) {" << endl
00475             << "        return sign(y) * (" << (M_PI/2.0) << " - atan(x, abs(y)));" << endl
00476             << "    } else {" << endl
00477             << "        return atan(y, x);" << endl
00478             << "    }" << endl
00479             << "}" << endl
00480             << "float atan2_safe(const in float y, const in float x) {" << endl
00481             << "    if (x >= 0.0) return atan2_xge0(y, x);" << endl
00482             << "    else return (sign(y) * " << M_PI << ") - atan2_xge0(y, -x);" << endl
00483             << "}" << endl
00484             << "float atan_safe(const in float yx) {" << endl
00485             << "    if (abs(yx) > 1.0) {" << endl
00486             << "        return sign(yx) * (" << (M_PI/2.0) << " - atan(1.0/abs(yx)));" << endl
00487             << "    } else {" << endl
00488             << "        return atan(yx);" << endl
00489             << "    }" << endl
00490             << "}" << endl;
00491     } else {
00492         oss << "float atan2_xge0(const in float y, const in float x) {" << endl
00493             << "    return atan(y, x);" << endl
00494             << "}" << endl
00495             << "float atan2_safe(const in float y, const in float x) {" << endl
00496             << "    return atan(y, x);" << endl
00497             << "}" << endl
00498             << "float atan_safe(const in float yx) {" << endl
00499             << "    return atan(yx);" << endl
00500             << "}" << endl;
00501     }
00502 
00503     oss << "void main(void)" << endl
00504         << "{" << endl
00505         << "    float discardA = 1.0;" << endl
00506         << "    float discardB = 0.0;" << endl
00507         << coordXformGLSL
00508         << "    src = src * discardA + vec2(-1000.0, -1000.0) * discardB;" << endl
00509         << "    gl_FragColor = vec4(src.s, 0.0, 0.0, src.t);" << endl
00510         << "}" << endl;
00511 
00512     std::string coordXformKernelSourceString = oss.str();
00513     const char* coordXformKernelSource = coordXformKernelSourceString.c_str();
00514     if(printDebug)
00515         cout << coordXformKernelSource;
00516 
00517     GLhandleARB coordXformProgramObject;
00518     GLhandleARB coordXformShaderObject;
00519     compileGLSL("coordinate transform",
00520                 coordXformProgramObject,
00521                 coordXformShaderObject,
00522                 &coordXformKernelSource);
00523 
00524 
00525 
00526     // Prepare alpha composite shader program.
00527     // This is the same for all images so we just do it once.
00528     static bool createdAlphaShader = false;
00529     static GLhandleARB alphaCompositeProgramObject;
00530     static GLhandleARB alphaCompositeShaderObject;
00531     static GLint srcAlphaTextureParam;
00532     if (!createdAlphaShader
00533         && (srcGLInternalFormat == srcGLTransferFormat)
00534         && (srcAlphaBuffer != NULL)) {
00535 
00536         compileGLSL("alpha composite",
00537                     alphaCompositeProgramObject,
00538                     alphaCompositeShaderObject,
00539                     &AlphaCompositeKernelSource);
00540         srcAlphaTextureParam = glGetUniformLocationARB(alphaCompositeProgramObject, "SrcAlphaTexture");
00541         createdAlphaShader = true;
00542     }
00543 
00544 
00545     // Prepare interpolation shader program.
00546     oss.str("");
00547     oss << std::setprecision(20) << std::showpoint;
00548     oss << "#version 110" << endl
00549         << "#extension GL_ARB_texture_rectangle : enable" << endl
00550         << "uniform sampler2DRect CoordTexture;" << endl
00551         << "uniform sampler2DRect SrcTexture;" << endl
00552         << "uniform sampler2DRect AccumTexture;" << endl
00553         << "uniform vec2 SrcUL;" << endl
00554         << "uniform vec2 SrcLR;" << endl
00555         << "uniform vec2 KernelUL;" << endl
00556         << "uniform vec2 KernelWH;" << endl
00557         << "float w(const in float i, const in float f) {" << endl
00558         << interpolatorGLSL
00559         << "}" << endl
00560         << "void main(void)" << endl
00561         << "{" << endl
00562         << "    vec2 src = texture2DRect(CoordTexture, gl_TexCoord[0].st).sq;" << endl
00563         << "    vec4 accum = texture2DRect(AccumTexture, gl_TexCoord[0].st);" << endl
00564         << endl;
00565 
00566     // Unexpectedly, this checking slows down the interpolator render passes by 3x-5x.
00568     //oss << "    if (any(lessThan(src, SrcUL - KernelLR + " << (interpolatorSize / 2.0) << "))) {" << endl
00569     //    << "        gl_FragColor = accum;" << endl
00570     //    << "        return;" << endl
00571     //    << "    }" << endl
00572     //    << "    if (any(greaterThanEqual(src, SrcLR - KernelUL + " << ((interpolatorSize / 2.0) - 1.0) << "))) {" << endl
00573     //    << "        gl_FragColor = accum;" << endl
00574     //    << "        return;" << endl
00575     //    << "    }" << endl
00576     //    << endl;
00577 
00578     oss << "    src -= SrcUL;" << endl
00579         << "    vec2 t = floor(src) + " << (1.5 - (interpolatorSize / 2)) << ";" << endl
00580         << "    vec2 f = fract(src);" << endl
00581         << "    vec2 k = vec2(0.0, 0.0);" << endl
00582         << endl;
00583 
00584     // Interpolator loop
00585     if (allInterpolatorChunksAreEqual) {
00586         oss << "    for (float ky = 0.0; ky < " << static_cast<double>(firstInterpolatorChunk.height()) << "; ky += 1.0) {" << endl;
00587     } else {
00588         oss << "    for (float ky = 0.0; ky < KernelWH.t; ky += 1.0) {" << endl;
00589     }
00590 
00591     oss << "        k.t = ky + KernelUL.t;" << endl
00592         << "        float wy = w(k.t, f.t);" << endl;
00593 
00594     if (allInterpolatorChunksAreEqual) {
00595         oss << "        for (float kx = 0.0; kx < " << static_cast<double>(firstInterpolatorChunk.width()) << "; kx += 1.0) {" << endl;
00596     } else {
00597         oss << "        for (float kx = 0.0; kx < KernelWH.s; kx += 1.0) {" << endl;
00598     }
00599 
00600     // FIXME support warparound
00601     oss << "            k.s = kx + KernelUL.s;" << endl
00602         << "            float wx = w(k.s, f.s);" << endl
00603         << "            vec2 ix = t + k;" << endl
00604         << "            vec4 sp = texture2DRect(SrcTexture, ix);" << endl
00605         << "            float weight = wx * wy * sp.a;" << endl
00606         << "            accum += sp * weight;" << endl
00607         << "        }" << endl
00608         << "    }" << endl;
00609 
00611     //for (int ky = 0; ky < interpolatorSize; ++ky) {
00612     //    double bounded_ky_offset = 1.5 + ky - (interpolatorSize / 2);
00613     //    for (int kx = 0; kx < interpolatorSize; ++kx) {
00614     //        double bounded_kx_offset = 1.5 + kx - (interpolatorSize / 2);
00615     //        oss << "    {" << endl
00616     //            << "        // (" << kx << ", " << ky << ")" << endl
00617     //            << "        vec2 ix = t + vec2(" << bounded_kx_offset << ", " << bounded_ky_offset << ");" << endl
00618     //            << "        vec4 sp = texture2DRect(SrcTexture, ix);" << endl
00619     //            //<< "        float weight = w[" << kx << "].s * w[" << ky << "].t * sp.a;" << endl
00620     //            << "        float weight = w(" << (double)kx << ", f.s) * w(" << (double)ky << ", f.t) * sp.a;" << endl
00621     //            << "        accum += sp * weight;" << endl
00622     //            << "    }" << endl;
00623     //    }
00624     //}
00625 
00626     oss << endl
00627         << "    gl_FragColor = accum;" << endl
00628         << "}" << endl
00629         << endl;
00630 
00631     std::string interpolatorKernelSourceString = oss.str();
00632     const char* interpolatorKernelSource = interpolatorKernelSourceString.c_str();
00633     if(printDebug)
00634         cout << interpolatorKernelSource;
00635 
00636     GLhandleARB interpolatorProgramObject;
00637     GLhandleARB interpolatorShaderObject;
00638     compileGLSL("interpolator",
00639                 interpolatorProgramObject,
00640                 interpolatorShaderObject,
00641                 &interpolatorKernelSource);
00642 
00643     GLint coordTextureParam = glGetUniformLocationARB(interpolatorProgramObject, "CoordTexture");
00644     GLint accumTextureParam = glGetUniformLocationARB(interpolatorProgramObject, "AccumTexture");
00645     GLint srcTextureParam = glGetUniformLocationARB(interpolatorProgramObject, "SrcTexture");
00646     GLint srcULParam = glGetUniformLocationARB(interpolatorProgramObject, "SrcUL");
00647     GLint srcLRParam = glGetUniformLocationARB(interpolatorProgramObject, "SrcLR");
00648     GLint kernelULParam = glGetUniformLocationARB(interpolatorProgramObject, "KernelUL");
00649     GLint kernelWHParam = glGetUniformLocationARB(interpolatorProgramObject, "KernelWH");
00650 
00651 
00652     // Prepare normalization/photometric shader program
00653     oss.str("");
00654     oss << std::setprecision(20) << std::showpoint;
00655     oss << "#version 120" << endl
00656         << "#extension GL_ARB_texture_rectangle : enable" << endl
00657         << "uniform sampler2DRect NormTexture;" << endl
00658         << "uniform sampler2DRect CoordTexture;" << endl;
00659 
00660     if (!invLut.empty()) {
00661         oss << "uniform sampler2DRect InvLutTexture;" << endl;
00662     }
00663 
00664     if (!destLut.empty()) {
00665         oss << "uniform sampler2DRect DestLutTexture;" << endl;
00666     }
00667 
00668     oss << "void main(void)" << endl
00669         << "{" << endl
00670         << "    // Normalization" << endl
00671         << "    vec4 n = texture2DRect(NormTexture, gl_TexCoord[0].st);" << endl
00672         << "    vec4 p = vec4(0.0, 0.0, 0.0, 0.0);" << endl
00673         << "    if (n.a >= 0.2) p = n / n.a;" << endl
00674         << endl
00675         << "    // Photometric" << endl
00676         << photometricGLSL
00677         << endl
00678         << "    gl_FragColor = p;" << endl
00679         << "}" << endl
00680         << endl;
00681 
00682     std::string normalizationPhotometricKernelSourceString = oss.str();
00683     const char* normalizationPhotometricKernelSource = normalizationPhotometricKernelSourceString.c_str();
00684     if(printDebug)
00685         cout << normalizationPhotometricKernelSource;
00686 
00687     GLhandleARB normalizationPhotometricProgramObject;
00688     GLhandleARB normalizationPhotometricShaderObject;
00689     compileGLSL("normalization/photometric",
00690                 normalizationPhotometricProgramObject,
00691                 normalizationPhotometricShaderObject,
00692                 &normalizationPhotometricKernelSource);
00693 
00694     GLint normTextureParam = glGetUniformLocationARB(normalizationPhotometricProgramObject, "NormTexture");
00695     GLint normCoordTextureParam = glGetUniformLocationARB(normalizationPhotometricProgramObject, "CoordTexture");
00696 
00697     float *invLutTextureData = NULL;
00698     GLuint invLutTexture;
00699     GLint invLutTextureParam;
00700     if (!invLut.empty()) {
00701         invLutTextureData = new float[invLut.size() * 2];
00702         for (int i = 0; i < invLut.size(); ++i) {
00703             invLutTextureData[2*i] = invLut[i];
00704             invLutTextureData[2*i+1] = ((i + 1) < invLut.size()) ? invLut[i+1] : invLut[i];
00705         }
00706         invLutTextureParam = glGetUniformLocationARB(normalizationPhotometricProgramObject, "InvLutTexture");
00707         glGenTextures(1, &invLutTexture);
00708         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, invLutTexture);
00709         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00710         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00711         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00712         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00713         glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA32F_ARB, invLut.size(), 1, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, invLutTextureData);
00714         CHECK_GL();
00715     }
00716 
00717     float *destLutTextureData = NULL;
00718     GLuint destLutTexture;
00719     GLint destLutTextureParam;
00720     if (!destLut.empty()) {
00721         destLutTextureData = new float[destLut.size() * 2];
00722         for (int i = 0; i < destLut.size(); ++i) {
00723             destLutTextureData[2*i] = destLut[i];
00724             destLutTextureData[2*i+1] = ((i + 1) < destLut.size()) ? destLut[i+1] : destLut[i];
00725         }
00726         destLutTextureParam = glGetUniformLocationARB(normalizationPhotometricProgramObject, "DestLutTexture");
00727         glGenTextures(1, &destLutTexture);
00728         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destLutTexture);
00729         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00730         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00731         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00732         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00733         glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA32F_ARB, destLut.size(), 1, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, destLutTextureData);
00734         CHECK_GL();
00735     }
00736 
00737     glFinish();
00738     if(printDebug)
00739     {
00740         t21=getms();
00741         cout << "gpu shader program compile time = " << ((t21 - t1)/1000.0) << endl;
00742     };
00743 
00744     // General GL setup
00745     glPixelStorei(GL_PACK_ALIGNMENT, 8);
00746     glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
00747 
00748     const float borderColor[] = {0.0, 0.0, 0.0, 0.0};
00749 
00750     glClearColor(0.0, 0.0, 0.0, 0.0);
00751 
00752     GLuint framebuffers[5];
00753     glGenFramebuffersEXT(5, framebuffers);
00754     GLuint srcFB       = framebuffers[0];
00755     GLuint coordFB     = framebuffers[1];
00756     GLuint accumFB     = framebuffers[2];
00757     GLuint destFB      = framebuffers[3];
00758     GLuint destAlphaFB = framebuffers[4];
00759 
00760     const int viewportWidth = std::max<int>(destChunks[0].width(), sourceChunks[0].width());
00761     const int viewportHeight = std::max<int>(destChunks[0].height(), sourceChunks[0].height());
00762     glMatrixMode(GL_PROJECTION);
00763     glLoadIdentity();
00764     gluOrtho2D(0.0, viewportWidth, 0.0, viewportHeight);
00765     glMatrixMode(GL_MODELVIEW);
00766     glLoadIdentity();
00767     glViewport(0, 0, viewportWidth, viewportHeight);
00768 
00769     const int destOdd = (destChunks[0].height() & 1);
00770     // Setup coordinate texture
00771     GLuint coordTexture;
00772     glGenTextures(1, &coordTexture);
00773     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, coordTexture);
00774     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00775     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00776     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00777     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00778     glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, destChunks[0].width(), destChunks[0].height() + destOdd, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, NULL);
00779     CHECK_GL();
00780 
00781     // Setup coordinate framebuffer
00782     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, coordFB);
00783     CHECK_GL();
00784     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, coordTexture, 0);
00785     CHECK_GL();
00786     if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
00787         exit(1);
00788     }
00789 
00790     // Setup accumulator ping-pong textures
00791     GLuint accumTextures[2];
00792     glGenTextures(2, accumTextures);
00793 
00794     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, accumTextures[0]);
00795     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00796     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00797     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00798     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00799     glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, destChunks[0].width(), destChunks[0].height() + destOdd, 0, GL_RGBA, GL_FLOAT, NULL);
00800     CHECK_GL();
00801 
00802     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, accumTextures[1]);
00803     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00804     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00805     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00806     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00807     glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, destChunks[0].width(), destChunks[0].height() + destOdd, 0, GL_RGBA, GL_FLOAT, NULL);
00808     CHECK_GL();
00809 
00810     // Attach accumulator ping-pong textures to framebuffer
00811     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, accumFB);
00812     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, accumTextures[0], 0);
00813     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, accumTextures[1], 0);
00814     if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
00815         exit(1);
00816     }
00817 
00818     // Setup src texture
00819     const int sourceOdd = (sourceChunks[0].height() & 1);
00820     GLuint srcTexture;
00821     glGenTextures(1, &srcTexture);
00822     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
00823     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00824     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00825     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
00826     glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
00827     glTexParameterfv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BORDER_COLOR, borderColor);
00828     glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, XGLMap[srcGLInternalFormat], sourceChunks[0].width(), sourceChunks[0].height() + sourceOdd, 0, XGLMap[srcGLFormat], XGLMap[srcGLType], NULL);
00829     CHECK_GL();
00830 
00831     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, srcFB);
00832     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, srcTexture, 0);
00833     if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
00834         exit(1);
00835     }
00836 
00837     // Setup alpha composite framebuffer
00838     GLuint srcAlphaTexture;
00839     if (srcAlphaBuffer != NULL) {
00840         // If there is a separate alpha buffer given, prepare to composite the alpha data into srcTexture.
00841         glGenTextures(1, &srcAlphaTexture);
00842         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcAlphaTexture);
00843         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00844         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00845         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00846         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00847         glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA, sourceChunks[0].width(), sourceChunks[0].height() + sourceOdd, 0, GL_ALPHA, XGLMap[srcAlphaGLType], NULL);
00848         CHECK_GL();
00849     }
00850 
00851     GLuint srcTransferTexture;
00852     if (srcGLInternalFormat != srcGLTransferFormat) {
00853         // If the rgb data layout does not match the rgb internal texture format, prepare a separate texture
00854         // for the rgb data for fast GPU I/O. Then composite into srcTexture.
00855         glGenTextures(1, &srcTransferTexture);
00856         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTransferTexture);
00857         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00858         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00859         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00860         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00861         glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, XGLMap[srcGLTransferFormat], sourceChunks[0].width(), sourceChunks[0].height() + sourceOdd, 0, XGLMap[srcGLFormat], XGLMap[srcGLType], NULL);
00862         CHECK_GL();
00863     }
00864 
00865     // Setup dest and destalpha textures and framebuffers
00866     GLuint destTexture;
00867     if (XGLMap[destGLTransferFormat] != GL_RGBA32F_ARB) {
00868         // If the dest image rgb data layout does not match that of the accumulator textures,
00869         // create a separate texture of the appropriate layout and prepare to copy the output accumulator
00870         // texture to it. This is for fast GPU I/O.
00871         glGenTextures(1, &destTexture);
00872         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
00873         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00874         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00875         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00876         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00877         glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, XGLMap[destGLInternalFormat], destChunks[0].width(), destChunks[0].height() + destOdd, 0, XGLMap[destGLFormat], XGLMap[destGLType], NULL);
00878 
00879         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, destFB);
00880         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
00881         if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
00882             exit(1);
00883         }
00884     }
00885 
00886     GLuint destAlphaTexture;
00887     if (destAlphaBuffer != NULL) {
00888         // If a separate dest alpha buffer is provided, create a texture for transferring this data out.
00889         // This is for fast GPU I/O.
00890         glGenTextures(1, &destAlphaTexture);
00891         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destAlphaTexture);
00892         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00893         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00894         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
00895         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
00896         glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, destChunks[0].width(), destChunks[0].height() + destOdd, 0, GL_ALPHA, XGLMap[destAlphaGLType], NULL);
00897         CHECK_GL();
00898 
00899         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, destAlphaFB);
00900         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destAlphaTexture, 0);
00901         if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
00902             exit(1);
00903         }
00904     }
00905 
00906 
00907     glFinish();
00908     if(printDebug)
00909     {
00910         cout << "gpu shader texture/framebuffer setup time = " << ((getms()-t21)/1000.0) << endl;
00911     };
00912 
00913     // Render each dest chunk
00914     int destChunkNumber = 0;
00915     for (vector<Rect2D>::iterator dI = destChunks.begin(); dI != destChunks.end(); ++dI, ++destChunkNumber) {
00916 
00917         glFinish();
00918         if(printDebug)
00919             t3=getms();
00920 
00921         // Render coord image
00922         glUseProgramObjectARB(coordXformProgramObject);
00923         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, coordFB);
00924         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00925 
00926         glPolygonMode(GL_FRONT, GL_FILL);
00927         glBegin(GL_QUADS);
00928             glTexCoord2f(xstart + dI->left(),  ystart + dI->top());     glVertex2f(0.0,         0.0);
00929             glTexCoord2f(xstart + dI->right(), ystart + dI->top());     glVertex2f(dI->width(), 0.0);
00930             glTexCoord2f(xstart + dI->right(), ystart + dI->bottom());  glVertex2f(dI->width(), dI->height());
00931             glTexCoord2f(xstart + dI->left(),  ystart + dI->bottom());  glVertex2f(0.0,         dI->height());
00932         glEnd();
00933         CHECK_GL();
00934 
00935         glFinish();
00936         if(printDebug)
00937         {
00938             long t4=getms();
00939             cout << "gpu dest chunk=" << *dI << " coord image render time = " << ((t4-t3)/1000.0) << endl;
00940         };
00941 
00942         // Multipass rendering of dest image
00943         int pass = 0;
00944         for (vector<Rect2D>::iterator sI = sourceChunks.begin(); sI != sourceChunks.end(); ++sI) {
00945 
00946             if (destChunkNumber == 0 || sourceChunks.size() > 1) {
00947                 glFinish();
00948                 if(printDebug)
00949                     t5=getms();
00950 
00951                 glPixelStorei(GL_UNPACK_ROW_LENGTH, srcSize.x);
00952                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, sI->left());
00953                 glPixelStorei(GL_UNPACK_SKIP_ROWS, sI->top());
00954                 CHECK_GL();
00955 
00956                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, srcFB);
00957                 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00958                 glClear(GL_COLOR_BUFFER_BIT);
00959 
00960                 if (srcGLInternalFormat == srcGLTransferFormat) {
00961                     // Upload directly to source texture.
00962                     glActiveTexture(GL_TEXTURE0);
00963                     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
00964                     glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, sI->width(), sI->height(), XGLMap[srcGLFormat], XGLMap[srcGLType], srcBuffer);
00965                     CHECK_GL();
00966 
00967                     glFinish();
00968                     if(printDebug)
00969                     {
00970                         t6=getms();
00971                         cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src upload = " << ((t6-t5)/1000.0) << endl;
00972                     };
00973 
00974                     if (srcAlphaBuffer != NULL) {
00975                         // Upload to srcAlphaTexture and composite to srcTexture.
00976                         glUseProgramObjectARB(alphaCompositeProgramObject);
00977 
00978                         glActiveTexture(GL_TEXTURE0);
00979                         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcAlphaTexture);
00980                         glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, sI->width(), sI->height(), GL_ALPHA, XGLMap[srcAlphaGLType], srcAlphaBuffer);
00981                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00982                         glUniform1iARB(srcAlphaTextureParam, 0);
00983                         CHECK_GL();
00984 
00985                         glFinish();
00986                         if(printDebug)
00987                         {
00988                             t7=getms();
00989                             cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src alpha upload = " << ((t7-t6)/1000.0) << endl;
00990                         };
00991 
00992                         glPolygonMode(GL_FRONT, GL_FILL);
00993                         glBegin(GL_QUADS);
00994                             glTexCoord2f(0.0,         0.0);           glVertex2f(0.0,         0.0);
00995                             glTexCoord2f(sI->width(), 0.0);           glVertex2f(sI->width(), 0.0);
00996                             glTexCoord2f(sI->width(), sI->height());  glVertex2f(sI->width(), sI->height());
00997                             glTexCoord2f(0.0,         sI->height());  glVertex2f(0.0,         sI->height());
00998                         glEnd();
00999                         CHECK_GL();
01000 
01001                         glFinish();
01002                         if(printDebug)
01003                         {
01004                             cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src+alpha render = " << ((getms()-t7)/1000.0) << endl;
01005                         };
01006                     }
01007                 }
01008                 else {
01009                     // Composite to srcTexture
01010                     glUseProgramObjectARB(0);
01011 
01012                     // Upload to srcTransferTexture
01013                     glActiveTexture(GL_TEXTURE0);
01014                     glEnable(GL_TEXTURE_RECTANGLE_ARB);
01015                     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTransferTexture);
01016                     glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, sI->width(), sI->height(), XGLMap[srcGLFormat], XGLMap[srcGLType], srcBuffer);
01017                     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01018                     CHECK_GL();
01019 
01020                     glFinish();
01021                     if(printDebug)
01022                     {
01023                         t6=getms();
01024                         cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src upload = " << ((t6-t5)/1000.0) << endl;
01025                     };
01026 
01027                     if (srcAlphaBuffer != NULL) {
01028                         // Upload to srcAlphaTexture
01029                         glActiveTexture(GL_TEXTURE1);
01030                         glEnable(GL_TEXTURE_RECTANGLE_ARB);
01031                         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcAlphaTexture);
01032                         glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, sI->width(), sI->height(), GL_ALPHA, XGLMap[srcAlphaGLType], srcAlphaBuffer);
01033                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01034                         CHECK_GL();
01035 
01036                         glFinish();
01037                         if(printDebug)
01038                         {
01039                             t7=getms();
01040                             cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src alpha upload = " << ((t7- t6)/1000.0) << endl;
01041                         };
01042 
01043                         glPolygonMode(GL_FRONT, GL_FILL);
01044                         glBegin(GL_QUADS);
01045                             glMultiTexCoord2f(GL_TEXTURE0, 0.0,         0.0);           glMultiTexCoord2f(GL_TEXTURE1, 0.0,         0.0);           glVertex2f(0.0,         0.0);
01046                             glMultiTexCoord2f(GL_TEXTURE0, sI->width(), 0.0);           glMultiTexCoord2f(GL_TEXTURE1, sI->width(), 0.0);           glVertex2f(sI->width(), 0.0);
01047                             glMultiTexCoord2f(GL_TEXTURE0, sI->width(), sI->height());  glMultiTexCoord2f(GL_TEXTURE1, sI->width(), sI->height());  glVertex2f(sI->width(), sI->height());
01048                             glMultiTexCoord2f(GL_TEXTURE0, 0.0,         sI->height());  glMultiTexCoord2f(GL_TEXTURE1, 0.0,         sI->height());  glVertex2f(0.0,         sI->height());
01049                         glEnd();
01050                         CHECK_GL();
01051 
01052                         glActiveTexture(GL_TEXTURE0);
01053                         glDisable(GL_TEXTURE_RECTANGLE_ARB);
01054                         glActiveTexture(GL_TEXTURE1);
01055                         glDisable(GL_TEXTURE_RECTANGLE_ARB);
01056                         CHECK_GL();
01057 
01058                         glFinish();
01059                         if(printDebug)
01060                         {
01061                             cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src+alpha render = " << ((getms()-t7)/1000.0) << endl;
01062                         };
01063                     }
01064                     else {
01065                         glPolygonMode(GL_FRONT, GL_FILL);
01066                         glBegin(GL_QUADS);
01067                             // According to the spec, GL_REPLACE uses the incoming fragment color for dest alpha when
01068                             // texturing a RGB texture into an RGBA texture. Thus the color is explicitly set
01069                             // with alpha=1.0, rather than relying on the default color.
01070                             glColor4f(0.0, 0.0, 0.0, 1.0);
01071                             glTexCoord2f(0.0,         0.0);           glVertex2f(0.0,         0.0);
01072                             glTexCoord2f(sI->width(), 0.0);           glVertex2f(sI->width(), 0.0);
01073                             glTexCoord2f(sI->width(), sI->height());  glVertex2f(sI->width(), sI->height());
01074                             glTexCoord2f(0.0,         sI->height());  glVertex2f(0.0,         sI->height());
01075                         glEnd();
01076                         CHECK_GL();
01077 
01078                         glActiveTexture(GL_TEXTURE0);
01079                         glDisable(GL_TEXTURE_RECTANGLE_ARB);
01080                         CHECK_GL();
01081 
01082                         glFinish();
01083                         if(printDebug)
01084                         {
01085                             t7=getms();
01086                             cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src render = " << ((t7-t6)/1000.0) << endl;
01087                         };
01088                     }
01089                 }
01090             }
01091 
01092             glFinish();
01093             if(printDebug)
01094                 t9=getms();
01095 
01096             // Render dest image
01097             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, accumFB);
01098             glUseProgramObjectARB(interpolatorProgramObject);
01099 
01100             if (pass == 0) {
01101                 // Clear ping accum texture on first pass.
01102                 glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
01103                 glClear(GL_COLOR_BUFFER_BIT);
01104             }
01105 
01106             glUniform2fARB(srcULParam, sI->left(), sI->top());
01107             CHECK_GL();
01108             glUniform2fARB(srcLRParam, sI->right(), sI->bottom());
01109             CHECK_GL();
01110 
01111             glActiveTexture(GL_TEXTURE0);
01112             glBindTexture(GL_TEXTURE_RECTANGLE_ARB, coordTexture);
01113             glUniform1iARB(coordTextureParam, 0);
01114             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01115             CHECK_GL();
01116 
01117             glActiveTexture(GL_TEXTURE1);
01118             glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
01119             glUniform1iARB(srcTextureParam, 1);
01120             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01121             CHECK_GL();
01122 
01123             glActiveTexture(GL_TEXTURE2);
01124             glUniform1iARB(accumTextureParam, 2);
01125             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01126             CHECK_GL();
01127 
01128             // Multipass interpolation.
01129             for (vector<Rect2D>::iterator iI = interpolatorChunks.begin(); iI != interpolatorChunks.end(); ++iI, ++pass) {
01130                 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, (pass & 1) ? accumTextures[0] : accumTextures[1]);
01131                 CHECK_GL();
01132 
01133                 glUniform2fARB(kernelULParam, iI->left(), iI->top());
01134                 CHECK_GL();
01135                 glUniform2fARB(kernelWHParam, iI->width(), iI->height());
01136                 CHECK_GL();
01137 
01138                 glDrawBuffer((pass & 1) ? GL_COLOR_ATTACHMENT1_EXT : GL_COLOR_ATTACHMENT0_EXT);
01139 
01140                 glFinish();
01141                 if(printDebug)
01142                 {
01143                     t10=getms();
01144                     cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " interpolation chunk=" << *iI << " setup = " << ((t10-t9)/1000.0) << endl;
01145                 };
01146 
01147                 glPolygonMode(GL_FRONT, GL_FILL);
01148                 glBegin(GL_QUADS);
01149                     glTexCoord2f(0.0,         0.0);           glVertex2f(0.0,         0.0);
01150                     glTexCoord2f(dI->width(), 0.0);           glVertex2f(dI->width(), 0.0);
01151                     glTexCoord2f(dI->width(), dI->height());  glVertex2f(dI->width(), dI->height());
01152                     glTexCoord2f(0.0,         dI->height());  glVertex2f(0.0,         dI->height());
01153                 glEnd();
01154                 CHECK_GL();
01155 
01156                 glFinish();
01157                 if(printDebug)
01158                 {
01159                     t11=getms();
01160                     t9=getms();
01161                     cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " interpolation chunk=" << *iI << " render = " << ((t11-t10)/1000.0) << endl;
01162                 };
01163 
01164             } // next interpolation chunk
01165 
01166         } // next source chunk
01167 
01168         // normalization/photometric rendering pass
01169         glUseProgramObjectARB(normalizationPhotometricProgramObject);
01170 
01171         glActiveTexture(GL_TEXTURE0);
01172         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, (pass & 1) ? accumTextures[0] : accumTextures[1]);
01173         glUniform1iARB(normTextureParam, 0);
01174         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01175         CHECK_GL();
01176 
01177         glActiveTexture(GL_TEXTURE1);
01178         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, coordTexture);
01179         glUniform1iARB(normCoordTextureParam, 1);
01180         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01181         CHECK_GL();
01182 
01183         if (!invLut.empty()) {
01184             glActiveTexture(GL_TEXTURE2);
01185             glBindTexture(GL_TEXTURE_RECTANGLE_ARB, invLutTexture);
01186             glUniform1iARB(invLutTextureParam, 2);
01187             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01188             CHECK_GL();
01189         }
01190 
01191         if (!destLut.empty()) {
01192             glActiveTexture(GL_TEXTURE3);
01193             glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destLutTexture);
01194             glUniform1iARB(destLutTextureParam, 3);
01195             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01196             CHECK_GL();
01197         }
01198 
01199         glDrawBuffer((pass & 1) ? GL_COLOR_ATTACHMENT1_EXT : GL_COLOR_ATTACHMENT0_EXT);
01200         
01201         glFinish();
01202         if(printDebug)
01203         {
01204             t12=getms();
01205             cout << "gpu dest chunk=" << *dI << " normalization setup = " << ((t12-t11)/1000.0) << endl;
01206         };
01207 
01208         glPolygonMode(GL_FRONT, GL_FILL);
01209         glBegin(GL_QUADS);
01210             glTexCoord2f(0.0,         0.0);           glVertex2f(0.0,         0.0);
01211             glTexCoord2f(dI->width(), 0.0);           glVertex2f(dI->width(), 0.0);
01212             glTexCoord2f(dI->width(), dI->height());  glVertex2f(dI->width(), dI->height());
01213             glTexCoord2f(0.0,         dI->height());  glVertex2f(0.0,         dI->height());
01214         glEnd();
01215         CHECK_GL();
01216 
01217         glFinish();
01218         if(printDebug)
01219         {
01220             t13=getms();
01221             cout << "gpu dest chunk=" << *dI << " normalization render = " << ((t13-t12)/1000.0) << endl;
01222         };
01223 
01224         pass++;
01225 
01226 
01227         // Readback dest chunk
01228         glPixelStorei(GL_PACK_ROW_LENGTH, destSize.x);
01229         glPixelStorei(GL_PACK_SKIP_PIXELS, dI->left());
01230         glPixelStorei(GL_PACK_SKIP_ROWS, dI->top());
01231 
01232         if (XGLMap[destGLTransferFormat] == GL_RGBA32F_ARB) {
01233             // Transfer to destBuffer directly from last-written accum texture.
01234             glReadBuffer((pass & 1) ? GL_COLOR_ATTACHMENT0_EXT : GL_COLOR_ATTACHMENT1_EXT);
01235 
01236             glReadPixels(0, 0, dI->width(), dI->height(), XGLMap[destGLFormat], XGLMap[destGLType], destBuffer);
01237             CHECK_GL();
01238 
01239             glFinish();
01240             if(printDebug)
01241             {
01242                 t14=getms();
01243                 cout << "gpu dest chunk=" << *dI << " rgb readback = " << ((t14-t13)/1000.0) << endl;
01244             };
01245         }
01246         else {
01247             // Move output accumTexture to dest texture then readback.
01248             glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
01249             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, destFB);
01250             glUseProgramObjectARB(0);
01251 
01252             glActiveTexture(GL_TEXTURE0);
01253             glEnable(GL_TEXTURE_RECTANGLE_ARB);
01254             glBindTexture(GL_TEXTURE_RECTANGLE_ARB, (pass & 1) ? accumTextures[0] : accumTextures[1]);
01255             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01256             CHECK_GL();
01257 
01258             glFinish();
01259             if(printDebug)
01260             {
01261                 t14=getms();
01262                 cout << "gpu dest chunk=" << *dI << " dest rgb disassembly setup = " << ((t14-t13)/1000.0) << endl;
01263             };
01264 
01265             glPolygonMode(GL_FRONT, GL_FILL);
01266             glBegin(GL_QUADS);
01267                 glTexCoord2f(0.0,         0.0);           glVertex2f(0.0,         0.0);
01268                 glTexCoord2f(dI->width(), 0.0);           glVertex2f(dI->width(), 0.0);
01269                 glTexCoord2f(dI->width(), dI->height());  glVertex2f(dI->width(), dI->height());
01270                 glTexCoord2f(0.0,         dI->height());  glVertex2f(0.0,         dI->height());
01271             glEnd();
01272             CHECK_GL();
01273 
01274             glActiveTexture(GL_TEXTURE0);
01275             glDisable(GL_TEXTURE_RECTANGLE_ARB);
01276             CHECK_GL();
01277 
01278             glFinish();
01279             if(printDebug)
01280             {
01281                 t15=getms();
01282                 cout << "gpu dest chunk=" << *dI << " dest rgb disassembly render = " << ((t15-t14)/1000.0) << endl;
01283             };
01284 
01285             glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
01286             CHECK_GL();
01287 
01288             glReadPixels(0, 0, dI->width(), dI->height(), XGLMap[destGLFormat], XGLMap[destGLType], destBuffer);
01289             CHECK_GL();
01290 
01291             glFinish();
01292             if(printDebug)
01293             {
01294                 t16=getms();
01295                 cout << "gpu dest chunk=" << *dI << " rgb readback = " << ((t16-t15)/1000.0) << endl;
01296             };
01297         }
01298 
01299         if (destAlphaBuffer != NULL) {
01300             // Move output accumTexture to dest alpha texture
01301             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, destAlphaFB);
01302             glUseProgramObjectARB(0);
01303 
01304             glActiveTexture(GL_TEXTURE0);
01305             glEnable(GL_TEXTURE_RECTANGLE_ARB);
01306             glBindTexture(GL_TEXTURE_RECTANGLE_ARB, (pass & 1) ? accumTextures[0] : accumTextures[1]);
01307             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01308             CHECK_GL();
01309 
01310             glFinish();
01311             if(printDebug)
01312             {
01313                 t17=getms();
01314                 cout << "gpu dest chunk=" << *dI << " dest alpha disassembly setup = " << ((t17-t16)/1000.0) << endl;
01315             };
01316 
01317             glPolygonMode(GL_FRONT, GL_FILL);
01318             glBegin(GL_QUADS);
01319                 glTexCoord2f(0.0,         0.0);           glVertex2f(0.0,         0.0);
01320                 glTexCoord2f(dI->width(), 0.0);           glVertex2f(dI->width(), 0.0);
01321                 glTexCoord2f(dI->width(), dI->height());  glVertex2f(dI->width(), dI->height());
01322                 glTexCoord2f(0.0,         dI->height());  glVertex2f(0.0,         dI->height());
01323             glEnd();
01324             CHECK_GL();
01325 
01326             glActiveTexture(GL_TEXTURE0);
01327             glDisable(GL_TEXTURE_RECTANGLE_ARB);
01328             CHECK_GL();
01329 
01330             glFinish();
01331             if(printDebug)
01332             {
01333                 t18=getms();
01334                 cout << "gpu dest chunk=" << *dI << " dest alpha disassembly render = " << ((t18-t17)/1000.0) << endl;
01335             };
01336 
01337             // Readback dest alpha chunk
01338             glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
01339             CHECK_GL();
01340 
01341             glReadPixels(0, 0, dI->width(), dI->height(), GL_ALPHA, XGLMap[destAlphaGLType], destAlphaBuffer);
01342             CHECK_GL();
01343 
01344             glFinish();
01345             if(printDebug)
01346             {
01347                 t19=getms();
01348                 cout << "gpu dest chunk=" << *dI << " alpha readback = " << ((t19-t18)/1000.0) << endl;
01349             };
01350         }
01351 
01352     } // next dest chunk
01353 
01354     glFinish();
01355     if(printDebug)
01356         t19=getms();
01357 
01358     glDeleteTextures(2, accumTextures);
01359     glDeleteTextures(1, &coordTexture);
01360     glDeleteTextures(1, &srcTexture);
01361     glDeleteTextures(1, &srcAlphaTexture);
01362     glDeleteTextures(1, &srcTransferTexture);
01363     glDeleteTextures(1, &destTexture);
01364     glDeleteTextures(1, &destAlphaTexture);
01365 
01366     if (!invLut.empty()) {
01367         glDeleteTextures(1, &invLutTexture);
01368         delete [] invLutTextureData;
01369     }
01370 
01371     if (!destLut.empty()) {
01372         glDeleteTextures(1, &destLutTexture);
01373         delete [] destLutTextureData;
01374     }
01375 
01376     glDeleteFramebuffersEXT(5, framebuffers);
01377 
01378     glUseProgramObjectARB(0);
01379     glDeleteObjectARB(coordXformShaderObject);
01380     glDeleteObjectARB(coordXformProgramObject);
01381     glDeleteObjectARB(interpolatorShaderObject);
01382     glDeleteObjectARB(interpolatorProgramObject);
01383     glDeleteObjectARB(normalizationPhotometricShaderObject);
01384     glDeleteObjectARB(normalizationPhotometricProgramObject);
01385 
01386     glFinish();
01387     if(printDebug)
01388     {
01389         long t20=getms();
01390         cout << "gpu destruct time = " << ((t20-t19)/1000.0) << endl;
01391         cout << "gpu total time = " << ((t20-t1)/1000.0) << endl;
01392     };
01393 
01394     return true;
01395 }
01396 
01397 }; // namespace

Generated on 25 Sep 2016 for Hugintrunk by  doxygen 1.4.7