VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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