aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/gl/GrGLDefines.h4
-rw-r--r--include/gpu/gl/GrGLInterface.h2
-rw-r--r--src/gpu/gl/GrGLCaps.cpp70
-rw-r--r--src/gpu/gl/GrGLCaps.h45
-rw-r--r--src/gpu/gl/GrGpuGL.cpp67
-rw-r--r--src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp4
-rw-r--r--src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp3
7 files changed, 173 insertions, 22 deletions
diff --git a/include/gpu/gl/GrGLDefines.h b/include/gpu/gl/GrGLDefines.h
index 22685105ba..0e03b556f1 100644
--- a/include/gpu/gl/GrGLDefines.h
+++ b/include/gpu/gl/GrGLDefines.h
@@ -194,6 +194,10 @@
#define GR_GL_SAMPLES 0x80A9
#define GR_GL_SAMPLE_COVERAGE_VALUE 0x80AA
#define GR_GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GR_GL_RENDERBUFFER_COVERAGE_SAMPLES 0x8CAB
+#define GR_GL_RENDERBUFFER_COLOR_SAMPLES 0x8E10
+#define GR_GL_MAX_MULTISAMPLE_COVERAGE_MODES 0x8E11
+#define GR_GL_MULTISAMPLE_COVERAGE_MODES 0x8E12
/* GetTextureParameter */
/* GL_TEXTURE_MAG_FILTER */
diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h
index a16b9b1d08..876c072f94 100644
--- a/include/gpu/gl/GrGLInterface.h
+++ b/include/gpu/gl/GrGLInterface.h
@@ -223,6 +223,7 @@ extern "C" {
typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLReadPixelsProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageProc)(GrGLenum target, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageMultisampleProc)(GrGLenum target, GrGLsizei samples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageMultisampleCoverageProc)(GrGLenum target, GrGLsizei coverageSamples, GrGLsizei colorSamples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLResolveMultisampleFramebufferProc)();
typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLScissorProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLShaderSourceProc)(GrGLuint shader, GrGLsizei count, const char** str, const GrGLint* length);
@@ -384,6 +385,7 @@ public:
GLPtr<GrGLReadPixelsProc> fReadPixels;
GLPtr<GrGLRenderbufferStorageProc> fRenderbufferStorage;
GLPtr<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisample;
+ GLPtr<GrGLRenderbufferStorageMultisampleCoverageProc> fRenderbufferStorageMultisampleCoverage;
GLPtr<GrGLResolveMultisampleFramebufferProc> fResolveMultisampleFramebuffer;
GLPtr<GrGLScissorProc> fScissor;
GLPtr<GrGLShaderSourceProc> fShaderSource;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 53619672d6..c7e9380c00 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -9,6 +9,7 @@
#include "GrGLCaps.h"
#include "GrGLContextInfo.h"
+#include "SkTSearch.h"
GrGLCaps::GrGLCaps() {
this->reset();
@@ -19,6 +20,7 @@ void GrGLCaps::reset() {
fStencilFormats.reset();
fStencilVerifiedColorConfigs.reset();
fMSFBOType = kNone_MSFBOType;
+ fCoverageAAType = kNone_CoverageAAType;
fMaxFragmentUniformVectors = 0;
fRGBA8RenderbufferSupport = false;
fBGRAFormatSupport = false;
@@ -43,6 +45,8 @@ GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
fStencilVerifiedColorConfigs = caps.fStencilVerifiedColorConfigs;
fMaxFragmentUniformVectors = caps.fMaxFragmentUniformVectors;
fMSFBOType = caps.fMSFBOType;
+ fCoverageAAType = caps.fCoverageAAType;
+ fMSAACoverageModes = caps.fMSAACoverageModes;
fRGBA8RenderbufferSupport = caps.fRGBA8RenderbufferSupport;
fBGRAFormatSupport = caps.fBGRAFormatSupport;
fBGRAIsInternalFormat = caps.fBGRAIsInternalFormat;
@@ -143,6 +147,22 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo) {
this->initStencilFormats(ctxInfo);
}
+namespace {
+int coverage_mode_compare(const GrGLCaps::MSAACoverageMode* left,
+ const GrGLCaps::MSAACoverageMode* right) {
+ if (left->fCoverageSampleCnt < right->fCoverageSampleCnt) {
+ return -1;
+ } else if (right->fCoverageSampleCnt < left->fCoverageSampleCnt) {
+ return 1;
+ } else if (left->fColorSampleCnt < right->fColorSampleCnt) {
+ return -1;
+ } else if (right->fColorSampleCnt < left->fColorSampleCnt) {
+ return 1;
+ }
+ return 0;
+}
+}
+
void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo) {
fMSFBOType = kNone_MSFBOType;
@@ -152,8 +172,8 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo) {
// and fbo_blit extensions.
fMSFBOType = kDesktopEXT_MSFBOType;
} else if (ctxInfo.hasExtension("GL_APPLE_framebuffer_multisample")) {
- fMSFBOType = kAppleES_MSFBOType;
- }
+ fMSFBOType = kAppleES_MSFBOType;
+ }
} else {
if ((ctxInfo.version() >= GR_GL_VER(3,0)) ||
ctxInfo.hasExtension("GL_ARB_framebuffer_object")) {
@@ -162,6 +182,52 @@ void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo) {
ctxInfo.hasExtension("GL_EXT_framebuffer_blit")) {
fMSFBOType = GrGLCaps::kDesktopEXT_MSFBOType;
}
+ // TODO: We could populate fMSAACoverageModes using GetInternalformativ
+ // on GL 4.2+. It's format-specific, though. See also
+ // http://code.google.com/p/skia/issues/detail?id=470 about using actual
+ // rather than requested sample counts in cache key.
+ if (ctxInfo.hasExtension("GL_NV_framebuffer_multisample_coverage")) {
+ fCoverageAAType = kNVDesktop_CoverageAAType;
+ GrGLint count;
+ GR_GL_GetIntegerv(ctxInfo.interface(),
+ GR_GL_MAX_MULTISAMPLE_COVERAGE_MODES,
+ &count);
+ fMSAACoverageModes.setCount(count);
+ GR_GL_GetIntegerv(ctxInfo.interface(),
+ GR_GL_MULTISAMPLE_COVERAGE_MODES,
+ (int*)&fMSAACoverageModes[0]);
+ // The NV driver seems to return the modes already sorted but the
+ // spec doesn't require this. So we sort.
+ SkQSortCompareProc compareProc =
+ reinterpret_cast<SkQSortCompareProc>(&coverage_mode_compare);
+ SkQSort(&fMSAACoverageModes[0],
+ count,
+ sizeof(MSAACoverageMode),
+ compareProc);
+ }
+ }
+}
+
+const GrGLCaps::MSAACoverageMode& GrGLCaps::getMSAACoverageMode(
+ int desiredSampleCount) const {
+ static const MSAACoverageMode kNoneMode = {0, 0};
+ if (0 == fMSAACoverageModes.count()) {
+ return kNoneMode;
+ } else {
+ GrAssert(kNone_CoverageAAType != fCoverageAAType);
+ int max = (fMSAACoverageModes.end() - 1)->fCoverageSampleCnt;
+ desiredSampleCount = GrMin(desiredSampleCount, max);
+ MSAACoverageMode desiredMode = {desiredSampleCount, 0};
+ int idx = SkTSearch<MSAACoverageMode>(&fMSAACoverageModes[0],
+ fMSAACoverageModes.count(),
+ desiredMode,
+ sizeof(MSAACoverageMode),
+ &coverage_mode_compare);
+ if (idx < 0) {
+ idx = ~idx;
+ }
+ GrAssert(idx >= 0 && idx < fMSAACoverageModes.count());
+ return fMSAACoverageModes[idx];
}
}
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 8b3f9e70a0..31c4392a10 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -24,6 +24,23 @@ public:
typedef GrGLStencilBuffer::Format StencilFormat;
/**
+ * Represents a supported multisampling/coverage-sampling mode.
+ */
+ struct MSAACoverageMode {
+ // "Coverage samples" includes samples that actually have color, depth,
+ // stencil, ... as well as those that don't (coverage only). All samples
+ // are coverage samples. (We're using the word "coverage sample" to
+ // match the NV extension language.)
+ int fCoverageSampleCnt;
+
+ // Color samples are samples that store data values (color, stencil,
+ // depth) rather than just representing coverage. They are a subset
+ // of coverage samples. (Again the wording was chosen to match the
+ // extension.)
+ int fColorSampleCnt;
+ };
+
+ /**
* The type of MSAA for FBOs supported. Different extensions have different
* semantics of how / when a resolve is performed.
*/
@@ -46,6 +63,18 @@ public:
kAppleES_MSFBOType,
};
+ enum CoverageAAType {
+ /**
+ * No coverage sample support
+ */
+ kNone_CoverageAAType,
+
+ /**
+ * GL_NV_framebuffer_multisample_coverage
+ */
+ kNVDesktop_CoverageAAType,
+ };
+
/**
* Creates a GrGLCaps that advertises no support for any extensions,
* formats, etc. Call init to initialize from a GrGLContextInfo.
@@ -108,6 +137,20 @@ public:
MSFBOType msFBOType() const { return fMSFBOType; }
/**
+ * Reports the type of coverage sample AA support.
+ */
+ CoverageAAType coverageAAType() const { return fCoverageAAType; }
+
+ /**
+ * Chooses a supported coverage mode based on a desired sample count. The
+ * desired sample count is rounded up the next supported coverage sample
+ * count unless a it is larger than the max in which case it is rounded
+ * down. Once a coverage sample count is decided, the supported mode with
+ * the fewest color samples is chosen.
+ */
+ const MSAACoverageMode& getMSAACoverageMode(int desiredSampleCount) const;
+
+ /**
* Prints the caps info using GrPrintf.
*/
void print() const;
@@ -214,6 +257,8 @@ private:
int fMaxFragmentUniformVectors;
MSFBOType fMSFBOType;
+ CoverageAAType fCoverageAAType;
+ SkTDArray<MSAACoverageMode> fMSAACoverageModes;
bool fRGBA8RenderbufferSupport : 1;
bool fBGRAFormatSupport : 1;
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index dcde84e6b2..9114a0e9cf 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -845,6 +845,38 @@ bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
return succeeded;
}
+namespace {
+bool renderbuffer_storage_msaa(GrGLContextInfo& ctxInfo,
+ int sampleCount,
+ GrGLenum format,
+ int width, int height) {
+ CLEAR_ERROR_BEFORE_ALLOC(ctxInfo.interface());
+ GrAssert(GrGLCaps::kNone_MSFBOType != ctxInfo.caps().msFBOType());
+ bool created = false;
+ if (GrGLCaps::kNVDesktop_CoverageAAType ==
+ ctxInfo.caps().coverageAAType()) {
+ const GrGLCaps::MSAACoverageMode& mode =
+ ctxInfo.caps().getMSAACoverageMode(sampleCount);
+ GL_ALLOC_CALL(ctxInfo.interface(),
+ RenderbufferStorageMultisampleCoverage(GR_GL_RENDERBUFFER,
+ mode.fCoverageSampleCnt,
+ mode.fColorSampleCnt,
+ format,
+ width, height));
+ created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctxInfo.interface()));
+ }
+ if (!created) {
+ GL_ALLOC_CALL(ctxInfo.interface(),
+ RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
+ sampleCount,
+ format,
+ width, height));
+ created = (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctxInfo.interface()));
+ }
+ return created;
+}
+}
+
bool GrGpuGL::createRenderTargetObjects(int width, int height,
GrGLuint texID,
GrGLRenderTarget::Desc* desc) {
@@ -854,7 +886,6 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height,
desc->fOwnIDs = true;
GrGLenum status;
- GrGLint err;
GrGLenum msColorFormat = 0; // suppress warning
@@ -890,14 +921,10 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height,
GrAssert(desc->fSampleCnt > 1);
GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER,
desc->fMSColorRenderbufferID));
- CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
- GL_ALLOC_CALL(this->glInterface(),
- RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
- desc->fSampleCnt,
- msColorFormat,
- width, height));
- err = CHECK_ALLOC_ERROR(this->glInterface());
- if (err != GR_GL_NO_ERROR) {
+ if (!renderbuffer_storage_msaa(fGLContextInfo,
+ desc->fSampleCnt,
+ msColorFormat,
+ width, height)) {
goto FAILED;
}
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fRTFBOID));
@@ -1128,23 +1155,23 @@ bool GrGpuGL::createStencilBufferForRenderTarget(GrRenderTarget* rt,
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
// we do this "if" so that we don't call the multisample
// version on a GL that doesn't have an MSAA extension.
- if (samples > 1) {
- GL_ALLOC_CALL(this->glInterface(),
- RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
- samples,
- sFmt.fInternalFormat,
- width, height));
+ bool created;
+ if (samples > 0) {
+ created = renderbuffer_storage_msaa(fGLContextInfo,
+ samples,
+ sFmt.fInternalFormat,
+ width, height);
} else {
GL_ALLOC_CALL(this->glInterface(),
RenderbufferStorage(GR_GL_RENDERBUFFER,
sFmt.fInternalFormat,
width, height));
+ created =
+ (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(this->glInterface()));
}
-
- GrGLenum err = CHECK_ALLOC_ERROR(this->glInterface());
- if (err == GR_GL_NO_ERROR) {
- // After sized formats we attempt an unsized format and take whatever
- // sizes GL gives us. In that case we query for the size.
+ if (created) {
+ // After sized formats we attempt an unsized format and take
+ // whatever sizes GL gives us. In that case we query for the size.
GrGLStencilBuffer::Format format = sFmt;
get_stencil_rb_sizes(this->glInterface(), sbID, &format);
sb = new GrGLStencilBuffer(this, sbID, width, height,
diff --git a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
index 1e9f2e04ad..be915ace81 100644
--- a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
+++ b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
@@ -102,6 +102,10 @@ const GrGLInterface* GrGLCreateNativeInterface() {
interface->fPixelStorei = glPixelStorei;
interface->fReadBuffer = glReadBuffer;
interface->fReadPixels = glReadPixels;
+ if (GrGLHasExtensionFromString("GL_NV_framebuffer_multisample_coverage",
+ extString)) {
+ GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisampleCoverage, NV);
+ }
interface->fScissor = glScissor;
GR_GL_GET_PROC(ShaderSource);
interface->fStencilFunc = glStencilFunc;
diff --git a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
index f050a6f038..2048974add 100644
--- a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
+++ b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
@@ -123,6 +123,9 @@ const GrGLInterface* GrGLCreateNativeInterface() {
GR_GL_GET_PROC(GetShaderiv);
GR_GL_GET_PROC(GetUniformLocation);
GR_GL_GET_PROC(LinkProgram);
+ if (GrGLHasExtensionFromString("GL_NV_framebuffer_multisample_coverage", extString)) {
+ GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisampleCoverage, NV);
+ }
GR_GL_GET_PROC(ShaderSource);
GR_GL_GET_PROC(StencilFuncSeparate);
GR_GL_GET_PROC(StencilMaskSeparate);