VirtualBox

source: vbox/trunk/src/VBox/Main/src-helper-apps/OpenGLTest/OpenGLTestApp.cpp@ 86857

Last change on this file since 86857 was 86857, checked in by vboxsync, 4 years ago

Main/OpenGLTestApp: Linux compilation fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.5 KB
Line 
1/* $Id: OpenGLTestApp.cpp 86857 2020-11-11 09:12:23Z vboxsync $ */
2/** @file
3 * VBox host opengl support test application.
4 */
5
6/*
7 * Copyright (C) 2009-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <iprt/assert.h>
19#include <iprt/buildconfig.h>
20#include <iprt/errcore.h>
21#include <iprt/getopt.h>
22#include <iprt/initterm.h>
23#include <iprt/ldr.h>
24#include <iprt/stream.h>
25#ifdef RT_OS_WINDOWS
26# include <iprt/win/windows.h>
27#endif
28#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
29# include <sys/resource.h>
30# include <fcntl.h>
31# include <unistd.h>
32#endif
33
34#include <string.h>
35
36#define VBOXGLTEST_WITH_LOGGING /** @todo r=andy Is this intentional? */
37
38#ifdef VBOXGLTEST_WITH_LOGGING
39# include "package-generated.h"
40
41# include <iprt/log.h>
42# include <iprt/param.h>
43# include <iprt/time.h>
44# include <iprt/system.h>
45# include <iprt/process.h>
46# include <iprt/env.h>
47
48# include <VBox/log.h>
49# include <VBox/version.h>
50#endif /* VBOXGLTEST_WITH_LOGGING */
51
52#ifndef RT_OS_WINDOWS
53# include <GL/gl.h> /* For GLubyte and friends. */
54#endif
55
56#ifdef VBOX_WITH_VIDEOHWACCEL
57# include <QGLWidget>
58# include <QApplication>
59# include <VBox/VBoxGL2D.h>
60#endif
61
62/**
63 * The OpenGL methods to look for when checking 3D presence.
64 */
65static const char * const g_apszOglMethods[] =
66{
67#ifdef RT_OS_WINDOWS
68 "wglCreateContext",
69 "wglDeleteContext",
70 "wglMakeCurrent",
71 "wglShareLists",
72#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS)
73 "glXQueryVersion",
74 "glXChooseVisual",
75 "glXCreateContext",
76 "glXMakeCurrent",
77 "glXDestroyContext",
78#endif
79 "glAlphaFunc",
80 "glBindTexture",
81 "glBlendFunc",
82 "glClear",
83 "glClearColor",
84 "glClearDepth",
85 "glClearStencil",
86 "glClipPlane",
87 "glColorMask",
88 "glColorPointer",
89 "glCullFace",
90 "glDeleteTextures",
91 "glDepthFunc",
92 "glDepthMask",
93 "glDepthRange",
94 "glDisable",
95 "glDisableClientState",
96 "glDrawArrays",
97 "glDrawElements",
98 "glEnable",
99 "glEnableClientState",
100 "glFogf",
101 "glFogfv",
102 "glFogi",
103 "glFrontFace",
104 "glGenTextures",
105 "glGetBooleanv",
106 "glGetError",
107 "glGetFloatv",
108 "glGetIntegerv",
109 "glGetString",
110 "glGetTexImage",
111 "glLightModelfv",
112 "glLightf",
113 "glLightfv",
114 "glLineWidth",
115 "glLoadIdentity",
116 "glLoadMatrixf",
117 "glMaterialfv",
118 "glMatrixMode",
119 "glMultMatrixf",
120 "glNormalPointer",
121 "glPixelStorei",
122 "glPointSize",
123 "glPolygonMode",
124 "glPolygonOffset",
125 "glPopAttrib",
126 "glPopMatrix",
127 "glPushAttrib",
128 "glPushMatrix",
129 "glScissor",
130 "glShadeModel",
131 "glStencilFunc",
132 "glStencilMask",
133 "glStencilOp",
134 "glTexCoordPointer",
135 "glTexImage2D",
136 "glTexParameterf",
137 "glTexParameterfv",
138 "glTexParameteri",
139 "glTexSubImage2D",
140 "glVertexPointer",
141 "glViewport"
142};
143
144
145/**
146 * Tries to resolve the given OpenGL symbol.
147 *
148 * @returns Pointer to the symbol or nULL on error.
149 * @param pszSymbol The symbol to resolve.
150 */
151DECLINLINE(PFNRT) vboxTestOglGetProc(const char *pszSymbol)
152{
153 int rc;
154
155#ifdef RT_OS_WINDOWS
156 static RTLDRMOD s_hOpenGL32 = NULL;
157 if (s_hOpenGL32 == NULL)
158 {
159 rc = RTLdrLoadSystem("opengl32", /* fNoUnload = */ true, &s_hOpenGL32);
160 if (RT_FAILURE(rc))
161 s_hOpenGL32 = NULL;
162 }
163
164 typedef PROC (WINAPI *PFNWGLGETPROCADDRESS)(LPCSTR);
165 static PFNWGLGETPROCADDRESS s_wglGetProcAddress = NULL;
166 if (s_wglGetProcAddress == NULL)
167 {
168 if (s_hOpenGL32 != NULL)
169 {
170 rc = RTLdrGetSymbol(s_hOpenGL32, "wglGetProcAddress", (void **)&s_wglGetProcAddress);
171 if (RT_FAILURE(rc))
172 s_wglGetProcAddress = NULL;
173 }
174 }
175
176 if (s_wglGetProcAddress)
177 {
178 /* Khronos: [on failure] "some implementations will return other values. 1, 2, and 3 are used, as well as -1". */
179 PFNRT p = (PFNRT)s_wglGetProcAddress(pszSymbol);
180 if (RT_VALID_PTR(p))
181 return p;
182
183 /* Might be an exported symbol. */
184 rc = RTLdrGetSymbol(s_hOpenGL32, pszSymbol, (void **)&p);
185 if (RT_SUCCESS(rc))
186 return p;
187 }
188#else /* The X11 gang */
189 static RTLDRMOD s_hGL = NULL;
190 if (s_hGL == NULL)
191 {
192 static const char s_szLibGL[] = "libGL.so.1";
193 rc = RTLdrLoadEx(s_szLibGL, &s_hGL, RTLDRLOAD_FLAGS_GLOBAL | RTLDRLOAD_FLAGS_NO_UNLOAD, NULL);
194 if (RT_FAILURE(rc))
195 {
196 s_hGL = NULL;
197 return NULL;
198 }
199 }
200
201 typedef PFNRT (* PFNGLXGETPROCADDRESS)(const GLubyte * procName);
202 static PFNGLXGETPROCADDRESS s_glXGetProcAddress = NULL;
203 if (s_glXGetProcAddress == NULL)
204 {
205 rc = RTLdrGetSymbol(s_hGL, "glXGetProcAddress", (void **)&s_glXGetProcAddress);
206 if (RT_FAILURE(rc))
207 {
208 s_glXGetProcAddress = NULL;
209 return NULL;
210 }
211 }
212
213 PFNRT p = s_glXGetProcAddress((const GLubyte *)pszSymbol);
214 if (RT_VALID_PTR(p))
215 return p;
216
217 /* Might be an exported symbol. */
218 rc = RTLdrGetSymbol(s_hGL, pszSymbol, (void **)&p);
219 if (RT_SUCCESS(rc))
220 return p;
221#endif
222
223 return NULL;
224}
225
226static int vboxCheck3DAccelerationSupported()
227{
228 LogRel(("Testing 3D Support:\n"));
229
230 for (uint32_t i = 0; i < RT_ELEMENTS(g_apszOglMethods); i++)
231 {
232 PFNRT pfn = vboxTestOglGetProc(g_apszOglMethods[i]);
233 if (!pfn)
234 {
235 LogRel(("Testing 3D Failed\n"));
236 return 1;
237 }
238 }
239
240 LogRel(("Testing 3D Succeeded!\n"));
241 return 0;
242}
243
244#ifdef VBOX_WITH_VIDEOHWACCEL
245static int vboxCheck2DVideoAccelerationSupported()
246{
247 LogRel(("Testing 2D Support:\n"));
248 static int dummyArgc = 1;
249 static char * dummyArgv = (char*)"GlTest";
250 QApplication app (dummyArgc, &dummyArgv);
251
252 VBoxGLTmpContext ctx;
253 const QGLContext *pContext = ctx.makeCurrent();
254 if(pContext)
255 {
256 VBoxVHWAInfo supportInfo;
257 supportInfo.init(pContext);
258 if(supportInfo.isVHWASupported())
259 {
260 LogRel(("Testing 2D Succeeded!\n"));
261 return 0;
262 }
263 }
264 else
265 {
266 LogRel(("Failed to create gl context\n"));
267 }
268 LogRel(("Testing 2D Failed\n"));
269 return 1;
270}
271#endif
272
273#ifdef VBOXGLTEST_WITH_LOGGING
274static int vboxInitLogging(const char *pszFilename, bool bGenNameSuffix)
275{
276 PRTLOGGER loggerRelease;
277 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
278 RTUINT fFlags = RTLOGFLAGS_PREFIX_TIME_PROG;
279#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
280 fFlags |= RTLOGFLAGS_USECRLF;
281#endif
282 const char * pszFilenameFmt;
283 RTLOGDEST enmLogDest;
284 if(pszFilename)
285 {
286 if(bGenNameSuffix)
287 pszFilenameFmt = "%s.%ld.log";
288 else
289 pszFilenameFmt = "%s";
290 enmLogDest = RTLOGDEST_FILE;
291 }
292 else
293 {
294 pszFilenameFmt = NULL;
295 enmLogDest = RTLOGDEST_STDOUT;
296 }
297
298 int vrc = RTLogCreateEx(&loggerRelease, fFlags, "all",
299 "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, UINT32_MAX, enmLogDest,
300 NULL /* pfnBeginEnd */, 0 /* cHistory */, 0 /* cbHistoryFileMax */, 0 /* uHistoryTimeMax */,
301 NULL /* pErrInfo */, pszFilenameFmt, pszFilename, RTTimeMilliTS());
302 if (RT_SUCCESS(vrc))
303 {
304 /* some introductory information */
305 RTTIMESPEC timeSpec;
306 char szTmp[256];
307 RTTimeSpecToString(RTTimeNow(&timeSpec), szTmp, sizeof(szTmp));
308 RTLogRelLogger(loggerRelease, 0, ~0U,
309 "VBoxTestGL %s r%u %s (%s %s) release log\n"
310#ifdef VBOX_BLEEDING_EDGE
311 "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n"
312#endif
313 "Log opened %s\n",
314 VBOX_VERSION_STRING, RTBldCfgRevision(), VBOX_BUILD_TARGET,
315 __DATE__, __TIME__, szTmp);
316
317 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
318 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
319 RTLogRelLogger(loggerRelease, 0, ~0U, "OS Product: %s\n", szTmp);
320 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
321 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
322 RTLogRelLogger(loggerRelease, 0, ~0U, "OS Release: %s\n", szTmp);
323 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
324 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
325 RTLogRelLogger(loggerRelease, 0, ~0U, "OS Version: %s\n", szTmp);
326 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp));
327 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
328 RTLogRelLogger(loggerRelease, 0, ~0U, "OS Service Pack: %s\n", szTmp);
329// RTLogRelLogger(loggerRelease, 0, ~0U, "Host RAM: %uMB RAM, available: %uMB\n",
330// uHostRamMb, uHostRamAvailMb);
331 /* the package type is interesting for Linux distributions */
332 char szExecName[RTPATH_MAX];
333 char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
334 RTLogRelLogger(loggerRelease, 0, ~0U,
335 "Executable: %s\n"
336 "Process ID: %u\n"
337 "Package type: %s"
338#ifdef VBOX_OSE
339 " (OSE)"
340#endif
341 "\n",
342 pszExecName ? pszExecName : "unknown",
343 RTProcSelf(),
344 VBOX_PACKAGE_STRING);
345
346 /* register this logger as the release logger */
347 RTLogRelSetDefaultInstance(loggerRelease);
348
349 return VINF_SUCCESS;
350 }
351
352 return vrc;
353}
354#endif
355
356static int vboxInitQuietMode()
357{
358#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
359 /* This small test application might crash on some hosts. Do never
360 * generate a core dump as most likely some OpenGL library is
361 * responsible. */
362 struct rlimit lim = { 0, 0 };
363 setrlimit(RLIMIT_CORE, &lim);
364
365 /* Redirect stderr to /dev/null */
366 int fd = open("/dev/null", O_WRONLY);
367 if (fd != -1)
368 dup2(fd, STDERR_FILENO);
369#endif
370 return 0;
371}
372
373int main(int argc, char **argv)
374{
375 int rc = 0;
376
377 RTR3InitExe(argc, &argv, 0);
378
379 if(argc < 2)
380 {
381 /* backwards compatibility: check 3D */
382 rc = vboxCheck3DAccelerationSupported();
383 }
384 else
385 {
386 static const RTGETOPTDEF s_aOptionDefs[] =
387 {
388 { "--test", 't', RTGETOPT_REQ_STRING },
389 { "-test", 't', RTGETOPT_REQ_STRING },
390#ifdef VBOXGLTEST_WITH_LOGGING
391 { "--log", 'l', RTGETOPT_REQ_STRING },
392#endif
393 };
394
395 RTGETOPTSTATE State;
396 rc = RTGetOptInit(&State, argc-1, argv+1, &s_aOptionDefs[0], RT_ELEMENTS(s_aOptionDefs), 0, 0);
397 AssertRCReturn(rc, 49);
398
399#ifdef VBOX_WITH_VIDEOHWACCEL
400 bool bTest2D = false;
401#endif
402 bool bTest3D = false;
403#ifdef VBOXGLTEST_WITH_LOGGING
404 bool bLog = false;
405 bool bLogSuffix = false;
406 const char * pLog = NULL;
407#endif
408
409 for (;;)
410 {
411 RTGETOPTUNION Val;
412 rc = RTGetOpt(&State, &Val);
413 if (!rc)
414 break;
415 switch (rc)
416 {
417 case 't':
418 if (!strcmp(Val.psz, "3D") || !strcmp(Val.psz, "3d"))
419 {
420 bTest3D = true;
421 rc = 0;
422 break;
423 }
424#ifdef VBOX_WITH_VIDEOHWACCEL
425 if (!strcmp(Val.psz, "2D") || !strcmp(Val.psz, "2d"))
426 {
427 bTest2D = true;
428 rc = 0;
429 break;
430 }
431#endif
432 rc = 1;
433 break;
434#ifdef VBOXGLTEST_WITH_LOGGING
435 case 'l':
436 bLog = true;
437 pLog = Val.psz;
438 rc = 0;
439 break;
440#endif
441 case 'h':
442 RTPrintf(VBOX_PRODUCT " Helper for testing 2D/3D OpenGL capabilities %u.%u.%u\n"
443 "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
444 "All rights reserved.\n"
445 "\n"
446 "Parameters:\n"
447#ifdef VBOX_WITH_VIDEOHWACCEL
448 " --test 2D test for 2D (video) OpenGL capabilities\n"
449#endif
450 " --test 3D test for 3D OpenGL capabilities\n"
451#ifdef VBOXGLTEST_WITH_LOGGING
452 " --log <log_file_name> log the GL test result to the given file\n"
453 "\n"
454 "Logging can alternatively be enabled by specifying the VBOXGLTEST_LOG=<log_file_name> env variable\n"
455
456#endif
457 "\n",
458 RTBldCfgVersionMajor(), RTBldCfgVersionMinor(), RTBldCfgVersionBuild());
459 break;
460
461 case 'V':
462 RTPrintf("$Revision: 86857 $\n");
463 return 0;
464
465 case VERR_GETOPT_UNKNOWN_OPTION:
466 case VINF_GETOPT_NOT_OPTION:
467 rc = 1;
468
469 default:
470 /* complain? RTGetOptPrintError(rc, &Val); */
471 break;
472 }
473
474 if (rc)
475 break;
476 }
477
478 if(!rc)
479 {
480#ifdef VBOXGLTEST_WITH_LOGGING
481 if(!bLog)
482 {
483 /* check the VBOXGLTEST_LOG env var */
484 pLog = RTEnvGet("VBOXGLTEST_LOG");
485 if(pLog)
486 bLog = true;
487 bLogSuffix = true;
488 }
489 if(bLog)
490 rc = vboxInitLogging(pLog, bLogSuffix);
491 else
492#endif
493 rc = vboxInitQuietMode();
494
495 if(!rc && bTest3D)
496 rc = vboxCheck3DAccelerationSupported();
497
498#ifdef VBOX_WITH_VIDEOHWACCEL
499 if(!rc && bTest2D)
500 rc = vboxCheck2DVideoAccelerationSupported();
501#endif
502
503 }
504 }
505
506 /*RTR3Term();*/
507 return rc;
508
509}
510
511#ifdef RT_OS_WINDOWS
512extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
513{
514 RT_NOREF(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
515 return main(__argc, __argv);
516}
517#endif
518
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette