aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/gl/GrGLCaps.cpp18
-rw-r--r--src/gpu/gl/GrGLCaps.h25
-rw-r--r--src/gpu/gl/GrGLGpu.cpp118
3 files changed, 93 insertions, 68 deletions
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index c2e8f11b3b..23b069f9f8 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -52,7 +52,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
fRGBAToBGRAReadbackConversionsAreSlow = false;
fDoManualMipmapping = false;
- fBlitFramebufferSupport = kNone_BlitFramebufferSupport;
+ fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag;
fShaderCaps.reset(new GrGLSLCaps(contextOptions));
@@ -919,8 +919,6 @@ bool GrGLCaps::readPixelsSupported(GrPixelConfig rtConfig,
}
void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
-
- fMSFBOType = kNone_MSFBOType;
if (kGL_GrGLStandard != ctxInfo.standard()) {
// We prefer the EXT/IMG extension over ES3 MSAA because we've observed
// ES3 driver bugs on at least one device with a tiled GPU (N10).
@@ -940,24 +938,28 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterfa
// Above determined the preferred MSAA approach, now decide whether glBlitFramebuffer
// is available.
if (ctxInfo.version() >= GR_GL_VER(3, 0)) {
- fBlitFramebufferSupport = kFull_BlitFramebufferSupport;
+ fBlitFramebufferFlags = kNoFormatConversionForMSAASrc_BlitFramebufferFlag |
+ kRectsMustMatchForMSAASrc_BlitFramebufferFlag;
} else if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
// The CHROMIUM extension uses the ANGLE version of glBlitFramebuffer and includes its
// limitations.
- fBlitFramebufferSupport = kNoScalingNoMirroring_BlitFramebufferSupport;
+ fBlitFramebufferFlags = kNoScalingOrMirroring_BlitFramebufferFlag |
+ kResolveMustBeFull_BlitFrambufferFlag |
+ kNoMSAADst_BlitFramebufferFlag |
+ kNoFormatConversion_BlitFramebufferFlag;
}
} else {
if (fUsesMixedSamples) {
fMSFBOType = kMixedSamples_MSFBOType;
- fBlitFramebufferSupport = kFull_BlitFramebufferSupport;
+ fBlitFramebufferFlags = 0;
} else if (ctxInfo.version() >= GR_GL_VER(3,0) ||
ctxInfo.hasExtension("GL_ARB_framebuffer_object")) {
fMSFBOType = kStandard_MSFBOType;
- fBlitFramebufferSupport = kFull_BlitFramebufferSupport;
+ fBlitFramebufferFlags = 0;
} else if (ctxInfo.hasExtension("GL_EXT_framebuffer_multisample") &&
ctxInfo.hasExtension("GL_EXT_framebuffer_blit")) {
fMSFBOType = kEXT_MSFBOType;
- fBlitFramebufferSupport = kFull_BlitFramebufferSupport;
+ fBlitFramebufferFlags = 0;
}
}
}
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index e162b38b9c..794bb75119 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -73,19 +73,14 @@ public:
kLast_MSFBOType = kMixedSamples_MSFBOType
};
- enum BlitFramebufferSupport {
- kNone_BlitFramebufferSupport,
- /**
- * ANGLE exposes a limited blit framebuffer extension that does not allow for stretching
- * or mirroring.
- */
- kNoScalingNoMirroring_BlitFramebufferSupport,
- /**
- * ES3 has restricted support when the src is MSAA: src rect == dst rect, dst format == src
- * format.
- */
- kRectsAndFormatsMatchForMSAASrc_BlitFramebufferSupport,
- kFull_BlitFramebufferSupport
+ enum BlitFramebufferFlags {
+ kNoSupport_BlitFramebufferFlag = 1 << 0,
+ kNoScalingOrMirroring_BlitFramebufferFlag = 1 << 1,
+ kResolveMustBeFull_BlitFrambufferFlag = 1 << 2,
+ kNoMSAADst_BlitFramebufferFlag = 1 << 3,
+ kNoFormatConversion_BlitFramebufferFlag = 1 << 4,
+ kNoFormatConversionForMSAASrc_BlitFramebufferFlag = 1 << 5,
+ kRectsMustMatchForMSAASrc_BlitFramebufferFlag = 1 << 6,
};
enum InvalidateFBType {
@@ -235,7 +230,7 @@ public:
/**
* What functionality is supported by glBlitFramebuffer.
*/
- BlitFramebufferSupport blitFramebufferSupport() const { return fBlitFramebufferSupport; }
+ uint32_t blitFramebufferSupportFlags() const { return fBlitFramebufferFlags; }
/**
* Is the MSAA FBO extension one where the texture is multisampled when bound to an FBO and
@@ -419,7 +414,7 @@ private:
bool fRGBAToBGRAReadbackConversionsAreSlow : 1;
bool fDoManualMipmapping : 1;
- BlitFramebufferSupport fBlitFramebufferSupport;
+ uint32_t fBlitFramebufferFlags;
/** Number type of the components (with out considering number of bits.) */
enum FormatType {
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index eae0aa9963..6b534a01bb 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2921,18 +2921,27 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) {
this->disableWindowRectangles();
GL_CALL(ResolveMultisampleFramebuffer());
} else {
- GrGLIRect r;
- r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
- dirtyRect.width(), dirtyRect.height(), target->origin());
-
- int right = r.fLeft + r.fWidth;
- int top = r.fBottom + r.fHeight;
+ int l, b, r, t;
+ if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag &
+ this->glCaps().blitFramebufferSupportFlags()) {
+ l = 0;
+ b = 0;
+ r = target->width();
+ t = target->height();
+ } else {
+ GrGLIRect rect;
+ rect.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
+ dirtyRect.width(), dirtyRect.height(), target->origin());
+ l = rect.fLeft;
+ b = rect.fBottom;
+ r = rect.fLeft + rect.fWidth;
+ t = rect.fBottom + rect.fHeight;
+ }
// BlitFrameBuffer respects the scissor, so disable it.
this->disableScissor();
this->disableWindowRectangles();
- GL_CALL(BlitFramebuffer(r.fLeft, r.fBottom, right, top,
- r.fLeft, r.fBottom, right, top,
+ GL_CALL(BlitFramebuffer(l, b, r, t, l, b, r, t,
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
}
}
@@ -3472,45 +3481,64 @@ void GrGLGpu::setScratchTextureUnit() {
fHWBoundTextureUniqueIDs[lastUnitIdx] = SK_InvalidUniqueID;
}
-// Determines whether glBlitFramebuffer could be used between src and dst.
-static inline bool can_blit_framebuffer(const GrSurface* dst,
- const GrSurface* src,
- const GrGLGpu* gpu) {
- if (gpu->glCaps().isConfigRenderable(dst->config(), dst->desc().fSampleCnt > 0) &&
- gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0)) {
- switch (gpu->glCaps().blitFramebufferSupport()) {
- case GrGLCaps::kNone_BlitFramebufferSupport:
- return false;
- case GrGLCaps::kNoScalingNoMirroring_BlitFramebufferSupport:
- // Our copy surface doesn't support scaling so just check for mirroring.
- if (dst->origin() != src->origin()) {
- return false;
- }
- break;
- // ES3 doesn't allow framebuffer blits when the src has MSAA and the configs don't
- // match or the rects are not the same (not just the same size but have the same
- // edges).
- case GrGLCaps::kRectsAndFormatsMatchForMSAASrc_BlitFramebufferSupport:
- if ((src->desc().fSampleCnt > 0 || src->config() != dst->config())) {
- return false;
- }
- break;
-
- case GrGLCaps::kFull_BlitFramebufferSupport:
- return true;
+// Determines whether glBlitFramebuffer could be used between src and dst by onCopySurface.
+static inline bool can_blit_framebuffer_for_copy_surface(const GrSurface* dst,
+ const GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint,
+ const GrGLGpu* gpu) {
+ auto blitFramebufferFlags = gpu->glCaps().blitFramebufferSupportFlags();
+ if (!gpu->glCaps().isConfigRenderable(dst->config(), dst->desc().fSampleCnt > 0) ||
+ !gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0)) {
+ return false;
+ }
+ const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
+ const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(dst->asTexture());
+ const GrRenderTarget* dstRT = dst->asRenderTarget();
+ const GrRenderTarget* srcRT = src->asRenderTarget();
+ if (dstTex && dstTex->target() != GR_GL_TEXTURE_2D) {
+ return false;
+ }
+ if (srcTex && srcTex->target() != GR_GL_TEXTURE_2D) {
+ return false;
+ }
+ if (GrGLCaps::kNoSupport_BlitFramebufferFlag & blitFramebufferFlags) {
+ return false;
+ }
+ if (GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag & blitFramebufferFlags) {
+ // We would mirror to compensate for origin changes. Note that copySurface is
+ // specified such that the src and dst rects are the same.
+ if (dst->origin() != src->origin()) {
+ return false;
}
- const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
- if (dstTex && dstTex->target() != GR_GL_TEXTURE_2D) {
+ }
+ if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag & blitFramebufferFlags) {
+ if (srcRT && srcRT->numColorSamples() && dstRT && !dstRT->numColorSamples()) {
return false;
}
- const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(dst->asTexture());
- if (srcTex && srcTex->target() != GR_GL_TEXTURE_2D) {
+ }
+ if (GrGLCaps::kNoMSAADst_BlitFramebufferFlag & blitFramebufferFlags) {
+ if (dstRT && dstRT->numColorSamples() > 0) {
+ return false;
+ }
+ }
+ if (GrGLCaps::kNoFormatConversion_BlitFramebufferFlag & blitFramebufferFlags) {
+ if (dst->config() != src->config()) {
+ return false;
+ }
+ } else if (GrGLCaps::kNoFormatConversionForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) {
+ const GrRenderTarget* srcRT = src->asRenderTarget();
+ if (srcRT && srcRT->numColorSamples() && dst->config() != src->config()) {
return false;
}
- return true;
- } else {
- return false;
}
+ if (GrGLCaps::kRectsMustMatchForMSAASrc_BlitFramebufferFlag & blitFramebufferFlags) {
+ if (srcRT && srcRT->numColorSamples() &&
+ (dstPoint.fX != srcRect.fLeft || dstPoint.fY != srcRect.fTop)) {
+ return false;
+ }
+ }
+ return true;
}
static inline bool can_copy_texsubimage(const GrSurface* dst,
@@ -3627,8 +3655,8 @@ bool GrGLGpu::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc)
// creation. It isn't clear that avoiding temporary fbo creation is actually optimal.
GrSurfaceOrigin originForBlitFramebuffer = kDefault_GrSurfaceOrigin;
- if (this->glCaps().blitFramebufferSupport() ==
- GrGLCaps::kNoScalingNoMirroring_BlitFramebufferSupport) {
+ if (this->glCaps().blitFramebufferSupportFlags() &
+ GrGLCaps::kNoScalingOrMirroring_BlitFramebufferFlag) {
originForBlitFramebuffer = src->origin();
}
@@ -3689,7 +3717,7 @@ bool GrGLGpu::onCopySurface(GrSurface* dst,
return true;
}
- if (can_blit_framebuffer(dst, src, this)) {
+ if (can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this)) {
return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint);
}
@@ -4279,7 +4307,7 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst,
GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint) {
- SkASSERT(can_blit_framebuffer(dst, src, this));
+ SkASSERT(can_blit_framebuffer_for_copy_surface(dst, src, srcRect, dstPoint, this));
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
srcRect.width(), srcRect.height());
if (dst == src) {