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