|
1 |
|
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 */ |
|
8 #include "gl/SkNativeGLContext.h" |
|
9 |
|
10 SkNativeGLContext::AutoContextRestore::AutoContextRestore() { |
|
11 fOldEGLContext = eglGetCurrentContext(); |
|
12 fOldDisplay = eglGetCurrentDisplay(); |
|
13 fOldSurface = eglGetCurrentSurface(EGL_DRAW); |
|
14 |
|
15 } |
|
16 |
|
17 SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { |
|
18 if (NULL != fOldDisplay) { |
|
19 eglMakeCurrent(fOldDisplay, fOldSurface, fOldSurface, fOldEGLContext); |
|
20 } |
|
21 } |
|
22 |
|
23 /////////////////////////////////////////////////////////////////////////////// |
|
24 |
|
25 SkNativeGLContext::SkNativeGLContext() |
|
26 : fContext(EGL_NO_CONTEXT) |
|
27 , fDisplay(EGL_NO_DISPLAY) |
|
28 , fSurface(EGL_NO_SURFACE) { |
|
29 } |
|
30 |
|
31 SkNativeGLContext::~SkNativeGLContext() { |
|
32 this->destroyGLContext(); |
|
33 } |
|
34 |
|
35 void SkNativeGLContext::destroyGLContext() { |
|
36 if (fDisplay) { |
|
37 eglMakeCurrent(fDisplay, 0, 0, 0); |
|
38 |
|
39 if (fContext) { |
|
40 eglDestroyContext(fDisplay, fContext); |
|
41 fContext = EGL_NO_CONTEXT; |
|
42 } |
|
43 |
|
44 if (fSurface) { |
|
45 eglDestroySurface(fDisplay, fSurface); |
|
46 fSurface = EGL_NO_SURFACE; |
|
47 } |
|
48 |
|
49 //TODO should we close the display? |
|
50 fDisplay = EGL_NO_DISPLAY; |
|
51 } |
|
52 } |
|
53 |
|
54 const GrGLInterface* SkNativeGLContext::createGLContext() { |
|
55 static const EGLint kEGLContextAttribsForOpenGL[] = { |
|
56 EGL_NONE |
|
57 }; |
|
58 |
|
59 static const EGLint kEGLContextAttribsForOpenGLES[] = { |
|
60 EGL_CONTEXT_CLIENT_VERSION, 2, |
|
61 EGL_NONE |
|
62 }; |
|
63 |
|
64 static const struct { |
|
65 const EGLint* fContextAttribs; |
|
66 EGLenum fAPI; |
|
67 EGLint fRenderableTypeBit; |
|
68 GrGLStandard fStandard; |
|
69 } kAPIs[] = { |
|
70 { // OpenGL |
|
71 kEGLContextAttribsForOpenGL, |
|
72 EGL_OPENGL_API, |
|
73 EGL_OPENGL_BIT, |
|
74 kGL_GrGLStandard |
|
75 }, |
|
76 { // OpenGL ES. This seems to work for both ES2 and 3 (when available). |
|
77 kEGLContextAttribsForOpenGLES, |
|
78 EGL_OPENGL_ES_API, |
|
79 EGL_OPENGL_ES2_BIT, |
|
80 kGLES_GrGLStandard |
|
81 }, |
|
82 }; |
|
83 |
|
84 const GrGLInterface* interface = NULL; |
|
85 |
|
86 for (size_t api = 0; NULL == interface && api < SK_ARRAY_COUNT(kAPIs); ++api) { |
|
87 fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
|
88 |
|
89 EGLint majorVersion; |
|
90 EGLint minorVersion; |
|
91 eglInitialize(fDisplay, &majorVersion, &minorVersion); |
|
92 |
|
93 #if 0 |
|
94 SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR)); |
|
95 SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS)); |
|
96 SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION)); |
|
97 SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS)); |
|
98 #endif |
|
99 |
|
100 if (!eglBindAPI(kAPIs[api].fAPI)) { |
|
101 continue; |
|
102 } |
|
103 |
|
104 EGLint numConfigs; |
|
105 const EGLint configAttribs[] = { |
|
106 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, |
|
107 EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit, |
|
108 EGL_RED_SIZE, 8, |
|
109 EGL_GREEN_SIZE, 8, |
|
110 EGL_BLUE_SIZE, 8, |
|
111 EGL_ALPHA_SIZE, 8, |
|
112 EGL_NONE |
|
113 }; |
|
114 |
|
115 EGLConfig surfaceConfig; |
|
116 if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) { |
|
117 SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError()); |
|
118 continue; |
|
119 } |
|
120 |
|
121 fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, kAPIs[api].fContextAttribs); |
|
122 if (EGL_NO_CONTEXT == fContext) { |
|
123 SkDebugf("eglCreateContext failed. EGL Error: 0x%08x\n", eglGetError()); |
|
124 continue; |
|
125 } |
|
126 |
|
127 static const EGLint kSurfaceAttribs[] = { |
|
128 EGL_WIDTH, 1, |
|
129 EGL_HEIGHT, 1, |
|
130 EGL_NONE |
|
131 }; |
|
132 |
|
133 fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs); |
|
134 if (EGL_NO_SURFACE == fSurface) { |
|
135 SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError()); |
|
136 this->destroyGLContext(); |
|
137 continue; |
|
138 } |
|
139 |
|
140 if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { |
|
141 SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError()); |
|
142 this->destroyGLContext(); |
|
143 continue; |
|
144 } |
|
145 |
|
146 interface = GrGLCreateNativeInterface(); |
|
147 if (NULL == interface) { |
|
148 SkDebugf("Failed to create gl interface.\n"); |
|
149 this->destroyGLContext(); |
|
150 continue; |
|
151 } |
|
152 |
|
153 if (!interface->validate()) { |
|
154 interface->unref(); |
|
155 interface = NULL; |
|
156 this->destroyGLContext(); |
|
157 } |
|
158 } |
|
159 |
|
160 return interface; |
|
161 } |
|
162 |
|
163 void SkNativeGLContext::makeCurrent() const { |
|
164 if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { |
|
165 SkDebugf("Could not set the context.\n"); |
|
166 } |
|
167 } |
|
168 |
|
169 void SkNativeGLContext::swapBuffers() const { |
|
170 if (!eglSwapBuffers(fDisplay, fSurface)) { |
|
171 SkDebugf("Could not complete eglSwapBuffers.\n"); |
|
172 } |
|
173 } |