diff options
author | 2012-02-23 15:39:54 +0000 | |
---|---|---|
committer | 2012-02-23 15:39:54 +0000 | |
commit | a91e923874ca0565b4f4816b5697dfdcd337b889 (patch) | |
tree | 15ef376614e2aa51ceb99b13523192970f922b57 /src/gpu/gl/GrGpuGL.cpp | |
parent | 78525202b8555a1538544aeb3aef5c49aa64b33d (diff) |
GPU device preserves pixel values across read/write/read of unpremul pixel values
Review URL: http://codereview.appspot.com/5695047/
git-svn-id: http://skia.googlecode.com/svn/trunk@3237 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu/gl/GrGpuGL.cpp')
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 68f33b11ca..bee2017272 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -207,6 +207,7 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) { this->initCaps(); fLastSuccessfulStencilFmtIdx = 0; + fCanPreserveUnpremulRoundtrip = kUnknown_CanPreserveUnpremulRoundtrip; } GrGpuGL::~GrGpuGL() { @@ -292,6 +293,85 @@ void GrGpuGL::initCaps() { fCaps.fFSAASupport = GrGLCaps::kNone_MSFBOType != this->glCaps().msFBOType(); } +bool GrGpuGL::canPreserveReadWriteUnpremulPixels() { + if (kUnknown_CanPreserveUnpremulRoundtrip == + fCanPreserveUnpremulRoundtrip) { + + SkAutoTMalloc<uint32_t> data(256 * 256 * 3); + uint32_t* srcData = data.get(); + uint32_t* firstRead = data.get() + 256 * 256; + uint32_t* secondRead = data.get() + 2 * 256 * 256; + + for (int y = 0; y < 256; ++y) { + for (int x = 0; x < 256; ++x) { + uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]); + color[3] = y; + color[2] = x; + color[1] = x; + color[0] = x; + } + } + + // We have broader support for read/write pixels on render targets + // than on textures. + GrTextureDesc dstDesc; + dstDesc.fFlags = kRenderTarget_GrTextureFlagBit | + kNoStencil_GrTextureFlagBit; + dstDesc.fWidth = 256; + dstDesc.fHeight = 256; + dstDesc.fConfig = kRGBA_8888_GrPixelConfig; + dstDesc.fSampleCnt = 0; + + SkAutoTUnref<GrTexture> dstTex(this->createTexture(dstDesc, NULL, 0)); + if (!dstTex.get()) { + return false; + } + GrRenderTarget* rt = dstTex.get()->asRenderTarget(); + GrAssert(NULL != rt); + + bool failed = true; + static const UnpremulConversion gMethods[] = { + kUpOnWrite_DownOnRead_UnpremulConversion, + kDownOnWrite_UpOnRead_UnpremulConversion, + }; + + // pretend that we can do the roundtrip to avoid recursive calls to + // this function + fCanPreserveUnpremulRoundtrip = kYes_CanPreserveUnpremulRoundtrip; + for (size_t i = 0; i < GR_ARRAY_COUNT(gMethods) && failed; ++i) { + fUnpremulConversion = gMethods[i]; + rt->writePixels(0, 0, + 256, 256, + kRGBA_8888_UPM_GrPixelConfig, srcData, 0); + rt->readPixels(0, 0, + 256, 256, + kRGBA_8888_UPM_GrPixelConfig, firstRead, 0); + rt->writePixels(0, 0, + 256, 256, + kRGBA_8888_UPM_GrPixelConfig, firstRead, 0); + rt->readPixels(0, 0, + 256, 256, + kRGBA_8888_UPM_GrPixelConfig, secondRead, 0); + failed = false; + for (int j = 0; j < 256 * 256; ++j) { + if (firstRead[j] != secondRead[j]) { + failed = true; + break; + } + } + } + fCanPreserveUnpremulRoundtrip = failed ? + kNo_CanPreserveUnpremulRoundtrip : + kYes_CanPreserveUnpremulRoundtrip; + } + + if (kYes_CanPreserveUnpremulRoundtrip == fCanPreserveUnpremulRoundtrip) { + return true; + } else { + return false; + } +} + GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig config) const { if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) { return GrPixelConfigSwapRAndB(config); |