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