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 }
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.
Definition: graphicsPipe.h:97
get_display_information
Gets the pipe's DisplayInformation.
Definition: graphicsPipe.h:100
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.
PT(GraphicsStateGuardian) GraphicsPipe
This is called when make_output() is used to create a CallbackGraphicsWindow.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.