15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_egl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 11a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "third_party/khronos/EGL/egl.h" 12a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "third_party/khronos/EGL/eglext.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/egl_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/gl_surface_egl.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_X11) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ui::GetLastEGLErrorString; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextEGL::GLContextEGL(GLShareGroup* share_group) 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : GLContextReal(share_group), 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_(NULL), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_(NULL), 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) config_(NULL), 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unbind_fbo_on_makecurrent_(false) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextEGL::Initialize( 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLSurface* compatible_surface, GpuPreference gpu_preference) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(compatible_surface); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!context_); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const EGLint kContextAttributes[] = { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_CONTEXT_CLIENT_VERSION, 2, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_NONE 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const EGLint kContextRobustnessAttributes[] = { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_CONTEXT_CLIENT_VERSION, 2, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_LOSE_CONTEXT_ON_RESET_EXT, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_NONE 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_ = compatible_surface->GetDisplay(); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_ = compatible_surface->GetConfig(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EGLint* context_attributes = NULL; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GLSurfaceEGL::IsCreateContextRobustnessSupported()) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "EGL_EXT_create_context_robustness supported."; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_attributes = kContextRobustnessAttributes; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // At some point we should require the presence of the robustness 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension and remove this code path. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "EGL_EXT_create_context_robustness NOT supported."; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_attributes = kContextAttributes; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_ = eglCreateContext( 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) share_group() ? share_group()->GetHandle() : NULL, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_attributes); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context_) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "eglCreateContext failed with error " 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << GetLastEGLErrorString(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextEGL::Destroy() { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (context_) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!eglDestroyContext(display_, context_)) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "eglDestroyContext failed with error " 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << GetLastEGLErrorString(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_ = NULL; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextEGL::MakeCurrent(GLSurface* surface) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(context_); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCurrent(surface)) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ScopedReleaseCurrent release_current; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT2("gpu", "GLContextEGL::MakeCurrent", 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "context", context_, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "surface", surface); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (unbind_fbo_on_makecurrent_ && 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) eglGetCurrentContext() != EGL_NO_CONTEXT) { 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) glBindFramebufferEXT(GL_FRAMEBUFFER, 0); 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!eglMakeCurrent(display_, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) surface->GetHandle(), 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) surface->GetHandle(), 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_)) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "eglMakeCurrent failed with error " 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << GetLastEGLErrorString(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Set this as soon as the context is current, since we might call into GL. 1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SetRealGLApi(); 1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetCurrent(surface); 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!InitializeDynamicBindings()) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!surface->OnMakeCurrent(this)) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not make current."; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 128e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch release_current.Cancel(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GLContextEGL::SetUnbindFboOnMakeCurrent() { 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unbind_fbo_on_makecurrent_ = true; 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextEGL::ReleaseCurrent(GLSurface* surface) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsCurrent(surface)) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (unbind_fbo_on_makecurrent_) 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) glBindFramebufferEXT(GL_FRAMEBUFFER, 0); 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SetCurrent(NULL); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) eglMakeCurrent(display_, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_NO_SURFACE, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_NO_SURFACE, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_NO_CONTEXT); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextEGL::IsCurrent(GLSurface* surface) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(context_); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool native_context_is_current = context_ == eglGetCurrentContext(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If our context is current then our notion of which GLContext is 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current must be correct. On the other hand, third-party code 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using OpenGL might change the current context. 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!native_context_is_current || (GetRealCurrent() == this)); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!native_context_is_current) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (surface) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (surface->GetHandle() != eglGetCurrentSurface(EGL_DRAW)) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLContextEGL::GetHandle() { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextEGL::SetSwapInterval(int interval) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsCurrent(NULL)); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!eglSwapInterval(display_, interval)) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "eglSwapInterval failed with error " 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << GetLastEGLErrorString(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GLContextEGL::GetExtensions() { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* extensions = eglQueryString(display_, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EGL_EXTENSIONS); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extensions) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GLContext::GetExtensions(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GLContext::GetExtensions() + " " + extensions; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextEGL::WasAllocatedUsingRobustnessExtension() { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GLSurfaceEGL::IsCreateContextRobustnessSupported(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextEGL::~GLContextEGL() { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Destroy(); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GLContextEGL::GetTotalGpuMemory(size_t* bytes) { 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(bytes); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *bytes = 0; 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gfx 209