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 TypeHandle GraphicsPipe::_type_handle;
103 
104 /**
105  *
106  */
107 GraphicsPipe::
108 GraphicsPipe() :
109  _lock("GraphicsPipe")
110 {
111  // Initially, we assume the GraphicsPipe is valid. A derived class should
112  // set this to false if it determines otherwise.
113  _is_valid = true;
114 
115  // A derived class must indicate the kinds of GraphicsOutput objects it can
116  // create.
117  _supported_types = 0;
118 
119  _display_width = 0;
120  _display_height = 0;
121 
122  _display_information = new DisplayInformation();
123 
124 #if defined(__i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
125  cpuid_info info;
126  const uint32_t max_cpuid = get_cpuid_max(0);
127  const uint32_t max_extended = get_cpuid_max(0x80000000);
128 
129  if (max_cpuid >= 1) {
130  get_cpuid(0, info);
131  std::swap(info.ecx, info.edx);
132  _display_information->_cpu_vendor_string = std::string(info.str + 4, 12);
133 
134  get_cpuid(1, info);
135  _display_information->_cpu_version_information = info.eax;
136  _display_information->_cpu_brand_index = info.ebx & 0xff;
137  }
138 
139  if (max_extended >= 0x80000004) {
140  char brand[49];
141  get_cpuid(0x80000002, info);
142  memcpy(brand, info.str, 16);
143  get_cpuid(0x80000003, info);
144  memcpy(brand + 16, info.str, 16);
145  get_cpuid(0x80000004, info);
146  memcpy(brand + 32, info.str, 16);
147  brand[48] = 0;
148  _display_information->_cpu_brand_string = brand;
149  }
150 #endif
151 
152 #if defined(IS_OSX)
153  // macOS exposes a lot of useful information through sysctl.
154  size_t len = sizeof(uint64_t);
155  sysctlbyname("hw.memsize", &_display_information->_physical_memory, &len, nullptr, 0);
156  len = sizeof(uint64_t);
157  sysctlbyname("hw.cpufrequency", &_display_information->_cpu_frequency, &len, nullptr, 0);
158  len = sizeof(uint64_t);
159  sysctlbyname("hw.cpufrequency", &_display_information->_current_cpu_frequency, &len, nullptr, 0);
160  len = sizeof(uint64_t);
161  sysctlbyname("hw.cpufrequency_max", &_display_information->_maximum_cpu_frequency, &len, nullptr, 0);
162  len = sizeof(int);
163  sysctlbyname("hw.physicalcpu", &_display_information->_num_cpu_cores, &len, nullptr, 0);
164  len = sizeof(int);
165  sysctlbyname("hw.logicalcpu", &_display_information->_num_logical_cpus, &len, nullptr, 0);
166 
167 #elif defined(IS_LINUX)
168  _display_information->_get_memory_information_function = &update_memory_info;
169  update_memory_info(_display_information);
170 
171 #elif defined(IS_FREEBSD)
172  size_t len = sizeof(uint64_t);
173  sysctlbyname("hw.physmem", &_display_information->_physical_memory, &len, nullptr, 0);
174  len = sizeof(uint64_t);
175  sysctlbyname("vm.swap_total", &_display_information->_page_file_size, &len, nullptr, 0);
176 
177 #elif defined(_WIN32)
178  MEMORYSTATUSEX status;
179  status.dwLength = sizeof(MEMORYSTATUSEX);
180  if (GlobalMemoryStatusEx(&status)) {
181  _display_information->_physical_memory = status.ullTotalPhys;
182  _display_information->_available_physical_memory = status.ullAvailPhys;
183  _display_information->_page_file_size = status.ullTotalPageFile;
184  _display_information->_available_page_file_size = status.ullAvailPageFile;
185  _display_information->_process_virtual_memory = status.ullTotalVirtual;
186  _display_information->_available_process_virtual_memory = status.ullAvailVirtual;
187  _display_information->_memory_load = status.dwMemoryLoad;
188  }
189 #endif
190 
191 #if defined(IS_LINUX) || defined(IS_FREEBSD)
192  long nproc = sysconf(_SC_NPROCESSORS_CONF);
193  if (nproc > 0) {
194  _display_information->_num_logical_cpus = nproc;
195  }
196 #endif
197 }
198 
199 /**
200  *
201  */
202 GraphicsPipe::
203 ~GraphicsPipe() {
204  delete _display_information;
205 }
206 
207 /**
208  * Returns an indication of the thread in which this GraphicsPipe requires its
209  * window processing to be performed: typically either the app thread (e.g.
210  * X) or the draw thread (Windows).
211  */
212 GraphicsPipe::PreferredWindowThread
214  return PWT_draw;
215 }
216 
217 /**
218  * This is called when make_output() is used to create a
219  * CallbackGraphicsWindow. If the GraphicsPipe can construct a GSG that's not
220  * associated with any particular window object, do so now, assuming the
221  * correct graphics context has been set up externally.
222  */
223 PT(GraphicsStateGuardian) GraphicsPipe::
224 make_callback_gsg(GraphicsEngine *engine) {
225  return nullptr;
226 }
227 
228 /**
229  * Creates a new device for the pipe. Only DirectX uses this device, for
230  * other api's it is NULL.
231  */
232 PT(GraphicsDevice) GraphicsPipe::
233 make_device(void *scrn) {
234  display_cat.error()
235  << "make_device() unimplemented by " << get_type() << "\n";
236  return nullptr;
237 }
238 
239 /**
240  * This will be called in the draw thread (the same thread in which the GSG
241  * was created via make_gsg, above) to close the indicated GSG and free its
242  * associated graphics objects just before it is destructed. This method
243  * exists to provide a hook for the graphics pipe to do any necessary cleanup,
244  * if any.
245  */
246 void GraphicsPipe::
247 close_gsg(GraphicsStateGuardian *gsg) {
248  if (gsg != nullptr) {
249  gsg->close_gsg();
250  }
251 }
252 
253 /**
254  * Creates a new window on the pipe, if possible.
255  */
256 PT(GraphicsOutput) GraphicsPipe::
257 make_output(const std::string &name,
258  const FrameBufferProperties &fb_prop,
259  const WindowProperties &win_prop,
260  int flags,
261  GraphicsEngine *engine,
263  GraphicsOutput *host,
264  int retry,
265  bool &precertify) {
266  display_cat.error()
267  << get_type() << " cannot create buffers or windows.\n";
268  return nullptr;
269 }
270 
271 /**
272  * Gets the pipe's DisplayInformation.
273  */
276  return _display_information;
277 }
278 
279 /**
280  * Looks up the detailed CPU information and stores it in
281  * _display_information, if supported by the OS. This may take a second or
282  * two.
283  */
285 lookup_cpu_data() {
286 }
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
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:98
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:285
graphicsWindow.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DisplayInformation
This class contains various display information.
Definition: displayInformation.h:36
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:213
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:223