Panda3D
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 
51 union 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  */
61 static 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  */
76 static 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  */
91 static 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.
103 static PN_stdfloat detected_display_zoom = 1.0;
104 
105 TypeHandle GraphicsPipe::_type_handle;
106 
107 /**
108  *
109  */
110 GraphicsPipe::
111 GraphicsPipe() :
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  */
205 GraphicsPipe::
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  */
215 GraphicsPipe::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  */
226 PT(GraphicsStateGuardian) GraphicsPipe::
227 make_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  */
235 PT(GraphicsDevice) GraphicsPipe::
236 make_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  */
249 void GraphicsPipe::
250 close_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  */
259 PT(GraphicsOutput) GraphicsPipe::
260 make_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  */
284 PN_stdfloat GraphicsPipe::
285 get_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  */
298 void GraphicsPipe::
299 set_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  */
317 lookup_cpu_data() {
318 }
graphicsBuffer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
ConfigVariableDouble::get_value
get_value
Returns the variable's value.
Definition: configVariableDouble.h:43
GraphicsDevice
An abstract device object that is part of Graphics Pipe.
Definition: graphicsDevice.h:30
GraphicsPipe::get_display_information
get_display_information
Gets the pipe's DisplayInformation.
Definition: graphicsPipe.h:100
WindowProperties
A container for the various kinds of properties we might ask to have on a graphics window before we o...
Definition: windowProperties.h:29
graphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
GraphicsPipe::lookup_cpu_data
virtual void lookup_cpu_data()
Looks up the detailed CPU information and stores it in _display_information, if supported by the OS.
Definition: graphicsPipe.cxx:317
graphicsWindow.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DisplayInformation
This class contains various display information.
Definition: displayInformation.h:36
GraphicsPipe::get_display_zoom
get_display_zoom
Returns the display zoom factor configured in the operating system.
Definition: graphicsPipe.h:97
displayInformation.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
mutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
GraphicsPipe::get_preferred_window_thread
virtual PreferredWindowThread get_preferred_window_thread() const
Returns an indication of the thread in which this GraphicsPipe requires its window processing to be p...
Definition: graphicsPipe.cxx:216
config_display.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT
PT(GraphicsStateGuardian) GraphicsPipe
This is called when make_output() is used to create a CallbackGraphicsWindow.
Definition: graphicsPipe.cxx:226
ConfigVariable::get_num_words
size_t get_num_words() const
Returns the number of words in the variable's value.
Definition: configVariable.I:100