Panda3D
|
00001 // Filename: frameBufferProperties.cxx 00002 // Created by: drose (27Jan03) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "frameBufferProperties.h" 00016 #include "string_utils.h" 00017 #include "renderBuffer.h" 00018 #include "config_display.h" 00019 00020 //////////////////////////////////////////////////////////////////// 00021 // Function: FrameBufferProperties::Constructor 00022 // Access: Published 00023 // Description: 00024 //////////////////////////////////////////////////////////////////// 00025 FrameBufferProperties:: 00026 FrameBufferProperties() { 00027 clear(); 00028 } 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Function: FrameBufferProperties::Copy Assignment Operator 00032 // Access: Published 00033 // Description: 00034 //////////////////////////////////////////////////////////////////// 00035 void FrameBufferProperties:: 00036 operator = (const FrameBufferProperties ©) { 00037 for (int i=0; i<FBP_COUNT; i++) { 00038 _specified[i] = copy._specified[i]; 00039 _property[i] = copy._property[i]; 00040 } 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: FrameBufferProperties::subsumes 00045 // Access: Public 00046 // Description: Returns true if this set of properties makes 00047 // strictly greater or equal demands of the framebuffer 00048 // than the other set of framebuffer properties. 00049 //////////////////////////////////////////////////////////////////// 00050 bool FrameBufferProperties:: 00051 subsumes(const FrameBufferProperties &other) const { 00052 for (int i=0; i<FBP_COUNT; i++) { 00053 if (other._property[i] > _property[i]) { 00054 return false; 00055 } 00056 } 00057 return true; 00058 } 00059 00060 //////////////////////////////////////////////////////////////////// 00061 // Function: FrameBufferProperties::get_default 00062 // Access: Published, Static 00063 // Description: Returns a FrameBufferProperties structure with all of 00064 // the default values filled in according to the user's 00065 // config file. 00066 //////////////////////////////////////////////////////////////////// 00067 const FrameBufferProperties &FrameBufferProperties:: 00068 get_default() { 00069 static bool default_ready = false; 00070 static FrameBufferProperties default_props; 00071 00072 if (default_ready) { 00073 return default_props; 00074 } 00075 00076 default_props.set_rgb_color(1); 00077 default_props.set_back_buffers(back_buffers); 00078 00079 int num_words = framebuffer_mode.get_num_words(); 00080 if (num_words > 0) { 00081 display_cat.error() 00082 << "The config-variable 'framebuffer-mode' no longer functions.\n"; 00083 display_cat.error() 00084 << "Instead, use one or more of these:\n"; 00085 display_cat.error() << " framebuffer-hardware #t\n"; 00086 display_cat.error() << " framebuffer-software #t\n"; 00087 display_cat.error() << " framebuffer-depth #t\n"; 00088 display_cat.error() << " framebuffer-alpha #t\n"; 00089 display_cat.error() << " framebuffer-stencil #t\n"; 00090 display_cat.error() << " framebuffer-multisample #t\n"; 00091 display_cat.error() << " framebuffer-stereo #t\n"; 00092 display_cat.error() << " depth-bits N\n"; 00093 display_cat.error() << " color-bits N\n"; 00094 display_cat.error() << " alpha-bits N\n"; 00095 display_cat.error() << " stencil-bits N\n"; 00096 display_cat.error() << " multisamples N\n"; 00097 display_cat.error() << " back-buffers N\n"; 00098 } 00099 00100 if (framebuffer_hardware) { 00101 default_props.set_force_hardware(1); 00102 } 00103 if (framebuffer_software) { 00104 default_props.set_force_software(1); 00105 } 00106 if (framebuffer_depth) { 00107 default_props.set_depth_bits(1); 00108 } 00109 if (framebuffer_alpha) { 00110 default_props.set_alpha_bits(1); 00111 } 00112 if (framebuffer_stencil) { 00113 default_props.set_stencil_bits(1); 00114 } 00115 if (framebuffer_accum) { 00116 default_props.set_accum_bits(1); 00117 } 00118 if (framebuffer_multisample) { 00119 default_props.set_multisamples(1); 00120 } 00121 if (framebuffer_stereo) { 00122 default_props.set_stereo(1); 00123 } 00124 if (depth_bits > 0) { 00125 default_props.set_depth_bits(depth_bits); 00126 } 00127 if (color_bits > 0) { 00128 default_props.set_color_bits(color_bits); 00129 } 00130 if (alpha_bits > 0) { 00131 default_props.set_alpha_bits(alpha_bits); 00132 } 00133 if (stencil_bits > 0) { 00134 default_props.set_stencil_bits(stencil_bits); 00135 } 00136 if (accum_bits > 0) { 00137 default_props.set_accum_bits(accum_bits); 00138 } 00139 if (multisamples > 0) { 00140 default_props.set_multisamples(multisamples); 00141 } 00142 00143 if ((default_props._property[FBP_force_software])&& 00144 (default_props._property[FBP_force_hardware])) { 00145 default_props._property[FBP_force_software] = 0; 00146 default_props._property[FBP_force_hardware] = 0; 00147 } 00148 00149 default_ready = true; 00150 return default_props; 00151 } 00152 00153 //////////////////////////////////////////////////////////////////// 00154 // Function: FrameBufferProperties::operator == 00155 // Access: Published 00156 // Description: 00157 //////////////////////////////////////////////////////////////////// 00158 bool FrameBufferProperties:: 00159 operator == (const FrameBufferProperties &other) const { 00160 for (int i=0; i<FBP_COUNT; i++) { 00161 if (_specified[i] != other._specified[i]) { 00162 return false; 00163 } 00164 if (_property[i] != other._property[i]) { 00165 return false; 00166 } 00167 } 00168 return true; 00169 } 00170 00171 //////////////////////////////////////////////////////////////////// 00172 // Function: FrameBufferProperties::clear 00173 // Access: Published 00174 // Description: Unsets all properties that have been specified so 00175 // far, and resets the FrameBufferProperties structure to its 00176 // initial empty state. 00177 //////////////////////////////////////////////////////////////////// 00178 void FrameBufferProperties:: 00179 clear() { 00180 for (int i=0; i<FBP_COUNT; i++) { 00181 _specified[i] = 0; 00182 _property[i] = 0; 00183 } 00184 } 00185 00186 //////////////////////////////////////////////////////////////////// 00187 // Function: FrameBufferProperties::add_properties 00188 // Access: Published 00189 // Description: Sets any properties that are explicitly specified in 00190 // other on this object. Leaves other properties 00191 // unchanged. 00192 //////////////////////////////////////////////////////////////////// 00193 void FrameBufferProperties:: 00194 add_properties(const FrameBufferProperties &other) { 00195 for (int i=0; i<FBP_COUNT; i++) { 00196 if (other._specified[i]) { 00197 _property[i] = other._property[i]; 00198 _specified[i] = true; 00199 } 00200 } 00201 } 00202 00203 //////////////////////////////////////////////////////////////////// 00204 // Function: FrameBufferProperties::output 00205 // Access: Published 00206 // Description: Sets any properties that are explicitly specified in 00207 // other on this object. Leaves other properties 00208 // unchanged. 00209 //////////////////////////////////////////////////////////////////// 00210 void FrameBufferProperties:: 00211 output(ostream &out) const { 00212 if (_property[FBP_depth_bits] > 0) { 00213 out << "depth_bits=" << _property[FBP_depth_bits] << " "; 00214 } 00215 if (_property[FBP_color_bits] > 0) { 00216 out << "color_bits=" << _property[FBP_color_bits] << " "; 00217 } 00218 if (_property[FBP_alpha_bits] > 0) { 00219 out << "alpha_bits=" << _property[FBP_alpha_bits] << " "; 00220 } 00221 if (_property[FBP_stencil_bits] > 0) { 00222 out << "stencil_bits=" << _property[FBP_stencil_bits] << " "; 00223 } 00224 if (_property[FBP_accum_bits] > 0) { 00225 out << "accum_bits=" << _property[FBP_accum_bits] << " "; 00226 } 00227 if (_property[FBP_aux_rgba] > 0) { 00228 out << "aux_rgba=" << _property[FBP_aux_rgba] << " "; 00229 } 00230 if (_property[FBP_aux_hrgba] > 0) { 00231 out << "aux_hrgba=" << _property[FBP_aux_hrgba] << " "; 00232 } 00233 if (_property[FBP_aux_float] > 0) { 00234 out << "aux_float=" << _property[FBP_aux_float] << " "; 00235 } 00236 if (_property[FBP_multisamples] > 0) { 00237 out << "multisamples=" << _property[FBP_multisamples] << " "; 00238 } 00239 if (_property[FBP_back_buffers] > 0) { 00240 out << "back_buffers=" << _property[FBP_back_buffers] << " "; 00241 } 00242 if (_property[FBP_indexed_color] > 0) { 00243 out << "indexed_color=" << _property[FBP_indexed_color] << " "; 00244 } 00245 if (_property[FBP_stereo] > 0) { 00246 out << "stereo=" << _property[FBP_stereo] << " "; 00247 } 00248 if (_property[FBP_force_hardware] > 0) { 00249 out << "force_hardware=" << _property[FBP_force_hardware] << " "; 00250 } 00251 if (_property[FBP_force_software] > 0) { 00252 out << "force_software=" << _property[FBP_force_software] << " "; 00253 } 00254 } 00255 00256 //////////////////////////////////////////////////////////////////// 00257 // Function: FrameBufferProperties::get_aux_mask 00258 // Access: Published 00259 // Description: Converts the aux bitplanes of the 00260 // framebuffer into a RenderBuffer::Type. 00261 //////////////////////////////////////////////////////////////////// 00262 int FrameBufferProperties:: 00263 get_aux_mask() const { 00264 int mask = 0; 00265 for (int i=0; i<_property[FBP_aux_rgba]; i++) { 00266 mask |= (RenderBuffer::T_aux_rgba_0 << i); 00267 } 00268 for (int i=0; i<_property[FBP_aux_hrgba]; i++) { 00269 mask |= (RenderBuffer::T_aux_hrgba_0 << i); 00270 } 00271 for (int i=0; i<_property[FBP_aux_float]; i++) { 00272 mask |= (RenderBuffer::T_aux_float_0 << i); 00273 } 00274 return mask; 00275 } 00276 00277 //////////////////////////////////////////////////////////////////// 00278 // Function: FrameBufferProperties::get_buffer_mask 00279 // Access: Private 00280 // Description: Converts the non-aux bitplanes of the 00281 // framebuffer into a RenderBuffer::Type. 00282 //////////////////////////////////////////////////////////////////// 00283 int FrameBufferProperties:: 00284 get_buffer_mask() const { 00285 int mask = 0; 00286 00287 if (_property[FBP_back_buffers] > 0) { 00288 mask = RenderBuffer::T_front | RenderBuffer::T_back; 00289 } else { 00290 mask = RenderBuffer::T_front; 00291 } 00292 if (_property[FBP_depth_bits] > 0) { 00293 mask |= RenderBuffer::T_depth; 00294 } 00295 if (_property[FBP_stencil_bits] > 0) { 00296 mask |= RenderBuffer::T_stencil; 00297 } 00298 return mask; 00299 } 00300 00301 //////////////////////////////////////////////////////////////////// 00302 // Function: FrameBufferProperties::is_any_specified 00303 // Access: Published 00304 // Description: Returns true if any properties have been specified, 00305 // false otherwise. 00306 //////////////////////////////////////////////////////////////////// 00307 bool FrameBufferProperties:: 00308 is_any_specified() const { 00309 for (int i=0; i<FBP_COUNT; i++) { 00310 if (_specified[i]) { 00311 return true; 00312 } 00313 } 00314 return false; 00315 } 00316 00317 //////////////////////////////////////////////////////////////////// 00318 // Function: FrameBufferProperties::set_all_specified 00319 // Access: Published 00320 // Description: sets all the specified bits. 00321 //////////////////////////////////////////////////////////////////// 00322 void FrameBufferProperties:: 00323 set_all_specified() { 00324 for (int i=0; i<FBP_COUNT; i++) { 00325 _specified[i] = true; 00326 } 00327 } 00328 00329 //////////////////////////////////////////////////////////////////// 00330 // Function: FrameBufferProperties::is_basic 00331 // Access: Published 00332 // Description: Returns true if the properties are extremely basic. 00333 // The following count as basic: rgb or rgba, depth. 00334 // If anything else is specified, the properties are 00335 // non-basic. 00336 //////////////////////////////////////////////////////////////////// 00337 bool FrameBufferProperties:: 00338 is_basic() const { 00339 if (_property[FBP_depth_bits] > 1) { 00340 return false; 00341 } 00342 if (_property[FBP_color_bits] > 1) { 00343 return false; 00344 } 00345 if (_property[FBP_alpha_bits] > 1) { 00346 return false; 00347 } 00348 if (_property[FBP_stencil_bits] > 0) { 00349 return false; 00350 } 00351 if (_property[FBP_aux_rgba] > 0) { 00352 return false; 00353 } 00354 if (_property[FBP_aux_hrgba] > 0) { 00355 return false; 00356 } 00357 if (_property[FBP_aux_float] > 0) { 00358 return false; 00359 } 00360 if (_property[FBP_multisamples] > 1) { 00361 return false; 00362 } 00363 if (_property[FBP_back_buffers] > 0) { 00364 return false; 00365 } 00366 if (_property[FBP_indexed_color] > 0) { 00367 return false; 00368 } 00369 if (_property[FBP_force_hardware] > 0) { 00370 return false; 00371 } 00372 if (_property[FBP_force_software] > 0) { 00373 return false; 00374 } 00375 return true; 00376 } 00377 00378 //////////////////////////////////////////////////////////////////// 00379 // Function: FrameBufferProperties::set_one_bit_per_channel 00380 // Access: Published 00381 // Description: If any of the depth, color, alpha, accum, or 00382 // stencil properties is set to more than one, 00383 // then they are reduced to one. 00384 //////////////////////////////////////////////////////////////////// 00385 void FrameBufferProperties:: 00386 set_one_bit_per_channel() { 00387 for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; ++prop) { 00388 if (_property[prop] > 1) { 00389 _property[prop] = 1; 00390 } 00391 } 00392 } 00393 00394 //////////////////////////////////////////////////////////////////// 00395 // Function: FrameBufferProperties::get_quality 00396 // Access: Published 00397 // Description: Assumes that these properties are a description of 00398 // a window. 00399 // 00400 // Measures how well this window satisfies a specified 00401 // set of requirements. A higher quality number means 00402 // that more requirements were satisfied. A quality of 00403 // zero means that the window is unsuitable. 00404 // 00405 // The routine deducts a lot if the window fails to 00406 // provide a requested feature. It deducts less 00407 // if the window provides a feature, but at a degraded 00408 // level of functionality (ie, the user asks for rgba8, 00409 // color, but the window only provides rgba4). The 00410 // routine also deducts a small amount for unnecessary 00411 // features. For example, if the window has an 00412 // accumulation buffer when one is not requested will 00413 // reduce quality slightly. Maximum quality is obtained 00414 // when the window exactly matches the request. 00415 // 00416 // If you want to know whether the window satisfies 00417 // all of the requirements, use the "subsumes" function. 00418 //////////////////////////////////////////////////////////////////// 00419 int FrameBufferProperties:: 00420 get_quality(const FrameBufferProperties &reqs) const { 00421 00422 if ((_property[FBP_indexed_color]==0) && (_property[FBP_rgb_color]==0)) { 00423 // Nonfunctioning window. 00424 return 0; 00425 } 00426 00427 if ((reqs._property[FBP_rgb_color] > _property[FBP_rgb_color])|| 00428 (reqs._property[FBP_indexed_color] > _property[FBP_indexed_color])) { 00429 // These properties are nonnegotiable. 00430 return 0; 00431 } 00432 00433 int quality = 100000000; 00434 00435 // Deduct for using the wrong kind of renderer (hardware or software). 00436 // Cost: 10,000,000 00437 00438 if ((reqs._property[FBP_force_hardware] > _property[FBP_force_hardware])|| 00439 (reqs._property[FBP_force_software] > _property[FBP_force_software])) { 00440 quality -= 10000000; 00441 } 00442 00443 // Deduct for missing depth, color, alpha, stencil, or accum. 00444 // Cost: 1,000,000 00445 00446 for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) { 00447 if ((reqs._property[prop]) && (_property[prop]==0)) { 00448 quality -= 1000000; 00449 } 00450 } 00451 00452 // Deduct for missing aux bitplanes. 00453 // Cost: 100,000 00454 00455 for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) { 00456 if (reqs._property[prop] > _property[prop]) { 00457 quality -= 100000; 00458 } 00459 } 00460 00461 // Deduct for stereo not enabled. 00462 // Cost: 100,000 00463 00464 if (reqs._property[FBP_stereo] > _property[FBP_stereo]) { 00465 quality -= 100000; 00466 } 00467 00468 // Deduct for insufficient back-buffers. 00469 // Cost: 100,000 00470 00471 if (reqs._property[FBP_back_buffers] > _property[FBP_back_buffers]) { 00472 quality -= 100000; 00473 } 00474 00475 // Deduct for lacking multisamples altogether. 00476 // Cost: 100,000 00477 if (reqs._property[FBP_multisamples] != 0 && _property[FBP_multisamples] == 0) { 00478 quality -= 100000; 00479 } 00480 00481 // Deduct for not enough bits in depth, color, alpha, stencil, or accum. 00482 // Cost: 10,000 00483 00484 for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) { 00485 if (_property[prop] != 0 && reqs._property[prop] > _property[prop]) { 00486 quality -= 10000; 00487 } 00488 } 00489 00490 // deduct for insufficient multisamples. 00491 // Cost: 1,000 00492 00493 if (_property[FBP_multisamples] != 0 && 00494 reqs._property[FBP_multisamples] > _property[FBP_multisamples]) { 00495 quality -= 1000; 00496 } 00497 00498 // Deduct for unrequested bitplanes. 00499 // Cost: 50 00500 00501 for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) { 00502 if ((_property[prop]) && (reqs._property[prop] == 0)) { 00503 quality -= 50; 00504 } 00505 } 00506 for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) { 00507 int extra = _property[prop] > reqs._property[prop]; 00508 if (extra > 0) { 00509 extra = min(extra, 3); 00510 quality -= extra*50; 00511 } 00512 } 00513 00514 // Deduct for excessive resolution in any bitplane (unless we asked 00515 // for only 1 bit, which is the convention for any amount). 00516 00517 // Cost: 50 00518 00519 for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) { 00520 if (reqs._property[prop] > 1 && 00521 _property[prop] > reqs._property[prop]) { 00522 quality -= 50; 00523 } 00524 } 00525 00526 // Bonus for each depth bit. 00527 // Extra: 2 per bit. 00528 if (reqs._property[FBP_depth_bits] != 0) { 00529 quality += 2 * _property[FBP_depth_bits]; 00530 } 00531 00532 // Bonus for each multisample. 00533 // Extra: 2 per sample. 00534 if (reqs._property[FBP_multisamples] != 0) { 00535 quality += 2 * _property[FBP_multisamples]; 00536 } 00537 00538 // Bonus for each color, alpha, stencil, and accum. 00539 // Extra: 1 per bit. 00540 for (int prop=FBP_color_bits; prop<=FBP_accum_bits; prop++) { 00541 if (reqs._property[prop] != 0) { 00542 quality += _property[prop]; 00543 } 00544 } 00545 00546 return quality; 00547 }; 00548 00549 //////////////////////////////////////////////////////////////////// 00550 // Function: FrameBufferProperties::verify_hardware_software 00551 // Access: Public 00552 // Description: Validates that the properties represent the desired 00553 // kind of renderer (hardware or software). If not, 00554 // prints out an error message and returns false. 00555 //////////////////////////////////////////////////////////////////// 00556 bool FrameBufferProperties:: 00557 verify_hardware_software(const FrameBufferProperties &props, const string &renderer) const { 00558 00559 if (get_force_hardware() < props.get_force_hardware()) { 00560 display_cat.error() 00561 << "The application requested harware acceleration, but your OpenGL\n"; 00562 display_cat.error() 00563 << "driver, " << renderer << ", only supports software rendering.\n"; 00564 display_cat.error() 00565 << "You need to install a hardware-accelerated OpenGL driver, or,\n"; 00566 display_cat.error() 00567 << "if you actually *want* to use a software renderer, then\n"; 00568 display_cat.error() 00569 << "alter the hardware/software configuration in your Config.prc file.\n"; 00570 return false; 00571 } 00572 00573 if (get_force_software() < props.get_force_software()) { 00574 display_cat.error() 00575 << "The application requested a software renderer, but your OpenGL\n"; 00576 display_cat.error() 00577 << "driver, " << renderer << ", is probably hardware-accelerated.\n"; 00578 display_cat.error() 00579 << "If you want to allow hardware acceleration, then alter the\n"; 00580 display_cat.error() 00581 << "hardware/software configuration in your Config.prc file.\n"; 00582 return false; 00583 } 00584 00585 return true; 00586 } 00587 00588