OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <EGL/egl.h> | 5 #include <EGL/egl.h> |
6 | 6 |
7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
8 #if defined(OS_LINUX) | 8 #if defined(OS_LINUX) |
9 #include "app/x11_util.h" | 9 #include "app/x11_util.h" |
10 #define EGL_HAS_PBUFFERS 1 | 10 #define EGL_HAS_PBUFFERS 1 |
11 #endif | 11 #endif |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/scoped_ptr.h" | 13 #include "base/scoped_ptr.h" |
14 #include "app/gfx/gl/gl_bindings.h" | 14 #include "app/gfx/gl/gl_bindings.h" |
15 #include "app/gfx/gl/gl_context_egl.h" | 15 #include "app/gfx/gl/gl_context_egl.h" |
16 | 16 |
17 namespace gfx { | 17 namespace gfx { |
18 | 18 |
19 namespace { | 19 namespace { |
20 | 20 |
21 // The EGL configuration to use. | 21 // The EGL configuration to use. |
22 EGLDisplay g_display; | 22 EGLDisplay g_display; |
23 EGLConfig g_config; | 23 EGLConfig g_config; |
24 | 24 |
| 25 // Returns the last EGL error as a string. |
| 26 const char* GetLastEGLErrorString() { |
| 27 EGLint error = eglGetError(); |
| 28 switch (error) { |
| 29 case EGL_SUCCESS: |
| 30 return "EGL_SUCCESS"; |
| 31 case EGL_BAD_ACCESS: |
| 32 return "EGL_BAD_ACCESS"; |
| 33 case EGL_BAD_ALLOC: |
| 34 return "EGL_BAD_ALLOC"; |
| 35 case EGL_BAD_ATTRIBUTE: |
| 36 return "EGL_BAD_ATTRIBUTE"; |
| 37 case EGL_BAD_CONTEXT: |
| 38 return "EGL_BAD_CONTEXT"; |
| 39 case EGL_BAD_CONFIG: |
| 40 return "EGL_BAD_CONFIG"; |
| 41 case EGL_BAD_CURRENT_SURFACE: |
| 42 return "EGL_BAD_CURRENT_SURFACE"; |
| 43 case EGL_BAD_DISPLAY: |
| 44 return "EGL_BAD_DISPLAY"; |
| 45 case EGL_BAD_SURFACE: |
| 46 return "EGL_BAD_SURFACE"; |
| 47 case EGL_BAD_MATCH: |
| 48 return "EGL_BAD_MATCH"; |
| 49 case EGL_BAD_PARAMETER: |
| 50 return "EGL_BAD_PARAMETER"; |
| 51 case EGL_BAD_NATIVE_PIXMAP: |
| 52 return "EGL_BAD_NATIVE_PIXMAP"; |
| 53 case EGL_BAD_NATIVE_WINDOW: |
| 54 return "EGL_BAD_NATIVE_WINDOW"; |
| 55 default: |
| 56 return "UNKNOWN"; |
| 57 } |
| 58 } |
25 } // namespace anonymous | 59 } // namespace anonymous |
26 | 60 |
27 bool BaseEGLContext::InitializeOneOff() { | 61 bool BaseEGLContext::InitializeOneOff() { |
28 static bool initialized = false; | 62 static bool initialized = false; |
29 if (initialized) | 63 if (initialized) |
30 return true; | 64 return true; |
31 | 65 |
32 #ifdef OS_LINUX | 66 #ifdef OS_LINUX |
33 EGLNativeDisplayType native_display = x11_util::GetXDisplay(); | 67 EGLNativeDisplayType native_display = x11_util::GetXDisplay(); |
34 #else | 68 #else |
35 EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY; | 69 EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY; |
36 #endif | 70 #endif |
37 g_display = eglGetDisplay(native_display); | 71 g_display = eglGetDisplay(native_display); |
38 if (!g_display) { | 72 if (!g_display) { |
39 LOG(ERROR) << "eglGetDisplay failed."; | 73 LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString(); |
40 return false; | 74 return false; |
41 } | 75 } |
42 | 76 |
43 if (!eglInitialize(g_display, NULL, NULL)) { | 77 if (!eglInitialize(g_display, NULL, NULL)) { |
44 LOG(ERROR) << "eglInitialize failed."; | 78 LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString(); |
45 return false; | 79 return false; |
46 } | 80 } |
47 | 81 |
48 // Choose an EGL configuration. | 82 // Choose an EGL configuration. |
49 static const EGLint kConfigAttribs[] = { | 83 static const EGLint kConfigAttribs[] = { |
50 EGL_BUFFER_SIZE, 32, | 84 EGL_BUFFER_SIZE, 32, |
51 EGL_ALPHA_SIZE, 8, | 85 EGL_ALPHA_SIZE, 8, |
52 EGL_BLUE_SIZE, 8, | 86 EGL_BLUE_SIZE, 8, |
53 EGL_RED_SIZE, 8, | 87 EGL_RED_SIZE, 8, |
54 EGL_DEPTH_SIZE, 16, | 88 EGL_DEPTH_SIZE, 16, |
55 EGL_STENCIL_SIZE, 8, | 89 EGL_STENCIL_SIZE, 8, |
56 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | 90 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
57 #ifdef EGL_HAS_PBUFFERS | 91 #ifdef EGL_HAS_PBUFFERS |
58 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, | 92 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, |
59 #else | 93 #else |
60 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | 94 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
61 #endif | 95 #endif |
62 EGL_NONE | 96 EGL_NONE |
63 }; | 97 }; |
64 | 98 |
65 EGLint num_configs; | 99 EGLint num_configs; |
66 if (!eglChooseConfig(g_display, | 100 if (!eglChooseConfig(g_display, |
67 kConfigAttribs, | 101 kConfigAttribs, |
68 NULL, | 102 NULL, |
69 0, | 103 0, |
70 &num_configs)) { | 104 &num_configs)) { |
71 LOG(ERROR) << "eglChooseConfig failed."; | 105 LOG(ERROR) << "eglChooseConfig failed failed with error " |
| 106 << GetLastEGLErrorString(); |
72 return false; | 107 return false; |
73 } | 108 } |
74 | 109 |
75 if (num_configs == 0) { | 110 if (num_configs == 0) { |
76 LOG(ERROR) << "No suitable EGL configs found."; | 111 LOG(ERROR) << "No suitable EGL configs found."; |
77 return false; | 112 return false; |
78 } | 113 } |
79 | 114 |
80 scoped_array<EGLConfig> configs(new EGLConfig[num_configs]); | 115 scoped_array<EGLConfig> configs(new EGLConfig[num_configs]); |
81 if (!eglChooseConfig(g_display, | 116 if (!eglChooseConfig(g_display, |
82 kConfigAttribs, | 117 kConfigAttribs, |
83 configs.get(), | 118 configs.get(), |
84 num_configs, | 119 num_configs, |
85 &num_configs)) { | 120 &num_configs)) { |
86 LOG(ERROR) << "eglChooseConfig failed."; | 121 LOG(ERROR) << "eglChooseConfig failed with error " |
| 122 << GetLastEGLErrorString(); |
87 return false; | 123 return false; |
88 } | 124 } |
89 | 125 |
90 g_config = configs[0]; | 126 g_config = configs[0]; |
91 | 127 |
92 initialized = true; | 128 initialized = true; |
93 return true; | 129 return true; |
94 } | 130 } |
95 | 131 |
96 EGLDisplay BaseEGLContext::GetDisplay() { | 132 EGLDisplay BaseEGLContext::GetDisplay() { |
(...skipping 20 matching lines...) Expand all Loading... |
117 | 153 |
118 bool NativeViewEGLContext::Initialize() { | 154 bool NativeViewEGLContext::Initialize() { |
119 DCHECK(!context_); | 155 DCHECK(!context_); |
120 | 156 |
121 // Create a surface for the native window. | 157 // Create a surface for the native window. |
122 EGLNativeWindowType native_window = | 158 EGLNativeWindowType native_window = |
123 reinterpret_cast<EGLNativeWindowType>(window_); | 159 reinterpret_cast<EGLNativeWindowType>(window_); |
124 surface_ = eglCreateWindowSurface(g_display, g_config, native_window, NULL); | 160 surface_ = eglCreateWindowSurface(g_display, g_config, native_window, NULL); |
125 | 161 |
126 if (!surface_) { | 162 if (!surface_) { |
127 LOG(ERROR) << "eglCreateWindowSurface failed."; | 163 LOG(ERROR) << "eglCreateWindowSurface failed with error " |
| 164 << GetLastEGLErrorString(); |
128 Destroy(); | 165 Destroy(); |
129 return false; | 166 return false; |
130 } | 167 } |
131 | 168 |
132 // Create a context. | 169 // Create a context. |
133 context_ = eglCreateContext(g_display, g_config, NULL, NULL); | 170 context_ = eglCreateContext(g_display, g_config, NULL, NULL); |
134 if (!context_) { | 171 if (!context_) { |
135 LOG(ERROR) << "eglCreateContext failed."; | 172 LOG(ERROR) << "eglCreateContext failed with error " |
| 173 << GetLastEGLErrorString(); |
136 Destroy(); | 174 Destroy(); |
137 return false; | 175 return false; |
138 } | 176 } |
139 | 177 |
140 if (!MakeCurrent()) { | 178 if (!MakeCurrent()) { |
141 LOG(ERROR) << "MakeCurrent failed."; | 179 LOG(ERROR) << "MakeCurrent failed."; |
142 Destroy(); | 180 Destroy(); |
143 return false; | 181 return false; |
144 } | 182 } |
145 | 183 |
146 if (!InitializeCommon()) { | 184 if (!InitializeCommon()) { |
147 LOG(ERROR) << "GLContext::InitializeCommon failed."; | 185 LOG(ERROR) << "GLContext::InitializeCommon failed."; |
148 Destroy(); | 186 Destroy(); |
149 return false; | 187 return false; |
150 } | 188 } |
151 | 189 |
152 return true; | 190 return true; |
153 } | 191 } |
154 | 192 |
155 void NativeViewEGLContext::Destroy() { | 193 void NativeViewEGLContext::Destroy() { |
156 if (context_) { | 194 if (context_) { |
157 eglDestroyContext(g_display, context_); | 195 if (!eglDestroyContext(g_display, context_)) { |
| 196 LOG(ERROR) << "eglDestroyContext failed with error " |
| 197 << GetLastEGLErrorString(); |
| 198 } |
| 199 |
158 context_ = NULL; | 200 context_ = NULL; |
159 } | 201 } |
160 | 202 |
161 if (surface_) { | 203 if (surface_) { |
162 eglDestroySurface(g_display, surface_); | 204 if (!eglDestroySurface(g_display, surface_)) { |
| 205 LOG(ERROR) << "eglDestroySurface failed with error " |
| 206 << GetLastEGLErrorString(); |
| 207 } |
| 208 |
163 surface_ = NULL; | 209 surface_ = NULL; |
164 } | 210 } |
165 } | 211 } |
166 | 212 |
167 bool NativeViewEGLContext::MakeCurrent() { | 213 bool NativeViewEGLContext::MakeCurrent() { |
168 DCHECK(context_); | 214 DCHECK(context_); |
169 return eglMakeCurrent(g_display, | 215 if (!eglMakeCurrent(g_display, |
170 surface_, surface_, | 216 surface_, surface_, |
171 context_) == GL_TRUE; | 217 context_)) { |
| 218 VLOG(1) << "eglMakeCurrent failed with error " |
| 219 << GetLastEGLErrorString(); |
| 220 return false; |
| 221 } |
| 222 |
| 223 return true; |
172 } | 224 } |
173 | 225 |
174 bool NativeViewEGLContext::IsCurrent() { | 226 bool NativeViewEGLContext::IsCurrent() { |
175 DCHECK(context_); | 227 DCHECK(context_); |
176 return context_ == eglGetCurrentContext(); | 228 return context_ == eglGetCurrentContext(); |
177 } | 229 } |
178 | 230 |
179 bool NativeViewEGLContext::IsOffscreen() { | 231 bool NativeViewEGLContext::IsOffscreen() { |
180 return false; | 232 return false; |
181 } | 233 } |
182 | 234 |
183 bool NativeViewEGLContext::SwapBuffers() { | 235 bool NativeViewEGLContext::SwapBuffers() { |
184 return eglSwapBuffers(g_display, surface_) == EGL_TRUE; | 236 if (!eglSwapBuffers(g_display, surface_)) { |
| 237 VLOG(1) << "eglSwapBuffers failed with error " |
| 238 << GetLastEGLErrorString(); |
| 239 return false; |
| 240 } |
| 241 |
| 242 return true; |
185 } | 243 } |
186 | 244 |
187 gfx::Size NativeViewEGLContext::GetSize() { | 245 gfx::Size NativeViewEGLContext::GetSize() { |
188 #if defined(OS_WIN) | 246 #if defined(OS_WIN) |
189 RECT rect; | 247 RECT rect; |
190 if (!GetClientRect(static_cast<HWND>(window_), &rect)) { | 248 if (!GetClientRect(static_cast<HWND>(window_), &rect)) { |
191 DCHECK(false) << "GetClientRect failed."; | 249 DCHECK(false) << "GetClientRect failed."; |
192 return gfx::Size(); | 250 return gfx::Size(); |
193 } | 251 } |
194 | 252 |
195 return gfx::Size(rect.right - rect.left, rect.bottom - rect.top); | 253 return gfx::Size(rect.right - rect.left, rect.bottom - rect.top); |
196 #else | 254 #else |
197 // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't | 255 // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't |
198 // get updated on resize. When it does, we can share the code. | 256 // get updated on resize. When it does, we can share the code. |
199 EGLint width; | 257 EGLint width; |
200 EGLint height; | 258 EGLint height; |
201 CHECK(eglQuerySurface(g_display, surface_, EGL_WIDTH, &width)); | 259 if (!eglQuerySurface(g_display, surface_, EGL_WIDTH, &width) || |
202 CHECK(eglQuerySurface(g_display, surface_, EGL_HEIGHT, &height)); | 260 !eglQuerySurface(g_display, surface_, EGL_HEIGHT, &height)) { |
| 261 NOTREACHED() << "eglQuerySurface failed with error " |
| 262 << GetLastEGLErrorString(); |
| 263 return gfx::Size(); |
| 264 } |
| 265 |
203 return gfx::Size(width, height); | 266 return gfx::Size(width, height); |
204 #endif | 267 #endif |
205 } | 268 } |
206 | 269 |
207 void* NativeViewEGLContext::GetHandle() { | 270 void* NativeViewEGLContext::GetHandle() { |
208 return context_; | 271 return context_; |
209 } | 272 } |
210 | 273 |
211 void NativeViewEGLContext::SetSwapInterval(int interval) { | 274 void NativeViewEGLContext::SetSwapInterval(int interval) { |
212 DCHECK(IsCurrent()); | 275 DCHECK(IsCurrent()); |
213 eglSwapInterval(g_display, interval); | 276 if (!eglSwapInterval(g_display, interval)) { |
| 277 LOG(ERROR) << "eglSwapInterval failed with error " |
| 278 << GetLastEGLErrorString(); |
| 279 } |
214 } | 280 } |
215 | 281 |
216 EGLSurface NativeViewEGLContext::GetSurface() { | 282 EGLSurface NativeViewEGLContext::GetSurface() { |
217 return surface_; | 283 return surface_; |
218 } | 284 } |
219 | 285 |
220 SecondaryEGLContext::SecondaryEGLContext() | 286 SecondaryEGLContext::SecondaryEGLContext() |
221 : surface_(NULL), | 287 : surface_(NULL), |
222 own_surface_(false), | 288 own_surface_(false), |
223 context_(NULL) | 289 context_(NULL) |
(...skipping 23 matching lines...) Expand all Loading... |
247 } else { | 313 } else { |
248 #ifdef EGL_HAS_PBUFFERS | 314 #ifdef EGL_HAS_PBUFFERS |
249 static const EGLint kPbufferAttribs[] = { | 315 static const EGLint kPbufferAttribs[] = { |
250 EGL_WIDTH, 1, | 316 EGL_WIDTH, 1, |
251 EGL_HEIGHT, 1, | 317 EGL_HEIGHT, 1, |
252 EGL_NONE | 318 EGL_NONE |
253 }; | 319 }; |
254 | 320 |
255 surface_ = eglCreatePbufferSurface(g_display, g_config, kPbufferAttribs); | 321 surface_ = eglCreatePbufferSurface(g_display, g_config, kPbufferAttribs); |
256 if (!surface_) { | 322 if (!surface_) { |
257 EGLint error = eglGetError(); | 323 LOG(ERROR) << "eglCreatePbufferSurface failed with error " |
258 LOG(ERROR) << "Error creating Pbuffer: " << error; | 324 << GetLastEGLErrorString(); |
259 return false; | 325 return false; |
260 } | 326 } |
261 own_surface_ = true; | 327 own_surface_ = true; |
262 | 328 |
263 context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes); | 329 context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes); |
264 #else | 330 #else |
265 NOTIMPLEMENTED() << "Offscreen non-shared GLES context"; | 331 NOTIMPLEMENTED() << "Offscreen non-shared GLES context"; |
266 return false; | 332 return false; |
267 #endif | 333 #endif |
268 } | 334 } |
269 | 335 |
270 if (!context_) { | 336 if (!context_) { |
271 EGLint error = eglGetError(); | 337 LOG(ERROR) << "eglCreateContext failed with error " |
272 LOG(ERROR) << "Error creating context: " << error; | 338 << GetLastEGLErrorString(); |
273 Destroy(); | 339 Destroy(); |
274 return false; | 340 return false; |
275 } | 341 } |
276 | 342 |
277 return true; | 343 return true; |
278 } | 344 } |
279 | 345 |
280 void SecondaryEGLContext::Destroy() { | 346 void SecondaryEGLContext::Destroy() { |
281 if (own_surface_) { | 347 if (own_surface_) { |
282 eglDestroySurface(g_display, surface_); | 348 if (!eglDestroySurface(g_display, surface_)) { |
| 349 LOG(ERROR) << "eglDestroySurface failed with error " |
| 350 << GetLastEGLErrorString(); |
| 351 } |
| 352 |
283 own_surface_ = false; | 353 own_surface_ = false; |
284 } | 354 } |
285 surface_ = NULL; | 355 surface_ = NULL; |
286 | 356 |
287 if (context_) { | 357 if (context_) { |
288 eglDestroyContext(g_display, context_); | 358 if (!eglDestroyContext(g_display, context_)) { |
| 359 LOG(ERROR) << "eglDestroyContext failed with error " |
| 360 << GetLastEGLErrorString(); |
| 361 } |
| 362 |
289 context_ = NULL; | 363 context_ = NULL; |
290 } | 364 } |
291 } | 365 } |
292 | 366 |
293 bool SecondaryEGLContext::MakeCurrent() { | 367 bool SecondaryEGLContext::MakeCurrent() { |
294 DCHECK(context_); | 368 DCHECK(context_); |
295 return eglMakeCurrent(g_display, | 369 if (!eglMakeCurrent(g_display, |
296 surface_, surface_, | 370 surface_, surface_, |
297 context_) == GL_TRUE; | 371 context_)) { |
| 372 VLOG(1) << "eglMakeCurrent failed with error " |
| 373 << GetLastEGLErrorString(); |
| 374 return false; |
| 375 } |
| 376 |
| 377 return true; |
298 } | 378 } |
299 | 379 |
300 bool SecondaryEGLContext::IsCurrent() { | 380 bool SecondaryEGLContext::IsCurrent() { |
301 DCHECK(context_); | 381 DCHECK(context_); |
302 return context_ == eglGetCurrentContext(); | 382 return context_ == eglGetCurrentContext(); |
303 } | 383 } |
304 | 384 |
305 bool SecondaryEGLContext::IsOffscreen() { | 385 bool SecondaryEGLContext::IsOffscreen() { |
306 return true; | 386 return true; |
307 } | 387 } |
(...skipping 15 matching lines...) Expand all Loading... |
323 void SecondaryEGLContext::SetSwapInterval(int interval) { | 403 void SecondaryEGLContext::SetSwapInterval(int interval) { |
324 DCHECK(IsCurrent()); | 404 DCHECK(IsCurrent()); |
325 NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext."; | 405 NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext."; |
326 } | 406 } |
327 | 407 |
328 EGLSurface SecondaryEGLContext::GetSurface() { | 408 EGLSurface SecondaryEGLContext::GetSurface() { |
329 return surface_; | 409 return surface_; |
330 } | 410 } |
331 | 411 |
332 } // namespace gfx | 412 } // namespace gfx |
OLD | NEW |