VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.1 KB
Line 
1/* $Id: OpenGLTestDarwin.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox host opengl support test
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
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/VBoxOGL.h>
33
34#include <IOKit/IOKitLib.h>
35#include <OpenGL/OpenGL.h>
36#include <ApplicationServices/ApplicationServices.h>
37#include <OpenGL/gl.h>
38#include <OpenGL/glu.h>
39
40#include <iprt/env.h>
41#include <iprt/log.h>
42#include <iprt/once.h>
43
44
45
46/**
47 * @callback_method_impl{FNRTONCE,
48 * For determining the cached VBoxOglIsOfflineRenderingAppropriate result.}
49 */
50static DECLCALLBACK(int32_t) vboxOglIsOfflineRenderingAppropriateOnce(void *pvUser)
51{
52 bool *pfAppropriate = (bool *)pvUser;
53
54 /* It is assumed that it is makes sense to enable offline rendering
55 only in case if host has more than one GPU installed. This routine
56 counts all the PCI devices in IORegistry which have IOName property
57 set to "display". If the number of such devices is greater than one,
58 it sets pfAppropriate to TRUE, otherwise to FALSE. */
59
60 CFStringRef apKeyStrings[] = { CFSTR(kIOProviderClassKey), CFSTR(kIONameMatchKey) };
61 CFStringRef apValueStrings[] = { CFSTR("IOPCIDevice"), CFSTR("display") };
62 Assert(RT_ELEMENTS(apKeyStrings) == RT_ELEMENTS(apValueStrings));
63
64 CFDictionaryRef pMatchingDictionary = CFDictionaryCreate(kCFAllocatorDefault,
65 (const void **)apKeyStrings,
66 (const void **)apValueStrings,
67 RT_ELEMENTS(apKeyStrings),
68 &kCFTypeDictionaryKeyCallBacks,
69 &kCFTypeDictionaryValueCallBacks);
70 if (pMatchingDictionary)
71 {
72 /* The reference to pMatchingDictionary is consumed by the function below => no IORelease(pMatchingDictionary)! */
73 io_iterator_t matchingServices;
74 kern_return_t krc = IOServiceGetMatchingServices(kIOMasterPortDefault, pMatchingDictionary, &matchingServices);
75 if (krc == kIOReturnSuccess)
76 {
77 io_object_t matchingService;
78 int cMatchingServices = 0;
79
80 while ((matchingService = IOIteratorNext(matchingServices)) != 0)
81 {
82 cMatchingServices++;
83 IOObjectRelease(matchingService);
84 }
85
86 *pfAppropriate = cMatchingServices > 1;
87
88 IOObjectRelease(matchingServices);
89 }
90 }
91
92 LogRel(("OpenGL: Offline rendering support is %s (pid=%d)\n", *pfAppropriate ? "ON" : "OFF", (int)getpid()));
93 return VINF_SUCCESS;
94}
95
96
97bool RTCALL VBoxOglIsOfflineRenderingAppropriate(void)
98{
99 /* In order to do not slowdown 3D engine which can ask about offline rendering several times,
100 let's cache the result and assume that renderers amount value is constant. Use the IPRT
101 execute once construct to make sure there aren't any threading issues. */
102 static RTONCE s_Once = RTONCE_INITIALIZER;
103 static bool s_fCached = false;
104 int rc = RTOnce(&s_Once, vboxOglIsOfflineRenderingAppropriateOnce, &s_fCached);
105 AssertRC(rc);
106 return s_fCached;
107}
108
109
110bool RTCALL VBoxOglIs3DAccelerationSupported(void)
111{
112 if (RTEnvExist("VBOX_3D_FORCE_SUPPORTED"))
113 {
114 LogRel(("VBOX_3D_FORCE_SUPPORTED is specified, skipping 3D test, and treating as supported\n"));
115 return true;
116 }
117
118 CGOpenGLDisplayMask cglDisplayMask = CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID());
119 CGLPixelFormatAttribute aAttribs[] =
120 {
121 kCGLPFADisplayMask,
122 (CGLPixelFormatAttribute)cglDisplayMask,
123 kCGLPFAAccelerated,
124 kCGLPFADoubleBuffer,
125 VBoxOglIsOfflineRenderingAppropriate() ? kCGLPFAAllowOfflineRenderers : (CGLPixelFormatAttribute)NULL,
126 (CGLPixelFormatAttribute)NULL
127 };
128 CGLPixelFormatObj pPixelFormat = NULL;
129 GLint cPixelFormatsIgnored = 0;
130 CGLError rcCgl = CGLChoosePixelFormat(aAttribs, &pPixelFormat, &cPixelFormatsIgnored);
131 if (rcCgl != kCGLNoError)
132 {
133 LogRel(("OpenGL Info: 3D test unable to choose pixel format (rcCgl=0x%X)\n", rcCgl));
134 return false;
135 }
136
137 if (pPixelFormat)
138 {
139 CGLContextObj pCglContext = 0;
140 rcCgl = CGLCreateContext(pPixelFormat, NULL, &pCglContext);
141 CGLDestroyPixelFormat(pPixelFormat);
142
143 if (rcCgl != kCGLNoError)
144 {
145 LogRel(("OpenGL Info: 3D test unable to create context (rcCgl=0x%X)\n", rcCgl));
146 return false;
147 }
148
149 if (pCglContext)
150 {
151 GLboolean isSupported = GL_TRUE;
152
153 /*
154 * In the Cocoa port we depend on the GL_EXT_framebuffer_object &
155 * the GL_EXT_texture_rectangle extension. If they are not
156 * available, disable 3D support.
157 */
158#pragma clang diagnostic ignored "-Wdeprecated-declarations" /* gluCheckExtension deprecated since 10.10 - use MetalKit. */
159 CGLSetCurrentContext(pCglContext);
160 const GLubyte *pszExts = glGetString(GL_EXTENSIONS);
161 isSupported = gluCheckExtension((const GLubyte *)"GL_EXT_framebuffer_object", pszExts);
162 if (isSupported)
163 {
164 isSupported = gluCheckExtension((const GLubyte *)"GL_EXT_texture_rectangle", pszExts);
165 if (!isSupported)
166 LogRel(("OpenGL Info: 3D test found that GL_EXT_texture_rectangle extension not supported.\n"));
167 }
168 else
169 LogRel(("OpenGL Info: 3D test found that GL_EXT_framebuffer_object extension not supported.\n"));
170
171 CGLDestroyContext(pCglContext);
172 LogRel(("OpenGL Info: 3D test %spassed\n", isSupported == GL_TRUE ? "" : "not "));
173 return isSupported == GL_TRUE;
174 }
175
176 LogRel(("OpenGL Info: 3D test unable to create context (internal error).\n"));
177 }
178 else
179 LogRel(("OpenGL Info: 3D test unable to choose pixel format (internal error).\n"));
180
181 return false;
182}
183
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