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

Generated on Wed Jul 16 01:25:39 2014 for Hugintrunk by  doxygen 1.3.9.1