ImageTransformsGPU.cpp

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

Generated on 27 Jun 2017 for Hugintrunk by  doxygen 1.4.7