VirtualBox

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

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

OpenGLTest: qt6 adjustments. [fix] bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.7 KB
Line 
1/* $Id: OpenGLTestApp.cpp 94138 2022-03-08 22:24:06Z 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 /*pErrInfo*/, pszFilenameFmt, pszFilename, RTTimeMilliTS());
306 if (RT_SUCCESS(vrc))
307 {
308 /* some introductory information */
309 RTTIMESPEC timeSpec;
310 char szTmp[256];
311 RTTimeSpecToString(RTTimeNow(&timeSpec), szTmp, sizeof(szTmp));
312 RTLogRelLogger(loggerRelease, 0, ~0U,
313 "VBoxTestGL %s r%u %s (%s %s) release log\n"
314#ifdef VBOX_BLEEDING_EDGE
315 "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n"
316#endif
317 "Log opened %s\n",
318 VBOX_VERSION_STRING, RTBldCfgRevision(), VBOX_BUILD_TARGET,
319 __DATE__, __TIME__, szTmp);
320
321 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
322 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
323 RTLogRelLogger(loggerRelease, 0, ~0U, "OS Product: %s\n", szTmp);
324 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
325 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
326 RTLogRelLogger(loggerRelease, 0, ~0U, "OS Release: %s\n", szTmp);
327 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
328 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
329 RTLogRelLogger(loggerRelease, 0, ~0U, "OS Version: %s\n", szTmp);
330 vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp));
331 if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
332 RTLogRelLogger(loggerRelease, 0, ~0U, "OS Service Pack: %s\n", szTmp);
333// RTLogRelLogger(loggerRelease, 0, ~0U, "Host RAM: %uMB RAM, available: %uMB\n",
334// uHostRamMb, uHostRamAvailMb);
335 /* the package type is interesting for Linux distributions */
336 char szExecName[RTPATH_MAX];
337 char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
338 RTLogRelLogger(loggerRelease, 0, ~0U,
339 "Executable: %s\n"
340 "Process ID: %u\n"
341 "Package type: %s"
342#ifdef VBOX_OSE
343 " (OSE)"
344#endif
345 "\n",
346 pszExecName ? pszExecName : "unknown",
347 RTProcSelf(),
348 VBOX_PACKAGE_STRING);
349
350 /* register this logger as the release logger */
351 RTLogRelSetDefaultInstance(loggerRelease);
352
353 return VINF_SUCCESS;
354 }
355
356 return vrc;
357}
358#endif
359
360static int vboxInitQuietMode()
361{
362#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
363 /* This small test application might crash on some hosts. Do never
364 * generate a core dump as most likely some OpenGL library is
365 * responsible. */
366 struct rlimit lim = { 0, 0 };
367 setrlimit(RLIMIT_CORE, &lim);
368
369 /* Redirect stderr to /dev/null */
370 int fd = open("/dev/null", O_WRONLY);
371 if (fd != -1)
372 dup2(fd, STDERR_FILENO);
373#endif
374 return 0;
375}
376
377int main(int argc, char **argv)
378{
379 RTR3InitExe(argc, &argv, 0);
380
381 int rc = 0;
382 if (argc < 2)
383 {
384 /* backwards compatibility: check 3D */
385 rc = vboxCheck3DAccelerationSupported();
386 }
387 else
388 {
389 static const RTGETOPTDEF s_aOptionDefs[] =
390 {
391 { "--test", 't', RTGETOPT_REQ_STRING },
392 { "-test", 't', RTGETOPT_REQ_STRING },
393#ifdef VBOXGLTEST_WITH_LOGGING
394 { "--log", 'l', RTGETOPT_REQ_STRING },
395 { "--log-to-stdout", 'L', RTGETOPT_REQ_NOTHING },
396#endif
397 };
398
399 RTGETOPTSTATE State;
400 rc = RTGetOptInit(&State, argc, argv, &s_aOptionDefs[0], RT_ELEMENTS(s_aOptionDefs), 1, 0);
401 AssertRCReturn(rc, 49);
402
403#ifdef VBOX_WITH_VIDEOHWACCEL
404 bool bTest2D = false;
405#endif
406 bool bTest3D = false;
407#ifdef VBOXGLTEST_WITH_LOGGING
408 bool bLog = false;
409 bool bLogSuffix = false;
410 const char * pLog = NULL;
411#endif
412
413 for (;;)
414 {
415 RTGETOPTUNION Val;
416 rc = RTGetOpt(&State, &Val);
417 if (!rc)
418 break;
419 switch (rc)
420 {
421 case 't':
422 if (!strcmp(Val.psz, "3D") || !strcmp(Val.psz, "3d"))
423 bTest3D = true;
424#ifdef VBOX_WITH_VIDEOHWACCEL
425 else if (!strcmp(Val.psz, "2D") || !strcmp(Val.psz, "2d"))
426 bTest2D = true;
427#endif
428 else
429 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unknown test: %s", Val.psz);
430 break;
431
432#ifdef VBOXGLTEST_WITH_LOGGING
433 case 'l':
434 bLog = true;
435 pLog = Val.psz;
436 break;
437 case 'L':
438 bLog = true;
439 pLog = NULL;
440 break;
441#endif
442 case 'h':
443 RTPrintf(VBOX_PRODUCT " Helper for testing 2D/3D OpenGL capabilities %u.%u.%u\n"
444 "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
445 "All rights reserved.\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: 94138 $\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.

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