| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "src/gpu/ganesh/gl/GrGLAttachment.h" |
| |
| #include "include/core/SkTraceMemoryDump.h" |
| #include "include/gpu/ganesh/gl/GrGLBackendSurface.h" |
| #include "src/gpu/ganesh/gl/GrGLGpu.h" |
| |
| #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) |
| |
| #define GL_ALLOC_CALL(call) \ |
| [&] { \ |
| if (gpu->glCaps().skipErrorChecks()) { \ |
| GR_GL_CALL(gpu->glInterface(), call); \ |
| return static_cast<GrGLenum>(GR_GL_NO_ERROR); \ |
| } else { \ |
| gpu->clearErrorsAndCheckForOOM(); \ |
| GR_GL_CALL_NOERRCHECK(gpu->glInterface(), call); \ |
| return gpu->getErrorAndCheckForOOM(); \ |
| } \ |
| }() |
| |
| static bool renderbuffer_storage_msaa(GrGLGpu* gpu, |
| int sampleCount, |
| GrGLenum format, |
| int width, |
| int height) { |
| SkASSERT(GrGLCaps::kNone_MSFBOType != gpu->glCaps().msFBOType()); |
| GrGLenum error; |
| switch (gpu->glCaps().msFBOType()) { |
| case GrGLCaps::kStandard_MSFBOType: |
| error = GL_ALLOC_CALL(RenderbufferStorageMultisample( |
| GR_GL_RENDERBUFFER, sampleCount, format, width, height)); |
| break; |
| case GrGLCaps::kES_Apple_MSFBOType: |
| error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2APPLE( |
| GR_GL_RENDERBUFFER, sampleCount, format, width, height)); |
| break; |
| case GrGLCaps::kES_EXT_MsToTexture_MSFBOType: |
| case GrGLCaps::kES_IMG_MsToTexture_MSFBOType: |
| error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2EXT( |
| GR_GL_RENDERBUFFER, sampleCount, format, width, height)); |
| break; |
| case GrGLCaps::kNone_MSFBOType: |
| SkUNREACHABLE; |
| } |
| return error == GR_GL_NO_ERROR; |
| } |
| |
| sk_sp<GrGLAttachment> GrGLAttachment::MakeStencil(GrGLGpu* gpu, |
| SkISize dimensions, |
| int sampleCnt, |
| GrGLFormat format) { |
| GrGLuint rbID = 0; |
| |
| GL_CALL(GenRenderbuffers(1, &rbID)); |
| if (!rbID) { |
| return nullptr; |
| } |
| GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbID)); |
| GrGLenum glFmt = GrGLFormatToEnum(format); |
| // we do this "if" so that we don't call the multisample |
| // version on a GL that doesn't have an MSAA extension. |
| if (sampleCnt > 1) { |
| if (!renderbuffer_storage_msaa(gpu, sampleCnt, glFmt, dimensions.width(), |
| dimensions.height())) { |
| GL_CALL(DeleteRenderbuffers(1, &rbID)); |
| return nullptr; |
| } |
| } else { |
| GrGLenum error = GL_ALLOC_CALL(RenderbufferStorage( |
| GR_GL_RENDERBUFFER, glFmt, dimensions.width(), dimensions.height())); |
| if (error != GR_GL_NO_ERROR) { |
| GL_CALL(DeleteRenderbuffers(1, &rbID)); |
| return nullptr; |
| } |
| } |
| |
| return sk_sp<GrGLAttachment>(new GrGLAttachment(gpu, |
| rbID, |
| dimensions, |
| GrAttachment::UsageFlags::kStencilAttachment, |
| sampleCnt, |
| format, |
| /*label=*/"GLAttachmentMakeStencil")); |
| } |
| |
| sk_sp<GrGLAttachment> GrGLAttachment::MakeMSAA(GrGLGpu* gpu, |
| SkISize dimensions, |
| int sampleCnt, |
| GrGLFormat format) { |
| GrGLuint rbID = 0; |
| |
| GL_CALL(GenRenderbuffers(1, &rbID)); |
| if (!rbID) { |
| return nullptr; |
| } |
| GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbID)); |
| GrGLenum glFmt = gpu->glCaps().getRenderbufferInternalFormat(format); |
| if (!renderbuffer_storage_msaa( |
| gpu, sampleCnt, glFmt, dimensions.width(), dimensions.height())) { |
| GL_CALL(DeleteRenderbuffers(1, &rbID)); |
| return nullptr; |
| } |
| |
| return sk_sp<GrGLAttachment>(new GrGLAttachment(gpu, |
| rbID, |
| dimensions, |
| GrAttachment::UsageFlags::kColorAttachment, |
| sampleCnt, |
| format, |
| /*label=*/"GLAttachmentMakeMSAA")); |
| } |
| |
| |
| void GrGLAttachment::onRelease() { |
| if (0 != fRenderbufferID) { |
| GrGLGpu* gpuGL = (GrGLGpu*)this->getGpu(); |
| const GrGLInterface* gl = gpuGL->glInterface(); |
| GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID)); |
| fRenderbufferID = 0; |
| } |
| |
| INHERITED::onRelease(); |
| } |
| |
| void GrGLAttachment::onAbandon() { |
| fRenderbufferID = 0; |
| |
| INHERITED::onAbandon(); |
| } |
| |
| GrBackendFormat GrGLAttachment::backendFormat() const { |
| return GrBackendFormats::MakeGL(GrGLFormatToEnum(fFormat), GR_GL_TEXTURE_NONE); |
| } |
| |
| void GrGLAttachment::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, |
| const SkString& dumpName) const { |
| SkString renderbuffer_id; |
| renderbuffer_id.appendU32(this->renderbufferID()); |
| traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer", renderbuffer_id.c_str()); |
| } |
| |
| void GrGLAttachment::onSetLabel() { |
| SkASSERT(fRenderbufferID); |
| if (!this->getLabel().empty()) { |
| const std::string label = "_Skia_" + this->getLabel(); |
| GrGLGpu* glGpu = static_cast<GrGLGpu*>(this->getGpu()); |
| if (glGpu->glCaps().debugSupport()) { |
| GR_GL_CALL(glGpu->glInterface(), |
| ObjectLabel(GR_GL_TEXTURE, fRenderbufferID, -1, label.c_str())); |
| } |
| } |
| } |