Panda3D

frameBufferProperties.cxx

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 &copy) {
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 
 All Classes Functions Variables Enumerations