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