VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp@ 53546

Last change on this file since 53546 was 53546, checked in by vboxsync, 10 years ago

Mac OS X host: make 3D test more informative when it determines that host 3D capabilities not sufficient.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.2 KB
Line 
1/* $Id: OpenGLTestDarwin.cpp 53546 2014-12-16 11:54:40Z vboxsync $ */
2
3/** @file
4 * VBox host opengl support test
5 */
6
7/*
8 * Copyright (C) 2009-2014 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.215389.xyz. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19
20#include <IOKit/IOKitLib.h>
21#include <OpenGL/OpenGL.h>
22#include <ApplicationServices/ApplicationServices.h>
23#include <OpenGL/gl.h>
24#ifdef VBOX_WITH_COCOA_QT
25# include <OpenGL/glu.h>
26# include <iprt/log.h>
27#endif /* VBOX_WITH_COCOA_QT */
28#include <iprt/env.h>
29#include <iprt/log.h>
30
31#include <iprt/asm.h>
32#include <iprt/thread.h>
33
34#include <VBox/VBoxOGLTest.h>
35
36bool RTCALL VBoxOglIsOfflineRenderingAppropriate()
37{
38 /* It is assumed that it is makes sense to enable offline rendering
39 only in case if host has more than one GPU installed. This routine
40 counts all the PCI devices in IORegistry which have IOName property
41 set to "display". If the amount of such devices if greater than one,
42 it returns TRUE or FALSE otherwise. */
43
44 kern_return_t krc;
45 io_iterator_t matchingServices;
46 CFDictionaryRef pMatchingDictionary;
47 static bool fAppropriate = false;
48
49 /* In order to do not slowdown 3D engine which can ask about offline rendering several times,
50 let's cache the result and assume that renderers amount value is constant. Also prevent threads race
51 on startup. */
52
53#define VBOX_OGL_CHECK_UNINITIALIZED (0)
54#define VBOX_OGL_CHECK_INITIALIZING (1)
55#define VBOX_OGL_CHECK_INITIALIZED (2)
56
57 /* Transition VBOX_OGL_CHECK_UNINITIALIZED -> VBOX_OGL_CHECK_INITIALIZING means the current thread
58 is the first one who entered the routine. In this case, it should detect number of GPUs, cache result
59 and return it. If it's not TRUE, then fInitialized is VBOX_OGL_CHECK_INITIALIZING (another thread is performing
60 the check; current thread should wait till result will be cached and return it) or VBOX_OGL_CHECK_INITIALIZED
61 (result is already cached; just return it.) */
62
63 static uint32_t volatile fInitialized = VBOX_OGL_CHECK_UNINITIALIZED;
64 if (!ASMAtomicCmpXchgU32(&fInitialized, VBOX_OGL_CHECK_INITIALIZING, VBOX_OGL_CHECK_UNINITIALIZED))
65 {
66 while (ASMAtomicReadU32(&fInitialized) != VBOX_OGL_CHECK_INITIALIZED)
67 RTThreadSleep(5);
68
69 return fAppropriate;
70 }
71
72#define VBOX_OGL_RENDERER_MATCH_KEYS_NUM (2)
73
74 CFStringRef ppDictionaryKeys[VBOX_OGL_RENDERER_MATCH_KEYS_NUM] = { CFSTR(kIOProviderClassKey), CFSTR(kIONameMatchKey) };
75 CFStringRef ppDictionaryVals[VBOX_OGL_RENDERER_MATCH_KEYS_NUM] = { CFSTR("IOPCIDevice"), CFSTR("display") };
76
77 pMatchingDictionary = CFDictionaryCreate(kCFAllocatorDefault,
78 (const void **)ppDictionaryKeys,
79 (const void **)ppDictionaryVals,
80 VBOX_OGL_RENDERER_MATCH_KEYS_NUM,
81 &kCFTypeDictionaryKeyCallBacks,
82 &kCFTypeDictionaryValueCallBacks);
83 if (pMatchingDictionary)
84 {
85 /* The reference to pMatchingDictionary is consumed by the function below => no IORelease(pMatchingDictionary)! */
86 krc = IOServiceGetMatchingServices(kIOMasterPortDefault, pMatchingDictionary, &matchingServices);
87 if (krc == kIOReturnSuccess)
88 {
89 io_object_t matchingService;
90 int cMatchingServices = 0;
91
92 while ((matchingService = IOIteratorNext(matchingServices)) != 0)
93 {
94 cMatchingServices++;
95 IOObjectRelease(matchingService);
96 }
97
98 fAppropriate = (cMatchingServices > 1);
99
100 IOObjectRelease(matchingServices);
101 }
102
103 }
104
105 LogRel(("OpenGL: Offline rendering support is %s (PID=%d)\n", fAppropriate ? "ON" : "OFF", (int)getpid()));
106
107 ASMAtomicWriteU32(&fInitialized, VBOX_OGL_CHECK_INITIALIZED);
108
109 return fAppropriate;
110}
111
112bool RTCALL VBoxOglIs3DAccelerationSupported()
113{
114 if (RTEnvExist("VBOX_CROGL_FORCE_SUPPORTED"))
115 {
116 LogRel(("VBOX_CROGL_FORCE_SUPPORTED is specified, skipping 3D test, and treating as supported\n"));
117 return true;
118 }
119
120 CGDirectDisplayID display = CGMainDisplayID ();
121 CGOpenGLDisplayMask cglDisplayMask = CGDisplayIDToOpenGLDisplayMask (display);
122 CGLPixelFormatObj pixelFormat = NULL;
123 GLint numPixelFormats = 0;
124 CGLError rcCgl;
125
126 CGLPixelFormatAttribute attribs[] = {
127 kCGLPFADisplayMask,
128 (CGLPixelFormatAttribute)cglDisplayMask,
129 kCGLPFAAccelerated,
130 kCGLPFADoubleBuffer,
131 kCGLPFAWindow,
132 VBoxOglIsOfflineRenderingAppropriate() ? kCGLPFAAllowOfflineRenderers : (CGLPixelFormatAttribute)NULL,
133 (CGLPixelFormatAttribute)NULL
134 };
135
136 display = CGMainDisplayID();
137 cglDisplayMask = CGDisplayIDToOpenGLDisplayMask(display);
138 rcCgl = CGLChoosePixelFormat(attribs, &pixelFormat, &numPixelFormats);
139 if (rcCgl != kCGLNoError)
140 {
141 LogRel(("OpenGL Info: 3D test unable to choose pixel format (rcCgl=0x%X)\n", rcCgl));
142 return false;
143 }
144
145 if (pixelFormat)
146 {
147 CGLContextObj cglContext = 0;
148 rcCgl = CGLCreateContext(pixelFormat, NULL, &cglContext);
149 CGLDestroyPixelFormat(pixelFormat);
150
151 if (rcCgl != kCGLNoError)
152 {
153 LogRel(("OpenGL Info: 3D test unable to create context (rcCgl=0x%X)\n", rcCgl));
154 return false;
155 }
156
157 if (cglContext)
158 {
159 GLboolean isSupported = GL_TRUE;
160#ifdef VBOX_WITH_COCOA_QT
161 /* On the Cocoa port we depend on the GL_EXT_framebuffer_object &
162 * the GL_EXT_texture_rectangle extension. If they are not
163 * available, disable 3D support. */
164 CGLSetCurrentContext(cglContext);
165 const GLubyte* strExt;
166 strExt = glGetString(GL_EXTENSIONS);
167 isSupported = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_object", strExt);
168 if (isSupported)
169 {
170 isSupported = gluCheckExtension((const GLubyte*)"GL_EXT_texture_rectangle", strExt);
171 if (!isSupported)
172 LogRel(("OpenGL Info: 3D test found that GL_EXT_texture_rectangle extension not supported\n"));
173 }
174 else
175 LogRel(("OpenGL Info: 3D test found that GL_EXT_framebuffer_object extension not supported\n"));
176#endif /* VBOX_WITH_COCOA_QT */
177 CGLDestroyContext(cglContext);
178 LogRel(("OpenGL Info: 3D test %spassed\n", isSupported == GL_TRUE ? "" : "not "));
179 return isSupported == GL_TRUE ? true : false;
180 }
181 else
182 LogRel(("OpenGL Info: 3D test unable to create context (internal error)\n"));
183 }
184 else
185 LogRel(("OpenGL Info: 3D test unable to choose pixel format (internal error)\n"));
186
187 return false;
188}
189
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