VirtualBox

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

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

/Config.kmk and many other places: Change VBOX_VENDOR to the official copyright holder text, needs follow-up changes and equivalent adjustments elsewhere.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.8 KB
Line 
1/* $Id: OpenGLTestApp.cpp 96399 2022-08-22 14:47:39Z 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 "Copyright (C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
446 "\n"
447 "Parameters:\n"
448#ifdef VBOX_WITH_VIDEOHWACCEL
449 " --test 2D test for 2D (video) OpenGL capabilities\n"
450#endif
451 " --test 3D test for 3D OpenGL capabilities\n"
452#ifdef VBOXGLTEST_WITH_LOGGING
453 " --log <log_file_name> log the GL test result to the given file\n"
454 " --log-to-stdout log the GL test result to stdout\n"
455 "\n"
456 "Logging can alternatively be enabled by specifying the VBOXGLTEST_LOG=<log_file_name> env variable\n"
457
458#endif
459 "\n",
460 RTBldCfgVersionMajor(), RTBldCfgVersionMinor(), RTBldCfgVersionBuild());
461 return RTEXITCODE_SUCCESS;
462
463 case 'V':
464 RTPrintf("$Revision: 96399 $\n");
465 return RTEXITCODE_SUCCESS;
466
467 case VERR_GETOPT_UNKNOWN_OPTION:
468 case VINF_GETOPT_NOT_OPTION:
469 default:
470 return RTGetOptPrintError(rc, &Val);
471 }
472 }
473
474 /*
475 * Init logging and output.
476 */
477#ifdef VBOXGLTEST_WITH_LOGGING
478 if (!bLog)
479 {
480 /* check the VBOXGLTEST_LOG env var */
481 pLog = RTEnvGet("VBOXGLTEST_LOG");
482 if(pLog)
483 bLog = true;
484 bLogSuffix = true;
485 }
486 if (bLog)
487 rc = vboxInitLogging(pLog, bLogSuffix);
488 else
489#endif
490 rc = vboxInitQuietMode();
491
492 /*
493 * Do the job.
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 /*RTR3Term();*/
505 return rc;
506
507}
508
509#ifdef RT_OS_WINDOWS
510extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
511{
512 RT_NOREF(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
513 return main(__argc, __argv);
514}
515#endif
516
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