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)// This file implements the GLContextWGL and PbufferGLContext classes.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_wgl.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface_wgl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextWGL::GLContextWGL(GLShareGroup* share_group)
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : GLContextReal(share_group),
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_(NULL) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextWGL::~GLContextWGL() {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GLContextWGL::GetExtensions() {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* extensions = NULL;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_driver_wgl.fn.wglGetExtensionsStringARBFn)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions = wglGetExtensionsStringARB(GLSurfaceWGL::GetDisplayDC());
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (g_driver_wgl.fn.wglGetExtensionsStringEXTFn)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions = wglGetExtensionsStringEXT();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extensions)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GLContext::GetExtensions() + " " + extensions;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GLContext::GetExtensions();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextWGL::Initialize(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLSurface* compatible_surface, GpuPreference gpu_preference) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the handle of another initialized context in the share group _before_
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // setting context_. Otherwise this context will be considered initialized
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and could potentially be returned by GetHandle.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HGLRC share_handle = static_cast<HGLRC>(share_group()->GetHandle());
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_ = wglCreateContext(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<HDC>(compatible_surface->GetHandle()));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!context_) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create GL context.";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Destroy();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (share_handle) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!wglShareLists(share_handle, context_)) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Could not share GL contexts.";
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Destroy();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextWGL::Destroy() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wglDeleteContext(context_);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_ = NULL;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextWGL::MakeCurrent(GLSurface* surface) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(context_);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsCurrent(surface))
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ScopedReleaseCurrent release_current;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TRACE_EVENT0("gpu", "GLContextWGL::MakeCurrent");
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!wglMakeCurrent(static_cast<HDC>(surface->GetHandle()), context_)) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Unable to make gl context current.";
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Set this as soon as the context is current, since we might call into GL.
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SetRealGLApi();
877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetCurrent(surface);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!InitializeDynamicBindings()) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!surface->OnMakeCurrent(this)) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Could not make current.";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  release_current.Cancel();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextWGL::ReleaseCurrent(GLSurface* surface) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsCurrent(surface))
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetCurrent(NULL);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wglMakeCurrent(NULL, NULL);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextWGL::IsCurrent(GLSurface* surface) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool native_context_is_current =
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wglGetCurrentContext() == context_;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If our context is current then our notion of which GLContext is
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // current must be correct. On the other hand, third-party code
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using OpenGL might change the current context.
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!native_context_is_current || (GetRealCurrent() == this));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!native_context_is_current)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (surface) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (wglGetCurrentDC() != surface->GetHandle())
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLContextWGL::GetHandle() {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextWGL::SetSwapInterval(int interval) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsCurrent(NULL));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gfx::g_driver_wgl.ext.b_WGL_EXT_swap_control) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wglSwapIntervalEXT(interval);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) <<
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "Could not disable vsync: driver does not "
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "support WGL_EXT_swap_control";
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
146