aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl/GrGpuGL.cpp
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-23 15:39:54 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-23 15:39:54 +0000
commita91e923874ca0565b4f4816b5697dfdcd337b889 (patch)
tree15ef376614e2aa51ceb99b13523192970f922b57 /src/gpu/gl/GrGpuGL.cpp
parent78525202b8555a1538544aeb3aef5c49aa64b33d (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.cpp80
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);