blob: da446be0b095ff7f230f2259cd549851ddc80a07 [file] [log] [blame]
bsalomon@google.com373a6632011-10-19 20:43:20 +00001
2/*
robertphillips@google.com6177e692013-02-28 20:16:25 +00003 * Copyright 2013 Google Inc.
bsalomon@google.com373a6632011-10-19 20:43:20 +00004 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
robertphillips@google.com6177e692013-02-28 20:16:25 +00008#include "gl/SkGLContextHelper.h"
bsalomon@google.com1744f972013-02-26 21:46:32 +00009#include "GrGLUtil.h"
bsalomon@google.com373a6632011-10-19 20:43:20 +000010
robertphillips@google.com6177e692013-02-28 20:16:25 +000011SkGLContextHelper::SkGLContextHelper()
bsalomon@google.com373a6632011-10-19 20:43:20 +000012 : fFBO(0)
robertphillips@google.com7c959422012-03-22 20:43:56 +000013 , fColorBufferID(0)
14 , fDepthStencilBufferID(0)
bsalomon@google.com373a6632011-10-19 20:43:20 +000015 , fGL(NULL) {
16}
17
robertphillips@google.com6177e692013-02-28 20:16:25 +000018SkGLContextHelper::~SkGLContextHelper() {
robertphillips@google.comf6f123d2012-03-21 17:57:55 +000019
20 if (fGL) {
robertphillips@google.comedbd21a2013-02-07 21:16:41 +000021 // 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));
robertphillips@google.comf6f123d2012-03-21 17:57:55 +000025 }
26
bsalomon@google.com373a6632011-10-19 20:43:20 +000027 SkSafeUnref(fGL);
28}
29
robertphillips@google.com6177e692013-02-28 20:16:25 +000030bool SkGLContextHelper::init(int width, int height) {
bsalomon@google.com373a6632011-10-19 20:43:20 +000031 if (fGL) {
32 fGL->unref();
33 this->destroyGLContext();
34 }
35
36 fGL = this->createGLContext();
37 if (fGL) {
robertphillips@google.comfe1b5362013-02-07 19:45:46 +000038 const GrGLubyte* temp;
39
bsalomon@google.com1744f972013-02-26 21:46:32 +000040 GrGLBinding bindingInUse = GrGLGetBindingInUse(this->gl());
41
42 if (!fGL->validate(bindingInUse) || !fExtensions.init(bindingInUse, fGL)) {
43 fGL = NULL;
44 this->destroyGLContext();
45 return false;
46 }
robertphillips@google.comfe1b5362013-02-07 19:45:46 +000047
48 SK_GL_RET(*this, temp, GetString(GR_GL_VERSION));
49 const char* versionStr = reinterpret_cast<const char*>(temp);
bsalomon@google.com6e859372012-02-09 15:25:13 +000050 GrGLVersion version = GrGLGetVersionFromString(versionStr);
51
bsalomon@google.com675c5c42011-12-06 19:54:37 +000052 // clear any existing GL erorrs
53 GrGLenum error;
54 do {
robertphillips@google.comfe1b5362013-02-07 19:45:46 +000055 SK_GL_RET(*this, error, GetError());
bsalomon@google.com675c5c42011-12-06 19:54:37 +000056 } while (GR_GL_NO_ERROR != error);
bsalomon@google.com6e859372012-02-09 15:25:13 +000057
bsalomon@google.com373a6632011-10-19 20:43:20 +000058 SK_GL(*this, GenFramebuffers(1, &fFBO));
59 SK_GL(*this, BindFramebuffer(GR_GL_FRAMEBUFFER, fFBO));
robertphillips@google.com7c959422012-03-22 20:43:56 +000060 SK_GL(*this, GenRenderbuffers(1, &fColorBufferID));
61 SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fColorBufferID));
bsalomon@google.com791816a2013-08-15 18:54:39 +000062 if (kES_GrGLBinding == bindingInUse) {
bsalomon@google.com675c5c42011-12-06 19:54:37 +000063 SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
64 GR_GL_RGBA8,
65 width, height));
66 } else {
67 SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
68 GR_GL_RGBA,
69 width, height));
70 }
bsalomon@google.com373a6632011-10-19 20:43:20 +000071 SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
72 GR_GL_COLOR_ATTACHMENT0,
rmistry@google.comfbfcd562012-08-23 18:09:54 +000073 GR_GL_RENDERBUFFER,
robertphillips@google.com7c959422012-03-22 20:43:56 +000074 fColorBufferID));
75 SK_GL(*this, GenRenderbuffers(1, &fDepthStencilBufferID));
76 SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fDepthStencilBufferID));
bsalomon@google.com6e859372012-02-09 15:25:13 +000077
78 // Some drivers that support packed depth stencil will only succeed
79 // in binding a packed format an FBO. However, we can't rely on packed
80 // depth stencil being available.
81 bool supportsPackedDepthStencil;
bsalomon@google.com791816a2013-08-15 18:54:39 +000082 if (kES_GrGLBinding == bindingInUse) {
commit-bot@chromium.org04c500f2013-09-06 15:28:01 +000083 supportsPackedDepthStencil = version >= GR_GL_VER(3,0) ||
84 this->hasExtension("GL_OES_packed_depth_stencil");
bsalomon@google.com675c5c42011-12-06 19:54:37 +000085 } else {
bsalomon@google.com6e859372012-02-09 15:25:13 +000086 supportsPackedDepthStencil = version >= GR_GL_VER(3,0) ||
bsalomon@google.com1744f972013-02-26 21:46:32 +000087 this->hasExtension("GL_EXT_packed_depth_stencil") ||
88 this->hasExtension("GL_ARB_framebuffer_object");
bsalomon@google.com6e859372012-02-09 15:25:13 +000089 }
90
91 if (supportsPackedDepthStencil) {
92 // ES2 requires sized internal formats for RenderbufferStorage
93 // On Desktop we let the driver decide.
bsalomon@google.com791816a2013-08-15 18:54:39 +000094 GrGLenum format = kES_GrGLBinding == bindingInUse ?
bsalomon@google.com6e859372012-02-09 15:25:13 +000095 GR_GL_DEPTH24_STENCIL8 :
96 GR_GL_DEPTH_STENCIL;
bsalomon@google.com675c5c42011-12-06 19:54:37 +000097 SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
bsalomon@google.com6e859372012-02-09 15:25:13 +000098 format,
bsalomon@google.com675c5c42011-12-06 19:54:37 +000099 width, height));
100 SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
101 GR_GL_DEPTH_ATTACHMENT,
102 GR_GL_RENDERBUFFER,
robertphillips@google.com7c959422012-03-22 20:43:56 +0000103 fDepthStencilBufferID));
bsalomon@google.com6e859372012-02-09 15:25:13 +0000104 } else {
bsalomon@google.com791816a2013-08-15 18:54:39 +0000105 GrGLenum format = kES_GrGLBinding == bindingInUse ?
bsalomon@google.com6e859372012-02-09 15:25:13 +0000106 GR_GL_STENCIL_INDEX8 :
107 GR_GL_STENCIL_INDEX;
108 SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
109 format,
110 width, height));
bsalomon@google.com675c5c42011-12-06 19:54:37 +0000111 }
bsalomon@google.com373a6632011-10-19 20:43:20 +0000112 SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
113 GR_GL_STENCIL_ATTACHMENT,
114 GR_GL_RENDERBUFFER,
robertphillips@google.com7c959422012-03-22 20:43:56 +0000115 fDepthStencilBufferID));
bsalomon@google.com373a6632011-10-19 20:43:20 +0000116 SK_GL(*this, Viewport(0, 0, width, height));
117 SK_GL(*this, ClearStencil(0));
118 SK_GL(*this, Clear(GR_GL_STENCIL_BUFFER_BIT));
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000119
robertphillips@google.comfe1b5362013-02-07 19:45:46 +0000120 SK_GL_RET(*this, error, GetError());
121 GrGLenum status;
122 SK_GL_RET(*this, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
bsalomon@google.com675c5c42011-12-06 19:54:37 +0000123
124 if (GR_GL_FRAMEBUFFER_COMPLETE != status ||
125 GR_GL_NO_ERROR != error) {
bsalomon@google.com373a6632011-10-19 20:43:20 +0000126 fFBO = 0;
robertphillips@google.com7c959422012-03-22 20:43:56 +0000127 fColorBufferID = 0;
128 fDepthStencilBufferID = 0;
bsalomon@google.com373a6632011-10-19 20:43:20 +0000129 fGL->unref();
130 fGL = NULL;
131 this->destroyGLContext();
132 return false;
133 } else {
134 return true;
135 }
136 }
137 return false;
138}