aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl/GrGLGpu.cpp
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2015-09-10 08:37:20 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-09-10 08:37:20 -0700
commitff1d547c72b7c70af7bddfba01d4646b2389db7a (patch)
treea96e9b61d9b2837969825d67e170966ff94e22b0 /src/gpu/gl/GrGLGpu.cpp
parent6c6f65885ba20ba9e8d8c36039f1c9eff4cc814b (diff)
Calculate pixel config and stencil fmt pairs once per pixel config.
We use a temp FB and stencil buffer to test different stencil formats with a given pixel config. We then keep a map from pixel config to desired stencil format. BUG=skia: Review URL: https://codereview.chromium.org/1317443004
Diffstat (limited to 'src/gpu/gl/GrGLGpu.cpp')
-rw-r--r--src/gpu/gl/GrGLGpu.cpp330
1 files changed, 215 insertions, 115 deletions
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 602eeca56d..0eac373f2e 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -159,6 +159,15 @@ bool GrGLGpu::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
///////////////////////////////////////////////////////////////////////////////
+// Used in the map of pixel configs to stencil format indices. This value is used to
+// indicate that a stencil format has not yet been set for the given config.
+static const int kUnknownStencilIndex = -1;
+// This value is used as the stencil index when no stencil configs are supported with the
+// given pixel config.
+static const int kUnsupportedStencilIndex = -2;
+
+///////////////////////////////////////////////////////////////////////////////
+
GrGpu* GrGLGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
GrContext* context) {
SkAutoTUnref<const GrGLInterface> glInterface(
@@ -211,7 +220,9 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
SkASSERT(this->glCaps().maxVertexAttributes() >= GrGeometryProcessor::kMaxVertexAttribs);
- fLastSuccessfulStencilFmtIdx = 0;
+ for (int i = 0; i < kGrPixelConfigCnt; ++i) {
+ fPixelConfigToStencilIndex[i] = kUnknownStencilIndex;
+ }
fHWProgramID = 0;
fTempSrcFBOID = 0;
fTempDstFBOID = 0;
@@ -1169,120 +1180,223 @@ void inline get_stencil_rb_sizes(const GrGLInterface* gl,
}
}
-bool GrGLGpu::createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int width, int height) {
- // All internally created RTs are also textures. We don't create
- // SBs for a client's standalone RT (that is a RT that isn't also a texture).
- SkASSERT(rt->asTexture());
- SkASSERT(width >= rt->width());
- SkASSERT(height >= rt->height());
-
- int samples = rt->numStencilSamples();
- GrGLStencilAttachment::IDDesc sbDesc;
+int GrGLGpu::getCompatibleStencilIndex(GrPixelConfig config) {
+ int size = this->caps()->minTextureSize();
+ if (kUnknownStencilIndex == fPixelConfigToStencilIndex[config]) {
+ // Default to unsupported
+ fPixelConfigToStencilIndex[config] = kUnsupportedStencilIndex;
+ // Create color texture
+ GrGLuint colorID;
+ GL_CALL(GenTextures(1, &colorID));
+ this->setScratchTextureUnit();
+ GL_CALL(BindTexture(GR_GL_TEXTURE_2D, colorID));
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_MAG_FILTER,
+ GR_GL_NEAREST));
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_MIN_FILTER,
+ GR_GL_NEAREST));
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_WRAP_S,
+ GR_GL_CLAMP_TO_EDGE));
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_WRAP_T,
+ GR_GL_CLAMP_TO_EDGE));
- int stencilFmtCnt = this->glCaps().stencilFormats().count();
- for (int i = 0; i < stencilFmtCnt; ++i) {
- if (!sbDesc.fRenderbufferID) {
- GL_CALL(GenRenderbuffers(1, &sbDesc.fRenderbufferID));
+ GrGLenum internalFormat = 0x0; // suppress warning
+ GrGLenum externalFormat = 0x0; // suppress warning
+ GrGLenum externalType = 0x0; // suppress warning
+ if (!this->configToGLFormats(config, false, &internalFormat,
+ &externalFormat, &externalType)) {
+ GL_CALL(DeleteTextures(1, &colorID));
+ fPixelConfigToStencilIndex[config] = kUnsupportedStencilIndex;
+ return kUnsupportedStencilIndex;
}
- if (!sbDesc.fRenderbufferID) {
- return false;
- }
- GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
- // we start with the last stencil format that succeeded in hopes
- // that we won't go through this loop more than once after the
- // first (painful) stencil creation.
- int sIdx = (i + fLastSuccessfulStencilFmtIdx) % stencilFmtCnt;
- const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats()[sIdx];
+
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.
- bool created;
- if (samples > 0) {
- created = renderbuffer_storage_msaa(*fGLContext,
- samples,
- sFmt.fInternalFormat,
- width, height);
- } else {
+ GL_ALLOC_CALL(this->glInterface(), TexImage2D(GR_GL_TEXTURE_2D,
+ 0, internalFormat,
+ size,
+ size,
+ 0,
+ externalFormat,
+ externalType,
+ NULL));
+ if (GR_GL_NO_ERROR != GR_GL_GET_ERROR(this->glInterface())) {
+ GL_CALL(DeleteTextures(1, &colorID));
+ fPixelConfigToStencilIndex[config] = kUnsupportedStencilIndex;
+ return kUnsupportedStencilIndex;
+ }
+
+ // unbind the texture from the texture unit before binding it to the frame buffer
+ GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0));
+
+ // Create Framebuffer
+ GrGLuint fb;
+ GL_CALL(GenFramebuffers(1, &fb));
+ GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fb));
+ fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
+ GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER,
+ GR_GL_COLOR_ATTACHMENT0,
+ GR_GL_TEXTURE_2D,
+ colorID,
+ 0));
+
+ // look over formats till I find a compatible one
+ int stencilFmtCnt = this->glCaps().stencilFormats().count();
+ GrGLuint sbRBID = 0;
+ for (int i = 0; i < stencilFmtCnt; ++i) {
+ const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats()[i];
+
+ GL_CALL(GenRenderbuffers(1, &sbRBID));
+ if (!sbRBID) {
+ break;
+ }
+ GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbRBID));
+ CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_RENDERBUFFER,
sFmt.fInternalFormat,
- width, height));
- created = (GR_GL_NO_ERROR == check_alloc_error(rt->desc(), this->glInterface()));
- }
- if (created) {
- fStats.incStencilAttachmentCreates();
- // After sized formats we attempt an unsized format and take
- // whatever sizes GL gives us. In that case we query for the size.
- GrGLStencilAttachment::Format format = sFmt;
- get_stencil_rb_sizes(this->glInterface(), &format);
- SkAutoTUnref<GrGLStencilAttachment> sb(
- new GrGLStencilAttachment(this, sbDesc, width, height, samples, format));
- if (this->attachStencilAttachmentToRenderTarget(sb, rt)) {
- fLastSuccessfulStencilFmtIdx = sIdx;
- rt->renderTargetPriv().didAttachStencilAttachment(sb);
-// This work around is currently breaking on windows 7 hd2000 bot when we bind a color buffer
-#if 0
- // Clear the stencil buffer. We use a special purpose FBO for this so that the
- // entire stencil buffer is cleared, even if it is attached to an FBO with a
- // smaller color target.
- if (0 == fStencilClearFBOID) {
- GL_CALL(GenFramebuffers(1, &fStencilClearFBOID));
- }
-
- GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fStencilClearFBOID));
- fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
- fStats.incRenderTargetBinds();
+ size, size));
+ if (GR_GL_NO_ERROR == GR_GL_GET_ERROR(this->glInterface())) {
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_STENCIL_ATTACHMENT,
- GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
+ GR_GL_RENDERBUFFER, sbRBID));
if (sFmt.fPacked) {
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
- GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
- }
-
- GL_CALL(ClearStencil(0));
- // Many GL implementations seem to have trouble with clearing an FBO with only
- // a stencil buffer.
- GrGLuint tempRB;
- GL_CALL(GenRenderbuffers(1, &tempRB));
- GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, tempRB));
- if (samples > 0) {
- renderbuffer_storage_msaa(fGLContext, samples, GR_GL_RGBA8, width, height);
+ GR_GL_RENDERBUFFER, sbRBID));
} else {
- GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, GR_GL_RGBA8, width, height));
- }
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_COLOR_ATTACHMENT0,
- GR_GL_RENDERBUFFER, tempRB));
-
- GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
-
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_COLOR_ATTACHMENT0,
- GR_GL_RENDERBUFFER, 0));
- GL_CALL(DeleteRenderbuffers(1, &tempRB));
-
- // Unbind the SB from the FBO so that we don't keep it alive.
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_STENCIL_ATTACHMENT,
- GR_GL_RENDERBUFFER, 0));
- if (sFmt.fPacked) {
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
}
-#endif
- return true;
+ GrGLenum status;
+ GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
+ if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
+ GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_STENCIL_ATTACHMENT,
+ GR_GL_RENDERBUFFER, 0));
+ if (sFmt.fPacked) {
+ GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_DEPTH_ATTACHMENT,
+ GR_GL_RENDERBUFFER, 0));
+ }
+ } else {
+ fPixelConfigToStencilIndex[config] = i;
+ break;
+ }
}
- // Remove the scratch key from this resource so we don't grab it from the cache ever
- // again.
- sb->resourcePriv().removeScratchKey();
- // Set this to 0 since we handed the valid ID off to the failed stencil buffer resource.
- sbDesc.fRenderbufferID = 0;
+ sbRBID = 0;
}
+ GL_CALL(DeleteTextures(1, &colorID));
+ GL_CALL(DeleteRenderbuffers(1, &sbRBID));
+ GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
+ GL_CALL(DeleteFramebuffers(1, &fb));
}
- GL_CALL(DeleteRenderbuffers(1, &sbDesc.fRenderbufferID));
- return false;
+ SkASSERT(kUnknownStencilIndex != fPixelConfigToStencilIndex[config]);
+ return fPixelConfigToStencilIndex[config];
+}
+
+bool GrGLGpu::createStencilAttachmentForRenderTarget(GrRenderTarget* rt, int width, int height) {
+ // All internally created RTs are also textures. We don't create
+ // SBs for a client's standalone RT (that is a RT that isn't also a texture).
+ SkASSERT(rt->asTexture());
+ SkASSERT(width >= rt->width());
+ SkASSERT(height >= rt->height());
+
+ int samples = rt->numStencilSamples();
+ GrGLStencilAttachment::IDDesc sbDesc;
+
+ int sIdx = this->getCompatibleStencilIndex(rt->config());
+ if (sIdx == kUnsupportedStencilIndex) {
+ return false;
+ }
+
+ if (!sbDesc.fRenderbufferID) {
+ GL_CALL(GenRenderbuffers(1, &sbDesc.fRenderbufferID));
+ }
+ if (!sbDesc.fRenderbufferID) {
+ return false;
+ }
+ GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
+ const GrGLCaps::StencilFormat& sFmt = this->glCaps().stencilFormats()[sIdx];
+ 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 > 0) {
+ SkAssertResult(renderbuffer_storage_msaa(*fGLContext,
+ samples,
+ sFmt.fInternalFormat,
+ width, height));
+ } else {
+ GL_ALLOC_CALL(this->glInterface(), RenderbufferStorage(GR_GL_RENDERBUFFER,
+ sFmt.fInternalFormat,
+ width, height));
+ SkASSERT(GR_GL_NO_ERROR == check_alloc_error(rt->desc(), this->glInterface()));
+ }
+ fStats.incStencilAttachmentCreates();
+ // After sized formats we attempt an unsized format and take
+ // whatever sizes GL gives us. In that case we query for the size.
+ GrGLStencilAttachment::Format format = sFmt;
+ get_stencil_rb_sizes(this->glInterface(), &format);
+ SkAutoTUnref<GrGLStencilAttachment> sb(
+ new GrGLStencilAttachment(this, sbDesc, width, height, samples, format));
+ SkAssertResult(this->attachStencilAttachmentToRenderTarget(sb, rt));
+ rt->renderTargetPriv().didAttachStencilAttachment(sb);
+ // This work around is currently breaking on windows 7 hd2000 bot when we bind a color buffer
+#if 0
+ // Clear the stencil buffer. We use a special purpose FBO for this so that the
+ // entire stencil buffer is cleared, even if it is attached to an FBO with a
+ // smaller color target.
+ if (0 == fStencilClearFBOID) {
+ GL_CALL(GenFramebuffers(1, &fStencilClearFBOID));
+ }
+
+ GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fStencilClearFBOID));
+ fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
+ fStats.incRenderTargetBinds();
+ GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_STENCIL_ATTACHMENT,
+ GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
+ if (sFmt.fPacked) {
+ GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_DEPTH_ATTACHMENT,
+ GR_GL_RENDERBUFFER, sbDesc.fRenderbufferID));
+ }
+
+ GL_CALL(ClearStencil(0));
+ // Many GL implementations seem to have trouble with clearing an FBO with only
+ // a stencil buffer.
+ GrGLuint tempRB;
+ GL_CALL(GenRenderbuffers(1, &tempRB));
+ GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, tempRB));
+ if (samples > 0) {
+ renderbuffer_storage_msaa(fGLContext, samples, GR_GL_RGBA8, width, height);
+ } else {
+ GL_CALL(RenderbufferStorage(GR_GL_RENDERBUFFER, GR_GL_RGBA8, width, height));
+ }
+ GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_COLOR_ATTACHMENT0,
+ GR_GL_RENDERBUFFER, tempRB));
+
+ GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
+
+ GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_COLOR_ATTACHMENT0,
+ GR_GL_RENDERBUFFER, 0));
+ GL_CALL(DeleteRenderbuffers(1, &tempRB));
+
+ // Unbind the SB from the FBO so that we don't keep it alive.
+ GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_STENCIL_ATTACHMENT,
+ GR_GL_RENDERBUFFER, 0));
+ if (sFmt.fPacked) {
+ GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
+ GR_GL_DEPTH_ATTACHMENT,
+ GR_GL_RENDERBUFFER, 0));
+ }
+#endif
+ return true;
}
bool GrGLGpu::attachStencilAttachmentToRenderTarget(GrStencilAttachment* sb, GrRenderTarget* rt) {
@@ -1325,25 +1439,11 @@ bool GrGLGpu::attachStencilAttachmentToRenderTarget(GrStencilAttachment* sb, GrR
GR_GL_RENDERBUFFER, 0));
}
+#ifdef SK_DEBUG
GrGLenum status;
- if (!this->glCaps().isColorConfigAndStencilFormatVerified(rt->config(), glsb->format())) {
- GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
- if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_STENCIL_ATTACHMENT,
- GR_GL_RENDERBUFFER, 0));
- if (glsb->format().fPacked) {
- GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_DEPTH_ATTACHMENT,
- GR_GL_RENDERBUFFER, 0));
- }
- return false;
- } else {
- fGLContext->caps()->markColorConfigAndStencilFormatAsVerified(
- rt->config(),
- glsb->format());
- }
- }
+ GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
+ SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
+#endif
return true;
}
}