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 "GrContextOptions.h"
|
||||||
#include "GrGLContext.h"
|
#include "GrGLContext.h"
|
||||||
|
#include "GrGLRenderTarget.h"
|
||||||
#include "glsl/GrGLSLCaps.h"
|
#include "glsl/GrGLSLCaps.h"
|
||||||
#include "SkTSearch.h"
|
#include "SkTSearch.h"
|
||||||
#include "SkTSort.h"
|
#include "SkTSort.h"
|
||||||
@ -17,6 +18,8 @@
|
|||||||
GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
|
GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
|
||||||
const GrGLContextInfo& ctxInfo,
|
const GrGLContextInfo& ctxInfo,
|
||||||
const GrGLInterface* glInterface) : INHERITED(contextOptions) {
|
const GrGLInterface* glInterface) : INHERITED(contextOptions) {
|
||||||
|
fStandard = ctxInfo.standard();
|
||||||
|
|
||||||
fStencilFormats.reset();
|
fStencilFormats.reset();
|
||||||
fMSFBOType = kNone_MSFBOType;
|
fMSFBOType = kNone_MSFBOType;
|
||||||
fInvalidateFBType = kNone_InvalidateFBType;
|
fInvalidateFBType = kNone_InvalidateFBType;
|
||||||
@ -648,47 +651,52 @@ bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrG
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
|
|
||||||
|
bool GrGLCaps::readPixelsSupported(GrPixelConfig rtConfig,
|
||||||
GrPixelConfig readConfig,
|
GrPixelConfig readConfig,
|
||||||
GrPixelConfig currFBOConfig) const {
|
std::function<void (GrGLenum, GrGLint*)> getIntegerv,
|
||||||
SkASSERT(this->isConfigRenderable(currFBOConfig, false));
|
std::function<bool ()> bindRenderTarget) const {
|
||||||
|
SkASSERT(this->isConfigRenderable(rtConfig, false));
|
||||||
|
|
||||||
GrGLenum readFormat;
|
GrGLenum readFormat;
|
||||||
GrGLenum readType;
|
GrGLenum readType;
|
||||||
if (!this->getReadPixelsFormat(currFBOConfig, readConfig, &readFormat, &readType)) {
|
if (!this->getReadPixelsFormat(rtConfig, readConfig, &readFormat, &readType)) {
|
||||||
return false;
|
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.
|
// All of our renderable configs can be converted to each other by glReadPixels in OpenGL.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See Section 16.1.2 in the ES 3.2 specification.
|
// 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) {
|
if (GR_GL_RGBA == readFormat && GR_GL_UNSIGNED_BYTE == readType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SkASSERT(kFloat_FormatType == fConfigTable[currFBOConfig].fFormatType);
|
SkASSERT(kFloat_FormatType == fConfigTable[rtConfig].fFormatType);
|
||||||
if (GR_GL_RGBA == readFormat && GR_GL_FLOAT == readType) {
|
if (GR_GL_RGBA == readFormat && GR_GL_FLOAT == readType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == fConfigTable[currFBOConfig].fSecondReadPixelsFormat.fFormat) {
|
if (0 == fConfigTable[rtConfig].fSecondReadPixelsFormat.fFormat) {
|
||||||
ReadPixelsFormat* rpFormat =
|
ReadPixelsFormat* rpFormat =
|
||||||
const_cast<ReadPixelsFormat*>(&fConfigTable[currFBOConfig].fSecondReadPixelsFormat);
|
const_cast<ReadPixelsFormat*>(&fConfigTable[rtConfig].fSecondReadPixelsFormat);
|
||||||
GrGLint format = 0, type = 0;
|
GrGLint format = 0, type = 0;
|
||||||
GR_GL_GetIntegerv(intf, GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
|
if (!bindRenderTarget()) {
|
||||||
GR_GL_GetIntegerv(intf, GR_GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);
|
return false;
|
||||||
|
}
|
||||||
|
getIntegerv(GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format);
|
||||||
|
getIntegerv(GR_GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);
|
||||||
rpFormat->fFormat = format;
|
rpFormat->fFormat = format;
|
||||||
rpFormat->fType = type;
|
rpFormat->fType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fConfigTable[currFBOConfig].fSecondReadPixelsFormat.fFormat == readFormat &&
|
return fConfigTable[rtConfig].fSecondReadPixelsFormat.fFormat == readFormat &&
|
||||||
fConfigTable[currFBOConfig].fSecondReadPixelsFormat.fType == readType;
|
fConfigTable[rtConfig].fSecondReadPixelsFormat.fType == readType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#ifndef GrGLCaps_DEFINED
|
#ifndef GrGLCaps_DEFINED
|
||||||
#define GrGLCaps_DEFINED
|
#define GrGLCaps_DEFINED
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "glsl/GrGLSL.h"
|
#include "glsl/GrGLSL.h"
|
||||||
#include "GrCaps.h"
|
#include "GrCaps.h"
|
||||||
#include "GrGLStencilAttachment.h"
|
#include "GrGLStencilAttachment.h"
|
||||||
@ -19,6 +21,7 @@
|
|||||||
|
|
||||||
class GrGLContextInfo;
|
class GrGLContextInfo;
|
||||||
class GrGLSLCaps;
|
class GrGLSLCaps;
|
||||||
|
class GrGLRenderTarget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores some capabilities of a GL context. Most are determined by the GL
|
* 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.
|
/// Use indices or vertices in CPU arrays rather than VBOs for dynamic content.
|
||||||
bool useNonVBOVertexAndIndexDynamicData() const { return fUseNonVBOVertexAndIndexDynamicData; }
|
bool useNonVBOVertexAndIndexDynamicData() const { return fUseNonVBOVertexAndIndexDynamicData; }
|
||||||
|
|
||||||
/// Does ReadPixels support the provided format/type combo?
|
/// Does ReadPixels support reading readConfig pixels from a FBO that is renderTargetConfig?
|
||||||
bool readPixelsSupported(const GrGLInterface* intf,
|
bool readPixelsSupported(GrPixelConfig renderTargetConfig,
|
||||||
GrPixelConfig readConfig,
|
GrPixelConfig readConfig,
|
||||||
GrPixelConfig currFBOConfig) const;
|
std::function<void (GrGLenum, GrGLint*)> getIntegerv,
|
||||||
|
std::function<bool ()> bindRenderTarget) const;
|
||||||
|
|
||||||
bool isCoreProfile() const { return fIsCoreProfile; }
|
bool isCoreProfile() const { return fIsCoreProfile; }
|
||||||
|
|
||||||
@ -348,6 +352,8 @@ private:
|
|||||||
const GrGLInterface* intf,
|
const GrGLInterface* intf,
|
||||||
GrGLSLCaps* glslCaps);
|
GrGLSLCaps* glslCaps);
|
||||||
|
|
||||||
|
GrGLStandard fStandard;
|
||||||
|
|
||||||
SkTArray<StencilFormat, true> fStencilFormats;
|
SkTArray<StencilFormat, true> fStencilFormats;
|
||||||
|
|
||||||
int fMaxFragmentUniformVectors;
|
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;
|
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,
|
bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
|
||||||
GrPixelConfig readConfig, DrawPreference* drawPreference,
|
GrPixelConfig readConfig, DrawPreference* drawPreference,
|
||||||
ReadPixelTempDrawInfo* tempDrawInfo) {
|
ReadPixelTempDrawInfo* tempDrawInfo) {
|
||||||
|
GrRenderTarget* srcAsRT = srcSurface->asRenderTarget();
|
||||||
|
|
||||||
// This subclass can only read pixels from a render target. We could use glTexSubImage2D on
|
// 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.
|
// GL versions that support it but we don't today.
|
||||||
if (!srcSurface->asRenderTarget()) {
|
if (!srcAsRT) {
|
||||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2099,33 +2142,38 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height,
|
|||||||
GrPixelConfig srcConfig = srcSurface->config();
|
GrPixelConfig srcConfig = srcSurface->config();
|
||||||
tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
|
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->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig;
|
||||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||||
tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig;
|
tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig;
|
||||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||||
} else if (kMesa_GrGLDriver == this->glContext().driver() &&
|
} else if (kMesa_GrGLDriver == this->glContext().driver() &&
|
||||||
GrBytesPerPixel(readConfig) == 4 &&
|
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.
|
// 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.
|
// Better to do a draw with a R/B swap and then read as the original config.
|
||||||
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
||||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||||
tempDrawInfo->fReadConfig = srcConfig;
|
tempDrawInfo->fReadConfig = srcConfig;
|
||||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||||
} else if (readConfig == kBGRA_8888_GrPixelConfig &&
|
} else if (!this->readPixelsSupported(srcSurface, readConfig)) {
|
||||||
!this->glCaps().readPixelsSupported(this->glInterface(), readConfig, srcConfig)) {
|
if (readConfig == kBGRA_8888_GrPixelConfig &&
|
||||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
this->glCaps().isConfigRenderable(kRGBA_8888_GrPixelConfig, false) &&
|
||||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPixelConfig)) {
|
||||||
tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
|
|
||||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
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 &&
|
||||||
if (!srcAsRT) {
|
read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig, rowBytes)) {
|
||||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
|
||||||
} else if (read_pixels_pays_for_y_flip(srcAsRT, this->glCaps(), width, height, readConfig,
|
|
||||||
rowBytes)) {
|
|
||||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +166,20 @@ private:
|
|||||||
bool onMakeCopyForTextureParams(GrTexture*, const GrTextureParams&,
|
bool onMakeCopyForTextureParams(GrTexture*, const GrTextureParams&,
|
||||||
GrTextureProducer::CopyParams*) const override;
|
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*,
|
bool onReadPixels(GrSurface*,
|
||||||
int left, int top,
|
int left, int top,
|
||||||
int width, int height,
|
int width, int height,
|
||||||
|
Loading…
Reference in New Issue
Block a user