| 1 | /* |
| 2 | * Copyright 2011 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #include "src/gpu/ganesh/gl/GrGLAttachment.h" |
| 9 | |
| 10 | #include "include/core/SkTraceMemoryDump.h" |
| 11 | #include "include/gpu/ganesh/gl/GrGLBackendSurface.h" |
| 12 | #include "src/gpu/ganesh/gl/GrGLGpu.h" |
| 13 | |
| 14 | #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) |
| 15 | |
| 16 | #define GL_ALLOC_CALL(call) \ |
| 17 | [&] { \ |
| 18 | if (gpu->glCaps().skipErrorChecks()) { \ |
| 19 | GR_GL_CALL(gpu->glInterface(), call); \ |
| 20 | return static_cast<GrGLenum>(GR_GL_NO_ERROR); \ |
| 21 | } else { \ |
| 22 | gpu->clearErrorsAndCheckForOOM(); \ |
| 23 | GR_GL_CALL_NOERRCHECK(gpu->glInterface(), call); \ |
| 24 | return gpu->getErrorAndCheckForOOM(); \ |
| 25 | } \ |
| 26 | }() |
| 27 | |
| 28 | static bool renderbuffer_storage_msaa(GrGLGpu* gpu, |
| 29 | int sampleCount, |
| 30 | GrGLenum format, |
| 31 | int width, |
| 32 | int height) { |
| 33 | SkASSERT(GrGLCaps::kNone_MSFBOType != gpu->glCaps().msFBOType()); |
| 34 | GrGLenum error; |
| 35 | switch (gpu->glCaps().msFBOType()) { |
| 36 | case GrGLCaps::kStandard_MSFBOType: |
| 37 | error = GL_ALLOC_CALL(RenderbufferStorageMultisample( |
| 38 | GR_GL_RENDERBUFFER, sampleCount, format, width, height)); |
| 39 | break; |
| 40 | case GrGLCaps::kES_Apple_MSFBOType: |
| 41 | error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2APPLE( |
| 42 | GR_GL_RENDERBUFFER, sampleCount, format, width, height)); |
| 43 | break; |
| 44 | case GrGLCaps::kES_EXT_MsToTexture_MSFBOType: |
| 45 | case GrGLCaps::kES_IMG_MsToTexture_MSFBOType: |
| 46 | error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2EXT( |
| 47 | GR_GL_RENDERBUFFER, sampleCount, format, width, height)); |
| 48 | break; |
| 49 | case GrGLCaps::kNone_MSFBOType: |
| 50 | SkUNREACHABLE; |
| 51 | } |
| 52 | return error == GR_GL_NO_ERROR; |
| 53 | } |
| 54 | |
| 55 | sk_sp<GrGLAttachment> GrGLAttachment::MakeStencil(GrGLGpu* gpu, |
| 56 | SkISize dimensions, |
| 57 | int sampleCnt, |
| 58 | GrGLFormat format) { |
| 59 | GrGLuint rbID = 0; |
| 60 | |
| 61 | GL_CALL(GenRenderbuffers(1, &rbID)); |
| 62 | if (!rbID) { |
| 63 | return nullptr; |
| 64 | } |
| 65 | GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbID)); |
| 66 | GrGLenum glFmt = GrGLFormatToEnum(format); |
| 67 | // we do this "if" so that we don't call the multisample |
| 68 | // version on a GL that doesn't have an MSAA extension. |
| 69 | if (sampleCnt > 1) { |
| 70 | if (!renderbuffer_storage_msaa(gpu, sampleCount: sampleCnt, format: glFmt, width: dimensions.width(), |
| 71 | height: dimensions.height())) { |
| 72 | GL_CALL(DeleteRenderbuffers(1, &rbID)); |
| 73 | return nullptr; |
| 74 | } |
| 75 | } else { |
| 76 | GrGLenum error = GL_ALLOC_CALL(RenderbufferStorage( |
| 77 | GR_GL_RENDERBUFFER, glFmt, dimensions.width(), dimensions.height())); |
| 78 | if (error != GR_GL_NO_ERROR) { |
| 79 | GL_CALL(DeleteRenderbuffers(1, &rbID)); |
| 80 | return nullptr; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | return sk_sp<GrGLAttachment>(new GrGLAttachment(gpu, |
| 85 | rbID, |
| 86 | dimensions, |
| 87 | GrAttachment::UsageFlags::kStencilAttachment, |
| 88 | sampleCnt, |
| 89 | format, |
| 90 | /*label=*/"GLAttachmentMakeStencil" )); |
| 91 | } |
| 92 | |
| 93 | sk_sp<GrGLAttachment> GrGLAttachment::MakeMSAA(GrGLGpu* gpu, |
| 94 | SkISize dimensions, |
| 95 | int sampleCnt, |
| 96 | GrGLFormat format) { |
| 97 | GrGLuint rbID = 0; |
| 98 | |
| 99 | GL_CALL(GenRenderbuffers(1, &rbID)); |
| 100 | if (!rbID) { |
| 101 | return nullptr; |
| 102 | } |
| 103 | GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbID)); |
| 104 | GrGLenum glFmt = gpu->glCaps().getRenderbufferInternalFormat(format); |
| 105 | if (!renderbuffer_storage_msaa( |
| 106 | gpu, sampleCount: sampleCnt, format: glFmt, width: dimensions.width(), height: dimensions.height())) { |
| 107 | GL_CALL(DeleteRenderbuffers(1, &rbID)); |
| 108 | return nullptr; |
| 109 | } |
| 110 | |
| 111 | return sk_sp<GrGLAttachment>(new GrGLAttachment(gpu, |
| 112 | rbID, |
| 113 | dimensions, |
| 114 | GrAttachment::UsageFlags::kColorAttachment, |
| 115 | sampleCnt, |
| 116 | format, |
| 117 | /*label=*/"GLAttachmentMakeMSAA" )); |
| 118 | } |
| 119 | |
| 120 | |
| 121 | void GrGLAttachment::onRelease() { |
| 122 | if (0 != fRenderbufferID) { |
| 123 | GrGLGpu* gpuGL = (GrGLGpu*)this->getGpu(); |
| 124 | const GrGLInterface* gl = gpuGL->glInterface(); |
| 125 | GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID)); |
| 126 | fRenderbufferID = 0; |
| 127 | } |
| 128 | |
| 129 | INHERITED::onRelease(); |
| 130 | } |
| 131 | |
| 132 | void GrGLAttachment::onAbandon() { |
| 133 | fRenderbufferID = 0; |
| 134 | |
| 135 | INHERITED::onAbandon(); |
| 136 | } |
| 137 | |
| 138 | GrBackendFormat GrGLAttachment::backendFormat() const { |
| 139 | return GrBackendFormats::MakeGL(format: GrGLFormatToEnum(format: fFormat), GR_GL_TEXTURE_NONE); |
| 140 | } |
| 141 | |
| 142 | void GrGLAttachment::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, |
| 143 | const SkString& dumpName) const { |
| 144 | SkString renderbuffer_id; |
| 145 | renderbuffer_id.appendU32(value: this->renderbufferID()); |
| 146 | traceMemoryDump->setMemoryBacking(dumpName: dumpName.c_str(), backingType: "gl_renderbuffer" , backingObjectId: renderbuffer_id.c_str()); |
| 147 | } |
| 148 | |
| 149 | void GrGLAttachment::onSetLabel() { |
| 150 | SkASSERT(fRenderbufferID); |
| 151 | if (!this->getLabel().empty()) { |
| 152 | const std::string label = "_Skia_" + this->getLabel(); |
| 153 | GrGLGpu* glGpu = static_cast<GrGLGpu*>(this->getGpu()); |
| 154 | if (glGpu->glCaps().debugSupport()) { |
| 155 | GR_GL_CALL(glGpu->glInterface(), |
| 156 | ObjectLabel(GR_GL_TEXTURE, fRenderbufferID, -1, label.c_str())); |
| 157 | } |
| 158 | } |
| 159 | } |
| 160 | |