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/gl/GrGLAttachment.h" 9 10#include "include/core/SkTraceMemoryDump.h" 11#include "src/gpu/gl/GrGLGpu.h" 12 13#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) 14 15#define GL_ALLOC_CALL(call) \ 16 [&] { \ 17 if (gpu->glCaps().skipErrorChecks()) { \ 18 GR_GL_CALL(gpu->glInterface(), call); \ 19 return static_cast<GrGLenum>(GR_GL_NO_ERROR); \ 20 } else { \ 21 gpu->clearErrorsAndCheckForOOM(); \ 22 GR_GL_CALL_NOERRCHECK(gpu->glInterface(), call); \ 23 return gpu->getErrorAndCheckForOOM(); \ 24 } \ 25 }() 26 27static bool renderbuffer_storage_msaa(GrGLGpu* gpu, 28 int sampleCount, 29 GrGLenum format, 30 int width, 31 int height) { 32 SkASSERT(GrGLCaps::kNone_MSFBOType != gpu->glCaps().msFBOType()); 33 GrGLenum error; 34 switch (gpu->glCaps().msFBOType()) { 35 case GrGLCaps::kStandard_MSFBOType: 36 error = GL_ALLOC_CALL(RenderbufferStorageMultisample( 37 GR_GL_RENDERBUFFER, sampleCount, format, width, height)); 38 break; 39 case GrGLCaps::kES_Apple_MSFBOType: 40 error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2APPLE( 41 GR_GL_RENDERBUFFER, sampleCount, format, width, height)); 42 break; 43 case GrGLCaps::kES_EXT_MsToTexture_MSFBOType: 44 case GrGLCaps::kES_IMG_MsToTexture_MSFBOType: 45 error = GL_ALLOC_CALL(RenderbufferStorageMultisampleES2EXT( 46 GR_GL_RENDERBUFFER, sampleCount, format, width, height)); 47 break; 48 case GrGLCaps::kNone_MSFBOType: 49 SkUNREACHABLE; 50 break; 51 } 52 return error == GR_GL_NO_ERROR; 53} 54 55sk_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, sampleCnt, glFmt, dimensions.width(), 71 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} 91 92sk_sp<GrGLAttachment> GrGLAttachment::MakeMSAA(GrGLGpu* gpu, 93 SkISize dimensions, 94 int sampleCnt, 95 GrGLFormat format) { 96 GrGLuint rbID = 0; 97 98 GL_CALL(GenRenderbuffers(1, &rbID)); 99 if (!rbID) { 100 return nullptr; 101 } 102 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbID)); 103 GrGLenum glFmt = gpu->glCaps().getRenderbufferInternalFormat(format); 104 if (!renderbuffer_storage_msaa( 105 gpu, sampleCnt, glFmt, dimensions.width(), dimensions.height())) { 106 GL_CALL(DeleteRenderbuffers(1, &rbID)); 107 return nullptr; 108 } 109 110 return sk_sp<GrGLAttachment>(new GrGLAttachment(gpu, 111 rbID, 112 dimensions, 113 GrAttachment::UsageFlags::kColorAttachment, 114 sampleCnt, 115 format)); 116} 117 118 119void GrGLAttachment::onRelease() { 120 if (0 != fRenderbufferID) { 121 GrGLGpu* gpuGL = (GrGLGpu*)this->getGpu(); 122 const GrGLInterface* gl = gpuGL->glInterface(); 123 GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID)); 124 fRenderbufferID = 0; 125 } 126 127 INHERITED::onRelease(); 128} 129 130void GrGLAttachment::onAbandon() { 131 fRenderbufferID = 0; 132 133 INHERITED::onAbandon(); 134} 135 136GrBackendFormat GrGLAttachment::backendFormat() const { 137 return GrBackendFormat::MakeGL(GrGLFormatToEnum(fFormat), GR_GL_TEXTURE_NONE); 138} 139 140void GrGLAttachment::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, 141 const SkString& dumpName) const { 142 SkString renderbuffer_id; 143 renderbuffer_id.appendU32(this->renderbufferID()); 144 traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer", renderbuffer_id.c_str()); 145} 146