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