| 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 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 case EGL_BAD_NATIVE_PIXMAP: | 51 case EGL_BAD_NATIVE_PIXMAP: |
| 52 return "EGL_BAD_NATIVE_PIXMAP"; | 52 return "EGL_BAD_NATIVE_PIXMAP"; |
| 53 case EGL_BAD_NATIVE_WINDOW: | 53 case EGL_BAD_NATIVE_WINDOW: |
| 54 return "EGL_BAD_NATIVE_WINDOW"; | 54 return "EGL_BAD_NATIVE_WINDOW"; |
| 55 default: | 55 default: |
| 56 return "UNKNOWN"; | 56 return "UNKNOWN"; |
| 57 } | 57 } |
| 58 } | 58 } |
| 59 } // namespace anonymous | 59 } // namespace anonymous |
| 60 | 60 |
| 61 SharedEGLSurface::SharedEGLSurface(EGLSurface surface) : surface_(surface) { |
| 62 } |
| 63 |
| 64 SharedEGLSurface::~SharedEGLSurface() { |
| 65 if (surface_) { |
| 66 if (!eglDestroySurface(g_display, surface_)) { |
| 67 LOG(ERROR) << "eglDestroySurface failed with error " |
| 68 << GetLastEGLErrorString(); |
| 69 } |
| 70 } |
| 71 } |
| 72 |
| 73 EGLSurface SharedEGLSurface::egl_surface() const { |
| 74 return surface_; |
| 75 } |
| 76 |
| 61 bool BaseEGLContext::InitializeOneOff() { | 77 bool BaseEGLContext::InitializeOneOff() { |
| 62 static bool initialized = false; | 78 static bool initialized = false; |
| 63 if (initialized) | 79 if (initialized) |
| 64 return true; | 80 return true; |
| 65 | 81 |
| 66 #ifdef OS_LINUX | 82 #ifdef OS_LINUX |
| 67 EGLNativeDisplayType native_display = x11_util::GetXDisplay(); | 83 EGLNativeDisplayType native_display = x11_util::GetXDisplay(); |
| 68 #else | 84 #else |
| 69 EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY; | 85 EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY; |
| 70 #endif | 86 #endif |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 std::string BaseEGLContext::GetExtensions() { | 152 std::string BaseEGLContext::GetExtensions() { |
| 137 const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS); | 153 const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS); |
| 138 if (!extensions) | 154 if (!extensions) |
| 139 return GLContext::GetExtensions(); | 155 return GLContext::GetExtensions(); |
| 140 | 156 |
| 141 return GLContext::GetExtensions() + " " + extensions; | 157 return GLContext::GetExtensions() + " " + extensions; |
| 142 } | 158 } |
| 143 | 159 |
| 144 NativeViewEGLContext::NativeViewEGLContext(void* window) | 160 NativeViewEGLContext::NativeViewEGLContext(void* window) |
| 145 : window_(window), | 161 : window_(window), |
| 146 surface_(NULL), | |
| 147 context_(NULL) | 162 context_(NULL) |
| 148 { | 163 { |
| 149 } | 164 } |
| 150 | 165 |
| 151 NativeViewEGLContext::~NativeViewEGLContext() { | 166 NativeViewEGLContext::~NativeViewEGLContext() { |
| 152 } | 167 } |
| 153 | 168 |
| 154 bool NativeViewEGLContext::Initialize() { | 169 bool NativeViewEGLContext::Initialize() { |
| 155 DCHECK(!context_); | 170 DCHECK(!context_); |
| 156 | 171 |
| 157 // Create a surface for the native window. | 172 // Create a surface for the native window. |
| 158 EGLNativeWindowType native_window = | 173 EGLNativeWindowType native_window = |
| 159 reinterpret_cast<EGLNativeWindowType>(window_); | 174 reinterpret_cast<EGLNativeWindowType>(window_); |
| 160 surface_ = eglCreateWindowSurface(g_display, g_config, native_window, NULL); | 175 surface_ = new SharedEGLSurface(eglCreateWindowSurface(g_display, |
| 176 g_config, |
| 177 native_window, |
| 178 NULL)); |
| 161 | 179 |
| 162 if (!surface_) { | 180 if (!surface_->egl_surface()) { |
| 163 LOG(ERROR) << "eglCreateWindowSurface failed with error " | 181 LOG(ERROR) << "eglCreateWindowSurface failed with error " |
| 164 << GetLastEGLErrorString(); | 182 << GetLastEGLErrorString(); |
| 165 Destroy(); | 183 Destroy(); |
| 166 return false; | 184 return false; |
| 167 } | 185 } |
| 168 | 186 |
| 169 static const EGLint kContextAttributes[] = { | 187 static const EGLint kContextAttributes[] = { |
| 170 EGL_CONTEXT_CLIENT_VERSION, 2, | 188 EGL_CONTEXT_CLIENT_VERSION, 2, |
| 171 EGL_NONE | 189 EGL_NONE |
| 172 }; | 190 }; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 197 void NativeViewEGLContext::Destroy() { | 215 void NativeViewEGLContext::Destroy() { |
| 198 if (context_) { | 216 if (context_) { |
| 199 if (!eglDestroyContext(g_display, context_)) { | 217 if (!eglDestroyContext(g_display, context_)) { |
| 200 LOG(ERROR) << "eglDestroyContext failed with error " | 218 LOG(ERROR) << "eglDestroyContext failed with error " |
| 201 << GetLastEGLErrorString(); | 219 << GetLastEGLErrorString(); |
| 202 } | 220 } |
| 203 | 221 |
| 204 context_ = NULL; | 222 context_ = NULL; |
| 205 } | 223 } |
| 206 | 224 |
| 207 if (surface_) { | 225 surface_ = NULL; |
| 208 if (!eglDestroySurface(g_display, surface_)) { | |
| 209 LOG(ERROR) << "eglDestroySurface failed with error " | |
| 210 << GetLastEGLErrorString(); | |
| 211 } | |
| 212 | |
| 213 surface_ = NULL; | |
| 214 } | |
| 215 } | 226 } |
| 216 | 227 |
| 217 bool NativeViewEGLContext::MakeCurrent() { | 228 bool NativeViewEGLContext::MakeCurrent() { |
| 218 DCHECK(context_); | 229 DCHECK(context_); |
| 219 if (!eglMakeCurrent(g_display, | 230 if (!eglMakeCurrent(g_display, |
| 220 surface_, surface_, | 231 surface_->egl_surface(), |
| 232 surface_->egl_surface(), |
| 221 context_)) { | 233 context_)) { |
| 222 VLOG(1) << "eglMakeCurrent failed with error " | 234 VLOG(1) << "eglMakeCurrent failed with error " |
| 223 << GetLastEGLErrorString(); | 235 << GetLastEGLErrorString(); |
| 224 return false; | 236 return false; |
| 225 } | 237 } |
| 226 | 238 |
| 227 return true; | 239 return true; |
| 228 } | 240 } |
| 229 | 241 |
| 230 bool NativeViewEGLContext::IsCurrent() { | 242 bool NativeViewEGLContext::IsCurrent() { |
| 231 DCHECK(context_); | 243 DCHECK(context_); |
| 232 return context_ == eglGetCurrentContext(); | 244 return context_ == eglGetCurrentContext(); |
| 233 } | 245 } |
| 234 | 246 |
| 235 bool NativeViewEGLContext::IsOffscreen() { | 247 bool NativeViewEGLContext::IsOffscreen() { |
| 236 return false; | 248 return false; |
| 237 } | 249 } |
| 238 | 250 |
| 239 bool NativeViewEGLContext::SwapBuffers() { | 251 bool NativeViewEGLContext::SwapBuffers() { |
| 240 if (!eglSwapBuffers(g_display, surface_)) { | 252 if (!eglSwapBuffers(g_display, surface_->egl_surface())) { |
| 241 VLOG(1) << "eglSwapBuffers failed with error " | 253 VLOG(1) << "eglSwapBuffers failed with error " |
| 242 << GetLastEGLErrorString(); | 254 << GetLastEGLErrorString(); |
| 243 return false; | 255 return false; |
| 244 } | 256 } |
| 245 | 257 |
| 246 return true; | 258 return true; |
| 247 } | 259 } |
| 248 | 260 |
| 249 gfx::Size NativeViewEGLContext::GetSize() { | 261 gfx::Size NativeViewEGLContext::GetSize() { |
| 250 #if defined(OS_WIN) | 262 #if defined(OS_WIN) |
| 251 RECT rect; | 263 RECT rect; |
| 252 if (!GetClientRect(static_cast<HWND>(window_), &rect)) { | 264 if (!GetClientRect(static_cast<HWND>(window_), &rect)) { |
| 253 DCHECK(false) << "GetClientRect failed."; | 265 DCHECK(false) << "GetClientRect failed."; |
| 254 return gfx::Size(); | 266 return gfx::Size(); |
| 255 } | 267 } |
| 256 | 268 |
| 257 return gfx::Size(rect.right - rect.left, rect.bottom - rect.top); | 269 return gfx::Size(rect.right - rect.left, rect.bottom - rect.top); |
| 258 #else | 270 #else |
| 259 // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't | 271 // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't |
| 260 // get updated on resize. When it does, we can share the code. | 272 // get updated on resize. When it does, we can share the code. |
| 261 EGLint width; | 273 EGLint width; |
| 262 EGLint height; | 274 EGLint height; |
| 263 if (!eglQuerySurface(g_display, surface_, EGL_WIDTH, &width) || | 275 if (!eglQuerySurface( |
| 264 !eglQuerySurface(g_display, surface_, EGL_HEIGHT, &height)) { | 276 g_display, surface_->egl_surface(), EGL_WIDTH, &width) || |
| 277 !eglQuerySurface( |
| 278 g_display, surface_->egl_surface(), EGL_HEIGHT, &height)) { |
| 265 NOTREACHED() << "eglQuerySurface failed with error " | 279 NOTREACHED() << "eglQuerySurface failed with error " |
| 266 << GetLastEGLErrorString(); | 280 << GetLastEGLErrorString(); |
| 267 return gfx::Size(); | 281 return gfx::Size(); |
| 268 } | 282 } |
| 269 | 283 |
| 270 return gfx::Size(width, height); | 284 return gfx::Size(width, height); |
| 271 #endif | 285 #endif |
| 272 } | 286 } |
| 273 | 287 |
| 274 void* NativeViewEGLContext::GetHandle() { | 288 void* NativeViewEGLContext::GetHandle() { |
| 275 return context_; | 289 return context_; |
| 276 } | 290 } |
| 277 | 291 |
| 278 void NativeViewEGLContext::SetSwapInterval(int interval) { | 292 void NativeViewEGLContext::SetSwapInterval(int interval) { |
| 279 DCHECK(IsCurrent()); | 293 DCHECK(IsCurrent()); |
| 280 if (!eglSwapInterval(g_display, interval)) { | 294 if (!eglSwapInterval(g_display, interval)) { |
| 281 LOG(ERROR) << "eglSwapInterval failed with error " | 295 LOG(ERROR) << "eglSwapInterval failed with error " |
| 282 << GetLastEGLErrorString(); | 296 << GetLastEGLErrorString(); |
| 283 } | 297 } |
| 284 } | 298 } |
| 285 | 299 |
| 286 EGLSurface NativeViewEGLContext::GetSurface() { | 300 SharedEGLSurface* NativeViewEGLContext::GetSurface() { |
| 287 return surface_; | 301 return surface_; |
| 288 } | 302 } |
| 289 | 303 |
| 290 SecondaryEGLContext::SecondaryEGLContext() | 304 SecondaryEGLContext::SecondaryEGLContext() |
| 291 : surface_(NULL), | 305 : context_(NULL) |
| 292 own_surface_(false), | |
| 293 context_(NULL) | |
| 294 { | 306 { |
| 295 } | 307 } |
| 296 | 308 |
| 297 SecondaryEGLContext::~SecondaryEGLContext() { | 309 SecondaryEGLContext::~SecondaryEGLContext() { |
| 298 } | 310 } |
| 299 | 311 |
| 300 bool SecondaryEGLContext::Initialize(GLContext* shared_context) { | 312 bool SecondaryEGLContext::Initialize(GLContext* shared_context) { |
| 301 DCHECK(!context_); | 313 DCHECK(!context_); |
| 302 | 314 |
| 303 static const EGLint kContextAttributes[] = { | 315 static const EGLint kContextAttributes[] = { |
| 304 EGL_CONTEXT_CLIENT_VERSION, 2, | 316 EGL_CONTEXT_CLIENT_VERSION, 2, |
| 305 EGL_NONE | 317 EGL_NONE |
| 306 }; | 318 }; |
| 307 | 319 |
| 308 if (shared_context) { | 320 if (shared_context) { |
| 309 surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface(); | 321 surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface(); |
| 310 own_surface_ = false; | |
| 311 | 322 |
| 312 // Create a context. | 323 // Create a context. |
| 313 context_ = eglCreateContext(g_display, | 324 context_ = eglCreateContext(g_display, |
| 314 g_config, | 325 g_config, |
| 315 shared_context->GetHandle(), | 326 shared_context->GetHandle(), |
| 316 kContextAttributes); | 327 kContextAttributes); |
| 317 } else { | 328 } else { |
| 318 #ifdef EGL_HAS_PBUFFERS | 329 #ifdef EGL_HAS_PBUFFERS |
| 319 static const EGLint kPbufferAttribs[] = { | 330 static const EGLint kPbufferAttribs[] = { |
| 320 EGL_WIDTH, 1, | 331 EGL_WIDTH, 1, |
| 321 EGL_HEIGHT, 1, | 332 EGL_HEIGHT, 1, |
| 322 EGL_NONE | 333 EGL_NONE |
| 323 }; | 334 }; |
| 324 | 335 |
| 325 surface_ = eglCreatePbufferSurface(g_display, g_config, kPbufferAttribs); | 336 surface_ = new SharedEGLSurface(eglCreatePbufferSurface(g_display, |
| 326 if (!surface_) { | 337 g_config, |
| 338 kPbufferAttribs)); |
| 339 if (!surface_->egl_surface()) { |
| 327 LOG(ERROR) << "eglCreatePbufferSurface failed with error " | 340 LOG(ERROR) << "eglCreatePbufferSurface failed with error " |
| 328 << GetLastEGLErrorString(); | 341 << GetLastEGLErrorString(); |
| 342 Destroy(); |
| 329 return false; | 343 return false; |
| 330 } | 344 } |
| 331 own_surface_ = true; | |
| 332 | 345 |
| 333 context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes); | 346 context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes); |
| 334 #else | 347 #else |
| 335 NOTIMPLEMENTED() << "Offscreen non-shared GLES context"; | 348 NOTIMPLEMENTED() << "Offscreen non-shared GLES context"; |
| 336 return false; | 349 return false; |
| 337 #endif | 350 #endif |
| 338 } | 351 } |
| 339 | 352 |
| 340 if (!context_) { | 353 if (!context_) { |
| 341 LOG(ERROR) << "eglCreateContext failed with error " | 354 LOG(ERROR) << "eglCreateContext failed with error " |
| 342 << GetLastEGLErrorString(); | 355 << GetLastEGLErrorString(); |
| 343 Destroy(); | 356 Destroy(); |
| 344 return false; | 357 return false; |
| 345 } | 358 } |
| 346 | 359 |
| 347 return true; | 360 return true; |
| 348 } | 361 } |
| 349 | 362 |
| 350 void SecondaryEGLContext::Destroy() { | 363 void SecondaryEGLContext::Destroy() { |
| 351 if (own_surface_) { | |
| 352 if (!eglDestroySurface(g_display, surface_)) { | |
| 353 LOG(ERROR) << "eglDestroySurface failed with error " | |
| 354 << GetLastEGLErrorString(); | |
| 355 } | |
| 356 | |
| 357 own_surface_ = false; | |
| 358 } | |
| 359 surface_ = NULL; | |
| 360 | |
| 361 if (context_) { | 364 if (context_) { |
| 362 if (!eglDestroyContext(g_display, context_)) { | 365 if (!eglDestroyContext(g_display, context_)) { |
| 363 LOG(ERROR) << "eglDestroyContext failed with error " | 366 LOG(ERROR) << "eglDestroyContext failed with error " |
| 364 << GetLastEGLErrorString(); | 367 << GetLastEGLErrorString(); |
| 365 } | 368 } |
| 366 | 369 |
| 367 context_ = NULL; | 370 context_ = NULL; |
| 368 } | 371 } |
| 372 |
| 373 surface_ = NULL; |
| 369 } | 374 } |
| 370 | 375 |
| 371 bool SecondaryEGLContext::MakeCurrent() { | 376 bool SecondaryEGLContext::MakeCurrent() { |
| 372 DCHECK(context_); | 377 DCHECK(context_); |
| 373 if (!eglMakeCurrent(g_display, | 378 if (!eglMakeCurrent(g_display, |
| 374 surface_, surface_, | 379 surface_->egl_surface(), |
| 380 surface_->egl_surface(), |
| 375 context_)) { | 381 context_)) { |
| 376 VLOG(1) << "eglMakeCurrent failed with error " | 382 VLOG(1) << "eglMakeCurrent failed with error " |
| 377 << GetLastEGLErrorString(); | 383 << GetLastEGLErrorString(); |
| 378 return false; | 384 return false; |
| 379 } | 385 } |
| 380 | 386 |
| 381 return true; | 387 return true; |
| 382 } | 388 } |
| 383 | 389 |
| 384 bool SecondaryEGLContext::IsCurrent() { | 390 bool SecondaryEGLContext::IsCurrent() { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 402 | 408 |
| 403 void* SecondaryEGLContext::GetHandle() { | 409 void* SecondaryEGLContext::GetHandle() { |
| 404 return context_; | 410 return context_; |
| 405 } | 411 } |
| 406 | 412 |
| 407 void SecondaryEGLContext::SetSwapInterval(int interval) { | 413 void SecondaryEGLContext::SetSwapInterval(int interval) { |
| 408 DCHECK(IsCurrent()); | 414 DCHECK(IsCurrent()); |
| 409 NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext."; | 415 NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext."; |
| 410 } | 416 } |
| 411 | 417 |
| 412 EGLSurface SecondaryEGLContext::GetSurface() { | 418 SharedEGLSurface* SecondaryEGLContext::GetSurface() { |
| 413 return surface_; | 419 return surface_; |
| 414 } | 420 } |
| 415 | 421 |
| 416 } // namespace gfx | 422 } // namespace gfx |
| OLD | NEW |