Add ability to query read pixels support without a render target.
Add more checks to onGetReadPixelsInfo. GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1615023003 Review URL: https://codereview.chromium.org/1615023003
This commit is contained in:
parent
6a377e629d
commit
1aa202935f
@ -10,6 +10,7 @@
|
||||
|
||||
#include "GrContextOptions.h"
|
||||
#include "GrGLContext.h"
|
||||
#include "GrGLRenderTarget.h"
|
||||
#include "glsl/GrGLSLCaps.h"
|
||||
#include "SkTSearch.h"
|
||||
#include "SkTSort.h"
|
||||
@ -17,6 +18,8 @@
|
||||
GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
|
||||
const GrGLContextInfo& ctxInfo,
|
||||
const GrGLInterface* glInterface) : INHERITED(contextOptions) {
|
||||
fStandard = ctxInfo.standard();
|
||||
|
||||
fStencilFormats.reset();
|
||||
fMSFBOType = kNone_MSFBOType;
|
||||
fInvalidateFBType = kNone_InvalidateFBType;
|
||||
@ -648,47 +651,52 @@ bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrG
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
|
||||
|
||||
bool GrGLCaps::readPixelsSupported(GrPixelConfig rtConfig,
|
||||
GrPixelConfig readConfig,
|
||||
GrPixelConfig currFBOConfig) const {
|
||||
SkASSERT(this->isConfigRenderable(currFBOConfig, false));
|
||||
std::function<void (GrGLenum, GrGLint*)> getIntegerv,
|
||||
std::function<bool ()> bindRenderTarget) const {
|
||||
SkASSERT(this->isConfigRenderable(rtConfig, false));
|
||||
|
||||
GrGLenum readFormat;
|
||||
GrGLenum readType;
|
||||
if (!this->getReadPixelsFormat(currFBOConfig, readConfig, &readFormat, &readType)) {
|
||||
if (!this->getReadPixelsFormat(rtConfig, readConfig, &readFormat, &readType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kGL_GrGLStandard == intf->fStandard) {
|
||||
if (kGL_GrGLStandard == fStandard) {
|
||||
// All of our renderable configs can be converted to each other by glReadPixels in OpenGL.
|
||||
return true;
|
||||
}
|
||||
|
||||
// See Section 16.1.2 in the ES 3.2 specification.
|
||||
|
||||
if (kNormalizedFixedPoint_FormatType == fConfigTable[currFBOConfig].fFormatType) {
|
||||
if (kNormalizedFixedPoint_FormatType == fConfigTable[rtConfig].fFormatType) {
|
||||
if (GR_GL_RGBA == readFormat && GR_GL_UNSIGNED_BYTE == readType) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
SkASSERT(kFloat_FormatType == fConfigTable[currFBOConfig].fFormatType);
|
||||
SkASSERT(kFloat_FormatType == fConfigTable[rtConfig].fFormatType);
|
||||
if (GR_GL_RGBA == readFormat && GR_GL_FLOAT == readType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == fConfigTable[currFBOConfig].fSecondReadPixelsFormat.fFormat) {
|
||||
if (0 == fConfigTable[rtConfig].fSecondReadPixelsFormat.fFormat) {
|
||||
ReadPixelsFormat* rpFormat =
|
||||
const_cast<ReadPixelsFormat*>(&fConfigTable[currFBOConfig].fSecondReadPixelsFormat);
|
||||
const_cast<ReadPixelsFormat*>(&fConfigTable[rtConfig].fSecondReadPixelsFormat);
|
||||
GrGLint format = 0, type = 0;
|
||||
GR_GL_GetIntegerv(intf, GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
|
||||
GR_GL_GetIntegerv(intf, GR_GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);
|
||||
if (!bindRenderTarget()) {
|
||||
return false;
|
||||
}
|
||||
getIntegerv(GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
|
||||
getIntegerv(GR_GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);
|
||||
rpFormat->fFormat = format;
|
||||
rpFormat->fType = type;
|
||||
}
|
||||
|
||||
return fConfigTable[currFBOConfig].fSecondReadPixelsFormat.fFormat == readFormat &&
|
||||
fConfigTable[currFBOConfig].fSecondReadPixelsFormat.fType == readType;
|
||||
return fConfigTable[rtConfig].fSecondReadPixelsFormat.fFormat == readFormat &&
|
||||
fConfigTable[rtConfig].fSecondReadPixelsFormat.fType == readType;
|
||||
}
|
||||
|
||||
void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||
|
@ -9,6 +9,8 @@
|
||||
#ifndef GrGLCaps_DEFINED
|
||||
#define GrGLCaps_DEFINED
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "glsl/GrGLSL.h"
|
||||
#include "GrCaps.h"
|
||||
#include "GrGLStencilAttachment.h"
|
||||
@ -19,6 +21,7 @@
|
||||
|
||||
class GrGLContextInfo;
|
||||
class GrGLSLCaps;
|
||||
class GrGLRenderTarget;
|
||||
|
||||
/**
|
||||
* Stores some capabilities of a GL context. Most are determined by the GL
|
||||
@ -283,10 +286,11 @@ public:
|
||||
/// Use indices or vertices in CPU arrays rather than VBOs for dynamic content.
|
||||
bool useNonVBOVertexAndIndexDynamicData() const { return fUseNonVBOVertexAndIndexDynamicData; }
|
||||
|
||||
/// Does ReadPixels support the provided format/type combo?
|
||||
bool readPixelsSupported(const GrGLInterface* intf,
|
||||
/// Does ReadPixels support reading readConfig pixels from a FBO that is renderTargetConfig?
|
||||
bool readPixelsSupported(GrPixelConfig renderTargetConfig,
|
||||
GrPixelConfig readConfig,
|
||||
GrPixelConfig currFBOConfig) const;
|
||||
std::function<void (GrGLenum, GrGLint*)> getIntegerv,
|
||||
std::function<bool ()> bindRenderTarget) const;
|
||||
|
||||
bool isCoreProfile() const { return fIsCoreProfile; }
|
||||
|
||||
@ -348,6 +352,8 @@ private:
|
||||
const GrGLInterface* intf,
|
||||
GrGLSLCaps* glslCaps);
|
||||
|
||||
GrGLStandard fStandard;
|
||||
|
||||
SkTArray<StencilFormat, true> fStencilFormats;
|
||||
|
||||
int fMaxFragmentUniformVectors;
|
||||
|
@ -2069,12 +2069,55 @@ static bool read_pixels_pays_for_y_flip(GrRenderTarget* renderTarget, const GrGL
|
||||
return caps.packRowLengthSupport() || GrBytesPerPixel(config) * width == rowBytes;
|
||||
}
|
||||
|
||||
bool GrGLGpu::readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig) {
|
||||
auto bindRenderTarget = [this, target]() -> bool {
|
||||
this->flushRenderTarget(static_cast<GrGLRenderTarget*>(target), &SkIRect::EmptyIRect());
|
||||
return true;
|
||||
};
|
||||
auto getIntegerv = [this](GrGLenum query, GrGLint* value) {
|
||||
GR_GL_GetIntegerv(this->glInterface(), query, value);
|
||||
};
|
||||
GrPixelConfig rtConfig = target->config();
|
||||
return this->glCaps().readPixelsSupported(rtConfig, readConfig, getIntegerv, bindRenderTarget);
|
||||
}
|
||||
|
||||
bool GrGLGpu::readPixelsSupported(GrPixelConfig rtConfig, GrPixelConfig readConfig) {
|
||||
auto bindRenderTarget = [this, rtConfig]() -> bool {
|
||||
GrTextureDesc desc;
|
||||
desc.fConfig = rtConfig;
|
||||
desc.fWidth = desc.fHeight = 16;
|
||||
desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
SkAutoTUnref<GrTexture> temp(this->createTexture(desc, false, nullptr, 0));
|
||||
if (!temp) {
|
||||
return false;
|
||||
}
|
||||
GrGLRenderTarget* glrt = static_cast<GrGLRenderTarget*>(temp->asRenderTarget());
|
||||
this->flushRenderTarget(glrt, &SkIRect::EmptyIRect());
|
||||
return true;
|
||||
};
|
||||
auto getIntegerv = [this](GrGLenum query, GrGLint* value) {
|
||||
GR_GL_GetIntegerv(this->glInterface(), query, value);
|
||||
};
|
||||
return this->glCaps().readPixelsSupported(rtConfig, readConfig, getIntegerv, bindRenderTarget);
|
||||
}
|
||||
|
||||
bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig) {
|
||||
if (GrRenderTarget* rt = surfaceForConfig->asRenderTarget()) {
|
||||
return this->readPixelsSupported(rt, readConfig);
|
||||
} else {
|
||||
GrPixelConfig config = surfaceForConfig->config();
|
||||
return this->readPixelsSupported(config, readConfig);
|
||||
}
|
||||
}
|
||||
|
||||
bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig readConfig, DrawPreference* drawPreference,
|
||||
ReadPixelTempDrawInfo* tempDrawInfo) {
|
||||
GrRenderTarget* srcAsRT = srcSurface->asRenderTarget();
|
||||
|
||||
// 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()) {
|
||||
if (!srcAsRT) {
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
}
|
||||
|
||||
@ -2099,33 +2142,38 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height,
|
||||
GrPixelConfig srcConfig = srcSurface->config();
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
|
||||
|
||||
if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig) {
|
||||
if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig &&
|
||||
this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelConfig)) {
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig;
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
} else if (kMesa_GrGLDriver == this->glContext().driver() &&
|
||||
GrBytesPerPixel(readConfig) == 4 &&
|
||||
GrPixelConfigSwapRAndB(readConfig) == srcConfig) {
|
||||
GrPixelConfigSwapRAndB(readConfig) == srcConfig &&
|
||||
this->readPixelsSupported(srcSurface, srcConfig)) {
|
||||
// Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa.
|
||||
// Better to do a draw with a R/B swap and then read as the original config.
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = srcConfig;
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
} else if (readConfig == kBGRA_8888_GrPixelConfig &&
|
||||
!this->glCaps().readPixelsSupported(this->glInterface(), readConfig, srcConfig)) {
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
} else if (!this->readPixelsSupported(srcSurface, readConfig)) {
|
||||
if (readConfig == kBGRA_8888_GrPixelConfig &&
|
||||
this->glCaps().isConfigRenderable(kRGBA_8888_GrPixelConfig, false) &&
|
||||
this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPixelConfig)) {
|
||||
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,20 @@ private:
|
||||
bool onMakeCopyForTextureParams(GrTexture*, const GrTextureParams&,
|
||||
GrTextureProducer::CopyParams*) const override;
|
||||
|
||||
// Checks whether glReadPixels can be called to get pixel values in readConfig from the
|
||||
// render target.
|
||||
bool readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig);
|
||||
|
||||
// Checks whether glReadPixels can be called to get pixel values in readConfig from a
|
||||
// render target that has renderTargetConfig. This may have to create a temporary
|
||||
// render target and thus is less preferable than the variant that takes a render target.
|
||||
bool readPixelsSupported(GrPixelConfig renderTargetConfig, GrPixelConfig readConfig);
|
||||
|
||||
// Checks whether glReadPixels can be called to get pixel values in readConfig from a
|
||||
// render target that has the same config as surfaceForConfig. Calls one of the the two
|
||||
// variations above, depending on whether the surface is a render target or not.
|
||||
bool readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig);
|
||||
|
||||
bool onReadPixels(GrSurface*,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
|
Loading…
Reference in New Issue
Block a user