summaryrefslogtreecommitdiffstats
path: root/ui/gl/gl_surface_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ui/gl/gl_surface_win.cc')
-rw-r--r--ui/gl/gl_surface_win.cc248
1 files changed, 248 insertions, 0 deletions
diff --git a/ui/gl/gl_surface_win.cc b/ui/gl/gl_surface_win.cc
new file mode 100644
index 0000000..ae55568
--- /dev/null
+++ b/ui/gl/gl_surface_win.cc
@@ -0,0 +1,248 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/gl_surface_osmesa.h"
+#include "ui/gl/gl_surface_stub.h"
+#include "ui/gl/gl_surface_wgl.h"
+
+namespace gfx {
+
+// This OSMesa GL surface can use GDI to swap the contents of the buffer to a
+// view.
+class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
+ public:
+ explicit NativeViewGLSurfaceOSMesa(gfx::AcceleratedWidget window);
+ virtual ~NativeViewGLSurfaceOSMesa();
+
+ // Implement subset of GLSurface.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+ virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
+
+ private:
+ gfx::AcceleratedWidget window_;
+ HDC device_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa);
+};
+
+// Helper routine that does one-off initialization like determining the
+// pixel format and initializing the GL bindings.
+bool GLSurface::InitializeOneOffInternal() {
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ if (!GLSurfaceWGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceWGL::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ case kGLImplementationEGLGLES2:
+ if (!GLSurfaceEGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ }
+ return true;
+}
+
+NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
+ gfx::AcceleratedWidget window)
+ : GLSurfaceOSMesa(OSMESA_RGBA, gfx::Size(1, 1)),
+ window_(window),
+ device_context_(NULL) {
+ DCHECK(window);
+}
+
+NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
+ Destroy();
+}
+
+bool NativeViewGLSurfaceOSMesa::Initialize() {
+ if (!GLSurfaceOSMesa::Initialize())
+ return false;
+
+ device_context_ = GetDC(window_);
+ return true;
+}
+
+void NativeViewGLSurfaceOSMesa::Destroy() {
+ if (window_ && device_context_)
+ ReleaseDC(window_, device_context_);
+
+ device_context_ = NULL;
+
+ GLSurfaceOSMesa::Destroy();
+}
+
+bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
+ return false;
+}
+
+bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
+ DCHECK(device_context_);
+
+ gfx::Size size = GetSize();
+
+ // Note: negating the height below causes GDI to treat the bitmap data as row
+ // 0 being at the top.
+ BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) };
+ info.bV4Width = size.width();
+ info.bV4Height = -size.height();
+ info.bV4Planes = 1;
+ info.bV4BitCount = 32;
+ info.bV4V4Compression = BI_BITFIELDS;
+ info.bV4RedMask = 0x000000FF;
+ info.bV4GreenMask = 0x0000FF00;
+ info.bV4BlueMask = 0x00FF0000;
+ info.bV4AlphaMask = 0xFF000000;
+
+ // Copy the back buffer to the window's device context. Do not check whether
+ // StretchDIBits succeeds or not. It will fail if the window has been
+ // destroyed but it is preferable to allow rendering to silently fail if the
+ // window is destroyed. This is because the primary application of this
+ // class of GLContext is for testing and we do not want every GL related ui /
+ // browser test to become flaky if there is a race condition between GL
+ // context destruction and window destruction.
+ StretchDIBits(device_context_,
+ 0, 0, size.width(), size.height(),
+ 0, 0, size.width(), size.height(),
+ GetHandle(),
+ reinterpret_cast<BITMAPINFO*>(&info),
+ DIB_RGB_COLORS,
+ SRCCOPY);
+
+ return true;
+}
+
+std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
+ std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
+ extensions += extensions.empty() ? "" : " ";
+ extensions += "GL_CHROMIUM_post_sub_buffer";
+ return extensions;
+}
+
+bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
+ int x, int y, int width, int height) {
+ DCHECK(device_context_);
+
+ gfx::Size size = GetSize();
+
+ // Note: negating the height below causes GDI to treat the bitmap data as row
+ // 0 being at the top.
+ BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) };
+ info.bV4Width = size.width();
+ info.bV4Height = -size.height();
+ info.bV4Planes = 1;
+ info.bV4BitCount = 32;
+ info.bV4V4Compression = BI_BITFIELDS;
+ info.bV4RedMask = 0x000000FF;
+ info.bV4GreenMask = 0x0000FF00;
+ info.bV4BlueMask = 0x00FF0000;
+ info.bV4AlphaMask = 0xFF000000;
+
+ // Copy the back buffer to the window's device context. Do not check whether
+ // StretchDIBits succeeds or not. It will fail if the window has been
+ // destroyed but it is preferable to allow rendering to silently fail if the
+ // window is destroyed. This is because the primary application of this
+ // class of GLContext is for testing and we do not want every GL related ui /
+ // browser test to become flaky if there is a race condition between GL
+ // context destruction and window destruction.
+ StretchDIBits(device_context_,
+ x, size.height() - y - height, width, height,
+ x, y, width, height,
+ GetHandle(),
+ reinterpret_cast<BITMAPINFO*>(&info),
+ DIB_RGB_COLORS,
+ SRCCOPY);
+
+ return true;
+}
+
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+ bool software,
+ gfx::AcceleratedWidget window) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLSurface> surface(
+ new NativeViewGLSurfaceOSMesa(window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(software,
+ window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationDesktopGL: {
+ if (software)
+ return NULL;
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceWGL(
+ window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationMockGL:
+ return new GLSurfaceStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+ bool software,
+ const gfx::Size& size) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
+ size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(software, size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationDesktopGL: {
+ if (software)
+ return NULL;
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceWGL(size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationMockGL:
+ return new GLSurfaceStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+} // namespace gfx