blob: c1b95056984a2139a585a3aee5b34239f8839be8 [file] [log] [blame]
bsalomon@google.com373a6632011-10-19 20:43:20 +00001
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 */
tomhudson@google.com6bf38b52012-02-14 15:11:59 +00008#include "gl/SkGLContext.h"
bsalomon@google.com9c1f1ac2012-05-07 17:09:37 +00009#include "gl/GrGLUtil.h"
bsalomon@google.com373a6632011-10-19 20:43:20 +000010
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000011SK_DEFINE_INST_COUNT(SkGLContext)
12
bsalomon@google.com373a6632011-10-19 20:43:20 +000013SkGLContext::SkGLContext()
14 : fFBO(0)
robertphillips@google.com7c959422012-03-22 20:43:56 +000015 , fColorBufferID(0)
16 , fDepthStencilBufferID(0)
bsalomon@google.com373a6632011-10-19 20:43:20 +000017 , fGL(NULL) {
18}
19
20SkGLContext::~SkGLContext() {
robertphillips@google.comf6f123d2012-03-21 17:57:55 +000021
22 if (fGL) {
robertphillips@google.comedbd21a2013-02-07 21:16:41 +000023 // TODO: determine why DeleteFramebuffers is generating a GL error in tests
24 SK_GL_NOERRCHECK(*this, DeleteFramebuffers(1, &fFBO));
25 SK_GL_NOERRCHECK(*this, DeleteRenderbuffers(1, &fColorBufferID));
26 SK_GL_NOERRCHECK(*this, DeleteRenderbuffers(1, &fDepthStencilBufferID));
robertphillips@google.comf6f123d2012-03-21 17:57:55 +000027 }
28
bsalomon@google.com373a6632011-10-19 20:43:20 +000029 SkSafeUnref(fGL);
30}
31
bsalomon@google.com6e859372012-02-09 15:25:13 +000032bool SkGLContext::hasExtension(const char* extensionName) const {
33 return GrGLHasExtensionFromString(extensionName, fExtensionString.c_str());
34}
35
bsalomon@google.com373a6632011-10-19 20:43:20 +000036bool SkGLContext::init(int width, int height) {
37 if (fGL) {
38 fGL->unref();
39 this->destroyGLContext();
40 }
41
42 fGL = this->createGLContext();
43 if (fGL) {
robertphillips@google.comfe1b5362013-02-07 19:45:46 +000044 const GrGLubyte* temp;
45
46 SK_GL_RET(*this, temp, GetString(GR_GL_EXTENSIONS));
47 fExtensionString = reinterpret_cast<const char*>(temp);
48
49 SK_GL_RET(*this, temp, GetString(GR_GL_VERSION));
50 const char* versionStr = reinterpret_cast<const char*>(temp);
bsalomon@google.com6e859372012-02-09 15:25:13 +000051 GrGLVersion version = GrGLGetVersionFromString(versionStr);
52
bsalomon@google.com675c5c42011-12-06 19:54:37 +000053 // clear any existing GL erorrs
54 GrGLenum error;
55 do {
robertphillips@google.comfe1b5362013-02-07 19:45:46 +000056 SK_GL_RET(*this, error, GetError());
bsalomon@google.com675c5c42011-12-06 19:54:37 +000057 } while (GR_GL_NO_ERROR != error);
bsalomon@google.com6e859372012-02-09 15:25:13 +000058
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000059 GrGLBinding bindingInUse = GrGLGetBindingInUse(this->gl());
60
bsalomon@google.com373a6632011-10-19 20:43:20 +000061 SK_GL(*this, GenFramebuffers(1, &fFBO));
62 SK_GL(*this, BindFramebuffer(GR_GL_FRAMEBUFFER, fFBO));
robertphillips@google.com7c959422012-03-22 20:43:56 +000063 SK_GL(*this, GenRenderbuffers(1, &fColorBufferID));
64 SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fColorBufferID));
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000065 if (kES2_GrGLBinding == bindingInUse) {
bsalomon@google.com675c5c42011-12-06 19:54:37 +000066 SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
67 GR_GL_RGBA8,
68 width, height));
69 } else {
70 SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
71 GR_GL_RGBA,
72 width, height));
73 }
bsalomon@google.com373a6632011-10-19 20:43:20 +000074 SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
75 GR_GL_COLOR_ATTACHMENT0,
rmistry@google.comfbfcd562012-08-23 18:09:54 +000076 GR_GL_RENDERBUFFER,
robertphillips@google.com7c959422012-03-22 20:43:56 +000077 fColorBufferID));
78 SK_GL(*this, GenRenderbuffers(1, &fDepthStencilBufferID));
79 SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fDepthStencilBufferID));
bsalomon@google.com6e859372012-02-09 15:25:13 +000080
81 // Some drivers that support packed depth stencil will only succeed
82 // in binding a packed format an FBO. However, we can't rely on packed
83 // depth stencil being available.
84 bool supportsPackedDepthStencil;
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000085 if (kES2_GrGLBinding == bindingInUse) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +000086 supportsPackedDepthStencil =
bsalomon@google.com6e859372012-02-09 15:25:13 +000087 this->hasExtension("GL_OES_packed_depth_stencil");
bsalomon@google.com675c5c42011-12-06 19:54:37 +000088 } else {
bsalomon@google.com6e859372012-02-09 15:25:13 +000089 supportsPackedDepthStencil = version >= GR_GL_VER(3,0) ||
90 this->hasExtension("GL_EXT_packed_depth_stencil") ||
91 this->hasExtension("GL_ARB_framebuffer_object");
92 }
93
94 if (supportsPackedDepthStencil) {
95 // ES2 requires sized internal formats for RenderbufferStorage
96 // On Desktop we let the driver decide.
rmistry@google.comfbfcd562012-08-23 18:09:54 +000097 GrGLenum format = kES2_GrGLBinding == bindingInUse ?
bsalomon@google.com6e859372012-02-09 15:25:13 +000098 GR_GL_DEPTH24_STENCIL8 :
99 GR_GL_DEPTH_STENCIL;
bsalomon@google.com675c5c42011-12-06 19:54:37 +0000100 SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
bsalomon@google.com6e859372012-02-09 15:25:13 +0000101 format,
bsalomon@google.com675c5c42011-12-06 19:54:37 +0000102 width, height));
103 SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
104 GR_GL_DEPTH_ATTACHMENT,
105 GR_GL_RENDERBUFFER,
robertphillips@google.com7c959422012-03-22 20:43:56 +0000106 fDepthStencilBufferID));
bsalomon@google.com6e859372012-02-09 15:25:13 +0000107 } else {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000108 GrGLenum format = kES2_GrGLBinding == bindingInUse ?
bsalomon@google.com6e859372012-02-09 15:25:13 +0000109 GR_GL_STENCIL_INDEX8 :
110 GR_GL_STENCIL_INDEX;
111 SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
112 format,
113 width, height));
bsalomon@google.com675c5c42011-12-06 19:54:37 +0000114 }
bsalomon@google.com373a6632011-10-19 20:43:20 +0000115 SK_GL(*this, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
116 GR_GL_STENCIL_ATTACHMENT,
117 GR_GL_RENDERBUFFER,
robertphillips@google.com7c959422012-03-22 20:43:56 +0000118 fDepthStencilBufferID));
bsalomon@google.com373a6632011-10-19 20:43:20 +0000119 SK_GL(*this, Viewport(0, 0, width, height));
120 SK_GL(*this, ClearStencil(0));
121 SK_GL(*this, Clear(GR_GL_STENCIL_BUFFER_BIT));
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000122
robertphillips@google.comfe1b5362013-02-07 19:45:46 +0000123 SK_GL_RET(*this, error, GetError());
124 GrGLenum status;
125 SK_GL_RET(*this, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
bsalomon@google.com675c5c42011-12-06 19:54:37 +0000126
127 if (GR_GL_FRAMEBUFFER_COMPLETE != status ||
128 GR_GL_NO_ERROR != error) {
bsalomon@google.com373a6632011-10-19 20:43:20 +0000129 fFBO = 0;
robertphillips@google.com7c959422012-03-22 20:43:56 +0000130 fColorBufferID = 0;
131 fDepthStencilBufferID = 0;
bsalomon@google.com373a6632011-10-19 20:43:20 +0000132 fGL->unref();
133 fGL = NULL;
134 this->destroyGLContext();
135 return false;
136 } else {
137 return true;
138 }
139 }
140 return false;
141}