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