Panda3D
Loading...
Searching...
No Matches
graphicsPipe.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file graphicsPipe.cxx
10 * @author mike
11 * @date 1997-01-09
12 */
13
14#include "graphicsPipe.h"
15#include "graphicsWindow.h"
16#include "graphicsBuffer.h"
17#include "config_display.h"
18#include "mutexHolder.h"
19#include "displayInformation.h"
20
21#ifdef IS_LINUX
22#include <sys/sysinfo.h>
23#include <unistd.h>
24#endif
25
26#if defined(IS_OSX) || defined(IS_FREEBSD)
27#include <sys/sysctl.h>
28#include <unistd.h>
29#endif
30
31#ifdef _WIN32
32#ifndef WIN32_LEAN_AND_MEAN
33#define WIN32_LEAN_AND_MEAN 1
34#endif
35#include <windows.h>
36#endif
37
38// CPUID is only available on i386 and x86-64 architectures.
39#if defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
40
41#if defined(__GNUC__) && !defined(__APPLE__)
42// GCC and Clang offer a useful cpuid.h header.
43#include <cpuid.h>
44#endif
45
46#ifdef _MSC_VER
47// MSVC has a __cpuid intrinsic.
48#include <intrin.h>
49#endif
50
51union cpuid_info {
52 char str[16];
53 struct {
54 uint32_t eax, ebx, ecx, edx;
55 };
56};
57
58/**
59 * Gets cpuid info for the given leaf.
60 */
61static inline void get_cpuid(uint32_t leaf, cpuid_info &info) {
62#if defined(__GNUC__) && !defined(__APPLE__)
63 __cpuid(leaf, info.eax, info.ebx, info.ecx, info.edx);
64#elif defined(_MSC_VER)
65 __cpuid((int *)info.str, leaf);
66#else
67 __asm__ ("cpuid\n\t"
68 : "=a" (info.eax), "=b" (info.ebx), "=c" (info.ecx), "=d" (info.edx)
69 : "0" (leaf));
70#endif
71}
72
73/**
74 * Returns the highest cpuid leaf that is supported by the CPU.
75 */
76static inline uint32_t get_cpuid_max(uint32_t leaf) {
77#if defined(__GNUC__) && !defined(__APPLE__)
78 return __get_cpuid_max(leaf, nullptr);
79#else
80 cpuid_info info;
81 get_cpuid(leaf, info);
82 return info.eax;
83#endif
84}
85#endif
86
87#ifdef IS_LINUX
88/**
89 * Updates the current memory usage statistics in the DisplayInformation.
90 */
91static void update_memory_info(DisplayInformation *info) {
92 struct sysinfo meminfo;
93 if (sysinfo(&meminfo) == 0) {
94 info->_physical_memory = meminfo.totalram;
95 info->_available_physical_memory = meminfo.freeram;
96 info->_page_file_size = meminfo.totalswap;
97 info->_available_page_file_size = meminfo.freeswap;
98 }
99}
100#endif
101
102// Temporarily declared as global float.
103static PN_stdfloat detected_display_zoom = 1.0;
104
105TypeHandle GraphicsPipe::_type_handle;
106
107/**
108 *
109 */
110GraphicsPipe::
111GraphicsPipe() :
112 _lock("GraphicsPipe")
113{
114 // Initially, we assume the GraphicsPipe is valid. A derived class should
115 // set this to false if it determines otherwise.
116 _is_valid = true;
117
118 // A derived class must indicate the kinds of GraphicsOutput objects it can
119 // create.
120 _supported_types = 0;
121
122 _display_width = 0;
123 _display_height = 0;
124
125 _display_information = new DisplayInformation();
126
127#if defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
128 cpuid_info info;
129 const uint32_t max_cpuid = get_cpuid_max(0);
130 const uint32_t max_extended = get_cpuid_max(0x80000000);
131
132 if (max_cpuid >= 1) {
133 get_cpuid(0, info);
134 std::swap(info.ecx, info.edx);
135 _display_information->_cpu_vendor_string = std::string(info.str + 4, 12);
136
137 get_cpuid(1, info);
138 _display_information->_cpu_version_information = info.eax;
139 _display_information->_cpu_brand_index = info.ebx & 0xff;
140 }
141
142 if (max_extended >= 0x80000004) {
143 char brand[49];
144 get_cpuid(0x80000002, info);
145 memcpy(brand, info.str, 16);
146 get_cpuid(0x80000003, info);
147 memcpy(brand + 16, info.str, 16);
148 get_cpuid(0x80000004, info);
149 memcpy(brand + 32, info.str, 16);
150 brand[48] = 0;
151 _display_information->_cpu_brand_string = brand;
152 }
153#endif
154
155#if defined(IS_OSX)
156 // macOS exposes a lot of useful information through sysctl.
157 size_t len = sizeof(uint64_t);
158 sysctlbyname("hw.memsize", &_display_information->_physical_memory, &len, nullptr, 0);
159 len = sizeof(uint64_t);
160 sysctlbyname("hw.cpufrequency", &_display_information->_cpu_frequency, &len, nullptr, 0);
161 len = sizeof(uint64_t);
162 sysctlbyname("hw.cpufrequency", &_display_information->_current_cpu_frequency, &len, nullptr, 0);
163 len = sizeof(uint64_t);
164 sysctlbyname("hw.cpufrequency_max", &_display_information->_maximum_cpu_frequency, &len, nullptr, 0);
165 len = sizeof(int);
166 sysctlbyname("hw.physicalcpu", &_display_information->_num_cpu_cores, &len, nullptr, 0);
167 len = sizeof(int);
168 sysctlbyname("hw.logicalcpu", &_display_information->_num_logical_cpus, &len, nullptr, 0);
169
170#elif defined(IS_LINUX)
171 _display_information->_get_memory_information_function = &update_memory_info;
172 update_memory_info(_display_information);
173
174#elif defined(IS_FREEBSD)
175 size_t len = sizeof(uint64_t);
176 sysctlbyname("hw.physmem", &_display_information->_physical_memory, &len, nullptr, 0);
177 len = sizeof(uint64_t);
178 sysctlbyname("vm.swap_total", &_display_information->_page_file_size, &len, nullptr, 0);
179
180#elif defined(_WIN32)
181 MEMORYSTATUSEX status;
182 status.dwLength = sizeof(MEMORYSTATUSEX);
183 if (GlobalMemoryStatusEx(&status)) {
184 _display_information->_physical_memory = status.ullTotalPhys;
185 _display_information->_available_physical_memory = status.ullAvailPhys;
186 _display_information->_page_file_size = status.ullTotalPageFile;
187 _display_information->_available_page_file_size = status.ullAvailPageFile;
188 _display_information->_process_virtual_memory = status.ullTotalVirtual;
189 _display_information->_available_process_virtual_memory = status.ullAvailVirtual;
190 _display_information->_memory_load = status.dwMemoryLoad;
191 }
192#endif
193
194#if defined(IS_LINUX) || defined(IS_FREEBSD)
195 long nproc = sysconf(_SC_NPROCESSORS_CONF);
196 if (nproc > 0) {
197 _display_information->_num_logical_cpus = nproc;
198 }
199#endif
200}
201
202/**
203 *
204 */
205GraphicsPipe::
206~GraphicsPipe() {
207 delete _display_information;
208}
209
210/**
211 * Returns an indication of the thread in which this GraphicsPipe requires its
212 * window processing to be performed: typically either the app thread (e.g.
213 * X) or the draw thread (Windows).
214 */
215GraphicsPipe::PreferredWindowThread
217 return PWT_draw;
218}
219
220/**
221 * This is called when make_output() is used to create a
222 * CallbackGraphicsWindow. If the GraphicsPipe can construct a GSG that's not
223 * associated with any particular window object, do so now, assuming the
224 * correct graphics context has been set up externally.
225 */
226PT(GraphicsStateGuardian) GraphicsPipe::
227make_callback_gsg(GraphicsEngine *engine) {
228 return nullptr;
229}
230
231/**
232 * Creates a new device for the pipe. Only DirectX uses this device, for
233 * other api's it is NULL.
234 */
235PT(GraphicsDevice) GraphicsPipe::
236make_device(void *scrn) {
237 display_cat.error()
238 << "make_device() unimplemented by " << get_type() << "\n";
239 return nullptr;
240}
241
242/**
243 * This will be called in the draw thread (the same thread in which the GSG
244 * was created via make_gsg, above) to close the indicated GSG and free its
245 * associated graphics objects just before it is destructed. This method
246 * exists to provide a hook for the graphics pipe to do any necessary cleanup,
247 * if any.
248 */
249void GraphicsPipe::
250close_gsg(GraphicsStateGuardian *gsg) {
251 if (gsg != nullptr) {
252 gsg->close_gsg();
253 }
254}
255
256/**
257 * Creates a new window on the pipe, if possible.
258 */
259PT(GraphicsOutput) GraphicsPipe::
260make_output(const std::string &name,
261 const FrameBufferProperties &fb_prop,
262 const WindowProperties &win_prop,
263 int flags,
264 GraphicsEngine *engine,
266 GraphicsOutput *host,
267 int retry,
268 bool &precertify) {
269 display_cat.error()
270 << get_type() << " cannot create buffers or windows.\n";
271 return nullptr;
272}
273
274/**
275 * Returns the display zoom factor configured in the operating system. If the
276 * operating system automatically scales windows to match the DPI (such as when
277 * dpi-aware is set to false), this will be 1.0. Otherwise, this will be set to
278 * a value approximating the density of the monitor divided by the standard
279 * density of the operating system (usually 96), yielding a value like 1.5 or
280 * 2.0.
281 *
282 * @since 1.10.8
283 */
284PN_stdfloat GraphicsPipe::
285get_display_zoom() const {
286 if (display_zoom.get_num_words() > 0) {
287 double override = display_zoom.get_value();
288 if (override != 0.0) {
289 return override;
290 }
291 }
292 return detected_display_zoom;
293}
294
295/**
296 * Called by derived class to set the display zoom factor.
297 */
298void GraphicsPipe::
299set_detected_display_zoom(PN_stdfloat zoom) {
300 detected_display_zoom = zoom;
301}
302
303/**
304 * Gets the pipe's DisplayInformation.
305 */
308 return _display_information;
309}
310
311/**
312 * Looks up the detailed CPU information and stores it in
313 * _display_information, if supported by the OS. This may take a second or
314 * two.
315 */
get_value
Returns the variable's value.
size_t get_num_words() const
Returns the number of words in the variable's value.
This class contains various display information.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
An abstract device object that is part of Graphics Pipe.
This class is the main interface to controlling the render process.
This is a base class for the various different classes that represent the result of a frame of render...
get_display_zoom
Returns the display zoom factor configured in the operating system.
get_display_information
Gets the pipe's DisplayInformation.
virtual void lookup_cpu_data()
Looks up the detailed CPU information and stores it in _display_information, if supported by the OS.
virtual PreferredWindowThread get_preferred_window_thread() const
Returns an indication of the thread in which this GraphicsPipe requires its window processing to be p...
Encapsulates all the communication with a particular instance of a given rendering backend.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
A container for the various kinds of properties we might ask to have on a graphics window before we o...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.