Home | History | Annotate | Download | only in gl
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This file implements the GLContextWGL and PbufferGLContext classes.
      6 
      7 #include "ui/gl/gl_context_wgl.h"
      8 
      9 #include "base/debug/trace_event.h"
     10 #include "base/logging.h"
     11 #include "ui/gl/gl_bindings.h"
     12 #include "ui/gl/gl_implementation.h"
     13 #include "ui/gl/gl_surface_wgl.h"
     14 
     15 namespace gfx {
     16 
     17 GLContextWGL::GLContextWGL(GLShareGroup* share_group)
     18     : GLContextReal(share_group),
     19       context_(NULL) {
     20 }
     21 
     22 GLContextWGL::~GLContextWGL() {
     23   Destroy();
     24 }
     25 
     26 std::string GLContextWGL::GetExtensions() {
     27   const char* extensions = NULL;
     28   if (g_driver_wgl.fn.wglGetExtensionsStringARBFn)
     29     extensions = wglGetExtensionsStringARB(GLSurfaceWGL::GetDisplayDC());
     30   else if (g_driver_wgl.fn.wglGetExtensionsStringEXTFn)
     31     extensions = wglGetExtensionsStringEXT();
     32 
     33   if (extensions)
     34     return GLContext::GetExtensions() + " " + extensions;
     35 
     36   return GLContext::GetExtensions();
     37 }
     38 
     39 bool GLContextWGL::Initialize(
     40     GLSurface* compatible_surface, GpuPreference gpu_preference) {
     41   // Get the handle of another initialized context in the share group _before_
     42   // setting context_. Otherwise this context will be considered initialized
     43   // and could potentially be returned by GetHandle.
     44   HGLRC share_handle = static_cast<HGLRC>(share_group()->GetHandle());
     45 
     46   context_ = wglCreateContext(
     47       static_cast<HDC>(compatible_surface->GetHandle()));
     48   if (!context_) {
     49     LOG(ERROR) << "Failed to create GL context.";
     50     Destroy();
     51     return false;
     52   }
     53 
     54   if (share_handle) {
     55     if (!wglShareLists(share_handle, context_)) {
     56       LOG(ERROR) << "Could not share GL contexts.";
     57       Destroy();
     58       return false;
     59     }
     60   }
     61 
     62   return true;
     63 }
     64 
     65 void GLContextWGL::Destroy() {
     66   if (context_) {
     67     wglDeleteContext(context_);
     68     context_ = NULL;
     69   }
     70 }
     71 
     72 bool GLContextWGL::MakeCurrent(GLSurface* surface) {
     73   DCHECK(context_);
     74   if (IsCurrent(surface))
     75     return true;
     76 
     77   ScopedReleaseCurrent release_current;
     78   TRACE_EVENT0("gpu", "GLContextWGL::MakeCurrent");
     79 
     80   if (!wglMakeCurrent(static_cast<HDC>(surface->GetHandle()), context_)) {
     81     LOG(ERROR) << "Unable to make gl context current.";
     82     return false;
     83   }
     84 
     85   // Set this as soon as the context is current, since we might call into GL.
     86   SetRealGLApi();
     87 
     88   SetCurrent(surface);
     89   if (!InitializeDynamicBindings()) {
     90     return false;
     91   }
     92 
     93   if (!surface->OnMakeCurrent(this)) {
     94     LOG(ERROR) << "Could not make current.";
     95     return false;
     96   }
     97 
     98   release_current.Cancel();
     99   return true;
    100 }
    101 
    102 void GLContextWGL::ReleaseCurrent(GLSurface* surface) {
    103   if (!IsCurrent(surface))
    104     return;
    105 
    106   SetCurrent(NULL);
    107   wglMakeCurrent(NULL, NULL);
    108 }
    109 
    110 bool GLContextWGL::IsCurrent(GLSurface* surface) {
    111   bool native_context_is_current =
    112       wglGetCurrentContext() == context_;
    113 
    114   // If our context is current then our notion of which GLContext is
    115   // current must be correct. On the other hand, third-party code
    116   // using OpenGL might change the current context.
    117   DCHECK(!native_context_is_current || (GetRealCurrent() == this));
    118 
    119   if (!native_context_is_current)
    120     return false;
    121 
    122   if (surface) {
    123     if (wglGetCurrentDC() != surface->GetHandle())
    124       return false;
    125   }
    126 
    127   return true;
    128 }
    129 
    130 void* GLContextWGL::GetHandle() {
    131   return context_;
    132 }
    133 
    134 void GLContextWGL::SetSwapInterval(int interval) {
    135   DCHECK(IsCurrent(NULL));
    136   if (gfx::g_driver_wgl.ext.b_WGL_EXT_swap_control) {
    137     wglSwapIntervalEXT(interval);
    138   } else {
    139       LOG(WARNING) <<
    140           "Could not disable vsync: driver does not "
    141           "support WGL_EXT_swap_control";
    142   }
    143 }
    144 
    145 }  // namespace gfx
    146