Home | History | Annotate | Download | only in gl
      1 
      2 /*
      3  * Copyright 2013 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "gl/SkGLContextHelper.h"
      9 #include "GrGLUtil.h"
     10 
     11 SkGLContextHelper::SkGLContextHelper()
     12     : fFBO(0)
     13     , fColorBufferID(0)
     14     , fDepthStencilBufferID(0)
     15     , fGL(NULL) {
     16 }
     17 
     18 SkGLContextHelper::~SkGLContextHelper() {
     19 
     20     if (fGL) {
     21         // TODO: determine why DeleteFramebuffers is generating a GL error in tests
     22         SK_GL_NOERRCHECK(*this, DeleteFramebuffers(1, &fFBO));
     23         SK_GL_NOERRCHECK(*this, DeleteRenderbuffers(1, &fColorBufferID));
     24         SK_GL_NOERRCHECK(*this, DeleteRenderbuffers(1, &fDepthStencilBufferID));
     25     }
     26 
     27     SkSafeUnref(fGL);
     28 }
     29 
     30 bool SkGLContextHelper::init(GrGLStandard forcedGpuAPI, int width,
     31                              int height) {
     32     if (fGL) {
     33         fGL->unref();
     34         this->destroyGLContext();
     35     }
     36 
     37     fGL = this->createGLContext(forcedGpuAPI);
     38     if (fGL) {
     39         const GrGLubyte* temp;
     40 
     41         if (!fGL->validate()) {
     42             fGL = NULL;
     43             this->destroyGLContext();
     44             return false;
     45         }
     46 
     47         SK_GL_RET(*this, temp, GetString(GR_GL_VERSION));
     48         const char* versionStr = reinterpret_cast<const char*>(temp);
     49         GrGLVersion version = GrGLGetVersionFromString(versionStr);
     50 
     51         // clear any existing GL erorrs
     52         GrGLenum error;
     53         do {
     54             SK_GL_RET(*this, error, GetError());
     55         } while (GR_GL_NO_ERROR != error);
     56 
     57         SK_GL(*this, GenFramebuffers(1, &fFBO));
     58         SK_GL(*this, BindFramebuffer(GR_GL_FRAMEBUFFER, fFBO));
     59         SK_GL(*this, GenRenderbuffers(1, &fColorBufferID));
     60         SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fColorBufferID));
     61         if (kGLES_GrGLStandard == this->gl()->fStandard) {
     62             SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
     63                                              GR_GL_RGBA8,
     64                                              width, height));
     65         } else {
     66             SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
     67                                              GR_GL_RGBA,
     68                                              width, height));
     69         }
     70         SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
     71                                              GR_GL_COLOR_ATTACHMENT0,
     72                                              GR_GL_RENDERBUFFER,
     73                                              fColorBufferID));
     74         SK_GL(*this, GenRenderbuffers(1, &fDepthStencilBufferID));
     75         SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fDepthStencilBufferID));
     76 
     77         // Some drivers that support packed depth stencil will only succeed
     78         // in binding a packed format an FBO. However, we can't rely on packed
     79         // depth stencil being available.
     80         bool supportsPackedDepthStencil;
     81         if (kGLES_GrGLStandard == this->gl()->fStandard) {
     82             supportsPackedDepthStencil = version >= GR_GL_VER(3,0) ||
     83                                          this->hasExtension("GL_OES_packed_depth_stencil");
     84         } else {
     85             supportsPackedDepthStencil = version >= GR_GL_VER(3,0) ||
     86                                          this->hasExtension("GL_EXT_packed_depth_stencil") ||
     87                                          this->hasExtension("GL_ARB_framebuffer_object");
     88         }
     89 
     90         if (supportsPackedDepthStencil) {
     91             // ES2 requires sized internal formats for RenderbufferStorage
     92             // On Desktop we let the driver decide.
     93             GrGLenum format = kGLES_GrGLStandard == this->gl()->fStandard ?
     94                                     GR_GL_DEPTH24_STENCIL8 :
     95                                     GR_GL_DEPTH_STENCIL;
     96             SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
     97                                              format,
     98                                              width, height));
     99             SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    100                                                  GR_GL_DEPTH_ATTACHMENT,
    101                                                  GR_GL_RENDERBUFFER,
    102                                                  fDepthStencilBufferID));
    103         } else {
    104             GrGLenum format = kGLES_GrGLStandard == this->gl()->fStandard ? GR_GL_STENCIL_INDEX8 :
    105                                                                           GR_GL_STENCIL_INDEX;
    106             SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
    107                                              format,
    108                                              width, height));
    109         }
    110         SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    111                                              GR_GL_STENCIL_ATTACHMENT,
    112                                              GR_GL_RENDERBUFFER,
    113                                              fDepthStencilBufferID));
    114         SK_GL(*this, Viewport(0, 0, width, height));
    115         SK_GL(*this, ClearStencil(0));
    116         SK_GL(*this, Clear(GR_GL_STENCIL_BUFFER_BIT));
    117 
    118         SK_GL_RET(*this, error, GetError());
    119         GrGLenum status;
    120         SK_GL_RET(*this, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    121 
    122         if (GR_GL_FRAMEBUFFER_COMPLETE != status ||
    123             GR_GL_NO_ERROR != error) {
    124             fFBO = 0;
    125             fColorBufferID = 0;
    126             fDepthStencilBufferID = 0;
    127             fGL->unref();
    128             fGL = NULL;
    129             this->destroyGLContext();
    130             return false;
    131         } else {
    132             return true;
    133         }
    134     }
    135     return false;
    136 }
    137 
    138 void SkGLContextHelper::testAbandon() {
    139     if (fGL) {
    140         fGL->abandon();
    141     }
    142 }
    143