|
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 } |