180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
3096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger * Copyright 2013 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
8096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "gl/SkGLContextHelper.h"
9096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "GrGLUtil.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSK_DEFINE_INST_COUNT(SkGLContextHelper)
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkGLContextHelper::SkGLContextHelper()
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : fFBO(0)
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fColorBufferID(0)
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fDepthStencilBufferID(0)
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fGL(NULL) {
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerSkGLContextHelper::~SkGLContextHelper() {
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fGL) {
23096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        // TODO: determine why DeleteFramebuffers is generating a GL error in tests
24096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_GL_NOERRCHECK(*this, DeleteFramebuffers(1, &fFBO));
25096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_GL_NOERRCHECK(*this, DeleteRenderbuffers(1, &fColorBufferID));
26096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_GL_NOERRCHECK(*this, DeleteRenderbuffers(1, &fDepthStencilBufferID));
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSafeUnref(fGL);
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenbergerbool SkGLContextHelper::init(int width, int height) {
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fGL) {
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fGL->unref();
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->destroyGLContext();
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fGL = this->createGLContext();
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fGL) {
40096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const GrGLubyte* temp;
41096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
42096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        GrGLBinding bindingInUse = GrGLGetBindingInUse(this->gl());
43096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
44096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (!fGL->validate(bindingInUse) || !fExtensions.init(bindingInUse, fGL)) {
45096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            fGL = NULL;
46096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            this->destroyGLContext();
47096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            return false;
48096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
49096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
50096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_GL_RET(*this, temp, GetString(GR_GL_VERSION));
51096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        const char* versionStr = reinterpret_cast<const char*>(temp);
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrGLVersion version = GrGLGetVersionFromString(versionStr);
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // clear any existing GL erorrs
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrGLenum error;
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
57096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            SK_GL_RET(*this, error, GetError());
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (GR_GL_NO_ERROR != error);
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, GenFramebuffers(1, &fFBO));
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, BindFramebuffer(GR_GL_FRAMEBUFFER, fFBO));
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, GenRenderbuffers(1, &fColorBufferID));
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fColorBufferID));
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (kES2_GrGLBinding == bindingInUse) {
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             GR_GL_RGBA8,
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             width, height));
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             GR_GL_RGBA,
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             width, height));
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             GR_GL_COLOR_ATTACHMENT0,
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             GR_GL_RENDERBUFFER,
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             fColorBufferID));
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, GenRenderbuffers(1, &fDepthStencilBufferID));
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fDepthStencilBufferID));
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Some drivers that support packed depth stencil will only succeed
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // in binding a packed format an FBO. However, we can't rely on packed
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // depth stencil being available.
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool supportsPackedDepthStencil;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (kES2_GrGLBinding == bindingInUse) {
85096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            supportsPackedDepthStencil = this->hasExtension("GL_OES_packed_depth_stencil");
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            supportsPackedDepthStencil = version >= GR_GL_VER(3,0) ||
88096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                         this->hasExtension("GL_EXT_packed_depth_stencil") ||
89096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                                         this->hasExtension("GL_ARB_framebuffer_object");
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (supportsPackedDepthStencil) {
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // ES2 requires sized internal formats for RenderbufferStorage
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // On Desktop we let the driver decide.
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrGLenum format = kES2_GrGLBinding == bindingInUse ?
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    GR_GL_DEPTH24_STENCIL8 :
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    GR_GL_DEPTH_STENCIL;
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             format,
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             width, height));
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                 GR_GL_DEPTH_ATTACHMENT,
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                 GR_GL_RENDERBUFFER,
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                 fDepthStencilBufferID));
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrGLenum format = kES2_GrGLBinding == bindingInUse ?
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    GR_GL_STENCIL_INDEX8 :
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    GR_GL_STENCIL_INDEX;
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             format,
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             width, height));
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             GR_GL_STENCIL_ATTACHMENT,
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             GR_GL_RENDERBUFFER,
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             fDepthStencilBufferID));
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, Viewport(0, 0, width, height));
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, ClearStencil(0));
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SK_GL(*this, Clear(GR_GL_STENCIL_BUFFER_BIT));
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
121096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_GL_RET(*this, error, GetError());
122096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        GrGLenum status;
123096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        SK_GL_RET(*this, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (GR_GL_FRAMEBUFFER_COMPLETE != status ||
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GR_GL_NO_ERROR != error) {
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fFBO = 0;
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fColorBufferID = 0;
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fDepthStencilBufferID = 0;
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fGL->unref();
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fGL = NULL;
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->destroyGLContext();
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
140