Add RGBA half float texture format.
authorjvanverth <jvanverth@google.com>
Thu, 21 May 2015 15:12:27 +0000 (08:12 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 21 May 2015 15:12:27 +0000 (08:12 -0700)
BUG=skia:3829

Review URL: https://codereview.chromium.org/1148243002

include/gpu/GrColor.h
include/gpu/GrTypes.h
src/gpu/GrDrawTarget.cpp
src/gpu/gl/GrGLCaps.cpp
src/gpu/gl/GrGLDefines.h
src/gpu/gl/GrGLGpu.cpp
tests/FloatingPointTextureTest.cpp

index 43bfd8d..f5757b9 100644 (file)
@@ -183,6 +183,7 @@ static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) {
         kRGBA_GrColorComponentFlags,    // kASTC_12x12_GrPixelConfig
         kRGBA_GrColorComponentFlags,    // kRGBA_float_GrPixelConfig
         kA_GrColorComponentFlag,        // kAlpha_16_GrPixelConfig
+        kRGBA_GrColorComponentFlags,    // kRGBA_half_GrPixelConfig
     };
     return kFlags[config];
 
@@ -200,6 +201,7 @@ static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) {
     GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig);
     GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig);
     GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig);
+    GR_STATIC_ASSERT(14 == kRGBA_half_GrPixelConfig);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFlags) == kGrPixelConfigCnt);
 }
 
index c1d324b..b38608e 100644 (file)
@@ -250,7 +250,12 @@ enum GrPixelConfig {
      */
     kAlpha_half_GrPixelConfig,
 
-    kLast_GrPixelConfig = kAlpha_half_GrPixelConfig
+    /**
+    * Byte order is r, g, b, a.  This color format is 16 bits per channel
+    */
+    kRGBA_half_GrPixelConfig,
+
+    kLast_GrPixelConfig = kRGBA_half_GrPixelConfig
 };
 static const int kGrPixelConfigCnt = kLast_GrPixelConfig + 1;
 
@@ -335,6 +340,8 @@ static inline size_t GrBytesPerPixel(GrPixelConfig config) {
         case kBGRA_8888_GrPixelConfig:
         case kSRGBA_8888_GrPixelConfig:
             return 4;
+        case kRGBA_half_GrPixelConfig:
+            return 8;
         case kRGBA_float_GrPixelConfig:
             return 16;
         default:
@@ -350,6 +357,7 @@ static inline size_t GrUnpackAlignment(GrPixelConfig config) {
         case kRGB_565_GrPixelConfig:
         case kRGBA_4444_GrPixelConfig:
         case kAlpha_half_GrPixelConfig:
+        case kRGBA_half_GrPixelConfig:
             return 2;
         case kRGBA_8888_GrPixelConfig:
         case kBGRA_8888_GrPixelConfig:
index 2d80bcc..847e497 100644 (file)
@@ -734,6 +734,7 @@ SkString GrCaps::dump() const {
         "ASTC12x12",// kASTC_12x12_GrPixelConfig,
         "RGBAFloat",// kRGBA_float_GrPixelConfig
         "AlphaHalf",// kAlpha_half_GrPixelConfig
+        "RGBAHalf", // kRGBA_half_GrPixelConfig
     };
     GR_STATIC_ASSERT(0  == kUnknown_GrPixelConfig);
     GR_STATIC_ASSERT(1  == kAlpha_8_GrPixelConfig);
@@ -749,6 +750,7 @@ SkString GrCaps::dump() const {
     GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig);
     GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig);
     GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig);
+    GR_STATIC_ASSERT(14 == kRGBA_half_GrPixelConfig);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
 
     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
index 7d9c50d..ea6b83f 100644 (file)
@@ -483,7 +483,7 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
                 fConfigRenderSupport[kRGBA_float_GrPixelConfig][kNo_MSAA] = false;
             }
             // for now we don't support floating point MSAA on ES
-            fConfigRenderSupport[kAlpha_half_GrPixelConfig][kYes_MSAA] = false;
+            fConfigRenderSupport[kRGBA_float_GrPixelConfig][kYes_MSAA] = false;
         }
     }
 
@@ -506,6 +506,25 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
         }
     }
     
+    if (this->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
+        if (kGL_GrGLStandard == standard) {
+            fConfigRenderSupport[kRGBA_half_GrPixelConfig][kNo_MSAA] = true;
+            fConfigRenderSupport[kRGBA_half_GrPixelConfig][kYes_MSAA] = true;
+        } else if (ctxInfo.version() >= GR_GL_VER(3, 0)) {
+            fConfigRenderSupport[kRGBA_half_GrPixelConfig][kNo_MSAA] = true;
+            // for now we don't support floating point MSAA on ES
+            fConfigRenderSupport[kRGBA_half_GrPixelConfig][kYes_MSAA] = false;
+        } else {
+            if (ctxInfo.hasExtension("GL_EXT_color_buffer_half_float")) {
+                fConfigRenderSupport[kRGBA_half_GrPixelConfig][kNo_MSAA] = true;
+            } else {
+                fConfigRenderSupport[kRGBA_half_GrPixelConfig][kNo_MSAA] = false;
+            }
+            // for now we don't support floating point MSAA on ES
+            fConfigRenderSupport[kRGBA_half_GrPixelConfig][kYes_MSAA] = false;
+        }
+    }
+
     // If we don't support MSAA then undo any places above where we set a config as renderable with
     // msaa.
     if (kNone_MSFBOType == fMSFBOType) {
@@ -663,6 +682,7 @@ void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const G
                              ctxInfo.hasExtension("GL_OES_texture_half_float"));
     }
     fConfigTextureSupport[kAlpha_half_GrPixelConfig] = hasHalfFPTextures;
+    fConfigTextureSupport[kRGBA_half_GrPixelConfig] = hasHalfFPTextures;
 }
 
 bool GrGLCaps::doReadPixelsSupported(const GrGLInterface* intf,
index 349e3c4..4c479ed 100644 (file)
 
 #define GR_GL_R8                             0x8229
 #define GR_GL_R16F                           0x822D
+#define GR_GL_RGBA16F                        0x881A
 #define GR_GL_ALPHA16F                       0x881C
 
 /* PixelType */
index df3a5e6..6a8d83b 100644 (file)
@@ -2493,6 +2493,16 @@ bool GrGLGpu::configToGLFormats(GrPixelConfig config,
             }
             break;
             
+        case kRGBA_half_GrPixelConfig:
+            *internalFormat = GR_GL_RGBA16F;
+            *externalFormat = GR_GL_RGBA;
+            if (kGL_GrGLStandard == this->glStandard() || this->glVersion() >= GR_GL_VER(3, 0)) {
+                *externalType = GR_GL_HALF_FLOAT;
+            } else {
+                *externalType = GR_GL_HALF_FLOAT_OES;
+            }
+            break;
+
         default:
             return false;
     }
index 69495b4..1adc744 100644 (file)
 #include "SkHalf.h"
 
 static const int DEV_W = 100, DEV_H = 100;
-static const int FP_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 4/*RGBA*/;
-static const float kMaxIntegerRepresentableInSPFloatingPoint = 16777216;  // 2 ^ 24
-
 static const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
 
-DEF_GPUTEST(FloatingPointTextureTest, reporter, factory) {
-    SkTDArray<float> controlPixelData, readBuffer;
-    controlPixelData.setCount(FP_CONTROL_ARRAY_SIZE);
-    readBuffer.setCount(FP_CONTROL_ARRAY_SIZE);
-
-    for (int i = 0; i < FP_CONTROL_ARRAY_SIZE; i += 4) {
-        controlPixelData[i + 0] = FLT_MIN;
-        controlPixelData[i + 1] = FLT_MAX;
-        controlPixelData[i + 2] = FLT_EPSILON;
-        controlPixelData[i + 3] = kMaxIntegerRepresentableInSPFloatingPoint;
+template <typename T>
+void runFPTest(skiatest::Reporter* reporter, GrContextFactory* factory,
+               T min, T max, T epsilon, T maxInt, int arraySize, GrPixelConfig config) {
+    SkTDArray<T> controlPixelData, readBuffer;
+    controlPixelData.setCount(arraySize);
+    readBuffer.setCount(arraySize);
+
+    for (int i = 0; i < arraySize; i += 4) {
+        controlPixelData[i + 0] = min;
+        controlPixelData[i + 1] = max;
+        controlPixelData[i + 2] = epsilon;
+        controlPixelData[i + 3] = maxInt;
     }
 
     for (int origin = 0; origin < 2; ++origin) {
         for (int glCtxType = 0; glCtxType < GrContextFactory::kGLContextTypeCnt; ++glCtxType) {
             GrSurfaceDesc desc;
-            desc.fFlags  = kRenderTarget_GrSurfaceFlag;
-            desc.fWidth  = DEV_W;
+            desc.fFlags = kRenderTarget_GrSurfaceFlag;
+            desc.fWidth = DEV_W;
             desc.fHeight = DEV_H;
-            desc.fConfig = kRGBA_float_GrPixelConfig;
+            desc.fConfig = config;
             desc.fOrigin = 0 == origin ?
-                kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
+            kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
 
             GrContextFactory::GLContextType type =
                 static_cast<GrContextFactory::GLContextType>(glCtxType);
@@ -56,7 +55,7 @@ DEF_GPUTEST(FloatingPointTextureTest, reporter, factory) {
                 continue;
             }
             GrContext* context = factory->get(type);
-            if (NULL == context){
+            if (NULL == context) {
                 continue;
             }
 
@@ -68,56 +67,35 @@ DEF_GPUTEST(FloatingPointTextureTest, reporter, factory) {
             }
             fpTexture->readPixels(0, 0, DEV_W, DEV_H, desc.fConfig, readBuffer.begin(), 0);
             REPORTER_ASSERT(reporter,
-                    0 == memcmp(readBuffer.begin(), controlPixelData.begin(), readBuffer.bytes()));
+                0 == memcmp(readBuffer.begin(), controlPixelData.begin(), readBuffer.bytes()));
         }
     }
 }
 
-static const int HALF_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 1 /*alpha-only*/;
+static const int FP_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 4/*RGBA*/;
+static const float kMaxIntegerRepresentableInSPFloatingPoint = 16777216;  // 2 ^ 24
 
-DEF_GPUTEST(HalfFloatTextureTest, reporter, factory) {
-    SkTDArray<SkHalf> controlPixelData, readBuffer;
-    controlPixelData.setCount(HALF_CONTROL_ARRAY_SIZE);
-    readBuffer.setCount(HALF_CONTROL_ARRAY_SIZE);
+DEF_GPUTEST(FloatingPointTextureTest, reporter, factory) {
+    runFPTest<float>(reporter, factory, FLT_MIN, FLT_MAX, FLT_EPSILON,
+                     kMaxIntegerRepresentableInSPFloatingPoint, 
+                     FP_CONTROL_ARRAY_SIZE, kRGBA_float_GrPixelConfig);
+}
 
-    for (int i = 0; i < HALF_CONTROL_ARRAY_SIZE; i += 4) {
-        controlPixelData[i + 0] = SK_HalfMin;
-        controlPixelData[i + 1] = SK_HalfMax;
-        controlPixelData[i + 2] = SK_HalfEpsilon;
-        controlPixelData[i + 3] = 0x6800;   // 2^11
-    }
+static const int HALF_ALPHA_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 1 /*alpha-only*/;
+static const SkHalf kMaxIntegerRepresentableInHalfFloatingPoint = 0x6800;  // 2 ^ 11
 
-    for (int origin = 0; origin < 2; ++origin) {
-        for (int glCtxType = 0; glCtxType < GrContextFactory::kGLContextTypeCnt; ++glCtxType) {
-            GrSurfaceDesc desc;
-            desc.fFlags  = kRenderTarget_GrSurfaceFlag;
-            desc.fWidth  = DEV_W;
-            desc.fHeight = DEV_H;
-            desc.fConfig = kAlpha_half_GrPixelConfig;
-            desc.fOrigin = 0 == origin ?
-                kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
+DEF_GPUTEST(HalfFloatAlphaTextureTest, reporter, factory) {
+    runFPTest<SkHalf>(reporter, factory, SK_HalfMin, SK_HalfMax, SK_HalfEpsilon,
+        kMaxIntegerRepresentableInHalfFloatingPoint,
+        HALF_ALPHA_CONTROL_ARRAY_SIZE, kAlpha_half_GrPixelConfig);
+}
 
-            GrContextFactory::GLContextType type =
-                static_cast<GrContextFactory::GLContextType>(glCtxType);
-            if (!GrContextFactory::IsRenderingGLContext(type)) {
-                continue;
-            }
-            GrContext* context = factory->get(type);
-            if (NULL == context){
-                continue;
-            }
+static const int HALF_RGBA_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 4 /*RGBA*/;
 
-            SkAutoTUnref<GrTexture> fpTexture(context->textureProvider()->createTexture(
-                desc, false, controlPixelData.begin(), 0));
-            // 16-bit floating point textures are NOT supported everywhere
-            if (NULL == fpTexture) {
-                continue;
-            }
-            fpTexture->readPixels(0, 0, DEV_W, DEV_H, desc.fConfig, readBuffer.begin(), 0);
-            REPORTER_ASSERT(reporter,
-                    0 == memcmp(readBuffer.begin(), controlPixelData.begin(), readBuffer.bytes()));
-        }
-    }
+DEF_GPUTEST(HalfFloatRGBATextureTest, reporter, factory) {
+    runFPTest<SkHalf>(reporter, factory, SK_HalfMin, SK_HalfMax, SK_HalfEpsilon,
+        kMaxIntegerRepresentableInHalfFloatingPoint,
+        HALF_RGBA_CONTROL_ARRAY_SIZE, kRGBA_half_GrPixelConfig);
 }
 
 #endif