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 "src/gpu/ganesh/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
renderbuffer_storage_msaa(GrGLGpu * gpu,int sampleCount,GrGLenum format,int width,int height)27 static 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 }
51 return error == GR_GL_NO_ERROR;
52 }
53
MakeStencil(GrGLGpu * gpu,SkISize dimensions,int sampleCnt,GrGLFormat format)54 sk_sp<GrGLAttachment> GrGLAttachment::MakeStencil(GrGLGpu* gpu,
55 SkISize dimensions,
56 int sampleCnt,
57 GrGLFormat format) {
58 GrGLuint rbID = 0;
59
60 GL_CALL(GenRenderbuffers(1, &rbID));
61 if (!rbID) {
62 return nullptr;
63 }
64 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, rbID));
65 GrGLenum glFmt = GrGLFormatToEnum(format);
66 // we do this "if" so that we don't call the multisample
67 // version on a GL that doesn't have an MSAA extension.
68 if (sampleCnt > 1) {
69 if (!renderbuffer_storage_msaa(gpu, sampleCnt, glFmt, dimensions.width(),
70 dimensions.height())) {
71 GL_CALL(DeleteRenderbuffers(1, &rbID));
72 return nullptr;
73 }
74 } else {
75 GrGLenum error = GL_ALLOC_CALL(RenderbufferStorage(
76 GR_GL_RENDERBUFFER, glFmt, dimensions.width(), dimensions.height()));
77 if (error != GR_GL_NO_ERROR) {
78 GL_CALL(DeleteRenderbuffers(1, &rbID));
79 return nullptr;
80 }
81 }
82
83 return sk_sp<GrGLAttachment>(new GrGLAttachment(gpu,
84 rbID,
85 dimensions,
86 GrAttachment::UsageFlags::kStencilAttachment,
87 sampleCnt,
88 format,
89 /*label=*/"GLAttachmentMakeStencil"));
90 }
91
MakeMSAA(GrGLGpu * gpu,SkISize dimensions,int sampleCnt,GrGLFormat format)92 sk_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 /*label=*/"GLAttachmentMakeMSAA"));
117 }
118
119
onRelease()120 void GrGLAttachment::onRelease() {
121 if (0 != fRenderbufferID) {
122 GrGLGpu* gpuGL = (GrGLGpu*)this->getGpu();
123 const GrGLInterface* gl = gpuGL->glInterface();
124 GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID));
125 fRenderbufferID = 0;
126 }
127
128 INHERITED::onRelease();
129 }
130
onAbandon()131 void GrGLAttachment::onAbandon() {
132 fRenderbufferID = 0;
133
134 INHERITED::onAbandon();
135 }
136
backendFormat() const137 GrBackendFormat GrGLAttachment::backendFormat() const {
138 return GrBackendFormat::MakeGL(GrGLFormatToEnum(fFormat), GR_GL_TEXTURE_NONE);
139 }
140
setMemoryBacking(SkTraceMemoryDump * traceMemoryDump,const SkString & dumpName) const141 void GrGLAttachment::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
142 const SkString& dumpName) const {
143 SkString renderbuffer_id;
144 renderbuffer_id.appendU32(this->renderbufferID());
145 traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer", renderbuffer_id.c_str());
146 }
147
onSetLabel()148 void GrGLAttachment::onSetLabel() {
149 SkASSERT(fRenderbufferID);
150 if (!this->getLabel().empty()) {
151 const std::string label = "_Skia_" + this->getLabel();
152 GrGLGpu* glGpu = static_cast<GrGLGpu*>(this->getGpu());
153 if (glGpu->glCaps().debugSupport()) {
154 GR_GL_CALL(glGpu->glInterface(),
155 ObjectLabel(GR_GL_TEXTURE, fRenderbufferID, -1, label.c_str()));
156 }
157 }
158 }
159