2
0
Эх сурвалжийг харах

sRGB texture support, add floating-point flags to FrameBufferProperties

rdb 11 жил өмнө
parent
commit
601922e49e

+ 4 - 0
panda/src/display/config_display.cxx

@@ -412,6 +412,10 @@ ConfigVariableBool framebuffer_srgb
           "means that the output will be properly gamma-corrected, as "
           "long as all the input textures are either converted from "
           "original sRGB to linear or sRGB textures are used."));
+ConfigVariableBool framebuffer_float
+("framebuffer-float", false,
+ PRC_DESC("Set this to request a framebuffer that uses floating-point "
+          "storage for the color channel."));
 
 ConfigVariableInt depth_bits
 ("depth-bits", 0,

+ 1 - 0
panda/src/display/config_display.h

@@ -93,6 +93,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_stencil;
 extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_accum;
 extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_stereo;
 extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_srgb;
+extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_float;
 extern EXPCL_PANDA_DISPLAY ConfigVariableInt depth_bits;
 extern EXPCL_PANDA_DISPLAY ConfigVariableInt color_bits;
 extern EXPCL_PANDA_DISPLAY ConfigVariableInt alpha_bits;

+ 121 - 26
panda/src/display/frameBufferProperties.I

@@ -59,7 +59,7 @@ is_single_buffered() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool FrameBufferProperties::
 is_stereo() const {
-  return (_property[FBP_stereo] != 0);
+  return (_flags & FBF_stereo) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -189,9 +189,9 @@ get_back_buffers() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_indexed_color() const {
-  return _property[FBP_indexed_color];
+  return (_flags & FBF_indexed_color) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -199,9 +199,9 @@ get_indexed_color() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_rgb_color() const {
-  return _property[FBP_rgb_color];
+  return (_flags & FBF_rgb_color) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -209,9 +209,9 @@ get_rgb_color() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_stereo() const {
-  return _property[FBP_stereo];
+  return (_flags & FBF_stereo) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -219,9 +219,9 @@ get_stereo() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_force_hardware() const {
-  return _property[FBP_force_hardware];
+  return (_flags & FBF_force_hardware) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -229,9 +229,39 @@ get_force_hardware() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_force_software() const {
-  return _property[FBP_force_software];
+  return (_flags & FBF_force_software) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::get_srgb_color
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FrameBufferProperties::
+get_srgb_color() const {
+  return (_flags & FBF_srgb_color) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::get_float_color
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FrameBufferProperties::
+get_float_color() const {
+  return (_flags & FBF_float_color) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::get_float_depth
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FrameBufferProperties::
+get_float_depth() const {
+  return (_flags & FBF_float_depth) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -365,9 +395,13 @@ set_back_buffers(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_indexed_color(int n) {
-  _property[FBP_indexed_color] = n;
-  _specified[FBP_indexed_color] = true;
+set_indexed_color(bool n) {
+  if (n) {
+    _flags |= FBF_indexed_color;
+  } else {
+    _flags &= ~FBF_indexed_color;
+  }
+  _flags_specified |= FBF_indexed_color;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -376,9 +410,13 @@ set_indexed_color(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_rgb_color(int n) {
-  _property[FBP_rgb_color] = n;
-  _specified[FBP_rgb_color] = true;
+set_rgb_color(bool n) {
+  if (n) {
+    _flags |= FBF_rgb_color;
+  } else {
+    _flags &= ~FBF_rgb_color;
+  }
+  _flags_specified |= FBF_rgb_color;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -387,9 +425,13 @@ set_rgb_color(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_stereo(int n) {
-  _property[FBP_stereo] = n;
-  _specified[FBP_stereo] = true;
+set_stereo(bool n) {
+  if (n) {
+    _flags |= FBF_stereo;
+  } else {
+    _flags &= ~FBF_stereo;
+  }
+  _flags_specified |= FBF_stereo;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -398,9 +440,13 @@ set_stereo(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_force_hardware(int n) {
-  _property[FBP_force_hardware] = n;
-  _specified[FBP_force_hardware] = true;
+set_force_hardware(bool n) {
+  if (n) {
+    _flags |= FBF_force_hardware;
+  } else {
+    _flags &= ~FBF_force_hardware;
+  }
+  _flags_specified |= FBF_force_hardware;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -409,7 +455,56 @@ set_force_hardware(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_force_software(int n) {
-  _property[FBP_force_software] = n;
-  _specified[FBP_force_software] = true;
+set_force_software(bool n) {
+  if (n) {
+    _flags |= FBF_force_software;
+  } else {
+    _flags &= ~FBF_force_software;
+  }
+  _flags_specified |= FBF_force_software;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::set_srgb_color
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FrameBufferProperties::
+set_srgb_color(bool n) {
+  if (n) {
+    _flags |= FBF_srgb_color;
+  } else {
+    _flags &= ~FBF_srgb_color;
+  }
+  _flags_specified |= FBF_srgb_color;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::set_float_color
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FrameBufferProperties::
+set_float_color(bool n) {
+  if (n) {
+    _flags |= FBF_float_color;
+  } else {
+    _flags &= ~FBF_float_color;
+  }
+  _flags_specified |= FBF_float_color;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::set_float_depth
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FrameBufferProperties::
+set_float_depth(bool n) {
+  if (n) {
+    _flags |= FBF_float_depth;
+  } else {
+    _flags &= ~FBF_float_depth;
+  }
+  _flags_specified |= FBF_float_depth;
 }

+ 121 - 58
panda/src/display/frameBufferProperties.cxx

@@ -34,7 +34,10 @@ FrameBufferProperties() {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 operator = (const FrameBufferProperties &copy) {
-  for (int i=0; i<FBP_COUNT; i++) {
+  _flags_specified = copy._flags_specified;
+  _flags = copy._flags;
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     _specified[i] = copy._specified[i];
     _property[i]  = copy._property[i];
   }
@@ -49,11 +52,17 @@ operator = (const FrameBufferProperties &copy) {
 ////////////////////////////////////////////////////////////////////
 bool FrameBufferProperties::
 subsumes(const FrameBufferProperties &other) const {
-  for (int i=0; i<FBP_COUNT; i++) {
+  if (((other._flags & other._flags_specified) & ~(_flags & _flags_specified)) != 0) {
+    // The other has bits enabled that we don't have enabled.
+    return false;
+  }
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     if (other._property[i] > _property[i]) {
       return false;
     }
   }
+
   return true;
 }
 
@@ -73,9 +82,9 @@ get_default() {
     return default_props;
   }
 
-  default_props.set_rgb_color(1);
+  default_props.set_rgb_color(true);
   default_props.set_back_buffers(back_buffers);
-  
+
   int num_words = framebuffer_mode.get_num_words();
   if (num_words > 0) {
     display_cat.error()
@@ -99,10 +108,10 @@ get_default() {
   }
 
   if (framebuffer_hardware) {
-    default_props.set_force_hardware(1);
+    default_props.set_force_hardware(true);
   }
   if (framebuffer_software) {
-    default_props.set_force_software(1);
+    default_props.set_force_software(true);
   }
   if (framebuffer_depth) {
     default_props.set_depth_bits(1);
@@ -120,7 +129,13 @@ get_default() {
     default_props.set_multisamples(1);
   }
   if (framebuffer_stereo) {
-    default_props.set_stereo(1);
+    default_props.set_stereo(true);
+  }
+  if (framebuffer_srgb) {
+    default_props.set_srgb_color(true);
+  }
+  if (framebuffer_float) {
+    default_props.set_float_color(true);
   }
   if (depth_bits > 0) {
     default_props.set_depth_bits(depth_bits);
@@ -141,10 +156,9 @@ get_default() {
     default_props.set_multisamples(multisamples);
   }
 
-  if ((default_props._property[FBP_force_software])&&
-      (default_props._property[FBP_force_hardware])) {
-    default_props._property[FBP_force_software] = 0;
-    default_props._property[FBP_force_hardware] = 0;
+  if ((default_props._flags & FBF_force_software) != 0 &&
+      (default_props._flags & FBF_force_hardware) != 0){
+    default_props._flags &= ~(FBF_force_software | FBF_force_hardware);
   }
 
   default_ready = true;
@@ -158,7 +172,11 @@ get_default() {
 ////////////////////////////////////////////////////////////////////
 bool FrameBufferProperties::
 operator == (const FrameBufferProperties &other) const {
-  for (int i=0; i<FBP_COUNT; i++) {
+  if ((_flags & _flags_specified) != (other._flags & other._flags_specified)) {
+    return false;
+  }
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     if (_specified[i] != other._specified[i]) {
       return false;
     }
@@ -166,6 +184,7 @@ operator == (const FrameBufferProperties &other) const {
       return false;
     }
   }
+
   return true;
 }
 
@@ -178,7 +197,10 @@ operator == (const FrameBufferProperties &other) const {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 clear() {
-  for (int i=0; i<FBP_COUNT; i++) {
+  _flags = 0;
+  _flags_specified = 0;
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     _specified[i] = 0;
     _property[i] = 0;
   }
@@ -193,7 +215,10 @@ clear() {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 add_properties(const FrameBufferProperties &other) {
-  for (int i=0; i<FBP_COUNT; i++) {
+  _flags &= ~other._flags_specified;
+  _flags |= other._flags & other._flags_specified;
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     if (other._specified[i]) {
       _property[i] = other._property[i];
       _specified[i] = true;
@@ -204,15 +229,25 @@ add_properties(const FrameBufferProperties &other) {
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::output
 //       Access: Published
-//  Description: Sets any properties that are explicitly specified in
-//               other on this object.  Leaves other properties
-//               unchanged.
+//  Description: Generates a string representation.
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 output(ostream &out) const {
+  if ((_flags & FBF_float_depth) != 0) {
+    out << "float_depth ";
+  }
   if (_property[FBP_depth_bits] > 0) {
     out << "depth_bits=" << _property[FBP_depth_bits] << " ";
   }
+  if ((_flags & FBF_float_color) != 0) {
+    out << "float_color ";
+  }
+  if ((_flags & FBF_srgb_color) != 0) {
+    out << "srgb_color ";
+  }
+  if ((_flags & FBF_indexed_color) != 0) {
+    out << "indexed_color ";
+  }
   if (_property[FBP_color_bits] > 0) {
     out << "color_bits=" << _property[FBP_color_bits] << " ";
   }
@@ -243,17 +278,14 @@ output(ostream &out) const {
   if (_property[FBP_back_buffers] > 0) {
     out << "back_buffers=" << _property[FBP_back_buffers] << " ";
   }
-  if (_property[FBP_indexed_color] > 0) {
-    out << "indexed_color=" << _property[FBP_indexed_color] << " ";
+  if ((_flags & FBF_stereo) != 0) {
+    out << "stereo ";
   }
-  if (_property[FBP_stereo] > 0) {
-    out << "stereo=" << _property[FBP_stereo] << " ";
+  if ((_flags & FBF_force_hardware) != 0) {
+    out << "force_hardware ";
   }
-  if (_property[FBP_force_hardware] > 0) {
-    out << "force_hardware=" << _property[FBP_force_hardware] << " ";
-  }
-  if (_property[FBP_force_software] > 0) {
-    out << "force_software=" << _property[FBP_force_software] << " ";
+  if ((_flags & FBF_force_software) != 0) {
+    out << "force_software ";
   }
 }
 
@@ -287,7 +319,7 @@ get_aux_mask() const {
 int FrameBufferProperties::
 get_buffer_mask() const {
   int mask = 0;
-  
+
   if (_property[FBP_back_buffers] > 0) {
     mask = RenderBuffer::T_front | RenderBuffer::T_back;
   } else {
@@ -310,7 +342,11 @@ get_buffer_mask() const {
 ////////////////////////////////////////////////////////////////////
 bool FrameBufferProperties::
 is_any_specified() const {
-  for (int i=0; i<FBP_COUNT; i++) {
+  if (_flags_specified != 0) {
+    return true;
+  }
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     if (_specified[i]) {
       return true;
     }
@@ -325,7 +361,9 @@ is_any_specified() const {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 set_all_specified() {
-  for (int i=0; i<FBP_COUNT; i++) {
+  _flags_specified = FBF_all;
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     _specified[i] = true;
   }
 }
@@ -370,13 +408,22 @@ is_basic() const {
   if (_property[FBP_back_buffers] > 0) {
     return false;
   }
-  if (_property[FBP_indexed_color] > 0) {
+  if ((_flags & FBF_indexed_color) != 0) {
+    return false;
+  }
+  if ((_flags & FBF_force_hardware) != 0) {
     return false;
   }
-  if (_property[FBP_force_hardware] > 0) {
+  if ((_flags & FBF_force_software) != 0) {
     return false;
   }
-  if (_property[FBP_force_software] > 0) {
+  if ((_flags & FBF_srgb_color) != 0) {
+    return false;
+  }
+  if ((_flags & FBF_float_color) != 0) {
+    return false;
+  }
+  if ((_flags & FBF_float_depth) != 0) {
     return false;
   }
   return true;
@@ -391,7 +438,7 @@ is_basic() const {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 set_one_bit_per_channel() {
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; ++prop) {
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
     if (_property[prop] > 1) {
       _property[prop] = 1;
     }
@@ -426,13 +473,13 @@ set_one_bit_per_channel() {
 int FrameBufferProperties::
 get_quality(const FrameBufferProperties &reqs) const {
 
-  if ((_property[FBP_indexed_color]==0) && (_property[FBP_rgb_color]==0)) {
+  if (!get_indexed_color() && !get_rgb_color()) {
     // Nonfunctioning window.
     return 0;
   }
-  
-  if ((reqs._property[FBP_rgb_color]      > _property[FBP_rgb_color])||
-      (reqs._property[FBP_indexed_color]  > _property[FBP_indexed_color])) {
+
+  if ((reqs.get_rgb_color() && !get_rgb_color()) ||
+      (reqs.get_indexed_color() && !get_indexed_color())) {
     // These properties are nonnegotiable.
     return 0;
   }
@@ -441,17 +488,17 @@ get_quality(const FrameBufferProperties &reqs) const {
 
   // Deduct for using the wrong kind of renderer (hardware or software).
   // Cost: 10,000,000
-  
-  if ((reqs._property[FBP_force_hardware] > _property[FBP_force_hardware])||
-      (reqs._property[FBP_force_software] > _property[FBP_force_software])) {
+
+  if ((reqs._flags & FBF_force_hardware) > (_flags & FBF_force_hardware) ||
+      (reqs._flags & FBF_force_software) > (_flags & FBF_force_software)) {
     quality -= 10000000;
   }
 
   // Deduct for missing depth, color, alpha, stencil, or accum.
   // Cost: 1,000,000
 
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
-    if ((reqs._property[prop]) && (_property[prop]==0)) {
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
+    if (reqs._property[prop] && _property[prop] == 0) {
       quality -= 1000000;
     }
   }
@@ -459,7 +506,7 @@ get_quality(const FrameBufferProperties &reqs) const {
   // Deduct for missing aux bitplanes.
   // Cost: 100,000
 
-  for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) {
+  for (int prop = FBP_aux_rgba; prop <= FBP_aux_float; ++prop) {
     if (reqs._property[prop] > _property[prop]) {
       quality -= 100000;
     }
@@ -468,13 +515,31 @@ get_quality(const FrameBufferProperties &reqs) const {
   // Deduct for stereo not enabled.
   // Cost: 100,000
 
-  if (reqs._property[FBP_stereo] > _property[FBP_stereo]) {
+  if (reqs.get_stereo() && !get_stereo()) {
+    quality -= 100000;
+  }
+
+  // Deduct for not being sRGB-capable.
+  // Cost: 100,000
+
+  if (reqs.get_srgb_color() && !get_srgb_color()) {
+    quality -= 100000;
+  }
+
+  // Deduct for not having a floating-point format if we requested it.
+  // Cost: 100,000
+
+  if (reqs.get_float_color() && !get_float_color()) {
+    quality -= 100000;
+  }
+
+  if (reqs.get_float_depth() && !get_float_depth()) {
     quality -= 100000;
   }
 
   // Deduct for insufficient back-buffers.
   // Cost: 100,000
-  
+
   if (reqs._property[FBP_back_buffers] > _property[FBP_back_buffers]) {
     quality -= 100000;
   }
@@ -488,7 +553,7 @@ get_quality(const FrameBufferProperties &reqs) const {
   // Deduct for not enough bits in depth, color, alpha, stencil, or accum.
   // Cost: 10,000
 
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
     if (_property[prop] != 0 && reqs._property[prop] > _property[prop]) {
       quality -= 10000;
     }
@@ -497,33 +562,33 @@ get_quality(const FrameBufferProperties &reqs) const {
   // deduct for insufficient multisamples.
   // Cost: 1,000
 
-  if (_property[FBP_multisamples] != 0 && 
+  if (_property[FBP_multisamples] != 0 &&
       reqs._property[FBP_multisamples] > _property[FBP_multisamples]) {
     quality -= 1000;
   }
 
   // Deduct for unrequested bitplanes.
   // Cost: 50
-  
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
+
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
     if ((_property[prop]) && (reqs._property[prop] == 0)) {
       quality -= 50;
     }
   }
-  for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) {
+  for (int prop = FBP_aux_rgba; prop <= FBP_aux_float; ++prop) {
     int extra = _property[prop] > reqs._property[prop];
     if (extra > 0) {
       extra = min(extra, 3);
       quality -= extra*50;
     }
   }
-  
+
   // Deduct for excessive resolution in any bitplane (unless we asked
   // for only 1 bit, which is the convention for any amount).
 
   // Cost: 50
-  
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
+
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
     if (reqs._property[prop] > 1 &&
         _property[prop] > reqs._property[prop]) {
       quality -= 50;
@@ -555,9 +620,9 @@ get_quality(const FrameBufferProperties &reqs) const {
       quality += _property[prop];
     }
   }
-  
+
   return quality;
-};
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::verify_hardware_software
@@ -594,8 +659,6 @@ verify_hardware_software(const FrameBufferProperties &props, const string &rende
       << "hardware/software configuration in your Config.prc file.\n";
     return false;
   }
-  
+
   return true;
 }
-
-

+ 38 - 21
panda/src/display/frameBufferProperties.h

@@ -17,6 +17,7 @@
 
 #include "pandabase.h"
 #include "pnotify.h"
+#include "colorSpace.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : FrameBufferProperties
@@ -44,18 +45,28 @@ private:
     FBP_multisamples,
     FBP_coverage_samples,
     FBP_back_buffers,
-    FBP_indexed_color,
-    FBP_rgb_color,
-    FBP_stereo,
-    FBP_force_hardware,
-    FBP_force_software,
-    
+
     // This is a sentinel value.
     FBP_COUNT
   };
-  
+
+  enum FrameBufferFlag {
+    FBF_indexed_color  = 0x001,
+    FBF_rgb_color      = 0x002,
+    FBF_stereo         = 0x004,
+    FBF_force_hardware = 0x008,
+    FBF_force_software = 0x010,
+    FBF_srgb_color     = 0x020,
+    FBF_float_color    = 0x040,
+    FBF_float_depth    = 0x080,
+    FBF_all            = 0x100-1,
+  };
+
   int _property[FBP_COUNT];
-  int _specified[FBP_COUNT];
+  bool _specified[FBP_COUNT];
+
+  int _flags;
+  int _flags_specified;
 
 PUBLISHED:
 
@@ -71,11 +82,14 @@ PUBLISHED:
   INLINE int get_multisamples() const;
   INLINE int get_coverage_samples() const;
   INLINE int get_back_buffers() const;
-  INLINE int get_indexed_color() const;
-  INLINE int get_rgb_color() const;
-  INLINE int get_stereo() const;
-  INLINE int get_force_hardware() const;
-  INLINE int get_force_software() const;
+  INLINE bool get_indexed_color() const;
+  INLINE bool get_rgb_color() const;
+  INLINE bool get_stereo() const;
+  INLINE bool get_force_hardware() const;
+  INLINE bool get_force_software() const;
+  INLINE bool get_srgb_color() const;
+  INLINE bool get_float_color() const;
+  INLINE bool get_float_depth() const;
 
   // Individual assigners.
   INLINE void set_depth_bits(int n);
@@ -89,11 +103,14 @@ PUBLISHED:
   INLINE void set_multisamples(int n);
   INLINE void set_coverage_samples(int n);
   INLINE void set_back_buffers(int n);
-  INLINE void set_indexed_color(int n);
-  INLINE void set_rgb_color(int n);
-  INLINE void set_stereo(int n);
-  INLINE void set_force_hardware(int n);
-  INLINE void set_force_software(int n);
+  INLINE void set_indexed_color(bool n);
+  INLINE void set_rgb_color(bool n);
+  INLINE void set_stereo(bool n);
+  INLINE void set_force_hardware(bool n);
+  INLINE void set_force_software(bool n);
+  INLINE void set_srgb_color(bool n);
+  INLINE void set_float_color(bool n);
+  INLINE void set_float_depth(bool n);
 
   // Other.
 
@@ -111,9 +128,9 @@ PUBLISHED:
   void add_properties(const FrameBufferProperties &other);
   void output(ostream &out) const;
   void set_one_bit_per_channel();
-  
-  bool is_stereo() const;
-  bool is_single_buffered() const;
+
+  INLINE bool is_stereo() const;
+  INLINE bool is_single_buffered() const;
   int get_quality(const FrameBufferProperties &reqs) const;
   bool is_any_specified() const;
   bool is_basic() const;

+ 5 - 1
panda/src/gles2gsg/gles2gsg.h

@@ -96,11 +96,15 @@ typedef char GLchar;
 #define GL_RG16F GL_RG16F_EXT
 #define GL_RGB16F GL_RGB16F_EXT
 #define GL_RGBA16F GL_RGBA16F_EXT
+#define GL_RGB16F GL_RGB16F_EXT
+#define GL_RGBA16F GL_RGBA16F_EXT
+#define GL_RGB32F GL_RGB32F_EXT
+#define GL_RGBA32F GL_RGBA32F_EXT
 
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY
 #define APIENTRYP *
 
 #include "glstuff_src.h"
- 
+
 #endif  // GLES2GSG_H

+ 5 - 1
panda/src/glesgsg/glesgsg.h

@@ -110,11 +110,15 @@
 #define GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES
 #define GL_FUNC_REVERSE_SUBTRACT GL_FUNC_REVERSE_SUBTRACT_OES
 #define GL_BGRA GL_BGRA_EXT
+#define GL_RGB16F GL_RGB16F_EXT
+#define GL_RGBA16F GL_RGBA16F_EXT
+#define GL_RGB32F GL_RGB32F_EXT
+#define GL_RGBA32F GL_RGBA32F_EXT
 
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY
 #define APIENTRYP *
 
 #include "glstuff_src.h"
- 
+
 #endif  // GLESGSG_H

+ 100 - 15
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -370,6 +370,11 @@ rebuild_bitplanes() {
       // explicitly bound something to RTP_depth.
       _use_depth_stencil = false;
 
+    } else if (_fb_properties.get_float_depth()) {
+      // Let's not bother with a depth-stencil buffer
+      // if a float buffer was requested.
+      _use_depth_stencil = false;
+
     } else if (_fb_properties.get_depth_bits() > 24) {
       // We can't give more than 24 depth bits with a depth-stencil buffer.
       _use_depth_stencil = false;
@@ -582,7 +587,10 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
     // Adjust the texture format based on the requested framebuffer settings.
     switch (slot) {
     case RTP_depth:
-      if (_fb_properties.get_depth_bits() > 24) {
+      if (_fb_properties.get_float_depth()) {
+        tex->set_format(Texture::F_depth_component32);
+        tex->set_component_type(Texture::T_float);
+      } else if (_fb_properties.get_depth_bits() > 24) {
         tex->set_format(Texture::F_depth_component32);
       } else if (_fb_properties.get_depth_bits() > 16) {
         tex->set_format(Texture::F_depth_component24);
@@ -594,7 +602,12 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
       break;
     case RTP_depth_stencil:
       tex->set_format(Texture::F_depth_stencil);
-      tex->set_component_type(Texture::T_unsigned_int_24_8);
+
+      if (_fb_properties.get_float_depth()) {
+        tex->set_component_type(Texture::T_float);
+      } else {
+        tex->set_component_type(Texture::T_unsigned_int_24_8);
+      }
       break;
     case RTP_aux_hrgba_0:
     case RTP_aux_hrgba_1:
@@ -611,16 +624,24 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
       tex->set_component_type(Texture::T_float);
       break;
     default:
-      if (_fb_properties.get_color_bits() > 48) {
-        tex->set_format(Texture::F_rgba32);
-        // Currently a float format.  Should change.
-        tex->set_component_type(Texture::T_float);
-      } else if (_fb_properties.get_color_bits() > 24) {
-        tex->set_format(Texture::F_rgba16);
-        // Currently a float format.  Should change.
-        tex->set_component_type(Texture::T_float);
+      if (_fb_properties.get_srgb_color()) {
+        if (_fb_properties.get_alpha_bits() == 0) {
+          tex->set_format(Texture::F_srgb);
+        } else {
+          tex->set_format(Texture::F_srgb_alpha);
+        }
       } else {
-        tex->set_format(Texture::F_rgba);
+        if (_fb_properties.get_float_color()) {
+          tex->set_component_type(Texture::T_float);
+        }
+        if (_fb_properties.get_color_bits() > 16 * 3) {
+          tex->set_format(Texture::F_rgba32);
+          tex->set_component_type(Texture::T_float);
+        } else if (_fb_properties.get_color_bits() > 8 * 3) {
+          tex->set_format(Texture::F_rgba16);
+        } else {
+          tex->set_format(Texture::F_rgba);
+        }
       }
     }
 
@@ -730,10 +751,16 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
     GLuint gl_format = GL_RGBA;
     switch (slot) {
       case RTP_depth_stencil:
-        gl_format = GL_DEPTH_STENCIL_EXT;
+        if (_fb_properties.get_float_depth()) {
+          gl_format = GL_DEPTH32F_STENCIL8;
+        } else {
+          gl_format = GL_DEPTH24_STENCIL8;
+        }
         break;
       case RTP_depth:
-        if (_fb_properties.get_depth_bits() > 24) {
+        if (_fb_properties.get_float_depth()) {
+          gl_format = GL_DEPTH_COMPONENT32F;
+        } else if (_fb_properties.get_depth_bits() > 24) {
           gl_format = GL_DEPTH_COMPONENT32;
         } else if (_fb_properties.get_depth_bits() > 16) {
           gl_format = GL_DEPTH_COMPONENT24;
@@ -763,7 +790,41 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
         break;
       default:
         if (_fb_properties.get_alpha_bits() == 0) {
-          gl_format = GL_RGB;
+          if (_fb_properties.get_srgb_color()) {
+            gl_format = GL_SRGB8;
+          } else if (_fb_properties.get_float_color()) {
+            if (_fb_properties.get_color_bits() > 16 * 3) {
+              gl_format = GL_RGB32F_ARB;
+            } else {
+              gl_format = GL_RGB16F_ARB;
+            }
+          } else {
+            if (_fb_properties.get_color_bits() > 16 * 3) {
+              gl_format = GL_RGBA32F_ARB;
+            } else if (_fb_properties.get_color_bits() > 8 * 3) {
+              gl_format = GL_RGB16_EXT;
+            } else {
+              gl_format = GL_RGB;
+            }
+          }
+        } else {
+          if (_fb_properties.get_srgb_color()) {
+            gl_format = GL_SRGB8_ALPHA8;
+          } else if (_fb_properties.get_float_color()) {
+            if (_fb_properties.get_color_bits() > 16 * 3) {
+              gl_format = GL_RGBA32F_ARB;
+            } else {
+              gl_format = GL_RGBA16F_ARB;
+            }
+          } else {
+            if (_fb_properties.get_color_bits() > 16 * 3) {
+              gl_format = GL_RGB32F_ARB;
+            } else if (_fb_properties.get_color_bits() > 8 * 3) {
+              gl_format = GL_RGB16_EXT;
+            } else {
+              gl_format = GL_RGB;
+            }
+          }
         }
     };
 #endif
@@ -1160,7 +1221,7 @@ open_buffer() {
 
   // Count total color buffers.
   int totalcolor =
-   (_fb_properties.is_stereo() ? 2 : 1) +
+   (_fb_properties.get_stereo() ? 2 : 1) +
     _fb_properties.get_aux_rgba() +
     _fb_properties.get_aux_hrgba() +
     _fb_properties.get_aux_float();
@@ -1215,6 +1276,30 @@ open_buffer() {
     _fb_properties.set_alpha_bits(32);
   }
 
+  if (_fb_properties.get_float_depth()) {
+    // GL_DEPTH_COMPONENT32F seems the only depth float format.
+    _fb_properties.set_depth_bits(32);
+  }
+
+  // We currently only support color formats this big as float.
+  if (_fb_properties.get_color_bits() > 16 * 3) {
+    _fb_properties.set_color_bits(32 * 3);
+    _fb_properties.set_float_color(true);
+
+    if (_fb_properties.get_alpha_bits() > 0) {
+      _fb_properties.set_alpha_bits(32);
+    }
+  }
+
+  if (_fb_properties.get_srgb_color()) {
+    _fb_properties.set_color_bits(24);
+    _fb_properties.set_float_color(false);
+
+    if (_fb_properties.get_alpha_bits() > 0) {
+      _fb_properties.set_alpha_bits(32);
+    }
+  }
+
   if (!_gsg->get_supports_depth_stencil()) {
     // At least we know we won't be getting stencil bits.
     _fb_properties.set_stencil_bits(0);

+ 246 - 48
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1603,7 +1603,6 @@ reset() {
 
     glGetIntegerv(GL_MAX_IMAGE_UNITS_EXT, &_max_image_units);
   }
-#endif
 
   // Check availability of multi-bind functions.
   _supports_multi_bind = false;
@@ -1618,6 +1617,7 @@ reset() {
         << "ARB_multi_bind advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n";
     }
   }
+#endif
 
   report_my_gl_errors();
 
@@ -2225,6 +2225,10 @@ begin_frame(Thread *current_thread) {
     glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
   }
 
+  if (_current_properties->get_srgb_color()) {
+    glEnable(GL_FRAMEBUFFER_SRGB);
+  }
+
   report_my_gl_errors();
   return true;
 }
@@ -2276,6 +2280,11 @@ end_scene() {
 void CLP(GraphicsStateGuardian)::
 end_frame(Thread *current_thread) {
   report_my_gl_errors();
+
+  if (_current_properties->get_srgb_color()) {
+    glDisable(GL_FRAMEBUFFER_SRGB);
+  }
+
 #ifdef DO_PSTATS
   // Check for textures, etc., that are no longer resident.  These
   // calls might be measurably expensive, and they don't have any
@@ -4304,11 +4313,19 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z,
 
     default:
       // If the texture is a color format, we want to match the
-      // presence of alpha according to the framebuffer.
-      if (_current_properties->get_alpha_bits()) {
-        tex->set_format(Texture::F_rgba);
+      // presence of sRGB and alpha according to the framebuffer.
+      if (_current_properties->get_srgb_color()) {
+        if (_current_properties->get_alpha_bits()) {
+          tex->set_format(Texture::F_srgb_alpha);
+        } else {
+          tex->set_format(Texture::F_srgb);
+        }
       } else {
-        tex->set_format(Texture::F_rgb);
+        if (_current_properties->get_alpha_bits()) {
+          tex->set_format(Texture::F_rgba);
+        } else {
+          tex->set_format(Texture::F_rgb);
+        }
       }
     }
   }
@@ -4444,11 +4461,17 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
   Texture::Format format = tex->get_format();
   switch (format) {
   case Texture::F_depth_stencil:
-    component_type = Texture::T_unsigned_int_24_8;
+    if (_current_properties->get_float_depth()) {
+      component_type = Texture::T_float;
+    } else {
+      component_type = Texture::T_unsigned_int_24_8;
+    }
     break;
 
   case Texture::F_depth_component:
-    if (_current_properties->get_depth_bits() <= 8) {
+    if (_current_properties->get_float_depth()) {
+      component_type = Texture::T_float;
+    } else if (_current_properties->get_depth_bits() <= 8) {
       component_type = Texture::T_unsigned_byte;
     } else if (_current_properties->get_depth_bits() <= 16) {
       component_type = Texture::T_unsigned_short;
@@ -4459,12 +4482,22 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
 
   default:
     color_mode = true;
-    if (_current_properties->get_alpha_bits()) {
-      format = Texture::F_rgba;
+    if (_current_properties->get_srgb_color()) {
+      if (_current_properties->get_alpha_bits()) {
+        format = Texture::F_srgb_alpha;
+      } else {
+        format = Texture::F_srgb;
+      }
     } else {
-      format = Texture::F_rgb;
+      if (_current_properties->get_alpha_bits()) {
+        format = Texture::F_rgba;
+      } else {
+        format = Texture::F_rgb;
+      }
     }
-    if (_current_properties->get_color_bits() <= 24) {
+    if (_current_properties->get_float_color()) {
+      component_type = Texture::T_float;
+    } else if (_current_properties->get_color_bits() <= 24) {
       component_type = Texture::T_unsigned_byte;
     } else {
       component_type = Texture::T_unsigned_short;
@@ -4504,7 +4537,7 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
     case GL_DEPTH_COMPONENT:
       GLCAT.spam(false) << "GL_DEPTH_COMPONENT, ";
       break;
-    case GL_DEPTH_STENCIL_EXT:
+    case GL_DEPTH_STENCIL:
       GLCAT.spam(false) << "GL_DEPTH_STENCIL, ";
       break;
     case GL_RGB:
@@ -4555,9 +4588,8 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
     }
   }
 
-  glReadPixels(xo, yo, w, h,
-                  external_format, get_component_type(component_type),
-                  image_ptr);
+  glReadPixels(xo, yo, w, h, external_format,
+               get_component_type(component_type), image_ptr);
 
   // We may have to reverse the byte ordering of the image if GL
   // didn't do it for us.
@@ -6324,12 +6356,13 @@ get_component_type(Texture::ComponentType component_type) {
 GLint CLP(GraphicsStateGuardian)::
 get_external_image_format(Texture *tex) const {
   Texture::CompressionMode compression = tex->get_ram_image_compression();
+  Texture::Format format = tex->get_format();
   if (compression != Texture::CM_off &&
       get_supports_compressed_texture_format(compression)) {
     switch (compression) {
     case Texture::CM_on:
 #ifndef OPENGLES
-      switch (tex->get_format()) {
+      switch (format) {
       case Texture::F_color_index:
       case Texture::F_depth_component:
       case Texture::F_depth_component16:
@@ -6374,13 +6407,29 @@ get_external_image_format(Texture *tex) const {
       case Texture::F_luminance_alpha:
       case Texture::F_luminance_alphamask:
         return GL_COMPRESSED_LUMINANCE_ALPHA;
+
+      case Texture::F_srgb:
+        return GL_COMPRESSED_SRGB;
+
+      case Texture::F_srgb_alpha:
+        return GL_COMPRESSED_SRGB_ALPHA;
+
+      case Texture::F_sluminance:
+        return GL_COMPRESSED_SLUMINANCE;
+
+      case Texture::F_sluminance_alpha:
+        return GL_COMPRESSED_SLUMINANCE_ALPHA;
       }
 #endif
       break;
 
 #ifndef OPENGLES_1
     case Texture::CM_dxt1:
-      if (Texture::has_alpha(tex->get_format())) {
+      if (format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+      } else if (format == Texture::F_srgb) {
+        return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+      } else if (Texture::has_alpha(format)) {
         return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
       } else {
         return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
@@ -6389,13 +6438,21 @@ get_external_image_format(Texture *tex) const {
 
 #ifndef OPENGLES
     case Texture::CM_dxt3:
-      return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+      if (format == Texture::F_srgb || format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+      } else {
+        return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+      }
 
     case Texture::CM_dxt5:
-      return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+      if (format == Texture::F_srgb || format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+      } else {
+        return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+      }
 
     case Texture::CM_fxt1:
-      if (Texture::has_alpha(tex->get_format())) {
+      if (Texture::has_alpha(format)) {
         return GL_COMPRESSED_RGBA_FXT1_3DFX;
       } else {
         return GL_COMPRESSED_RGB_FXT1_3DFX;
@@ -6403,14 +6460,22 @@ get_external_image_format(Texture *tex) const {
 
 #else
     case Texture::CM_pvr1_2bpp:
-      if (Texture::has_alpha(tex->get_format())) {
+      if (format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT;
+      } else if (format == Texture::F_srgb) {
+        return GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT;
+      } else if (Texture::has_alpha(format)) {
         return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
       } else {
         return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
       }
 
     case Texture::CM_pvr1_4bpp:
-      if (Texture::has_alpha(tex->get_format())) {
+      if (format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT;
+      } else if (format == Texture::F_srgb) {
+        return GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT;
+      } else if (Texture::has_alpha(format)) {
         return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
       } else {
         return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
@@ -6427,7 +6492,7 @@ get_external_image_format(Texture *tex) const {
     }
   }
 
-  switch (tex->get_format()) {
+  switch (format) {
 #ifndef OPENGLES
   case Texture::F_color_index:
     return GL_COLOR_INDEX;
@@ -6438,7 +6503,7 @@ get_external_image_format(Texture *tex) const {
   case Texture::F_depth_component32:
     return GL_DEPTH_COMPONENT;
   case Texture::F_depth_stencil:
-    return _supports_depth_stencil ? GL_DEPTH_STENCIL_EXT : GL_DEPTH_COMPONENT;
+    return _supports_depth_stencil ? GL_DEPTH_STENCIL : GL_DEPTH_COMPONENT;
 #ifndef OPENGLES
   case Texture::F_red:
   case Texture::F_r16:
@@ -6460,6 +6525,7 @@ get_external_image_format(Texture *tex) const {
   case Texture::F_rgb12:
   case Texture::F_rgb332:
   case Texture::F_rgb16:
+  case Texture::F_srgb:
 #ifdef OPENGLES
     return GL_RGB;
 #else
@@ -6473,15 +6539,18 @@ get_external_image_format(Texture *tex) const {
   case Texture::F_rgba12:
   case Texture::F_rgba16:
   case Texture::F_rgba32:
+  case Texture::F_srgb_alpha:
 #ifdef OPENGLES_2
     return GL_RGBA;
 #else
     return _supports_bgr ? GL_BGRA : GL_RGBA;
 #endif
   case Texture::F_luminance:
+  case Texture::F_sluminance:
     return GL_LUMINANCE;
   case Texture::F_luminance_alphamask:
   case Texture::F_luminance_alpha:
+  case Texture::F_sluminance_alpha:
     return GL_LUMINANCE_ALPHA;
   }
   GLCAT.error()
@@ -6502,6 +6571,7 @@ get_internal_image_format(Texture *tex) const {
   if (compression == Texture::CM_default) {
     compression = (compressed_textures) ? Texture::CM_on : Texture::CM_off;
   }
+  Texture::Format format = tex->get_format();
   if (tex->get_render_to_texture()) {
     // no compression for render targets
     compression = Texture::CM_off;
@@ -6520,7 +6590,7 @@ get_internal_image_format(Texture *tex) const {
       // appropriate choice), since that makes saving the result as a
       // pre-compressed texture more dependable--this way, we will know
       // which compression algorithm was applied.
-      switch (tex->get_format()) {
+      switch (format) {
       case Texture::F_color_index:
       case Texture::F_depth_component:
       case Texture::F_depth_stencil:
@@ -6612,11 +6682,33 @@ get_internal_image_format(Texture *tex) const {
         return GL_COMPRESSED_LUMINANCE_ALPHA;
       }
       break;
+
+      case Texture::F_srgb:
+        if (get_supports_compressed_texture_format(Texture::CM_dxt1) && !is_3d) {
+          return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+        }
+        return GL_COMPRESSED_SRGB;
+
+      case Texture::F_srgb_alpha:
+        if (get_supports_compressed_texture_format(Texture::CM_dxt5) && !is_3d) {
+          return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+        }
+        return GL_COMPRESSED_SRGB_ALPHA;
+
+      case Texture::F_sluminance:
+        return GL_COMPRESSED_SLUMINANCE;
+
+      case Texture::F_sluminance_alpha:
+        return GL_COMPRESSED_SLUMINANCE_ALPHA;
 #endif
 
 #ifndef OPENGLES_1
     case Texture::CM_dxt1:
-      if (Texture::has_alpha(tex->get_format())) {
+      if (format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+      } else if (format == Texture::F_srgb) {
+        return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+      } else if (Texture::has_alpha(format)) {
         return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
       } else {
         return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
@@ -6625,27 +6717,43 @@ get_internal_image_format(Texture *tex) const {
 
 #ifndef OPENGLES
     case Texture::CM_dxt3:
-      return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+      if (format == Texture::F_srgb || format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+      } else {
+        return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+      }
 
     case Texture::CM_dxt5:
-      return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+      if (format == Texture::F_srgb || format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+      } else {
+        return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+      }
 
     case Texture::CM_fxt1:
-      if (Texture::has_alpha(tex->get_format())) {
+      if (Texture::has_alpha(format)) {
         return GL_COMPRESSED_RGBA_FXT1_3DFX;
       } else {
         return GL_COMPRESSED_RGB_FXT1_3DFX;
       }
 #else
     case Texture::CM_pvr1_2bpp:
-      if (Texture::has_alpha(tex->get_format())) {
+      if (format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT;
+      } else if (format == Texture::F_srgb) {
+        return GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT;
+      } else if (Texture::has_alpha(format)) {
         return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
       } else {
         return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
       }
 
     case Texture::CM_pvr1_4bpp:
-      if (Texture::has_alpha(tex->get_format())) {
+      if (format == Texture::F_srgb_alpha) {
+        return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT;
+      } else if (format == Texture::F_srgb) {
+        return GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT;
+      } else if (Texture::has_alpha(format)) {
         return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
       } else {
         return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
@@ -6661,11 +6769,22 @@ get_internal_image_format(Texture *tex) const {
     }
   }
 
-  switch (tex->get_format()) {
+  switch (format) {
 #ifndef OPENGLES
   case Texture::F_color_index:
     return GL_COLOR_INDEX;
 #endif
+
+  case Texture::F_depth_stencil:
+    if (_supports_depth_stencil) {
+      if (tex->get_component_type() == Texture::T_float) {
+        return GL_DEPTH32F_STENCIL8;
+      } else {
+        return GL_DEPTH_STENCIL;
+      }
+    }
+    // Fall through.
+
   case Texture::F_depth_component:
 #ifndef OPENGLES
     if (tex->get_component_type() == Texture::T_float) {
@@ -6710,16 +6829,14 @@ get_internal_image_format(Texture *tex) const {
     }
 #endif
 
-  case Texture::F_depth_stencil:
-    if (_supports_depth_stencil) {
-      return GL_DEPTH_STENCIL_EXT;
+  case Texture::F_rgba:
+  case Texture::F_rgbm:
+    if (tex->get_component_type() == Texture::T_float) {
+      return GL_RGBA16F;
     } else {
-      return GL_DEPTH_COMPONENT;
+      return GL_RGBA;
     }
 
-  case Texture::F_rgba:
-  case Texture::F_rgbm:
-    return GL_RGBA;
   case Texture::F_rgba4:
     return GL_RGBA4;
 
@@ -6730,23 +6847,28 @@ get_internal_image_format(Texture *tex) const {
     return GL_RGBA;
 #ifndef OPENGLES_1
   case Texture::F_rgba16:
-    return GL_RGBA16F_EXT;
+    return GL_RGBA16F;
 #endif  // OPENGLES_1
   case Texture::F_rgba32:
-    return GL_RGBA32F_EXT;
+    return GL_RGBA32F;
 #else
   case Texture::F_rgba8:
     return GL_RGBA8;
   case Texture::F_rgba12:
     return GL_RGBA12;
   case Texture::F_rgba16:
-    return GL_RGBA16F_ARB;
+    return GL_RGBA16F;
   case Texture::F_rgba32:
-    return GL_RGBA32F_ARB;
+    return GL_RGBA32F;
 #endif  // OPENGLES
 
   case Texture::F_rgb:
-    return GL_RGB;
+    if (tex->get_component_type() == Texture::T_float) {
+      return GL_RGB16F;
+    } else {
+      return GL_RGB;
+    }
+
   case Texture::F_rgb5:
 #ifdef OPENGLES
     // Close enough.
@@ -6763,7 +6885,7 @@ get_internal_image_format(Texture *tex) const {
   case Texture::F_rgb12:
     return GL_RGB;
   case Texture::F_rgb16:
-    return GL_RGB16F_EXT;
+    return GL_RGB16F;
 #else
   case Texture::F_rgb8:
     return GL_RGB8;
@@ -6818,6 +6940,15 @@ get_internal_image_format(Texture *tex) const {
   case Texture::F_luminance_alphamask:
     return GL_LUMINANCE_ALPHA;
 
+  case Texture::F_srgb:
+    return GL_SRGB8;
+  case Texture::F_srgb_alpha:
+    return GL_SRGB8_ALPHA8;
+  case Texture::F_sluminance:
+    return GL_SLUMINANCE8;
+  case Texture::F_sluminance_alpha:
+    return GL_SLUMINANCE8_ALPHA8;
+
   default:
     GLCAT.error()
       << "Invalid image format in get_internal_image_format(): "
@@ -9366,7 +9497,7 @@ upload_texture_image(CLP(TextureContext) *gtc,
     }
 
     if (num_ram_mipmap_levels == 0) {
-      if ((external_format == GL_DEPTH_STENCIL_EXT) && get_supports_depth_stencil()) {
+      if ((external_format == GL_DEPTH_STENCIL) && get_supports_depth_stencil()) {
 #ifdef OPENGLES
         component_type = GL_UNSIGNED_INT_24_8_OES;
 #else
@@ -9870,11 +10001,15 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     format = Texture::F_depth_component;
     break;
 #endif
-  case GL_DEPTH_STENCIL_EXT:
-  case GL_DEPTH24_STENCIL8_EXT:
+  case GL_DEPTH_STENCIL:
+  case GL_DEPTH24_STENCIL8:
     type = Texture::T_unsigned_int_24_8;
     format = Texture::F_depth_stencil;
     break;
+  case GL_DEPTH32F_STENCIL8:
+    type = Texture::T_float;
+    format = Texture::F_depth_stencil;
+    break;
   case GL_RGBA:
   case 4:
     format = Texture::F_rgba;
@@ -9985,6 +10120,19 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     format = Texture::F_luminance_alpha;
     break;
 
+  case GL_SRGB:
+    format = Texture::F_srgb;
+    break;
+  case GL_SRGB_ALPHA:
+    format = Texture::F_srgb_alpha;
+    break;
+  case GL_SLUMINANCE:
+    format = Texture::F_sluminance;
+    break;
+  case GL_SLUMINANCE_ALPHA:
+    format = Texture::F_sluminance_alpha;
+    break;
+
 #ifndef OPENGLES
   case GL_COMPRESSED_RGB:
     format = Texture::F_rgb;
@@ -10006,6 +10154,23 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     format = Texture::F_luminance_alpha;
     compression = Texture::CM_on;
     break;
+
+  case GL_COMPRESSED_SRGB:
+    format = Texture::F_srgb;
+    compression = Texture::CM_on;
+    break;
+  case GL_COMPRESSED_SRGB_ALPHA:
+    format = Texture::F_srgb_alpha;
+    compression = Texture::CM_on;
+    break;
+  case GL_COMPRESSED_SLUMINANCE:
+    format = Texture::F_sluminance;
+    compression = Texture::CM_on;
+    break;
+  case GL_COMPRESSED_SLUMINANCE_ALPHA:
+    format = Texture::F_sluminance_alpha;
+    compression = Texture::CM_on;
+    break;
 #endif
 
 #ifndef OPENGLES_1
@@ -10017,6 +10182,14 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     format = Texture::F_rgbm;
     compression = Texture::CM_dxt1;
     break;
+  case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+    format = Texture::F_srgb;
+    compression = Texture::CM_dxt1;
+    break;
+  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+    format = Texture::F_srgb_alpha;
+    compression = Texture::CM_dxt1;
+    break;
 #endif
 #ifdef OPENGLES
   case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
@@ -10035,6 +10208,23 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     format = Texture::F_rgba;
     compression = Texture::CM_pvr1_4bpp;
     break;
+
+  case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
+    format = Texture::F_srgb;
+    compression = Texture::CM_pvr1_2bpp;
+    break;
+  case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
+    format = Texture::F_srgb_alpha;
+    compression = Texture::CM_pvr1_2bpp;
+    break;
+  case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
+    format = Texture::F_srgb;
+    compression = Texture::CM_pvr1_4bpp;
+    break;
+  case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
+    format = Texture::F_srgb_alpha;
+    compression = Texture::CM_pvr1_4bpp;
+    break;
 #else
   case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
     format = Texture::F_rgba;
@@ -10044,6 +10234,14 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     format = Texture::F_rgba;
     compression = Texture::CM_dxt5;
     break;
+  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+    format = Texture::F_srgb_alpha;
+    compression = Texture::CM_dxt3;
+    break;
+  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+    format = Texture::F_srgb_alpha;
+    compression = Texture::CM_dxt5;
+    break;
   case GL_COMPRESSED_RGB_FXT1_3DFX:
     format = Texture::F_rgb;
     compression = Texture::CM_fxt1;

+ 10 - 1
panda/src/glxdisplay/glxGraphicsStateGuardian.cxx

@@ -153,7 +153,7 @@ get_properties_advanced(FrameBufferProperties &properties,
     // Now update our framebuffer_mode and bit depth appropriately.
     int render_type, double_buffer, stereo, red_size, green_size, blue_size,
       alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
-      depth_size, stencil_size, samples, drawable_type, caveat;
+      depth_size, stencil_size, samples, drawable_type, caveat, srgb_capable;
 
     _glXGetFBConfigAttrib(_display, config, GLX_RENDER_TYPE, &render_type);
     _glXGetFBConfigAttrib(_display, config, GLX_DOUBLEBUFFER, &double_buffer);
@@ -171,6 +171,7 @@ get_properties_advanced(FrameBufferProperties &properties,
     _glXGetFBConfigAttrib(_display, config, GLX_SAMPLES, &samples);
     _glXGetFBConfigAttrib(_display, config, GLX_DRAWABLE_TYPE, &drawable_type);
     _glXGetFBConfigAttrib(_display, config, GLX_CONFIG_CAVEAT, &caveat);
+    _glXGetFBConfigAttrib(_display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable);
 
     context_has_pbuffer = false;
     if ((drawable_type & GLX_PBUFFER_BIT)!=0) {
@@ -200,6 +201,10 @@ get_properties_advanced(FrameBufferProperties &properties,
       properties.set_stereo(true);
     }
 
+    if (srgb_capable) {
+      properties.set_srgb_color(true);
+    }
+
     if ((render_type & GLX_RGBA_BIT)!=0) {
       properties.set_rgb_color(true);
     }
@@ -353,6 +358,10 @@ choose_pixel_format(const FrameBufferProperties &properties,
         get_properties_advanced(_fbprops, _context_has_pbuffer, _context_has_pixmap,
                                 _slow, _fbconfig);
 
+        if (!properties.get_srgb_color()) {
+          _fbprops.set_srgb_color(false);
+        }
+
         if (glxdisplay_cat.is_debug()) {
           glxdisplay_cat.debug()
             << "Selected context " << best_result << ": " << _fbprops << "\n";

+ 44 - 4
panda/src/gobj/texture.cxx

@@ -532,6 +532,8 @@ estimate_texture_memory() const {
   case Texture::F_luminance:
   case Texture::F_luminance_alpha:
   case Texture::F_luminance_alphamask:
+  case Texture::F_sluminance:
+  case Texture::F_sluminance_alpha:
     bpp = 4;
     break;
 
@@ -541,12 +543,14 @@ estimate_texture_memory() const {
   case Texture::F_rgb:
   case Texture::F_rgb5:
   case Texture::F_rgba5:
+  case Texture::F_srgb:
     bpp = 4;
     break;
 
   case Texture::F_color_index:
   case Texture::F_rgb8:
   case Texture::F_rgba8:
+  case Texture::F_srgb_alpha:
     bpp = 4;
     break;
 
@@ -1690,6 +1694,19 @@ write(ostream &out, int indent_level) const {
   case F_rgb16:
     out << "rgb16";
     break;
+
+  case F_srgb:
+    out << "srgb";
+    break;
+  case F_srgb_alpha:
+    out << "srgb_alpha";
+    break;
+  case F_sluminance:
+    out << "sluminance";
+    break;
+  case F_sluminance_alpha:
+    out << "sluminance_alpha";
+    break;
   }
 
   if (cdata->_compression != CM_default) {
@@ -2112,6 +2129,14 @@ format_format(Format format) {
     return "rg16";
   case F_rgb16:
     return "rgb16";
+  case F_srgb:
+    return "srgb";
+  case F_srgb_alpha:
+    return "srgb_alpha";
+  case F_sluminance:
+    return "sluminance";
+  case F_sluminance_alpha:
+    return "sluminance_alpha";
   }
   return "**invalid**";
 }
@@ -2182,6 +2207,14 @@ string_format(const string &str) {
     return F_rg16;
   } else if (cmp_nocase(str, "rgb16") == 0 || cmp_nocase(str, "r16g16b16") == 0) {
     return F_rgb16;
+  } else if (cmp_nocase(str, "srgb") == 0) {
+    return F_srgb;
+  } else if (cmp_nocase(str, "srgb_alpha") == 0) {
+    return F_srgb_alpha;
+  } else if (cmp_nocase(str, "sluminance") == 0) {
+    return F_sluminance;
+  } else if (cmp_nocase(str, "sluminance_alpha") == 0) {
+    return F_sluminance_alpha;
   }
 
   gobj_cat->error()
@@ -2541,6 +2574,8 @@ has_alpha(Format format) {
   case F_rgba32:
   case F_luminance_alpha:
   case F_luminance_alphamask:
+  case F_srgb_alpha:
+  case F_sluminance_alpha:
     return true;
 
   default:
@@ -4743,6 +4778,7 @@ do_reconsider_image_properties(CData *cdata, int x_size, int y_size, int num_com
     // But only do this the first time the file is loaded, or if the
     // number of channels in the image changes on subsequent loads.
 
+    //TODO: handle sRGB properly
     switch (num_components) {
     case 1:
       if (component_type == T_float) {
@@ -4751,19 +4787,19 @@ do_reconsider_image_properties(CData *cdata, int x_size, int y_size, int num_com
         cdata->_format = F_luminance;
       }
       break;
-      
+
     case 2:
       cdata->_format = F_luminance_alpha;
       break;
-      
+
     case 3:
       cdata->_format = F_rgb;
       break;
-      
+
     case 4:
       cdata->_format = F_rgba;
       break;
-      
+
     default:
       // Eh?
       nassertr(false, false);
@@ -5023,12 +5059,14 @@ do_set_format(CData *cdata, Texture::Format format) {
   case F_alpha:
   case F_luminance:
   case F_r16:
+  case F_sluminance:
     cdata->_num_components = 1;
     break;
 
   case F_luminance_alpha:
   case F_luminance_alphamask:
   case F_rg16:
+  case F_sluminance_alpha:
     cdata->_num_components = 2;
     break;
 
@@ -5038,6 +5076,7 @@ do_set_format(CData *cdata, Texture::Format format) {
   case F_rgb12:
   case F_rgb332:
   case F_rgb16:
+  case F_srgb:
     cdata->_num_components = 3;
     break;
 
@@ -5049,6 +5088,7 @@ do_set_format(CData *cdata, Texture::Format format) {
   case F_rgba12:
   case F_rgba16:
   case F_rgba32:
+  case F_srgb_alpha:
     cdata->_num_components = 4;
     break;
   }

+ 8 - 1
panda/src/gobj/texture.h

@@ -132,6 +132,13 @@ PUBLISHED:
     F_r16,
     F_rg16,
     F_rgb16,
+
+    // These formats are in the sRGB color space.
+    // RGB is 2.2 gamma corrected, alpha is always linear.
+    F_srgb,
+    F_srgb_alpha,
+    F_sluminance,
+    F_sluminance_alpha,
   };
 
   enum FilterType {
@@ -160,7 +167,7 @@ PUBLISHED:
 
     // The OpenGL ARB_shadow extension can be thought of as a kind of filtering.
     FT_shadow,
-    
+
     // Default is usually linear, but it depends on format.
     // This was added at the end of the list to avoid bumping TXO version #.
     FT_default,