Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImageTransformsGPU.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
26 #include <iostream>
27 #include <iomanip>
28 
29 #include "hugin_config.h"
30 #if defined HAVE_EPOXY && HAVE_EPOXY
31 #ifdef _WIN32
32 #define NOMINMAX
33 #include <windows.h>
34 #endif
35 #include <epoxy/gl.h>
36 #ifdef __APPLE__
37 #include <OpenGL/glu.h>
38 #include <GLUT/glut.h>
39 #else
40 #include <GL/glu.h>
41 #endif
42 #else
43 #include <GL/glew.h>
44 #endif
45 
46 #include <string.h>
47 #ifdef _WIN32
48 // weird errors in accessor.hxx if DIFFERENCE is defined
49  #undef DIFFERENCE
50 #endif
51 #include <vigra/diff2d.hxx>
52 #include <vigra/utilities.hxx>
53 #include <vigra/error.hxx>
55 
56 #ifdef _WIN32
57 #include <windows.h>
58 long getms()
59 {
60  return GetTickCount();
61 };
62 #else
63 #include <sys/time.h>
64 long getms()
65 {
66  struct timeval tv;
67  gettimeofday(&tv,NULL);
68  return (long)(tv.tv_sec*1000+(tv.tv_usec/1000));
69 };
70 #endif
71 #include <time.h>
72 
73 #include <vector>
74 
75 using std::cout;
76 using std::cerr;
77 using std::endl;
78 using std::vector;
79 
80 using vigra::Rect2D;
81 
82 #define ___NCFILE___ ((char *) __FILE__)
83 #define CHECK_GL() checkGLErrors(__LINE__, ___NCFILE___)
84 
85 
86 static GLenum XGLMap[] = {
87  // gltypes
88  GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT,
89  // Internalformats
90  GL_RGBA8, GL_RGBA16, GL_RGBA32F_ARB, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA32F_ARB,
91  GL_RGB8, GL_RGB16, GL_RGB32F_ARB, GL_LUMINANCE8, GL_LUMINANCE16, GL_LUMINANCE32F_ARB,
92  // formats
93  GL_LUMINANCE, GL_RGB, GL_LUMINANCE_ALPHA, GL_RGBA
94 };
95 
96 static const char* XGLStringMap[] = {
97  // gltypes
98  "GL_BYTE", "GL_UNSIGNED_BYTE", "GL_SHORT", "GL_UNSIGNED_SHORT", "GL_INT", "GL_UNSIGNED_INT", "GL_FLOAT",
99  // Internalformats
100  "GL_RGBA8", "GL_RGBA16", "GL_RGBA32F_ARB", "GL_LUMINANCE8_ALPHA8", "GL_LUMINANCE16_ALPHA16", "GL_LUMINANCE_ALPHA32F_ARB",
101  "GL_RGB8", "GL_RGB16", "GL_RGB32F_ARB", "GL_LUMINANCE8", "GL_LUMINANCE16", "GL_LUMINANCE32F_ARB",
102  // formats
103  "GL_LUMINANCE", "GL_RGB", "GL_LUMINANCE_ALPHA", "GL_RGBA"
104 };
105 
106 static int BytesPerPixel[] = {
107  1, 1, 2, 2, 4, 4, 4,
108  4, 8, 16, 2, 4, 8,
109  3, 6, 12, 1, 2, 4,
110  0, 0, 0, 0
111 };
112 
113 static const char* AlphaCompositeKernelSource = {
114 "#version 110\n"
115 "#extension GL_ARB_texture_rectangle : enable\n"
116 "uniform sampler2DRect SrcAlphaTexture;\n"
117 "void main(void)\n"
118 "{\n"
119 " float alpha = texture2DRect(SrcAlphaTexture, gl_TexCoord[0].st).a;\n"
120 " if (alpha != 0.0) discard;\n"
121 " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
122 "}\n"
123 };
124 
125 static void checkGLErrors(int line, char* file) {
126  GLenum errCode = glGetError();
127  if (errCode != GL_NO_ERROR)
128  {
129  while (errCode != GL_NO_ERROR)
130  {
131  const GLubyte* message = gluErrorString(errCode);
132  std::cerr << "nona: GL error in " << file << ":" << line << std::endl;
133  if (message)
134  {
135 #ifdef _WIN32
136  const char* messageChar = reinterpret_cast<const char*>(message);
137  size_t size = strlen(messageChar);
138  LPSTR OEMmessageBuffer = (LPSTR)LocalAlloc(LPTR, (size + 1)*sizeof(char));
139  if (OEMmessageBuffer)
140  {
141  if (CharToOemBuff(messageChar, OEMmessageBuffer, size))
142  {
143  std::cerr << OEMmessageBuffer << " (0x" << std::hex << errCode << ")" << std::endl;
144  }
145  else
146  {
147  std::cerr << message << " (0x" << std::hex << errCode << ")" << std::endl;
148  };
149  }
150  else
151  {
152  std::cerr << message << " (0x" << std::hex << errCode << ")" << std::endl;
153  };
154  LocalFree(OEMmessageBuffer);
155 #else
156  std::cerr << message << " (0x" << std::hex << errCode << ")" << std::endl;
157 #endif
158  }
159  else
160  {
161  std::cerr << "Error code: 0x" << std::hex << errCode << std::endl;
162  }
163  errCode = glGetError();
164  };
165  exit(1);
166  }
167 }
168 
169 static void printInfoLog(GLhandleARB obj) {
170  GLint infologLength = 0;
171  GLint charsWritten = 0;
172  glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
173  if (infologLength > 1) {
174  char* infoLog = new char[infologLength];
175  glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
176  cout << "nona: GL info log:" << endl << infoLog << endl << endl;
177  delete[] infoLog;
178  }
179 }
180 
181 static bool printDebug=false;
182 
183 static bool checkFramebufferStatus(int line, char* file) {
184  GLenum status;
185  status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
186  switch(status) {
187  case GL_FRAMEBUFFER_COMPLETE_EXT:
188  return true;
189  case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
190  cerr << "nona: GL error: Framebuffer incomplete, incomplete attachment in: " << file << ":" << line << endl;
191  return false;
192  case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
193  cerr << "nona: Unsupported framebuffer format in: " << file << ":" << line << endl;
194  return false;
195  case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
196  cerr << "nona: Framebuffer incomplete, missing attachment in: " << file << ":" << line << endl;
197  return false;
198  case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
199  cerr << "nona: Framebuffer incomplete, attached images must have same dimensions in: " << file << ":" << line << endl;
200  return false;
201  case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
202  cerr << "nona: Framebuffer incomplete, attached images must have same format in: " << file << ":" << line << endl;
203  return false;
204  case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
205  cerr << "nona: Framebuffer incomplete, missing draw buffer in: " << file << ":" << line << endl;
206  return false;
207  case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
208  cerr << "nona: Framebuffer incomplete, missing read buffer in: " << file << ":" << line << endl;
209  return false;
210  }
211 
212  return false;
213 }
214 
215 static void compileGLSL(const char* programName,
216  GLhandleARB& programObject,
217  GLhandleARB& shaderObject,
218  const char** source)
219 {
220  GLint success;
221 
222  programObject = glCreateProgramObjectARB();
223  shaderObject = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
224 
225  glShaderSourceARB(shaderObject, 1, source, NULL);
226  glCompileShaderARB(shaderObject);
227 
228  glGetObjectParameterivARB(shaderObject, GL_OBJECT_COMPILE_STATUS_ARB, &success);
229  if (!success) {
230  cerr << "nona: " << programName << " shader program could not be compiled." << endl;
231  printInfoLog(shaderObject);
232  exit(1);
233  }
234 
235  if(printDebug)
236  printInfoLog(shaderObject);
237 
238  glAttachObjectARB(programObject, shaderObject);
239  glLinkProgramARB(programObject);
240 
241  glGetObjectParameterivARB(programObject, GL_OBJECT_LINK_STATUS_ARB, &success);
242  if (!success) {
243  cerr << "nona: " << programName << " shader program could not be linked." << endl;
244  printInfoLog(programObject);
245  exit(1);
246  }
247 
248  if(printDebug)
249  printInfoLog(programObject);
250 }
251 
252 static void makeChunks(const int width,
253  const int height,
254  const int maxTextureSize,
255  const long long int maxPixels,
256  vector<Rect2D>& result)
257 {
258  int numXChunks = 1;
259  int numYChunks = 1;
260 
261  // Make chunks small enough to fit into maxTextureSize
262  while (ceil(static_cast<double>(width) / numXChunks) > maxTextureSize) numXChunks++;
263  while (ceil(static_cast<double>(height) / numYChunks) > maxTextureSize) numYChunks++;
264 
265  // Make chunks small enough to fit into maxPixels limit
266  while ((ceil(static_cast<double>(width) / numXChunks) * ceil(static_cast<double>(height) / numYChunks))
267  > maxPixels) {
268 
269  if (ceil(static_cast<double>(width) / numXChunks) > ceil(static_cast<double>(height) / numYChunks)) {
270  ++numXChunks;
271  } else {
272  ++numYChunks;
273  }
274  }
275 
276  // Make chunks small enough to fit in GL_PROXY_TEXTURE_2D of the biggest internalformat type.
277  while (1) {
278  glTexImage2D(GL_PROXY_TEXTURE_2D,
279  0,
280  GL_RGBA32F_ARB,
281  static_cast<int>(ceil(static_cast<double>(width) / numXChunks)),
282  static_cast<int>(ceil(static_cast<double>(height) / numYChunks)),
283  0,
284  GL_RGBA,
285  GL_FLOAT,
286  NULL);
287  GLint returnedWidth;
288  glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &returnedWidth);
289 
290  if (returnedWidth != 0) break;
291 
292  if (ceil(static_cast<double>(width) / numXChunks) > ceil(static_cast<double>(height) / numYChunks)) {
293  ++numXChunks;
294  } else {
295  ++numYChunks;
296  }
297  }
298 
299  for (int yChunk = 0, y = 0; yChunk < numYChunks; yChunk++) {
300  int yEnd = std::min<int>(height, static_cast<int>(ceil(static_cast<double>(height) / numYChunks)) + y);
301  for (int xChunk = 0, x = 0; xChunk < numXChunks; xChunk++) {
302  int xEnd = std::min<int>(width, static_cast<int>(ceil(static_cast<double>(width) / numXChunks)) + x);
303  result.push_back(Rect2D(x, y, xEnd, yEnd));
304  x = xEnd;
305  }
306  y = yEnd;
307  }
308 }
309 
310 
311 namespace vigra_ext
312 {
313 
314 void SetGPUDebugMessages(const bool doPrint)
315 {
316  printDebug=doPrint;
317 };
318 
319 bool transformImageGPUIntern(const std::string& coordXformGLSL,
320  const std::string& interpolatorGLSL,
321  const int interpolatorSize,
322  const std::string& photometricGLSL,
323  const vector<double>& invLut,
324  const vector<double>& destLut,
325  const vigra::Diff2D srcSize,
326  const void* const srcBuffer,
327  const int srcGLInternalFormat, const int srcGLTransferFormat, const int srcGLFormat, const int srcGLType,
328  const void* const srcAlphaBuffer,
329  const int srcAlphaGLType,
330  const vigra::Diff2D destUL,
331  const vigra::Diff2D destSize,
332  void* const destBuffer,
333  const int destGLInternalFormat, const int destGLTransferFormat, const int destGLFormat, const int destGLType,
334  void* const destAlphaBuffer,
335  const int destAlphaGLType,
336  const bool warparound)
337 {
338  long t1, t3, t5, t6, t7, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t21;
339 
340  const int xstart = destUL.x;
341  const int xend = destUL.x + destSize.x;
342  const int ystart = destUL.y;
343  const int yend = destUL.y + destSize.y;
344 
345  if(printDebug)
346  {
347  t1=getms();
348  cout << "destStart=[" << xstart << ", " << ystart << "]" << endl
349  << "destEnd=[" << xend << ", " << yend << "]" << endl
350  << "destSize=[" << destSize << "]" << endl
351  << "srcSize=[" << srcSize << "]" << endl
352  << "srcBuffer=" << srcBuffer << endl
353  << "srcAlphaBuffer=" << srcAlphaBuffer << endl
354  << "destBuffer=" << destBuffer << endl
355  << "destAlphaBuffer=" << destAlphaBuffer << endl
356  << "destGLInternalFormat=" << XGLStringMap[destGLInternalFormat] << endl
357  << "destGLFormat=" << XGLStringMap[destGLFormat] << endl
358  << "destGLType=" << XGLStringMap[destGLType] << endl
359  << "srcGLInternalFormat=" << XGLStringMap[srcGLInternalFormat] << endl
360  << "srcGLFormat=" << XGLStringMap[srcGLFormat] << endl
361  << "srcGLType=" << XGLStringMap[srcGLType] << endl
362  << "srcAlphaGLType=" << XGLStringMap[srcAlphaGLType] << endl
363  << "destAlphaGLType=" << XGLStringMap[destAlphaGLType] << endl
364  << endl
365  << "warparound=" << warparound << endl;
366  };
367 
368  vigra_precondition((srcSize.x % 8) == 0, "src image width not a multiple of 8");
369  vigra_precondition((destSize.x % 8) == 0, "dest image width not a multiple of 8");
370 
371  vigra_precondition((reinterpret_cast<const uintptr_t>(srcBuffer) & 0x7) == 0, "src image buffer not 8-byte aligned");
372  vigra_precondition((reinterpret_cast<const uintptr_t>(srcAlphaBuffer) & 0x7) == 0, "src alpha image buffer not 8-byte aligned");
373  vigra_precondition((reinterpret_cast<const uintptr_t>(destBuffer) & 0x7) == 0, "dest image buffer not 8-byte aligned");
374  vigra_precondition((reinterpret_cast<const uintptr_t>(destAlphaBuffer) & 0x7) == 0, "dest alpha image buffer not 8-byte aligned");
375 
376  const char* const gpuVendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
377  const bool needsAtanWorkaround = (strncmp(gpuVendor, "ATI", 3) == 0);
378 
379  if(printDebug)
380  cout << "needsAtanWorkaround=" << needsAtanWorkaround << endl;
381 
382  GLint maxTextureSize;
383  // check maximum possible texture size, GL_MAX_RECTANGLE_TEXTURE_SIZE is only available in OpenGL 3.1 and later
384  glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxTextureSize);
385  if (printDebug)
386  {
387  cout << "Retrieving GL_MAX_RECTANGLE_TEXTURE_SIZE: " << maxTextureSize << std::endl;
388  };
389  if (glGetError() != GL_NO_ERROR || maxTextureSize < 1024)
390  {
391  // fall back to GL_MAX_TEXTURE_SIZE
392  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
393  if (printDebug)
394  {
395  cout << "Retrieving GL_MAX_TEXTURE_SIZE: " << maxTextureSize << std::endl;
396  };
397  };
398  // both functions can return only a rough estimate, so do some more test
399  // if graphic card can handle this size of textures
400  {
401  GLint textureWidth=0;
402  while (textureWidth < maxTextureSize)
403  {
404  glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA32F_ARB, maxTextureSize, maxTextureSize, 0, GL_RGBA, GL_FLOAT, NULL);
405  glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &textureWidth);
406  if (printDebug)
407  {
408  cout << "Testing texture size " << maxTextureSize << ", result=" << textureWidth << std::endl;
409  };
410  if (textureWidth != maxTextureSize)
411  {
412  maxTextureSize /= 2;
413  };
414  if (maxTextureSize < 1024)
415  {
416  cerr << "nona: Can't allocate texture with a size of at least 1024 pixels." << std::endl;;
417  exit(1);
418  };
419  };
420  };
421  if(printDebug)
422  cout << "maxTextureSize=" << maxTextureSize << endl;
423 
424  // Artificial limit: binding big textures to fbos seems to be very slow.
425  //maxTextureSize = 2048;
426 
427  long long int GpuMemoryInBytes = 512 << 20;
428  // read memory size, not implemented on all graphic cards
429  {
430  // for nvidia cards
431 #define GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX 0x9048
432  GLint total_mem_kb = 0;
433  glGetIntegerv(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX, &total_mem_kb);
434  if (glGetError() == GL_NO_ERROR)
435  {
436  GpuMemoryInBytes = total_mem_kb * 1024ll;
437  };
438  };
439  {
440  //for amd/ati cards
441 #define TEXTURE_FREE_MEMORY_ATI 0x87FC
442  GLint param[4];
443  glGetIntegerv(TEXTURE_FREE_MEMORY_ATI, param);
444  if (glGetError() == GL_NO_ERROR)
445  {
446  GpuMemoryInBytes = param[0] * 1024ll;
447  };
448  }
449  const double SourceAllocationRatio = 0.7;
450 
451  const int bytesPerSourcePixel = BytesPerPixel[srcGLInternalFormat]
452  + ((srcGLInternalFormat != srcGLTransferFormat) ? BytesPerPixel[srcGLTransferFormat] : 0)
453  + ((srcAlphaBuffer != NULL) ? 1 : 0);
454  const long long int maxSourcePixels = static_cast<long long int>(GpuMemoryInBytes * SourceAllocationRatio) / bytesPerSourcePixel;
455 
456  vector<Rect2D> sourceChunks;
457  makeChunks(srcSize.x, srcSize.y, maxTextureSize, maxSourcePixels, sourceChunks);
458 
459  const long long int actualSourcePixels = sourceChunks[0].area();
460  const long long int gpuMemoryRemaining = GpuMemoryInBytes - (actualSourcePixels * bytesPerSourcePixel);
461 
462  // 16 bytes/pixel * 2 dest images for ping/pong multipass rendering
463  // 8 bytes/pixel for coordinate texture
464  // destXfer + GL_ALPHA
465  const int bytesPerDestPixel = 16 + 16 + 8
466  + ((XGLMap[destGLTransferFormat] != GL_RGBA32F_ARB) ? BytesPerPixel[destGLTransferFormat] : 0)
467  + ((destAlphaBuffer != NULL) ? 1 : 0);
468  const long long int maxDestPixels = gpuMemoryRemaining / bytesPerDestPixel;
469 
470  vector<Rect2D> destChunks;
471  makeChunks(destSize.x, destSize.y, maxTextureSize, maxDestPixels, destChunks);
472 
473  const long long int totalGpuMemoryUsed = (sourceChunks[0].area() * bytesPerSourcePixel) + (destChunks[0].area() * bytesPerDestPixel);
474  vigra_assert(totalGpuMemoryUsed <= GpuMemoryInBytes,
475  "failed to subdivide source and dest images into pieces small enough to fit in gpu memory.");
476 
477  if(printDebug)
478  {
479  cout << "Source chunks:" << endl;
480  for (vector<Rect2D>::iterator rI = sourceChunks.begin(); rI != sourceChunks.end(); ++rI) {
481  cout << " " << *rI << endl;
482  }
483  cout << "Dest chunks:" << endl;
484  for (vector<Rect2D>::iterator rI = destChunks.begin(); rI != destChunks.end(); ++rI) {
485  cout << " " << *rI << endl;
486  }
487  cout << "Total GPU memory used: " << totalGpuMemoryUsed << endl;
488  };
489 
490 
491  const int TextureFetchesPerInterpolatorPass = 16;
492  vector<Rect2D> interpolatorChunks;
493  makeChunks(interpolatorSize, interpolatorSize, TextureFetchesPerInterpolatorPass, TextureFetchesPerInterpolatorPass, interpolatorChunks);
494  if(printDebug)
495  {
496  cout << "Interpolator chunks:" << endl;
497  for (vector<Rect2D>::iterator rI = interpolatorChunks.begin(); rI != interpolatorChunks.end(); ++rI) {
498  cout << " " << *rI << endl;
499  }
500  };
501  bool allInterpolatorChunksAreEqual = true;
502  const Rect2D& firstInterpolatorChunk = interpolatorChunks.front();
503  for (vector<Rect2D>::iterator rI = ++(interpolatorChunks.begin()); rI != interpolatorChunks.end(); ++rI) {
504  if (rI->width() != firstInterpolatorChunk.width()
505  || rI->height() != firstInterpolatorChunk.height()) {
506  allInterpolatorChunksAreEqual = false;
507  break;
508  }
509  }
510 
511 
512  // Prepare coord transform GLSL program
513  std::ostringstream oss;
514  oss << std::setprecision(20) << std::showpoint;
515  oss << "#version 110" << endl
516  << "#extension GL_ARB_texture_rectangle : enable" << endl
517  << "uniform sampler2DRect SrcTexture;" << endl
518  << "float sinh(in float x) { return (exp(x) - exp(-x)) / 2.0; }" << endl
519  << "float cosh(in float x) { return (exp(x) + exp(-x)) / 2.0; }" << endl;
520  // TODO: OpenGL Shader vers. 1.5 has built-in sinh and cosh function,
521  // need to check is this functions are available and compile only when
522  // this functions are not available
523 
524  if (needsAtanWorkaround) {
525  oss << "float atan2_xge0(const in float y, const in float x) {" << endl
526  << " if (abs(y) > x) {" << endl
527  << " return sign(y) * (" << (M_PI/2.0) << " - atan(x, abs(y)));" << endl
528  << " } else {" << endl
529  << " return atan(y, x);" << endl
530  << " }" << endl
531  << "}" << endl
532  << "float atan2_safe(const in float y, const in float x) {" << endl
533  << " if (x >= 0.0) return atan2_xge0(y, x);" << endl
534  << " else return (sign(y) * " << M_PI << ") - atan2_xge0(y, -x);" << endl
535  << "}" << endl
536  << "float atan_safe(const in float yx) {" << endl
537  << " if (abs(yx) > 1.0) {" << endl
538  << " return sign(yx) * (" << (M_PI/2.0) << " - atan(1.0/abs(yx)));" << endl
539  << " } else {" << endl
540  << " return atan(yx);" << endl
541  << " }" << endl
542  << "}" << endl;
543  } else {
544  oss << "float atan2_xge0(const in float y, const in float x) {" << endl
545  << " return atan(y, x);" << endl
546  << "}" << endl
547  << "float atan2_safe(const in float y, const in float x) {" << endl
548  << " return atan(y, x);" << endl
549  << "}" << endl
550  << "float atan_safe(const in float yx) {" << endl
551  << " return atan(yx);" << endl
552  << "}" << endl;
553  }
554 
555  oss << "void main(void)" << endl
556  << "{" << endl
557  << " float discardA = 1.0;" << endl
558  << " float discardB = 0.0;" << endl
559  << coordXformGLSL
560  << " src = src * discardA + vec2(-1000.0, -1000.0) * discardB;" << endl
561  << " gl_FragColor = vec4(src.s, 0.0, 0.0, src.t);" << endl
562  << "}" << endl;
563 
564  std::string coordXformKernelSourceString = oss.str();
565  const char* coordXformKernelSource = coordXformKernelSourceString.c_str();
566  if(printDebug)
567  cout << coordXformKernelSource;
568 
569  GLhandleARB coordXformProgramObject;
570  GLhandleARB coordXformShaderObject;
571  compileGLSL("coordinate transform",
572  coordXformProgramObject,
573  coordXformShaderObject,
574  &coordXformKernelSource);
575 
576 
577 
578  // Prepare alpha composite shader program.
579  // This is the same for all images so we just do it once.
580  static bool createdAlphaShader = false;
581  static GLhandleARB alphaCompositeProgramObject;
582  static GLhandleARB alphaCompositeShaderObject;
583  static GLint srcAlphaTextureParam;
584  if (!createdAlphaShader
585  && (srcGLInternalFormat == srcGLTransferFormat)
586  && (srcAlphaBuffer != NULL)) {
587 
588  compileGLSL("alpha composite",
589  alphaCompositeProgramObject,
590  alphaCompositeShaderObject,
592  srcAlphaTextureParam = glGetUniformLocationARB(alphaCompositeProgramObject, "SrcAlphaTexture");
593  createdAlphaShader = true;
594  }
595 
596 
597  // Prepare interpolation shader program.
598  oss.str("");
599  oss << std::setprecision(20) << std::showpoint;
600  oss << "#version 110" << endl
601  << "#extension GL_ARB_texture_rectangle : enable" << endl
602  << "uniform sampler2DRect CoordTexture;" << endl
603  << "uniform sampler2DRect SrcTexture;" << endl
604  << "uniform sampler2DRect AccumTexture;" << endl
605  << "uniform vec2 SrcUL;" << endl
606  << "uniform vec2 SrcLR;" << endl
607  << "uniform vec2 KernelUL;" << endl
608  << "uniform vec2 KernelWH;" << endl
609  << "float w(const in float i, const in float f) {" << endl
610  << interpolatorGLSL
611  << "}" << endl
612  << "void main(void)" << endl
613  << "{" << endl
614  << " vec2 src = texture2DRect(CoordTexture, gl_TexCoord[0].st).sq;" << endl
615  << " vec4 accum = texture2DRect(AccumTexture, gl_TexCoord[0].st);" << endl
616  << endl;
617 
618  // Unexpectedly, this checking slows down the interpolator render passes by 3x-5x.
620  //oss << " if (any(lessThan(src, SrcUL - KernelLR + " << (interpolatorSize / 2.0) << "))) {" << endl
621  // << " gl_FragColor = accum;" << endl
622  // << " return;" << endl
623  // << " }" << endl
624  // << " if (any(greaterThanEqual(src, SrcLR - KernelUL + " << ((interpolatorSize / 2.0) - 1.0) << "))) {" << endl
625  // << " gl_FragColor = accum;" << endl
626  // << " return;" << endl
627  // << " }" << endl
628  // << endl;
629 
630  oss << " src -= SrcUL;" << endl
631  << " vec2 t = floor(src) + " << (1.5 - (interpolatorSize / 2)) << ";" << endl
632  << " vec2 f = fract(src);" << endl
633  << " vec2 k = vec2(0.0, 0.0);" << endl
634  << endl;
635 
636  // Interpolator loop
637  if (allInterpolatorChunksAreEqual) {
638  oss << " for (float ky = 0.0; ky < " << static_cast<double>(firstInterpolatorChunk.height()) << "; ky += 1.0) {" << endl;
639  } else {
640  oss << " for (float ky = 0.0; ky < KernelWH.t; ky += 1.0) {" << endl;
641  }
642 
643  oss << " k.t = ky + KernelUL.t;" << endl
644  << " float wy = w(k.t, f.t);" << endl;
645 
646  if (allInterpolatorChunksAreEqual) {
647  oss << " for (float kx = 0.0; kx < " << static_cast<double>(firstInterpolatorChunk.width()) << "; kx += 1.0) {" << endl;
648  } else {
649  oss << " for (float kx = 0.0; kx < KernelWH.s; kx += 1.0) {" << endl;
650  }
651 
652  // FIXME support warparound
653  oss << " k.s = kx + KernelUL.s;" << endl
654  << " float wx = w(k.s, f.s);" << endl
655  << " vec2 ix = t + k;" << endl
656  << " vec4 sp = texture2DRect(SrcTexture, ix);" << endl
657  << " float weight = wx * wy * sp.a;" << endl
658  << " accum += sp * weight;" << endl
659  << " }" << endl
660  << " }" << endl;
661 
663  //for (int ky = 0; ky < interpolatorSize; ++ky) {
664  // double bounded_ky_offset = 1.5 + ky - (interpolatorSize / 2);
665  // for (int kx = 0; kx < interpolatorSize; ++kx) {
666  // double bounded_kx_offset = 1.5 + kx - (interpolatorSize / 2);
667  // oss << " {" << endl
668  // << " // (" << kx << ", " << ky << ")" << endl
669  // << " vec2 ix = t + vec2(" << bounded_kx_offset << ", " << bounded_ky_offset << ");" << endl
670  // << " vec4 sp = texture2DRect(SrcTexture, ix);" << endl
671  // //<< " float weight = w[" << kx << "].s * w[" << ky << "].t * sp.a;" << endl
672  // << " float weight = w(" << (double)kx << ", f.s) * w(" << (double)ky << ", f.t) * sp.a;" << endl
673  // << " accum += sp * weight;" << endl
674  // << " }" << endl;
675  // }
676  //}
677 
678  oss << endl
679  << " gl_FragColor = accum;" << endl
680  << "}" << endl
681  << endl;
682 
683  std::string interpolatorKernelSourceString = oss.str();
684  const char* interpolatorKernelSource = interpolatorKernelSourceString.c_str();
685  if(printDebug)
686  cout << interpolatorKernelSource;
687 
688  GLhandleARB interpolatorProgramObject;
689  GLhandleARB interpolatorShaderObject;
690  compileGLSL("interpolator",
691  interpolatorProgramObject,
692  interpolatorShaderObject,
693  &interpolatorKernelSource);
694 
695  GLint coordTextureParam = glGetUniformLocationARB(interpolatorProgramObject, "CoordTexture");
696  GLint accumTextureParam = glGetUniformLocationARB(interpolatorProgramObject, "AccumTexture");
697  GLint srcTextureParam = glGetUniformLocationARB(interpolatorProgramObject, "SrcTexture");
698  GLint srcULParam = glGetUniformLocationARB(interpolatorProgramObject, "SrcUL");
699  GLint srcLRParam = glGetUniformLocationARB(interpolatorProgramObject, "SrcLR");
700  GLint kernelULParam = glGetUniformLocationARB(interpolatorProgramObject, "KernelUL");
701  GLint kernelWHParam = glGetUniformLocationARB(interpolatorProgramObject, "KernelWH");
702 
703 
704  // Prepare normalization/photometric shader program
705  oss.str("");
706  oss << std::setprecision(20) << std::showpoint;
707  oss << "#version 120" << endl
708  << "#extension GL_ARB_texture_rectangle : enable" << endl
709  << "uniform sampler2DRect NormTexture;" << endl
710  << "uniform sampler2DRect CoordTexture;" << endl;
711 
712  if (!invLut.empty()) {
713  oss << "uniform sampler2DRect InvLutTexture;" << endl;
714  }
715 
716  if (!destLut.empty()) {
717  oss << "uniform sampler2DRect DestLutTexture;" << endl;
718  }
719 
720  oss << "void main(void)" << endl
721  << "{" << endl
722  << " // Normalization" << endl
723  << " vec4 n = texture2DRect(NormTexture, gl_TexCoord[0].st);" << endl
724  << " vec4 p = vec4(0.0, 0.0, 0.0, 0.0);" << endl
725  << " if (n.a >= 0.2) p = n / n.a;" << endl
726  << endl
727  << " // Photometric" << endl
728  << photometricGLSL
729  << endl
730  << " gl_FragColor = p;" << endl
731  << "}" << endl
732  << endl;
733 
734  std::string normalizationPhotometricKernelSourceString = oss.str();
735  const char* normalizationPhotometricKernelSource = normalizationPhotometricKernelSourceString.c_str();
736  if(printDebug)
737  cout << normalizationPhotometricKernelSource;
738 
739  GLhandleARB normalizationPhotometricProgramObject;
740  GLhandleARB normalizationPhotometricShaderObject;
741  compileGLSL("normalization/photometric",
742  normalizationPhotometricProgramObject,
743  normalizationPhotometricShaderObject,
744  &normalizationPhotometricKernelSource);
745 
746  GLint normTextureParam = glGetUniformLocationARB(normalizationPhotometricProgramObject, "NormTexture");
747  GLint normCoordTextureParam = glGetUniformLocationARB(normalizationPhotometricProgramObject, "CoordTexture");
748 
749  float *invLutTextureData = NULL;
750  GLuint invLutTexture;
751  GLint invLutTextureParam;
752  if (!invLut.empty()) {
753  invLutTextureData = new float[invLut.size() * 2];
754  for (int i = 0; i < invLut.size(); ++i) {
755  invLutTextureData[2*i] = invLut[i];
756  invLutTextureData[2*i+1] = ((i + 1) < invLut.size()) ? invLut[i+1] : invLut[i];
757  }
758  invLutTextureParam = glGetUniformLocationARB(normalizationPhotometricProgramObject, "InvLutTexture");
759  glGenTextures(1, &invLutTexture);
760  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, invLutTexture);
761  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
762  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
763  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
764  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
765  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA32F_ARB, invLut.size(), 1, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, invLutTextureData);
766  CHECK_GL();
767  }
768 
769  float *destLutTextureData = NULL;
770  GLuint destLutTexture;
771  GLint destLutTextureParam;
772  if (!destLut.empty()) {
773  destLutTextureData = new float[destLut.size() * 2];
774  for (int i = 0; i < destLut.size(); ++i) {
775  destLutTextureData[2*i] = destLut[i];
776  destLutTextureData[2*i+1] = ((i + 1) < destLut.size()) ? destLut[i+1] : destLut[i];
777  }
778  destLutTextureParam = glGetUniformLocationARB(normalizationPhotometricProgramObject, "DestLutTexture");
779  glGenTextures(1, &destLutTexture);
780  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destLutTexture);
781  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
782  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
783  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
784  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
785  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA32F_ARB, destLut.size(), 1, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, destLutTextureData);
786  CHECK_GL();
787  }
788 
789  glFinish();
790  if(printDebug)
791  {
792  t21=getms();
793  cout << "gpu shader program compile time = " << ((t21 - t1)/1000.0) << endl;
794  };
795 
796  // General GL setup
797  glPixelStorei(GL_PACK_ALIGNMENT, 8);
798  glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
799 
800  const float borderColor[] = {0.0, 0.0, 0.0, 0.0};
801 
802  glClearColor(0.0, 0.0, 0.0, 0.0);
803 
804  GLuint framebuffers[5];
805  glGenFramebuffersEXT(5, framebuffers);
806  GLuint srcFB = framebuffers[0];
807  GLuint coordFB = framebuffers[1];
808  GLuint accumFB = framebuffers[2];
809  GLuint destFB = framebuffers[3];
810  GLuint destAlphaFB = framebuffers[4];
811 
812  const int viewportWidth = std::max<int>(destChunks[0].width(), sourceChunks[0].width());
813  const int viewportHeight = std::max<int>(destChunks[0].height(), sourceChunks[0].height());
814  glMatrixMode(GL_PROJECTION);
815  glLoadIdentity();
816  gluOrtho2D(0.0, viewportWidth, 0.0, viewportHeight);
817  glMatrixMode(GL_MODELVIEW);
818  glLoadIdentity();
819  glViewport(0, 0, viewportWidth, viewportHeight);
820 
821  const int destOdd = (destChunks[0].height() & 1);
822  // Setup coordinate texture
823  GLuint coordTexture;
824  glGenTextures(1, &coordTexture);
825  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, coordTexture);
826  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
827  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
828  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
829  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
830  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, destChunks[0].width(), destChunks[0].height() + destOdd, 0, GL_LUMINANCE_ALPHA, GL_FLOAT, NULL);
831  CHECK_GL();
832 
833  // Setup coordinate framebuffer
834  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, coordFB);
835  CHECK_GL();
836  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, coordTexture, 0);
837  CHECK_GL();
838  if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
839  exit(1);
840  }
841 
842  // Setup accumulator ping-pong textures
843  GLuint accumTextures[2];
844  glGenTextures(2, accumTextures);
845 
846  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, accumTextures[0]);
847  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
848  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
849  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
850  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
851  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, destChunks[0].width(), destChunks[0].height() + destOdd, 0, GL_RGBA, GL_FLOAT, NULL);
852  CHECK_GL();
853 
854  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, accumTextures[1]);
855  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
856  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
857  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
858  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
859  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, destChunks[0].width(), destChunks[0].height() + destOdd, 0, GL_RGBA, GL_FLOAT, NULL);
860  CHECK_GL();
861 
862  // Attach accumulator ping-pong textures to framebuffer
863  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, accumFB);
864  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, accumTextures[0], 0);
865  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, accumTextures[1], 0);
866  if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
867  exit(1);
868  }
869 
870  // Setup src texture
871  const int sourceOdd = (sourceChunks[0].height() & 1);
872  GLuint srcTexture;
873  glGenTextures(1, &srcTexture);
874  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
875  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
876  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
877  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
878  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
879  glTexParameterfv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BORDER_COLOR, borderColor);
880  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, XGLMap[srcGLInternalFormat], sourceChunks[0].width(), sourceChunks[0].height() + sourceOdd, 0, XGLMap[srcGLFormat], XGLMap[srcGLType], NULL);
881  CHECK_GL();
882 
883  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, srcFB);
884  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, srcTexture, 0);
885  if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
886  exit(1);
887  }
888 
889  // Setup alpha composite framebuffer
890  GLuint srcAlphaTexture;
891  if (srcAlphaBuffer != NULL) {
892  // If there is a separate alpha buffer given, prepare to composite the alpha data into srcTexture.
893  glGenTextures(1, &srcAlphaTexture);
894  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcAlphaTexture);
895  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
896  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
897  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
898  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
899  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA, sourceChunks[0].width(), sourceChunks[0].height() + sourceOdd, 0, GL_ALPHA, XGLMap[srcAlphaGLType], NULL);
900  CHECK_GL();
901  }
902 
903  GLuint srcTransferTexture;
904  if (srcGLInternalFormat != srcGLTransferFormat) {
905  // If the rgb data layout does not match the rgb internal texture format, prepare a separate texture
906  // for the rgb data for fast GPU I/O. Then composite into srcTexture.
907  glGenTextures(1, &srcTransferTexture);
908  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTransferTexture);
909  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
910  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
911  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
912  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
913  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, XGLMap[srcGLTransferFormat], sourceChunks[0].width(), sourceChunks[0].height() + sourceOdd, 0, XGLMap[srcGLFormat], XGLMap[srcGLType], NULL);
914  CHECK_GL();
915  }
916 
917  // Setup dest and destalpha textures and framebuffers
918  GLuint destTexture;
919  if (XGLMap[destGLTransferFormat] != GL_RGBA32F_ARB) {
920  // If the dest image rgb data layout does not match that of the accumulator textures,
921  // create a separate texture of the appropriate layout and prepare to copy the output accumulator
922  // texture to it. This is for fast GPU I/O.
923  glGenTextures(1, &destTexture);
924  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destTexture);
925  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
926  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
927  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
928  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
929  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, XGLMap[destGLInternalFormat], destChunks[0].width(), destChunks[0].height() + destOdd, 0, XGLMap[destGLFormat], XGLMap[destGLType], NULL);
930 
931  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, destFB);
932  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destTexture, 0);
933  if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
934  exit(1);
935  }
936  }
937 
938  GLuint destAlphaTexture;
939  if (destAlphaBuffer != NULL) {
940  // If a separate dest alpha buffer is provided, create a texture for transferring this data out.
941  // This is for fast GPU I/O.
942  glGenTextures(1, &destAlphaTexture);
943  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destAlphaTexture);
944  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
945  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
946  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
947  glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
948  glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, destChunks[0].width(), destChunks[0].height() + destOdd, 0, GL_ALPHA, XGLMap[destAlphaGLType], NULL);
949  CHECK_GL();
950 
951  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, destAlphaFB);
952  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, destAlphaTexture, 0);
953  if (!checkFramebufferStatus(__LINE__, ___NCFILE___)) {
954  exit(1);
955  }
956  }
957 
958 
959  glFinish();
960  if(printDebug)
961  {
962  cout << "gpu shader texture/framebuffer setup time = " << ((getms()-t21)/1000.0) << endl;
963  };
964 
965  // Render each dest chunk
966  int destChunkNumber = 0;
967  for (vector<Rect2D>::iterator dI = destChunks.begin(); dI != destChunks.end(); ++dI, ++destChunkNumber) {
968 
969  glFinish();
970  if(printDebug)
971  t3=getms();
972 
973  // Render coord image
974  glUseProgramObjectARB(coordXformProgramObject);
975  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, coordFB);
976  glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
977 
978  glPolygonMode(GL_FRONT, GL_FILL);
979  glBegin(GL_QUADS);
980  glTexCoord2f(xstart + dI->left(), ystart + dI->top()); glVertex2f(0.0, 0.0);
981  glTexCoord2f(xstart + dI->right(), ystart + dI->top()); glVertex2f(dI->width(), 0.0);
982  glTexCoord2f(xstart + dI->right(), ystart + dI->bottom()); glVertex2f(dI->width(), dI->height());
983  glTexCoord2f(xstart + dI->left(), ystart + dI->bottom()); glVertex2f(0.0, dI->height());
984  glEnd();
985  CHECK_GL();
986 
987  glFinish();
988  if(printDebug)
989  {
990  long t4=getms();
991  cout << "gpu dest chunk=" << *dI << " coord image render time = " << ((t4-t3)/1000.0) << endl;
992  };
993 
994  // Multipass rendering of dest image
995  int pass = 0;
996  for (vector<Rect2D>::iterator sI = sourceChunks.begin(); sI != sourceChunks.end(); ++sI) {
997 
998  if (destChunkNumber == 0 || sourceChunks.size() > 1) {
999  glFinish();
1000  if(printDebug)
1001  t5=getms();
1002 
1003  glPixelStorei(GL_UNPACK_ROW_LENGTH, srcSize.x);
1004  glPixelStorei(GL_UNPACK_SKIP_PIXELS, sI->left());
1005  glPixelStorei(GL_UNPACK_SKIP_ROWS, sI->top());
1006  CHECK_GL();
1007 
1008  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, srcFB);
1009  glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
1010  glClear(GL_COLOR_BUFFER_BIT);
1011 
1012  if (srcGLInternalFormat == srcGLTransferFormat) {
1013  // Upload directly to source texture.
1014  glActiveTexture(GL_TEXTURE0);
1015  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
1016  glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, sI->width(), sI->height(), XGLMap[srcGLFormat], XGLMap[srcGLType], srcBuffer);
1017  CHECK_GL();
1018 
1019  glFinish();
1020  if(printDebug)
1021  {
1022  t6=getms();
1023  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src upload = " << ((t6-t5)/1000.0) << endl;
1024  };
1025 
1026  if (srcAlphaBuffer != NULL) {
1027  // Upload to srcAlphaTexture and composite to srcTexture.
1028  glUseProgramObjectARB(alphaCompositeProgramObject);
1029 
1030  glActiveTexture(GL_TEXTURE0);
1031  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcAlphaTexture);
1032  glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, sI->width(), sI->height(), GL_ALPHA, XGLMap[srcAlphaGLType], srcAlphaBuffer);
1033  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1034  glUniform1iARB(srcAlphaTextureParam, 0);
1035  CHECK_GL();
1036 
1037  glFinish();
1038  if(printDebug)
1039  {
1040  t7=getms();
1041  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src alpha upload = " << ((t7-t6)/1000.0) << endl;
1042  };
1043 
1044  glPolygonMode(GL_FRONT, GL_FILL);
1045  glBegin(GL_QUADS);
1046  glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
1047  glTexCoord2f(sI->width(), 0.0); glVertex2f(sI->width(), 0.0);
1048  glTexCoord2f(sI->width(), sI->height()); glVertex2f(sI->width(), sI->height());
1049  glTexCoord2f(0.0, sI->height()); glVertex2f(0.0, sI->height());
1050  glEnd();
1051  CHECK_GL();
1052 
1053  glFinish();
1054  if(printDebug)
1055  {
1056  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src+alpha render = " << ((getms()-t7)/1000.0) << endl;
1057  };
1058  }
1059  }
1060  else {
1061  // Composite to srcTexture
1062  glUseProgramObjectARB(0);
1063 
1064  // Upload to srcTransferTexture
1065  glActiveTexture(GL_TEXTURE0);
1066  glEnable(GL_TEXTURE_RECTANGLE_ARB);
1067  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTransferTexture);
1068  glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, sI->width(), sI->height(), XGLMap[srcGLFormat], XGLMap[srcGLType], srcBuffer);
1069  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1070  CHECK_GL();
1071 
1072  glFinish();
1073  if(printDebug)
1074  {
1075  t6=getms();
1076  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src upload = " << ((t6-t5)/1000.0) << endl;
1077  };
1078 
1079  if (srcAlphaBuffer != NULL) {
1080  // Upload to srcAlphaTexture
1081  glActiveTexture(GL_TEXTURE1);
1082  glEnable(GL_TEXTURE_RECTANGLE_ARB);
1083  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcAlphaTexture);
1084  glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, sI->width(), sI->height(), GL_ALPHA, XGLMap[srcAlphaGLType], srcAlphaBuffer);
1085  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1086  CHECK_GL();
1087 
1088  glFinish();
1089  if(printDebug)
1090  {
1091  t7=getms();
1092  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src alpha upload = " << ((t7- t6)/1000.0) << endl;
1093  };
1094 
1095  glPolygonMode(GL_FRONT, GL_FILL);
1096  glBegin(GL_QUADS);
1097  glMultiTexCoord2f(GL_TEXTURE0, 0.0, 0.0); glMultiTexCoord2f(GL_TEXTURE1, 0.0, 0.0); glVertex2f(0.0, 0.0);
1098  glMultiTexCoord2f(GL_TEXTURE0, sI->width(), 0.0); glMultiTexCoord2f(GL_TEXTURE1, sI->width(), 0.0); glVertex2f(sI->width(), 0.0);
1099  glMultiTexCoord2f(GL_TEXTURE0, sI->width(), sI->height()); glMultiTexCoord2f(GL_TEXTURE1, sI->width(), sI->height()); glVertex2f(sI->width(), sI->height());
1100  glMultiTexCoord2f(GL_TEXTURE0, 0.0, sI->height()); glMultiTexCoord2f(GL_TEXTURE1, 0.0, sI->height()); glVertex2f(0.0, sI->height());
1101  glEnd();
1102  CHECK_GL();
1103 
1104  glActiveTexture(GL_TEXTURE0);
1105  glDisable(GL_TEXTURE_RECTANGLE_ARB);
1106  glActiveTexture(GL_TEXTURE1);
1107  glDisable(GL_TEXTURE_RECTANGLE_ARB);
1108  CHECK_GL();
1109 
1110  glFinish();
1111  if(printDebug)
1112  {
1113  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src+alpha render = " << ((getms()-t7)/1000.0) << endl;
1114  };
1115  }
1116  else {
1117  glPolygonMode(GL_FRONT, GL_FILL);
1118  glBegin(GL_QUADS);
1119  // According to the spec, GL_REPLACE uses the incoming fragment color for dest alpha when
1120  // texturing a RGB texture into an RGBA texture. Thus the color is explicitly set
1121  // with alpha=1.0, rather than relying on the default color.
1122  glColor4f(0.0, 0.0, 0.0, 1.0);
1123  glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
1124  glTexCoord2f(sI->width(), 0.0); glVertex2f(sI->width(), 0.0);
1125  glTexCoord2f(sI->width(), sI->height()); glVertex2f(sI->width(), sI->height());
1126  glTexCoord2f(0.0, sI->height()); glVertex2f(0.0, sI->height());
1127  glEnd();
1128  CHECK_GL();
1129 
1130  glActiveTexture(GL_TEXTURE0);
1131  glDisable(GL_TEXTURE_RECTANGLE_ARB);
1132  CHECK_GL();
1133 
1134  glFinish();
1135  if(printDebug)
1136  {
1137  t7=getms();
1138  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " src render = " << ((t7-t6)/1000.0) << endl;
1139  };
1140  }
1141  }
1142  }
1143 
1144  glFinish();
1145  if(printDebug)
1146  t9=getms();
1147 
1148  // Render dest image
1149  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, accumFB);
1150  glUseProgramObjectARB(interpolatorProgramObject);
1151 
1152  if (pass == 0) {
1153  // Clear ping accum texture on first pass.
1154  glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
1155  glClear(GL_COLOR_BUFFER_BIT);
1156  }
1157 
1158  glUniform2fARB(srcULParam, sI->left(), sI->top());
1159  CHECK_GL();
1160  glUniform2fARB(srcLRParam, sI->right(), sI->bottom());
1161  CHECK_GL();
1162 
1163  glActiveTexture(GL_TEXTURE0);
1164  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, coordTexture);
1165  glUniform1iARB(coordTextureParam, 0);
1166  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1167  CHECK_GL();
1168 
1169  glActiveTexture(GL_TEXTURE1);
1170  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
1171  glUniform1iARB(srcTextureParam, 1);
1172  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1173  CHECK_GL();
1174 
1175  glActiveTexture(GL_TEXTURE2);
1176  glUniform1iARB(accumTextureParam, 2);
1177  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1178  CHECK_GL();
1179 
1180  // Multipass interpolation.
1181  for (vector<Rect2D>::iterator iI = interpolatorChunks.begin(); iI != interpolatorChunks.end(); ++iI, ++pass) {
1182  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, (pass & 1) ? accumTextures[0] : accumTextures[1]);
1183  CHECK_GL();
1184 
1185  glUniform2fARB(kernelULParam, iI->left(), iI->top());
1186  CHECK_GL();
1187  glUniform2fARB(kernelWHParam, iI->width(), iI->height());
1188  CHECK_GL();
1189 
1190  glDrawBuffer((pass & 1) ? GL_COLOR_ATTACHMENT1_EXT : GL_COLOR_ATTACHMENT0_EXT);
1191 
1192  glFinish();
1193  if(printDebug)
1194  {
1195  t10=getms();
1196  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " interpolation chunk=" << *iI << " setup = " << ((t10-t9)/1000.0) << endl;
1197  };
1198 
1199  glPolygonMode(GL_FRONT, GL_FILL);
1200  glBegin(GL_QUADS);
1201  glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
1202  glTexCoord2f(dI->width(), 0.0); glVertex2f(dI->width(), 0.0);
1203  glTexCoord2f(dI->width(), dI->height()); glVertex2f(dI->width(), dI->height());
1204  glTexCoord2f(0.0, dI->height()); glVertex2f(0.0, dI->height());
1205  glEnd();
1206  CHECK_GL();
1207 
1208  glFinish();
1209  if(printDebug)
1210  {
1211  t11=getms();
1212  t9=getms();
1213  cout << "gpu dest chunk=" << *dI << " source chunk=" << *sI << " interpolation chunk=" << *iI << " render = " << ((t11-t10)/1000.0) << endl;
1214  };
1215 
1216  } // next interpolation chunk
1217 
1218  } // next source chunk
1219 
1220  // normalization/photometric rendering pass
1221  glUseProgramObjectARB(normalizationPhotometricProgramObject);
1222 
1223  glActiveTexture(GL_TEXTURE0);
1224  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, (pass & 1) ? accumTextures[0] : accumTextures[1]);
1225  glUniform1iARB(normTextureParam, 0);
1226  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1227  CHECK_GL();
1228 
1229  glActiveTexture(GL_TEXTURE1);
1230  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, coordTexture);
1231  glUniform1iARB(normCoordTextureParam, 1);
1232  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1233  CHECK_GL();
1234 
1235  if (!invLut.empty()) {
1236  glActiveTexture(GL_TEXTURE2);
1237  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, invLutTexture);
1238  glUniform1iARB(invLutTextureParam, 2);
1239  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1240  CHECK_GL();
1241  }
1242 
1243  if (!destLut.empty()) {
1244  glActiveTexture(GL_TEXTURE3);
1245  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, destLutTexture);
1246  glUniform1iARB(destLutTextureParam, 3);
1247  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1248  CHECK_GL();
1249  }
1250 
1251  glDrawBuffer((pass & 1) ? GL_COLOR_ATTACHMENT1_EXT : GL_COLOR_ATTACHMENT0_EXT);
1252 
1253  glFinish();
1254  if(printDebug)
1255  {
1256  t12=getms();
1257  cout << "gpu dest chunk=" << *dI << " normalization setup = " << ((t12-t11)/1000.0) << endl;
1258  };
1259 
1260  glPolygonMode(GL_FRONT, GL_FILL);
1261  glBegin(GL_QUADS);
1262  glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
1263  glTexCoord2f(dI->width(), 0.0); glVertex2f(dI->width(), 0.0);
1264  glTexCoord2f(dI->width(), dI->height()); glVertex2f(dI->width(), dI->height());
1265  glTexCoord2f(0.0, dI->height()); glVertex2f(0.0, dI->height());
1266  glEnd();
1267  CHECK_GL();
1268 
1269  glFinish();
1270  if(printDebug)
1271  {
1272  t13=getms();
1273  cout << "gpu dest chunk=" << *dI << " normalization render = " << ((t13-t12)/1000.0) << endl;
1274  };
1275 
1276  pass++;
1277 
1278 
1279  // Readback dest chunk
1280  glPixelStorei(GL_PACK_ROW_LENGTH, destSize.x);
1281  glPixelStorei(GL_PACK_SKIP_PIXELS, dI->left());
1282  glPixelStorei(GL_PACK_SKIP_ROWS, dI->top());
1283 
1284  if (XGLMap[destGLTransferFormat] == GL_RGBA32F_ARB) {
1285  // Transfer to destBuffer directly from last-written accum texture.
1286  glReadBuffer((pass & 1) ? GL_COLOR_ATTACHMENT0_EXT : GL_COLOR_ATTACHMENT1_EXT);
1287 
1288  glReadPixels(0, 0, dI->width(), dI->height(), XGLMap[destGLFormat], XGLMap[destGLType], destBuffer);
1289  CHECK_GL();
1290 
1291  glFinish();
1292  if(printDebug)
1293  {
1294  t14=getms();
1295  cout << "gpu dest chunk=" << *dI << " rgb readback = " << ((t14-t13)/1000.0) << endl;
1296  };
1297  }
1298  else {
1299  // Move output accumTexture to dest texture then readback.
1300  glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
1301  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, destFB);
1302  glUseProgramObjectARB(0);
1303 
1304  glActiveTexture(GL_TEXTURE0);
1305  glEnable(GL_TEXTURE_RECTANGLE_ARB);
1306  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, (pass & 1) ? accumTextures[0] : accumTextures[1]);
1307  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1308  CHECK_GL();
1309 
1310  glFinish();
1311  if(printDebug)
1312  {
1313  t14=getms();
1314  cout << "gpu dest chunk=" << *dI << " dest rgb disassembly setup = " << ((t14-t13)/1000.0) << endl;
1315  };
1316 
1317  glPolygonMode(GL_FRONT, GL_FILL);
1318  glBegin(GL_QUADS);
1319  glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
1320  glTexCoord2f(dI->width(), 0.0); glVertex2f(dI->width(), 0.0);
1321  glTexCoord2f(dI->width(), dI->height()); glVertex2f(dI->width(), dI->height());
1322  glTexCoord2f(0.0, dI->height()); glVertex2f(0.0, dI->height());
1323  glEnd();
1324  CHECK_GL();
1325 
1326  glActiveTexture(GL_TEXTURE0);
1327  glDisable(GL_TEXTURE_RECTANGLE_ARB);
1328  CHECK_GL();
1329 
1330  glFinish();
1331  if(printDebug)
1332  {
1333  t15=getms();
1334  cout << "gpu dest chunk=" << *dI << " dest rgb disassembly render = " << ((t15-t14)/1000.0) << endl;
1335  };
1336 
1337  glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1338  CHECK_GL();
1339 
1340  glReadPixels(0, 0, dI->width(), dI->height(), XGLMap[destGLFormat], XGLMap[destGLType], destBuffer);
1341  CHECK_GL();
1342 
1343  glFinish();
1344  if(printDebug)
1345  {
1346  t16=getms();
1347  cout << "gpu dest chunk=" << *dI << " rgb readback = " << ((t16-t15)/1000.0) << endl;
1348  };
1349  }
1350 
1351  if (destAlphaBuffer != NULL) {
1352  // Move output accumTexture to dest alpha texture
1353  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, destAlphaFB);
1354  glUseProgramObjectARB(0);
1355 
1356  glActiveTexture(GL_TEXTURE0);
1357  glEnable(GL_TEXTURE_RECTANGLE_ARB);
1358  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, (pass & 1) ? accumTextures[0] : accumTextures[1]);
1359  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1360  CHECK_GL();
1361 
1362  glFinish();
1363  if(printDebug)
1364  {
1365  t17=getms();
1366  cout << "gpu dest chunk=" << *dI << " dest alpha disassembly setup = " << ((t17-t16)/1000.0) << endl;
1367  };
1368 
1369  glPolygonMode(GL_FRONT, GL_FILL);
1370  glBegin(GL_QUADS);
1371  glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
1372  glTexCoord2f(dI->width(), 0.0); glVertex2f(dI->width(), 0.0);
1373  glTexCoord2f(dI->width(), dI->height()); glVertex2f(dI->width(), dI->height());
1374  glTexCoord2f(0.0, dI->height()); glVertex2f(0.0, dI->height());
1375  glEnd();
1376  CHECK_GL();
1377 
1378  glActiveTexture(GL_TEXTURE0);
1379  glDisable(GL_TEXTURE_RECTANGLE_ARB);
1380  CHECK_GL();
1381 
1382  glFinish();
1383  if(printDebug)
1384  {
1385  t18=getms();
1386  cout << "gpu dest chunk=" << *dI << " dest alpha disassembly render = " << ((t18-t17)/1000.0) << endl;
1387  };
1388 
1389  // Readback dest alpha chunk
1390  glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1391  CHECK_GL();
1392 
1393  glReadPixels(0, 0, dI->width(), dI->height(), GL_ALPHA, XGLMap[destAlphaGLType], destAlphaBuffer);
1394  CHECK_GL();
1395 
1396  glFinish();
1397  if(printDebug)
1398  {
1399  t19=getms();
1400  cout << "gpu dest chunk=" << *dI << " alpha readback = " << ((t19-t18)/1000.0) << endl;
1401  };
1402  }
1403 
1404  } // next dest chunk
1405 
1406  glFinish();
1407  if(printDebug)
1408  t19=getms();
1409 
1410  glDeleteTextures(2, accumTextures);
1411  glDeleteTextures(1, &coordTexture);
1412  glDeleteTextures(1, &srcTexture);
1413  glDeleteTextures(1, &srcAlphaTexture);
1414  glDeleteTextures(1, &srcTransferTexture);
1415  glDeleteTextures(1, &destTexture);
1416  glDeleteTextures(1, &destAlphaTexture);
1417 
1418  if (!invLut.empty()) {
1419  glDeleteTextures(1, &invLutTexture);
1420  delete [] invLutTextureData;
1421  }
1422 
1423  if (!destLut.empty()) {
1424  glDeleteTextures(1, &destLutTexture);
1425  delete [] destLutTextureData;
1426  }
1427 
1428  glDeleteFramebuffersEXT(5, framebuffers);
1429 
1430  glUseProgramObjectARB(0);
1431  glDeleteObjectARB(coordXformShaderObject);
1432  glDeleteObjectARB(coordXformProgramObject);
1433  glDeleteObjectARB(interpolatorShaderObject);
1434  glDeleteObjectARB(interpolatorProgramObject);
1435  glDeleteObjectARB(normalizationPhotometricShaderObject);
1436  glDeleteObjectARB(normalizationPhotometricProgramObject);
1437 
1438  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1439  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1440  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1441 
1442  glFinish();
1443  if(printDebug)
1444  {
1445  long t20=getms();
1446  cout << "gpu destruct time = " << ((t20-t19)/1000.0) << endl;
1447  cout << "gpu total time = " << ((t20-t1)/1000.0) << endl;
1448  };
1449 
1450  return true;
1451 }
1452 
1453 }; // namespace
static void compileGLSL(const char *programName, GLhandleARB &programObject, GLhandleARB &shaderObject, const char **source)
static void checkGLErrors(int line, char *file)
static GLenum XGLMap[]
#define TEXTURE_FREE_MEMORY_ATI
static char * line
Definition: svm.cpp:2784
void SetGPUDebugMessages(const bool doPrint)
#define ___NCFILE___
#define GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX
static const char * AlphaCompositeKernelSource
static bool checkFramebufferStatus(int line, char *file)
bool transformImageGPUIntern(const std::string &coordXformGLSL, const std::string &interpolatorGLSL, const int interpolatorSize, const std::string &photometricGLSL, const vector< double > &invLut, const vector< double > &destLut, const vigra::Diff2D srcSize, const void *const srcBuffer, const int srcGLInternalFormat, const int srcGLTransferFormat, const int srcGLFormat, const int srcGLType, const void *const srcAlphaBuffer, const int srcAlphaGLType, const vigra::Diff2D destUL, const vigra::Diff2D destSize, void *const destBuffer, const int destGLInternalFormat, const int destGLTransferFormat, const int destGLFormat, const int destGLType, void *const destAlphaBuffer, const int destAlphaGLType, const bool warparound)
static void makeChunks(const int width, const int height, const int maxTextureSize, const long long int maxPixels, vector< Rect2D > &result)
#define CHECK_GL()
long getms()
static bool printDebug
static void printInfoLog(GLhandleARB obj)
static const char * XGLStringMap[]
static int BytesPerPixel[]
#define M_PI
Definition: GaborFilter.cpp:34
Contains functions to transform whole images.