kA_GrColorComponentFlag, // kR11_EAC_GrPixelConfig
kRGBA_GrColorComponentFlags, // kASTC_12x12_GrPixelConfig
kRGBA_GrColorComponentFlags, // kRGBA_float_GrPixelConfig
+ kA_GrColorComponentFlag, // kAlpha_16_GrPixelConfig
};
return kFlags[config];
GR_STATIC_ASSERT(9 == kR11_EAC_GrPixelConfig);
GR_STATIC_ASSERT(10 == kASTC_12x12_GrPixelConfig);
GR_STATIC_ASSERT(11 == kRGBA_float_GrPixelConfig);
+ GR_STATIC_ASSERT(12 == kAlpha_half_GrPixelConfig);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFlags) == kGrPixelConfigCnt);
}
* Byte order is r, g, b, a. This color format is 32 bits per channel
*/
kRGBA_float_GrPixelConfig,
- kLast_GrPixelConfig = kRGBA_float_GrPixelConfig
+
+ /**
+ * This color format is a single 16 bit float channel
+ */
+ kAlpha_half_GrPixelConfig,
+
+ kLast_GrPixelConfig = kAlpha_half_GrPixelConfig
};
static const int kGrPixelConfigCnt = kLast_GrPixelConfig + 1;
return 1;
case kRGB_565_GrPixelConfig:
case kRGBA_4444_GrPixelConfig:
+ case kAlpha_half_GrPixelConfig:
return 2;
case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig:
return 1;
case kRGB_565_GrPixelConfig:
case kRGBA_4444_GrPixelConfig:
+ case kAlpha_half_GrPixelConfig:
return 2;
case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig:
case kLATC_GrPixelConfig:
case kASTC_12x12_GrPixelConfig:
case kAlpha_8_GrPixelConfig:
+ case kAlpha_half_GrPixelConfig:
return true;
default:
return false;
// only used for storage
typedef uint16_t SkHalf;
+#define SK_HalfMin 0x0400 // 2^-24 (minimum positive normal value)
+#define SK_HalfMax 0x7bff // 65504
+#define SK_HalfEpsilon 0x1400 // 2^-10
+
// convert between half and single precision floating point
float SkHalfToFloat(SkHalf h);
SkHalf SkFloatToHalf(float f);
"LATC", // kLATC_GrPixelConfig,
"R11EAC", // kR11_EAC_GrPixelConfig,
"ASTC12x12",// kASTC_12x12_GrPixelConfig,
- "RGBAFloat", // kRGBA_float_GrPixelConfig
+ "RGBAFloat",// kRGBA_float_GrPixelConfig
+ "AlphaHalf",// kAlpha_half_GrPixelConfig
};
GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
GR_STATIC_ASSERT(9 == kR11_EAC_GrPixelConfig);
GR_STATIC_ASSERT(10 == kASTC_12x12_GrPixelConfig);
GR_STATIC_ASSERT(11 == kRGBA_float_GrPixelConfig);
+ GR_STATIC_ASSERT(12 == kAlpha_half_GrPixelConfig);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
}
void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
-
// OpenGL < 3.0
// no support for render targets unless the GL_ARB_framebuffer_object
// extension is supported (in which case we get ALPHA, RED, RG, RGB,
if (this->isConfigTexturable(kRGBA_float_GrPixelConfig)) {
fConfigRenderSupport[kRGBA_float_GrPixelConfig][kNo_MSAA] = true;
+ if (kGL_GrGLStandard == standard) {
+ fConfigRenderSupport[kRGBA_float_GrPixelConfig][kYes_MSAA] = true;
+ } else {
+ // for now we don't support float point MSAA on ES
+ fConfigRenderSupport[kAlpha_half_GrPixelConfig][kYes_MSAA] = false;
+ }
}
+ if (this->isConfigTexturable(kAlpha_half_GrPixelConfig)) {
+ fConfigRenderSupport[kAlpha_half_GrPixelConfig][kNo_MSAA] = true;
+ if (kGL_GrGLStandard == standard) {
+ fConfigRenderSupport[kAlpha_half_GrPixelConfig][kYes_MSAA] = true;
+ } else {
+ // for now we don't support float point MSAA on ES
+ fConfigRenderSupport[kAlpha_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) {
ctxInfo.hasExtension("GL_OES_texture_float"));
}
fConfigTextureSupport[kRGBA_float_GrPixelConfig] = hasFPTextures;
+
+ // Check for fp16 texture support
+ // NOTE: We disallow floating point textures on ES devices if linear
+ // filtering modes are not supported. This is for simplicity, but a more
+ // granular approach is possible. Coincidentally, 16-bit floating point textures became part of
+ // the standard in ES3.1 / OGL 3.1, hence the shorthand
+ bool hasHalfFPTextures = version >= GR_GL_VER(3, 1);
+ if (!hasHalfFPTextures) {
+ hasHalfFPTextures = ctxInfo.hasExtension("GL_ARB_texture_float") ||
+ (ctxInfo.hasExtension("OES_texture_half_float_linear") &&
+ ctxInfo.hasExtension("GL_OES_texture_half_float"));
+ }
+ fConfigTextureSupport[kAlpha_half_GrPixelConfig] = hasHalfFPTextures && fTextureRedSupport;
}
bool GrGLCaps::doReadPixelsSupported(const GrGLInterface* intf,
#define GR_GL_INT 0x1404
#define GR_GL_UNSIGNED_INT 0x1405
#define GR_GL_FLOAT 0x1406
+#define GR_GL_HALF_FLOAT 0x140B
#define GR_GL_FIXED 0x140C
+#define GR_GL_HALF_FLOAT_OES 0x8D61
/* Lighting */
#define GR_GL_LIGHTING 0x0B50
#define GR_GL_ALPHA8 0x803C
#define GR_GL_R8 0x8229
+#define GR_GL_R16F 0x822D
+#define GR_GL_ALPHA16F 0x881C
/* PixelType */
/* GL_UNSIGNED_BYTE */
*externalType = GR_GL_FLOAT;
break;
+ case kAlpha_half_GrPixelConfig:
+ if (this->glCaps().textureRedSupport()) {
+ *internalFormat = GR_GL_R16F;
+ *externalFormat = GR_GL_RED;
+ *externalType = (kGLES_GrGLStandard == this->glStandard()) ? GR_GL_HALF_FLOAT
+ : GR_GL_HALF_FLOAT_OES;
+ } else {
+ *internalFormat = GR_GL_ALPHA16F;
+ *externalFormat = GR_GL_ALPHA;
+ *externalType = (kGLES_GrGLStandard == this->glStandard()) ? GR_GL_HALF_FLOAT
+ : GR_GL_HALF_FLOAT_OES;
+ }
+ break;
+
default:
return false;
}
#include "GrContext.h"
#include "GrTexture.h"
#include "GrContextFactory.h"
+
#include "SkGpuDevice.h"
+#include "SkHalf.h"
static const int DEV_W = 100, DEV_H = 100;
-static const int FP_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * sizeof(float);
+static const int FP_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 4;
static const float kMaxIntegerRepresentableInSPFloatingPoint = 16777216; // 2 ^ 24
static const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
}
}
+static const int HALF_CONTROL_ARRAY_SIZE = DEV_W * DEV_H;
+
+DEF_GPUTEST(HalfFloatTextureTest, reporter, factory) {
+ SkHalf controlPixelData[HALF_CONTROL_ARRAY_SIZE];
+ SkHalf readBuffer[HALF_CONTROL_ARRAY_SIZE];
+ for (int i = 0; i < HALF_CONTROL_ARRAY_SIZE; i += 4) {
+ controlPixelData[i] = SK_HalfMin;
+ controlPixelData[i + 1] = SK_HalfMax;
+ controlPixelData[i + 2] = SK_HalfEpsilon;
+ controlPixelData[i + 3] = 0x6800; // 2^11
+ }
+
+ for (int origin = 0; origin < 2; ++origin) {
+ int glCtxTypeCnt = 1;
+ glCtxTypeCnt = GrContextFactory::kGLContextTypeCnt;
+ for (int glCtxType = 0; glCtxType < glCtxTypeCnt; ++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;
+
+ GrContext* context = NULL;
+ GrContextFactory::GLContextType type =
+ static_cast<GrContextFactory::GLContextType>(glCtxType);
+ if (!GrContextFactory::IsRenderingGLContext(type)) {
+ continue;
+ }
+ context = factory->get(type);
+ if (NULL == context){
+ continue;
+ }
+
+ SkAutoTUnref<GrTexture> fpTexture(context->createUncachedTexture(desc,
+ NULL,
+ 0));
+
+ // 16-bit floating point textures are NOT supported everywhere
+ if (NULL == fpTexture) {
+ continue;
+ }
+
+ // write square
+ fpTexture->writePixels(0, 0, DEV_W, DEV_H, desc.fConfig, controlPixelData, 0);
+ fpTexture->readPixels(0, 0, DEV_W, DEV_H, desc.fConfig, readBuffer, 0);
+ for (int j = 0; j < HALF_CONTROL_ARRAY_SIZE; ++j) {
+ SkASSERT(readBuffer[j] == controlPixelData[j]);
+ REPORTER_ASSERT(reporter, readBuffer[j] == controlPixelData[j]);
+ }
+ }
+ }
+}
+
#endif