VirtualBox

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

Last change on this file since 85938 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

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