ImageTransformsGPU.cpp

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

Generated on 28 Aug 2015 for Hugintrunk by  doxygen 1.4.7