xref: /third_party/skia/src/gpu/gl/GrGLAttachment.cpp (revision cb93a386)
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