Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(632)

Side by Side Diff: src/gpu/gl/GrGLGpu.cpp

Issue 1613903005: Make A8 readbacks work from non-A8 surfaces (Closed) Base URL: https://skia.googlesource.com/skia.git@checksupp
Patch Set: Address comments Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/gl/GrGLCaps.cpp ('k') | tests/ReadWriteAlphaTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 8
9 #include "GrGLGpu.h" 9 #include "GrGLGpu.h"
10 #include "GrGLGLSL.h" 10 #include "GrGLGLSL.h"
(...skipping 1986 matching lines...) Expand 10 before | Expand all | Expand 10 after
1997 1997
1998 bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig rea dConfig) { 1998 bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig rea dConfig) {
1999 if (GrRenderTarget* rt = surfaceForConfig->asRenderTarget()) { 1999 if (GrRenderTarget* rt = surfaceForConfig->asRenderTarget()) {
2000 return this->readPixelsSupported(rt, readConfig); 2000 return this->readPixelsSupported(rt, readConfig);
2001 } else { 2001 } else {
2002 GrPixelConfig config = surfaceForConfig->config(); 2002 GrPixelConfig config = surfaceForConfig->config();
2003 return this->readPixelsSupported(config, readConfig); 2003 return this->readPixelsSupported(config, readConfig);
2004 } 2004 }
2005 } 2005 }
2006 2006
2007 static bool requires_srgb_conversion(GrPixelConfig a, GrPixelConfig b) {
2008 if (GrPixelConfigIsSRGB(a)) {
2009 return !GrPixelConfigIsSRGB(b) && !GrPixelConfigIsAlphaOnly(b);
2010 } else if (GrPixelConfigIsSRGB(b)) {
2011 return !GrPixelConfigIsSRGB(a) && !GrPixelConfigIsAlphaOnly(a);
2012 }
2013 return false;
2014 }
2015
2007 bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes, 2016 bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
2008 GrPixelConfig readConfig, DrawPreference* draw Preference, 2017 GrPixelConfig readConfig, DrawPreference* draw Preference,
2009 ReadPixelTempDrawInfo* tempDrawInfo) { 2018 ReadPixelTempDrawInfo* tempDrawInfo) {
2010 GrRenderTarget* srcAsRT = srcSurface->asRenderTarget(); 2019 GrPixelConfig srcConfig = srcSurface->config();
2011 2020
2012 // This subclass can only read pixels from a render target. We could use glT exSubImage2D on 2021 // These settings we will always want if a temp draw is performed.
2013 // GL versions that support it but we don't today.
2014 if (!srcAsRT) {
2015 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2016 }
2017
2018 if (GrPixelConfigIsSRGB(srcSurface->config()) != GrPixelConfigIsSRGB(readCon fig)) {
2019 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2020 }
2021
2022 tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
2023 tempDrawInfo->fReadConfig = readConfig;
2024
2025 // These settings we will always want if a temp draw is performed. The confi g is set below
2026 // depending on whether we want to do a R/B swap or not.
2027 tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag; 2022 tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
2028 tempDrawInfo->fTempSurfaceDesc.fWidth = width; 2023 tempDrawInfo->fTempSurfaceDesc.fWidth = width;
2029 tempDrawInfo->fTempSurfaceDesc.fHeight = height; 2024 tempDrawInfo->fTempSurfaceDesc.fHeight = height;
2030 tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0; 2025 tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
2031 tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL. 2026 tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
2032 tempDrawInfo->fUseExactScratch = this->glCaps().partialFBOReadIsSlow(); 2027 tempDrawInfo->fUseExactScratch = this->glCaps().partialFBOReadIsSlow();
2033 2028
2034 // Start off assuming that any temp draw should be to the readConfig, then c heck if that will 2029 // For now assume no swizzling, we may change that below.
2035 // be inefficient. 2030 tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
2036 GrPixelConfig srcConfig = srcSurface->config(); 2031
2037 tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig; 2032 // Depends on why we need/want a temp draw. Start off assuming no change, th e surface we read
2033 // from will be srcConfig and we will read readConfig pixels from it.
2034 // Not that if we require a draw and return a non-renderable format for the temp surface the
2035 // base class will fail for us.
2036 tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
2037 tempDrawInfo->fReadConfig = readConfig;
2038
2039 if (requires_srgb_conversion(srcConfig, readConfig)) {
2040 if (!this->readPixelsSupported(readConfig, readConfig)) {
2041 return false;
2042 }
2043 // Draw to do srgb to linear conversion or vice versa.
2044 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2045 tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
2046 tempDrawInfo->fReadConfig = readConfig;
2047 return true;
2048 }
2049
2050 GrRenderTarget* srcAsRT = srcSurface->asRenderTarget();
2051 if (!srcAsRT) {
2052 // For now keep assuming the draw is not a format transformation, just a draw to get to a
2053 // RT. We may add additional transformations below.
2054 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2055 }
2038 2056
2039 if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig && 2057 if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig &&
2040 this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelCo nfig)) { 2058 this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelCo nfig)) {
2041 tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig; 2059 tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig;
2042 tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); 2060 tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2043 tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig; 2061 tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig;
2044 ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); 2062 ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
2045 } else if (kMesa_GrGLDriver == this->glContext().driver() && 2063 } else if (kMesa_GrGLDriver == this->glContext().driver() &&
2046 GrBytesPerPixel(readConfig) == 4 && 2064 GrBytesPerPixel(readConfig) == 4 &&
2047 GrPixelConfigSwapRAndB(readConfig) == srcConfig && 2065 GrPixelConfigSwapRAndB(readConfig) == srcConfig &&
2048 this->readPixelsSupported(srcSurface, srcConfig)) { 2066 this->readPixelsSupported(srcSurface, srcConfig)) {
2049 // Mesa 3D takes a slow path on when reading back BGRA from an RGBA surf ace and vice-versa. 2067 // Mesa 3D takes a slow path on when reading back BGRA from an RGBA surf ace and vice-versa.
2050 // Better to do a draw with a R/B swap and then read as the original con fig. 2068 // Better to do a draw with a R/B swap and then read as the original con fig.
2051 tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig; 2069 tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
2052 tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); 2070 tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2053 tempDrawInfo->fReadConfig = srcConfig; 2071 tempDrawInfo->fReadConfig = srcConfig;
2054 ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); 2072 ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
2055 } else if (!this->readPixelsSupported(srcSurface, readConfig)) { 2073 } else if (!this->readPixelsSupported(srcSurface, readConfig)) {
2056 if (readConfig == kBGRA_8888_GrPixelConfig && 2074 if (readConfig == kBGRA_8888_GrPixelConfig &&
2057 this->glCaps().isConfigRenderable(kRGBA_8888_GrPixelConfig, false) & & 2075 this->glCaps().isConfigRenderable(kRGBA_8888_GrPixelConfig, false) & &
2058 this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPix elConfig)) { 2076 this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPix elConfig)) {
2059 2077 // We're trying to read BGRA but it's not supported. If RGBA is rend erable and
2078 // we can read it back, then do a swizzling draw to a RGBA and read it back (which
2079 // will effectively be BGRA).
2060 tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig; 2080 tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
2061 tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); 2081 tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2062 tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig; 2082 tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
2063 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); 2083 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2084 } else if (readConfig == kAlpha_8_GrPixelConfig) {
2085 // onReadPixels implements a fallback for cases where we are want to read kAlpha_8,
2086 // it's unsupported, but 32bit RGBA reads are supported.
2087 // Don't attempt to do any srgb conversions since we only care about alpha.
2088 GrPixelConfig cpuTempConfig = kRGBA_8888_GrPixelConfig;
2089 if (GrPixelConfigIsSRGB(srcSurface->config())) {
2090 cpuTempConfig = kSRGBA_8888_GrPixelConfig;
2091 }
2092 if (!this->readPixelsSupported(srcSurface, cpuTempConfig)) {
2093 // If we can't read RGBA from the src try to draw to a kRGBA_888 8 (or kSRGBA_8888)
2094 // first and then onReadPixels will read that to a 32bit tempora ry buffer.
2095 if (this->caps()->isConfigRenderable(cpuTempConfig, false)) {
2096 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPrefe rence);
2097 tempDrawInfo->fTempSurfaceDesc.fConfig = cpuTempConfig;
2098 tempDrawInfo->fReadConfig = kAlpha_8_GrPixelConfig;
2099 } else {
2100 return false;
2101 }
2102 } else {
2103 SkASSERT(tempDrawInfo->fTempSurfaceDesc.fConfig == srcConfig);
2104 SkASSERT(tempDrawInfo->fReadConfig == kAlpha_8_GrPixelConfig);
2105 }
2064 } else { 2106 } else {
2065 return false; 2107 return false;
2066 } 2108 }
2067 } 2109 }
2068 2110
2069 if (srcAsRT && 2111 if (srcAsRT &&
2070 read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, read Config, rowBytes)) { 2112 read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, read Config, rowBytes)) {
2071 ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); 2113 ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
2072 } 2114 }
2073 2115
2074 return true; 2116 return true;
2075 } 2117 }
2076 2118
2077 bool GrGLGpu::onReadPixels(GrSurface* surface, 2119 bool GrGLGpu::onReadPixels(GrSurface* surface,
2078 int left, int top, 2120 int left, int top,
2079 int width, int height, 2121 int width, int height,
2080 GrPixelConfig config, 2122 GrPixelConfig config,
2081 void* buffer, 2123 void* buffer,
2082 size_t rowBytes) { 2124 size_t rowBytes) {
2083 SkASSERT(surface); 2125 SkASSERT(surface);
2084 2126
2085 GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(surface->asRenderTarg et()); 2127 GrGLRenderTarget* renderTarget = static_cast<GrGLRenderTarget*>(surface->asR enderTarget());
2086 if (!tgt) { 2128 if (!renderTarget) {
2087 return false; 2129 return false;
2088 } 2130 }
2089 2131
2090 // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pi xels. 2132 // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pi xels.
2091 if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { 2133 if (requires_srgb_conversion(surface->config(), config)) {
2134 return false;
2135 }
2136
2137 // We have a special case fallback for reading eight bit alpha. We will read back all four 8
2138 // bit channels as RGBA and then extract A.
2139 if (!this->readPixelsSupported(renderTarget, config)) {
2140 // Don't attempt to do any srgb conversions since we only care about alp ha.
2141 GrPixelConfig tempConfig = kRGBA_8888_GrPixelConfig;
2142 if (GrPixelConfigIsSRGB(renderTarget->config())) {
2143 tempConfig = kSRGBA_8888_GrPixelConfig;
2144 }
2145 if (kAlpha_8_GrPixelConfig == config &&
2146 this->readPixelsSupported(renderTarget, tempConfig)) {
2147 SkAutoTDeleteArray<uint32_t> temp(new uint32_t[width * height * 4]);
2148 if (this->onReadPixels(renderTarget, left, top, width, height, tempC onfig, temp.get(),
2149 width*4)) {
2150 uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);
2151 for (int j = 0; j < height; ++j) {
2152 for (int i = 0; i < width; ++i) {
2153 dst[j*rowBytes + i] = (0xFF000000U & temp[j*width+i]) >> 24;
2154 }
2155 }
2156 return true;
2157 }
2158 }
2092 return false; 2159 return false;
2093 } 2160 }
2094 2161
2095 GrGLenum externalFormat; 2162 GrGLenum externalFormat;
2096 GrGLenum externalType; 2163 GrGLenum externalType;
2097 if (!this->glCaps().getReadPixelsFormat(surface->config(), config, &external Format, 2164 if (!this->glCaps().getReadPixelsFormat(renderTarget->config(), config, &ext ernalFormat,
2098 &externalType)) { 2165 &externalType)) {
2099 return false; 2166 return false;
2100 } 2167 }
2101 bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); 2168 bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
2102 2169
2103 // resolve the render target if necessary 2170 // resolve the render target if necessary
2104 switch (tgt->getResolveType()) { 2171 switch (renderTarget->getResolveType()) {
2105 case GrGLRenderTarget::kCantResolve_ResolveType: 2172 case GrGLRenderTarget::kCantResolve_ResolveType:
2106 return false; 2173 return false;
2107 case GrGLRenderTarget::kAutoResolves_ResolveType: 2174 case GrGLRenderTarget::kAutoResolves_ResolveType:
2108 this->flushRenderTarget(tgt, &SkIRect::EmptyIRect()); 2175 this->flushRenderTarget(renderTarget, &SkIRect::EmptyIRect());
2109 break; 2176 break;
2110 case GrGLRenderTarget::kCanResolve_ResolveType: 2177 case GrGLRenderTarget::kCanResolve_ResolveType:
2111 this->onResolveRenderTarget(tgt); 2178 this->onResolveRenderTarget(renderTarget);
2112 // we don't track the state of the READ FBO ID. 2179 // we don't track the state of the READ FBO ID.
2113 fStats.incRenderTargetBinds(); 2180 fStats.incRenderTargetBinds();
2114 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()) ); 2181 GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textur eFBOID()));
2115 break; 2182 break;
2116 default: 2183 default:
2117 SkFAIL("Unknown resolve type"); 2184 SkFAIL("Unknown resolve type");
2118 } 2185 }
2119 2186
2120 const GrGLIRect& glvp = tgt->getViewport(); 2187 const GrGLIRect& glvp = renderTarget->getViewport();
2121 2188
2122 // the read rect is viewport-relative 2189 // the read rect is viewport-relative
2123 GrGLIRect readRect; 2190 GrGLIRect readRect;
2124 readRect.setRelativeTo(glvp, left, top, width, height, tgt->origin()); 2191 readRect.setRelativeTo(glvp, left, top, width, height, renderTarget->origin( ));
2125 2192
2126 size_t tightRowBytes = GrBytesPerPixel(config) * width; 2193 size_t tightRowBytes = GrBytesPerPixel(config) * width;
2127 2194
2128 size_t readDstRowBytes = tightRowBytes; 2195 size_t readDstRowBytes = tightRowBytes;
2129 void* readDst = buffer; 2196 void* readDst = buffer;
2130 2197
2131 // determine if GL can read using the passed rowBytes or if we need 2198 // determine if GL can read using the passed rowBytes or if we need
2132 // a scratch buffer. 2199 // a scratch buffer.
2133 SkAutoSMalloc<32 * sizeof(GrColor)> scratch; 2200 SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
2134 if (rowBytes != tightRowBytes) { 2201 if (rowBytes != tightRowBytes) {
(...skipping 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after
3556 if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() || 3623 if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() ||
3557 GR_GL_TEXTURE_RECTANGLE == glTexture->target()) { 3624 GR_GL_TEXTURE_RECTANGLE == glTexture->target()) {
3558 copyParams->fFilter = GrTextureParams::kNone_FilterMode; 3625 copyParams->fFilter = GrTextureParams::kNone_FilterMode;
3559 copyParams->fWidth = texture->width(); 3626 copyParams->fWidth = texture->width();
3560 copyParams->fHeight = texture->height(); 3627 copyParams->fHeight = texture->height();
3561 return true; 3628 return true;
3562 } 3629 }
3563 } 3630 }
3564 return false; 3631 return false;
3565 } 3632 }
OLDNEW
« no previous file with comments | « src/gpu/gl/GrGLCaps.cpp ('k') | tests/ReadWriteAlphaTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698