aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/gl/GrGLConfig.h9
-rw-r--r--include/gpu/gl/GrGLConfig_chrome.h4
-rw-r--r--include/gpu/gl/GrGLInterface.h24
-rw-r--r--src/gpu/gl/GrGLCaps.cpp34
-rw-r--r--src/gpu/gl/GrGLCaps.h6
-rw-r--r--src/gpu/gl/GrGLInterface.cpp24
-rw-r--r--src/gpu/gl/GrGpuGL.cpp38
-rw-r--r--src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp33
8 files changed, 155 insertions, 17 deletions
diff --git a/include/gpu/gl/GrGLConfig.h b/include/gpu/gl/GrGLConfig.h
index 1f7c9e29f5..0da2c0bf2c 100644
--- a/include/gpu/gl/GrGLConfig.h
+++ b/include/gpu/gl/GrGLConfig.h
@@ -170,6 +170,15 @@
#define GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE 0
#endif
+// We now have a separate GrGLInterface function pointer entry for the IMG/EXT version of
+// glRenderbufferStorageMultisampled. However, Chrome is setting the one we now use for
+// ES3 MSAA to point to the IMG/EXT function. This macro exists to make Skia ignore the
+// ES3 MSAA and instead use the IMG/EXT version with the old function pointer entry. It will
+// be removed as soon as Chrome is updated to set the new function pointer.
+#if !defined(GR_GL_IGNORE_ES3_MSAA)
+ #define GR_GL_IGNORE_ES3_MSAA 0
+#endif
+
/**
* There is a strange bug that occurs on Macs with NVIDIA GPUs. We don't
* fully understand it. When (element) array buffers are continually
diff --git a/include/gpu/gl/GrGLConfig_chrome.h b/include/gpu/gl/GrGLConfig_chrome.h
index e08692fb61..fe3578339c 100644
--- a/include/gpu/gl/GrGLConfig_chrome.h
+++ b/include/gpu/gl/GrGLConfig_chrome.h
@@ -41,4 +41,8 @@
// (const char* const instead of char**).
#define GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE 1
+#if !defined(GR_GL_IGNORE_ES3_MSAA)
+ #define GR_GL_IGNORE_ES3_MSAA 1
+#endif
+
#endif
diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h
index 67d6840e42..de1b29143f 100644
--- a/include/gpu/gl/GrGLInterface.h
+++ b/include/gpu/gl/GrGLInterface.h
@@ -229,7 +229,31 @@ public:
GLPtr<GrGLReadBufferProc> fReadBuffer;
GLPtr<GrGLReadPixelsProc> fReadPixels;
GLPtr<GrGLRenderbufferStorageProc> fRenderbufferStorage;
+
+#if !GR_GL_IGNORE_ES3_MSAA
+ // On OpenGL ES there are multiple incompatible extensions that add support for MSAA
+ // and ES3 adds MSAA support to the standard. On an ES3 driver we may still use the
+ // older extensions for performance reasons or due to ES3 driver bugs. We want the function
+ // that creates the GrGLInterface to provide all available functions and internally
+ // we will select among them. They all have a method called glRenderbufferStorageMultisample*.
+ // So we have separate function pointers for GL_IMG/EXT_multisampled_to_texture,
+ // GL_CHROMIUM/ANGLE_framebuffer_multisample/ES3, and GL_APPLE_framebuffer_multisample
+ // variations.
+ //
+ // If a driver supports multiple GL_ARB_framebuffer_multisample-style extensions then we will
+ // assume the function pointers for the standard (or equivalent GL_ARB) version have
+ // been preferred over GL_EXT, GL_CHROMIUM, or GL_ANGLE variations that have reduced
+ // functionality.
+
+ // GL_EXT_multisampled_render_to_texture (preferred) or GL_IMG_multisampled_render_to_texture
+ GLPtr<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisampleES2EXT;
+ // GL_APPLE_framebuffer_multisample
+ GLPtr<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisampleES2APPLE;
+#endif
+ // This is used to store the pointer for GL_ARB/EXT/ANGLE/CHROMIUM_framebuffer_multisample or
+ // the standard function in ES3+ or GL 3.0+.
GLPtr<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisample;
+
GLPtr<GrGLRenderbufferStorageMultisampleCoverageProc> fRenderbufferStorageMultisampleCoverage;
GLPtr<GrGLResolveMultisampleFramebufferProc> fResolveMultisampleFramebuffer;
GLPtr<GrGLScissorProc> fScissor;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 382bfba68d..1488e75c29 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -386,17 +386,21 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterfa
fMSFBOType = kNone_MSFBOType;
if (kDesktop_GrGLBinding != ctxInfo.binding()) {
- if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
- // chrome's extension is equivalent to the EXT msaa
- // and fbo_blit extensions.
- fMSFBOType = kDesktop_EXT_MSFBOType;
- } else if (ctxInfo.hasExtension("GL_APPLE_framebuffer_multisample")) {
- fMSFBOType = kES_Apple_MSFBOType;
- } else if (ctxInfo.hasExtension("GL_EXT_multisampled_render_to_texture")) {
- fMSFBOType = kES_EXT_MsToTexture_MSFBOType;
- } else if (ctxInfo.hasExtension("GL_IMG_multisampled_render_to_texture")) {
- fMSFBOType = kES_IMG_MsToTexture_MSFBOType;
- }
+ // 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).
+ if (ctxInfo.hasExtension("GL_EXT_multisampled_render_to_texture")) {
+ fMSFBOType = kES_EXT_MsToTexture_MSFBOType;
+ } else if (ctxInfo.hasExtension("GL_IMG_multisampled_render_to_texture")) {
+ fMSFBOType = kES_IMG_MsToTexture_MSFBOType;
+ } else if (!GR_GL_IGNORE_ES3_MSAA && ctxInfo.version() >= GR_GL_VER(3,0)) {
+ fMSFBOType = GrGLCaps::kES_3_0_MSFBOType;
+ } else if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
+ // chrome's extension is equivalent to the EXT msaa
+ // and fbo_blit extensions.
+ fMSFBOType = kDesktop_EXT_MSFBOType;
+ } else if (ctxInfo.hasExtension("GL_APPLE_framebuffer_multisample")) {
+ fMSFBOType = kES_Apple_MSFBOType;
+ }
} else {
if ((ctxInfo.version() >= GR_GL_VER(3,0)) ||
ctxInfo.hasExtension("GL_ARB_framebuffer_object")) {
@@ -569,6 +573,7 @@ void GrGLCaps::print() const {
"None",
"ARB",
"EXT",
+ "ES 3.0",
"Apple",
"IMG MS To Texture",
"EXT MS To Texture",
@@ -576,9 +581,10 @@ void GrGLCaps::print() const {
GR_STATIC_ASSERT(0 == kNone_MSFBOType);
GR_STATIC_ASSERT(1 == kDesktop_ARB_MSFBOType);
GR_STATIC_ASSERT(2 == kDesktop_EXT_MSFBOType);
- GR_STATIC_ASSERT(3 == kES_Apple_MSFBOType);
- GR_STATIC_ASSERT(4 == kES_IMG_MsToTexture_MSFBOType);
- GR_STATIC_ASSERT(5 == kES_EXT_MsToTexture_MSFBOType);
+ GR_STATIC_ASSERT(3 == kES_3_0_MSFBOType);
+ GR_STATIC_ASSERT(4 == kES_Apple_MSFBOType);
+ GR_STATIC_ASSERT(5 == kES_IMG_MsToTexture_MSFBOType);
+ GR_STATIC_ASSERT(6 == kES_EXT_MsToTexture_MSFBOType);
GR_STATIC_ASSERT(GR_ARRAY_COUNT(kMSFBOExtStr) == kLast_MSFBOType + 1);
static const char* kFBFetchTypeStr[] = {
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index a4d567351e..a05d2b6faa 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -54,7 +54,7 @@ public:
*/
kNone_MSFBOType = 0,
/**
- * GL3.0-style MSAA FBO (GL_ARB_framebuffer_object)
+ * GL3.0-style MSAA FBO (GL_ARB_framebuffer_object).
*/
kDesktop_ARB_MSFBOType,
/**
@@ -62,6 +62,10 @@ public:
*/
kDesktop_EXT_MSFBOType,
/**
+ * Similar to kDesktop_ARB but with additional restrictions on glBlitFramebuffer.
+ */
+ kES_3_0_MSFBOType,
+ /**
* GL_APPLE_framebuffer_multisample ES extension
*/
kES_Apple_MSFBOType,
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index d15b4cc48b..7e557da4f5 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -336,25 +336,45 @@ bool GrGLInterface::validate(GrGLBinding binding) const {
}
}
} else {
+#if GR_GL_IGNORE_ES3_MSAA
if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
if (NULL == fRenderbufferStorageMultisample ||
NULL == fBlitFramebuffer) {
return false;
}
+ } else if (extensions.has("GL_APPLE_framebuffer_multisample")) {
+ if (NULL == fRenderbufferStorageMultisample ||
+ NULL == fResolveMultisampleFramebuffer) {
+ return false;
+ }
+ } else if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
+ extensions.has("GL_EXT_multisampled_render_to_texture")) {
+ if (NULL == fRenderbufferStorageMultisample ||
+ NULL == fFramebufferTexture2DMultisample) {
+ return false;
+ }
}
- if (extensions.has("GL_APPLE_framebuffer_multisample")) {
+#else
+ if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
if (NULL == fRenderbufferStorageMultisample ||
+ NULL == fBlitFramebuffer) {
+ return false;
+ }
+ }
+ if (extensions.has("GL_APPLE_framebuffer_multisample")) {
+ if (NULL == fRenderbufferStorageMultisampleES2APPLE ||
NULL == fResolveMultisampleFramebuffer) {
return false;
}
}
if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
extensions.has("GL_EXT_multisampled_render_to_texture")) {
- if (NULL == fRenderbufferStorageMultisample ||
+ if (NULL == fRenderbufferStorageMultisampleES2EXT ||
NULL == fFramebufferTexture2DMultisample) {
return false;
}
}
+#endif
}
// On ES buffer mapping is an extension. On Desktop
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index a9fd41ed5a..75b4191366 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -789,11 +789,43 @@ bool renderbuffer_storage_msaa(GrGLContext& ctx,
created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctx.interface()));
}
if (!created) {
+#if GR_GL_IGNORE_ES3_MSAA
GL_ALLOC_CALL(ctx.interface(),
RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
sampleCount,
format,
width, height));
+#else
+ switch (ctx.info().caps()->msFBOType()) {
+ case GrGLCaps::kDesktop_ARB_MSFBOType:
+ case GrGLCaps::kDesktop_EXT_MSFBOType:
+ case GrGLCaps::kES_3_0_MSFBOType:
+ GL_ALLOC_CALL(ctx.interface(),
+ RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
+ sampleCount,
+ format,
+ width, height));
+ break;
+ case GrGLCaps::kES_Apple_MSFBOType:
+ GL_ALLOC_CALL(ctx.interface(),
+ RenderbufferStorageMultisampleES2APPLE(GR_GL_RENDERBUFFER,
+ sampleCount,
+ format,
+ width, height));
+ break;
+ case GrGLCaps::kES_EXT_MsToTexture_MSFBOType:
+ case GrGLCaps::kES_IMG_MsToTexture_MSFBOType:
+ GL_ALLOC_CALL(ctx.interface(),
+ RenderbufferStorageMultisampleES2EXT(GR_GL_RENDERBUFFER,
+ sampleCount,
+ format,
+ width, height));
+ break;
+ case GrGLCaps::kNone_MSFBOType:
+ GrCrash("Shouldn't be here if we don't support multisampled renderbuffers.");
+ break;
+ }
+#endif
created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctx.interface()));
}
return created;
@@ -2313,6 +2345,12 @@ inline bool can_blit_framebuffer(const GrSurface* dst,
if (gpu->isConfigRenderable(dst->config()) &&
gpu->isConfigRenderable(src->config()) &&
gpu->glCaps().usesMSAARenderBuffers()) {
+ // 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).
+ if (GrGLCaps::kES_3_0_MSFBOType == gpu->glCaps().msFBOType() &&
+ (src->desc().fSampleCnt > 0 || src->config() != dst->config())) {
+ return false;
+ }
if (NULL != wouldNeedTempFBO) {
*wouldNeedTempFBO = NULL == dst->asRenderTarget() || NULL == src->asRenderTarget();
}
diff --git a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
index 881a46b476..5e5411e54e 100644
--- a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
+++ b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
@@ -147,6 +147,8 @@ static const GrGLInterface* create_es_interface(GrGLVersion version,
interface->fDeleteRenderbuffers = glDeleteRenderbuffers;
interface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
interface->fFramebufferTexture2D = glFramebufferTexture2D;
+#if GR_GL_IGNORE_ES3_MSAA
+
if (extensions.has("GL_EXT_multisampled_render_to_texture")) {
#if GL_EXT_multisampled_render_to_texture
interface->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleEXT;
@@ -164,6 +166,37 @@ static const GrGLInterface* create_es_interface(GrGLVersion version,
interface->fRenderbufferStorageMultisample = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleIMG");
#endif
}
+
+#else // GR_GL_IGNORE_ES3_MSAA
+
+ if (version >= GR_GL_VER(3,0)) {
+#if GL_ES_VERSION_3_0
+ interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisample;
+ interface->fBlitFramebuffer = glBlitFramebuffer;
+#else
+ interface->fRenderbufferStorageMultisample = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisample");
+ interface->fBlitFramebuffer = (GrGLBlitFramebufferProc) eglGetProcAddress("glBlitFramebuffer");
+#endif
+ }
+ if (extensions.has("GL_EXT_multisampled_render_to_texture")) {
+#if GL_EXT_multisampled_render_to_texture
+ interface->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleEXT;
+ interface->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleEXT;
+#else
+ interface->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleEXT");
+ interface->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleEXT");
+#endif
+ } else if (extensions.has("GL_IMG_multisampled_render_to_texture")) {
+#if GL_IMG_multisampled_render_to_texture
+ interface->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleIMG;
+ interface->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleIMG;
+#else
+ interface->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleIMG");
+ interface->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleIMG");
+#endif
+ }
+
+#endif // GR_GL_IGNORE_ES3_MSAA
interface->fGenFramebuffers = glGenFramebuffers;
interface->fGenRenderbuffers = glGenRenderbuffers;
interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;