aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/gl/GrGLCaps.cpp28
-rw-r--r--src/gpu/gl/GrGLGpu.cpp42
2 files changed, 63 insertions, 7 deletions
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 678c62abb8..0c2ed73d7c 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -637,7 +637,22 @@ bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
}
if (kGL_GrGLStandard == intf->fStandard) {
- // All of our renderable configs can be converted to each other by glReadPixels in OpenGL.
+ // Some OpenGL implementations allow GL_ALPHA as a format to glReadPixels. However,
+ // the manual (https://www.opengl.org/sdk/docs/man/) says only these formats are allowed:
+ // GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, GL_RED, GL_GREEN, GL_BLUE,
+ // GL_RGB, GL_BGR, GL_RGBA, and GL_BGRA. We check for the subset that we would use.
+ if (readFormat != GR_GL_RED && readFormat != GR_GL_RGB && readFormat != GR_GL_RGBA &&
+ readFormat != GR_GL_BGRA) {
+ return false;
+ }
+ // There is also a set of allowed types, but all the types we use are in the set:
+ // GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT,
+ // GL_HALF_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ // GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4,
+ // GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ // GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,GL_UNSIGNED_INT_10_10_10_2,
+ // GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
+ // GL_UNSIGNED_INT_5_9_9_9_REV, or GL_FLOAT_32_UNSIGNED_INT_24_8_REV.
return true;
}
@@ -1051,6 +1066,17 @@ bool GrGLCaps::getExternalFormat(GrPixelConfig surfaceConfig, GrPixelConfig memo
*externalFormat = fConfigTable[memoryConfig].fFormats.fExternalFormat[usage];
*externalType = fConfigTable[memoryConfig].fFormats.fExternalType;
+ // When GL_RED is supported as a texture format, our alpha-only textures are stored using
+ // GL_RED and we swizzle in order to map all components to 'r'. However, in this case the
+ // surface is not alpha-only and we want alpha to really mean the alpha component of the
+ // texture, not the red component.
+ if (memoryIsAlphaOnly && !surfaceIsAlphaOnly) {
+ if (this->textureRedSupport()) {
+ SkASSERT(GR_GL_RED == *externalFormat);
+ *externalFormat = GR_GL_ALPHA;
+ }
+ }
+
return true;
}
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 8033ea60e5..972049aa56 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1951,7 +1951,8 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height,
ReadPixelTempDrawInfo* tempDrawInfo) {
// This subclass can only read pixels from a render target. We could use glTexSubImage2D on
// GL versions that support it but we don't today.
- if (!srcSurface->asRenderTarget()) {
+ GrRenderTarget* srcAsRT = srcSurface->asRenderTarget();
+ if (!srcAsRT) {
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
}
@@ -1992,13 +1993,20 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height,
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
tempDrawInfo->fSwapRAndB = true;
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
+ } else if (kRequireDraw_DrawPreference == *drawPreference &&
+ readConfig == kAlpha_8_GrPixelConfig &&
+ !this->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
+ // On some GLs there is no renderable single channel format. In that case we fall back
+ // to rendering to a RGBA and then will extract the alpha from that.
+ if (this->caps()->isConfigRenderable(kRGBA_8888_GrPixelConfig, false)) {
+ tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ } else {
+ return false;
+ }
}
- GrRenderTarget* srcAsRT = srcSurface->asRenderTarget();
- if (!srcAsRT) {
- ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
- } else if (read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig,
- rowBytes)) {
+ if (srcAsRT && read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig,
+ rowBytes)) {
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
}
@@ -2049,6 +2057,28 @@ bool GrGLGpu::onReadPixels(GrSurface* surface,
SkFAIL("Unknown resolve type");
}
+ // We have a special case fallback for reading alpha from a RGBA/BGRA surface. We will read
+ // back all the channels as RGBA and then extract A.
+ // This must be called after the RT is bound as the FBO above.
+ if (!this->glCaps().readPixelsSupported(this->glInterface(), config, tgt->config())) {
+ if ((tgt->config() == kRGBA_8888_GrPixelConfig ||
+ tgt->config() == kBGRA_8888_GrPixelConfig) &&
+ kAlpha_8_GrPixelConfig == config) {
+ SkAutoTDeleteArray<uint32_t> temp(new uint32_t[width * height * 4]);
+ if (this->onReadPixels(surface, left, top, width, height, kRGBA_8888_GrPixelConfig,
+ temp.get(), width*4)) {
+ uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);
+ for (int j = 0; j < height; ++j) {
+ for (int i = 0; i < width; ++i) {
+ dst[j*rowBytes + i] = (0xFF000000U & temp[j*width+i]) >> 24;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
const GrGLIRect& glvp = tgt->getViewport();
// the read rect is viewport-relative