VirtualBox

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

Last change on this file since 94884 was 94624, checked in by vboxsync, 3 years ago

Runtime/log: Allow setting a custom output interface for the file destination (for encryption), bugref:9955

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

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