1 ////////////////////////////////////////////////////////////////////////////
2 // File: GlobalUtil.cpp
3 // Author: Changchang Wu
4 // Description : Global Utility class for SiftGPU
5 //
6 //
7 //
8 // Copyright (c) 2007 University of North Carolina at Chapel Hill
9 // All Rights Reserved
10 //
11 // Permission to use, copy, modify and distribute this software and its
12 // documentation for educational, research and non-profit purposes, without
13 // fee, and without a written agreement is hereby granted, provided that the
14 // above copyright notice and the following paragraph appear in all copies.
15 //
16 // The University of North Carolina at Chapel Hill make no representations
17 // about the suitability of this software for any purpose. It is provided
18 // 'as is' without express or implied warranty.
19 //
20 // Please send BUG REPORTS to ccwu@cs.unc.edu
21 //
22 ////////////////////////////////////////////////////////////////////////////
23 #include <string.h>
24 #include <iostream>
25 using std::cout;
26
27 #include "GL/glew.h"
28 #include "GlobalUtil.h"
29
30 #if defined(_WIN32)
31 #define WIN32_LEAN_AND_MEAN
32 #include <windows.h>
33 #else
34 #include <stdio.h>
35 #endif
36
37 #include "LiteWindow.h"
38
39 //
40 int GlobalParam:: _verbose = 1;
41 int GlobalParam:: _timingS = 1; //print out information of each step
42 int GlobalParam:: _timingO = 0; //print out information of each octave
43 int GlobalParam:: _timingL = 0; //print out information of each level
44 GLuint GlobalParam:: _texTarget = GL_TEXTURE_RECTANGLE_ARB; //only this one is supported
45 GLuint GlobalParam:: _iTexFormat =GL_RGBA32F_ARB; //or GL_RGBA16F_ARB
46 int GlobalParam:: _debug = 0; //enable debug code?
47 int GlobalParam:: _usePackedTex = 1;//packed implementation
48 int GlobalParam:: _UseCUDA = 0;
49 int GlobalParam:: _UseOpenCL = 0;
50 int GlobalParam:: _MaxFilterWidth = -1; //maximum filter width, use when GPU is not good enough
51 float GlobalParam:: _FilterWidthFactor = 4.0f; //the filter size will be _FilterWidthFactor*sigma*2+1
52 float GlobalParam:: _DescriptorWindowFactor = 3.0f; //descriptor sampling window factor
53 int GlobalParam:: _SubpixelLocalization = 1; //sub-pixel and sub-scale localization
54 int GlobalParam:: _MaxOrientation = 2; //whether we find multiple orientations for each feature
55 int GlobalParam:: _OrientationPack2 = 0; //use one float to store two orientations
56 float GlobalParam:: _MaxFeaturePercent = 0.005f;//at most 0.005 of all pixels
57 int GlobalParam:: _MaxLevelFeatureNum = 4096; //maximum number of features of a level
58 int GlobalParam:: _FeatureTexBlock = 4; //feature texture storagte alignment
59 int GlobalParam:: _NarrowFeatureTex = 0;
60
61 //if _ForceTightPyramid is not 0, pyramid will be reallocated to fit the size of input images.
62 //otherwise, pyramid can be reused for smaller input images.
63 int GlobalParam:: _ForceTightPyramid = 0;
64
65 //use gpu or cpu to generate feature list ...gpu is a little bit faster
66 int GlobalParam:: _ListGenGPU = 1;
67 int GlobalParam:: _ListGenSkipGPU = 6; //how many levels are skipped on gpu
68 int GlobalParam:: _PreProcessOnCPU = 1; //convert rgb 2 intensity on gpu, down sample on GPU
69
70 //hardware parameter, automatically retrieved
71 int GlobalParam:: _texMaxDim = 3200; //Maximum working size for SiftGPU, 3200 for packed
72 int GlobalParam:: _texMaxDimGL = 4096; //GPU texture limit
73 int GlobalParam:: _texMinDim = 16; //
74 int GlobalParam:: _MemCapGPU = 0;
75 int GlobalParam:: _FitMemoryCap = 0;
76 int GlobalParam:: _IsNvidia = 0; //GPU vendor
77 int GlobalParam:: _KeepShaderLoop = 0;
78
79 //you can't change the following 2 values
80 //all other versions of code are now dropped
81 int GlobalParam:: _DescriptorPPR = 8;
82 int GlobalParam:: _DescriptorPPT = 16;
83
84 //whether orientation/descriptor is supported by hardware
85 int GlobalParam:: _SupportNVFloat = 0;
86 int GlobalParam:: _SupportTextureRG = 0;
87 int GlobalParam:: _UseDynamicIndexing = 0;
88 int GlobalParam:: _FullSupported = 1;
89
90 //when SiftGPUEX is not used, display VBO generation is skipped
91 int GlobalParam:: _UseSiftGPUEX = 0;
92 int GlobalParam:: _InitPyramidWidth=0;
93 int GlobalParam:: _InitPyramidHeight=0;
94 int GlobalParam:: _octave_min_default=0;
95 int GlobalParam:: _octave_num_default=-1;
96
97
98 //////////////////////////////////////////////////////////////////
99 int GlobalParam:: _GoodOpenGL = -1; //indicates OpenGl initialization status
100 int GlobalParam:: _FixedOrientation = 0; //upright
101 int GlobalParam:: _LoweOrigin = 0; //(0, 0) to be at the top-left corner.
102 int GlobalParam:: _NormalizedSIFT = 1; //normalize descriptor
103 int GlobalParam:: _BinarySIFT = 0; //saving binary format
104 int GlobalParam:: _ExitAfterSIFT = 0; //exif after saving result
105 int GlobalParam:: _KeepExtremumSign = 0; // if 1, scales of dog-minimum will be multiplied by -1
106 ///
107 int GlobalParam:: _KeyPointListForceLevel0 = 0;
108 int GlobalParam:: _DarknessAdaption = 0;
109 int GlobalParam:: _ProcessOBO = 0;
110 int GlobalParam:: _TruncateMethod = 0;
111 int GlobalParam:: _PreciseBorder = 1;
112
113 // parameter changing for better matching with Lowe's SIFT
114 float GlobalParam:: _OrientationWindowFactor = 2.0f; // 1.0(-v292), 2(v293-),
115 float GlobalParam:: _OrientationGaussianFactor = 1.5f; // 4.5(-v292), 1.5(v293-)
116 float GlobalParam:: _MulitiOrientationThreshold = 0.8f;
117 ///
118 int GlobalParam:: _FeatureCountThreshold = -1;
119
120 ///////////////////////////////////////////////
121 int GlobalParam:: _WindowInitX = -1;
122 int GlobalParam:: _WindowInitY = -1;
123 int GlobalParam:: _DeviceIndex = 0;
124 const char * GlobalParam:: _WindowDisplay = NULL;
125
126
127
128 /////////////////
129 ////
130 ClockTimer GlobalUtil:: _globalTimer;
131
132
133 #ifdef _DEBUG
CheckErrorsGL(const char * location)134 void GlobalUtil::CheckErrorsGL(const char* location)
135 {
136 GLuint errnum;
137 const char *errstr;
138 while (errnum = glGetError())
139 {
140 errstr = (const char *)(gluErrorString(errnum));
141 if(errstr) {
142 std::cerr << errstr;
143 }
144 else {
145 std::cerr << "Error " << errnum;
146 }
147
148 if(location) std::cerr << " at " << location;
149 std::cerr << "\n";
150 }
151 return;
152 }
153
154 #endif
155
CleanupOpenGL()156 void GlobalUtil::CleanupOpenGL()
157 {
158 glActiveTexture(GL_TEXTURE0);
159 }
160
SetDeviceParam(int argc,char ** argv)161 void GlobalUtil::SetDeviceParam(int argc, char** argv)
162 {
163 if(GlobalParam::_GoodOpenGL!= -1) return;
164
165 #define CHAR1_TO_INT(x) ((x >= 'A' && x <= 'Z') ? x + 32 : x)
166 #define CHAR2_TO_INT(str, i) (str[i] ? CHAR1_TO_INT(str[i]) + (CHAR1_TO_INT(str[i+1]) << 8) : 0)
167 #define CHAR3_TO_INT(str, i) (str[i] ? CHAR1_TO_INT(str[i]) + (CHAR2_TO_INT(str, i + 1) << 8) : 0)
168 #define STRING_TO_INT(str) (CHAR1_TO_INT(str[0]) + (CHAR3_TO_INT(str, 1) << 8))
169
170 char* arg, * opt;
171 for(int i = 0; i< argc; i++)
172 {
173 arg = argv[i];
174 if(arg == NULL || arg[0] != '-')continue;
175 opt = arg+1;
176
177 ////////////////////////////////
178 switch( STRING_TO_INT(opt))
179 {
180 case 'w' + ('i' << 8) + ('n' << 16) + ('p' << 24):
181 if(_GoodOpenGL != 2 && i + 1 < argc)
182 {
183 int x =0, y=0;
184 if(sscanf(argv[++i], "%dx%d", &x, &y) == 2)
185 {
186 GlobalParam::_WindowInitX = x;
187 GlobalParam::_WindowInitY = y;
188 }
189 }
190 break;
191 case 'd' + ('i' << 8) + ('s' << 16) + ('p' << 24):
192 if(_GoodOpenGL != 2 && i + 1 < argc)
193 {
194 GlobalParam::_WindowDisplay = argv[++i];
195 }
196 break;
197 case 'c' + ('u' << 8) + ('d' << 16) + ('a' << 24):
198 if(i + 1 < argc)
199 {
200 int device = 0;
201 scanf(argv[++i], "%d", &device) ;
202 GlobalParam::_DeviceIndex = device;
203 }
204 break;
205 default:
206 break;
207 }
208 }
209 }
210
SetTextureParameter()211 void GlobalUtil::SetTextureParameter()
212 {
213
214 glTexParameteri (_texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
215 glTexParameteri (_texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
216 glTexParameteri(_texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
217 glTexParameteri(_texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
218 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
219 }
220
221 //if image need to be up sampled ..use this one
222
SetTextureParameterUS()223 void GlobalUtil::SetTextureParameterUS()
224 {
225
226 glTexParameteri (_texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
227 glTexParameteri (_texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
228 glTexParameteri(_texTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
229 glTexParameteri(_texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
230 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
231 }
232
233
FitViewPort(int width,int height)234 void GlobalUtil::FitViewPort(int width, int height)
235 {
236 GLint port[4];
237 glGetIntegerv(GL_VIEWPORT, port);
238 if(port[2] !=width || port[3] !=height)
239 {
240 glViewport(0, 0, width, height);
241 glMatrixMode(GL_PROJECTION);
242 glLoadIdentity();
243 glOrtho(0, width, 0, height, 0, 1);
244 glMatrixMode(GL_MODELVIEW);
245 glLoadIdentity();
246 }
247 }
248
249
CheckFramebufferStatus()250 bool GlobalUtil::CheckFramebufferStatus() {
251 GLenum status;
252 status=(GLenum)glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
253 switch(status) {
254 case GL_FRAMEBUFFER_COMPLETE_EXT:
255 return true;
256 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
257 std::cerr<<("Framebuffer incomplete,incomplete attachment\n");
258 return false;
259 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
260 std::cerr<<("Unsupported framebuffer format\n");
261 return false;
262 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
263 std::cerr<<("Framebuffer incomplete,missing attachment\n");
264 return false;
265 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
266 std::cerr<<("Framebuffer incomplete,attached images must have same dimensions\n");
267 return false;
268 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
269 std::cerr<<("Framebuffer incomplete,attached images must have same format\n");
270 return false;
271 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
272 std::cerr<<("Framebuffer incomplete,missing draw buffer\n");
273 return false;
274 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
275 std::cerr<<("Framebuffer incomplete,missing read buffer\n");
276 return false;
277 }
278 return false;
279 }
280
281
ClockMS()282 int ClockTimer::ClockMS()
283 {
284 return 0;
285 }
286
CLOCK()287 double ClockTimer::CLOCK()
288 {
289 return 0;
290 }
291
InitHighResolution()292 void ClockTimer::InitHighResolution()
293 {
294 }
295
StartTimer(const char * event,int verb)296 void ClockTimer::StartTimer(const char* event, int verb)
297 {
298
299 }
300
StopTimer(int verb)301 void ClockTimer::StopTimer(int verb)
302 {
303
304 }
305
GetElapsedTime()306 float ClockTimer::GetElapsedTime()
307 {
308 return 0;
309 }
310
SetGLParam()311 void GlobalUtil::SetGLParam()
312 {
313 if(GlobalUtil::_UseCUDA) return;
314 else if(GlobalUtil::_UseOpenCL) return;
315 glEnable(GlobalUtil::_texTarget);
316 glActiveTexture(GL_TEXTURE0);
317 }
318
InitGLParam(int NotTargetGL)319 void GlobalUtil::InitGLParam(int NotTargetGL)
320 {
321 //IF the OpenGL context passed the check
322 if(GlobalUtil::_GoodOpenGL == 2) return;
323 //IF the OpenGl context failed the check
324 if(GlobalUtil::_GoodOpenGL == 0) return;
325 //IF se use CUDA or OpenCL
326 if(NotTargetGL && !GlobalUtil::_UseSiftGPUEX)
327 {
328 GlobalUtil::_GoodOpenGL = 1;
329 }else
330 {
331 //first time in this function
332 glewInit();
333
334 GlobalUtil::_GoodOpenGL = 2;
335
336 const char * vendor = (const char * )glGetString(GL_VENDOR);
337 if(vendor)
338 {
339 GlobalUtil::_IsNvidia = (strstr(vendor, "NVIDIA") !=NULL ? 1 : 0);
340
341 // Let nVidia compiler to take care of the unrolling.
342 if (GlobalUtil::_IsNvidia) GlobalUtil::_KeepShaderLoop = 1;
343
344 #ifndef WIN32
345 else if(!strstr(vendor, "ATI") )
346 {
347 // For non-nVidia non-ATI cards...simply assume it is Mesa
348 // Keep the original shader loop, because some of the unrolled
349 // loopes are too large, and it may take too much time to compile
350 GlobalUtil::_KeepShaderLoop = 1;
351 }
352 #endif
353
354 if(GlobalUtil::_IsNvidia && glewGetExtension("GL_NVX_gpu_memory_info"))
355 {
356 glGetIntegerv(0x9049/*GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX*/, &_MemCapGPU);
357 _MemCapGPU /= (1024);
358 if(GlobalUtil::_verbose) std::cout << "[GPU VENDOR]:\t" << vendor << ' ' <<_MemCapGPU << "MB\n";
359 }else if(strstr(vendor, "ATI") && glewGetExtension("GL_ATI_meminfo"))
360 {
361 int info[4]; glGetIntegerv(0x87FC/*GL_TEXTURE_FREE_MEMORY_ATI*/, info);
362 _MemCapGPU = info[0] / (1024);
363 if(GlobalUtil::_verbose) std::cout << "[GPU VENDOR]:\t" << vendor << ' ' <<_MemCapGPU << "MB\n";
364 }else
365 {
366 if(GlobalUtil::_verbose) std::cout << "[GPU VENDOR]:\t" << vendor << "\n";
367 }
368
369 }
370 if(GlobalUtil::_IsNvidia == 0 )GlobalUtil::_UseCUDA = 0;
371
372 if (glewGetExtension("GL_ARB_fragment_shader") != GL_TRUE ||
373 glewGetExtension("GL_ARB_shader_objects") != GL_TRUE ||
374 glewGetExtension("GL_ARB_shading_language_100") != GL_TRUE)
375 {
376 std::cerr << "Shader not supported by your hardware!\n";
377 GlobalUtil::_GoodOpenGL = 0;
378 }
379
380 if (glewGetExtension("GL_EXT_framebuffer_object") != GL_TRUE)
381 {
382 std::cerr << "Framebuffer object not supported!\n";
383 GlobalUtil::_GoodOpenGL = 0;
384 }
385
386 if(glewGetExtension("GL_ARB_texture_rectangle")==GL_TRUE)
387 {
388 GLint value;
389 GlobalUtil::_texTarget = GL_TEXTURE_RECTANGLE_ARB;
390 glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &value);
391 GlobalUtil::_texMaxDimGL = value;
392 if(GlobalUtil::_verbose) std::cout << "TEXTURE:\t" << GlobalUtil::_texMaxDimGL << "\n";
393
394 if(GlobalUtil::_texMaxDim == 0 || GlobalUtil::_texMaxDim > GlobalUtil::_texMaxDimGL)
395 {
396 GlobalUtil::_texMaxDim = GlobalUtil::_texMaxDimGL;
397 }
398 glEnable(GlobalUtil::_texTarget);
399 }else
400 {
401 std::cerr << "GL_ARB_texture_rectangle not supported!\n";
402 GlobalUtil::_GoodOpenGL = 0;
403 }
404
405 GlobalUtil::_SupportNVFloat = glewGetExtension("GL_NV_float_buffer");
406 GlobalUtil::_SupportTextureRG = glewGetExtension("GL_ARB_texture_rg");
407
408
409 glShadeModel(GL_FLAT);
410 glPolygonMode(GL_FRONT, GL_FILL);
411
412 GlobalUtil::SetTextureParameter();
413
414 }
415 }
416
SelectDisplay()417 void GlobalUtil::SelectDisplay()
418 {
419 #ifdef WIN32
420 if(_WindowDisplay == NULL) return;
421
422 HDC hdc = CreateDC(_WindowDisplay, _WindowDisplay, NULL, NULL);
423 _WindowDisplay = NULL;
424 if(hdc == NULL)
425 {
426 std::cout << "ERROR: invalid dispaly specified\n";
427 return;
428 }
429
430 PIXELFORMATDESCRIPTOR pfd =
431 {
432 sizeof(PIXELFORMATDESCRIPTOR),1,
433 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,
434 PFD_TYPE_RGBA,24,0, 0, 0, 0, 0, 0,0,0,0,0, 0, 0, 0,16,0,0,
435 PFD_MAIN_PLANE,0,0, 0, 0
436 };
437 ChoosePixelFormat(hdc, &pfd);
438 #endif
439 }
440
CreateWindowEZ(LiteWindow * window)441 int GlobalUtil::CreateWindowEZ(LiteWindow* window)
442 {
443 if(window == NULL) return 0;
444 if(!window->IsValid())window->Create(_WindowInitX, _WindowInitY, _WindowDisplay);
445 if(window->IsValid())
446 {
447 window->MakeCurrent();
448 return 1;
449 }
450 else
451 {
452 std::cerr << "Unable to create OpenGL Context!\n";
453 std::cerr << "For nVidia cards, you can try change to CUDA mode in this case\n";
454 return 0;
455 }
456 }
457
CreateWindowEZ()458 int GlobalUtil::CreateWindowEZ()
459 {
460 static LiteWindow window;
461 return CreateWindowEZ(&window);
462 }
463
CreateLiteWindow(LiteWindow * window)464 int CreateLiteWindow(LiteWindow* window)
465 {
466 return GlobalUtil::CreateWindowEZ(window);
467 }
468