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