Add a stub __cxa_demangle to disable LLVM's demangler.
[chromium-blink-merge.git] / ui / gl / gl_surface_wgl.cc
blob82e34ecf7f55fd0dbfbcfd216495140ad7523d71
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.
5 #include "ui/gl/gl_surface_wgl.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/trace_event/trace_event.h"
10 #include "ui/gl/gl_bindings.h"
11 #include "ui/gl/gl_gl_api_implementation.h"
12 #include "ui/gl/gl_wgl_api_implementation.h"
14 namespace gfx {
16 namespace {
17 const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
18 sizeof(kPixelFormatDescriptor), // Size of structure.
19 1, // Default version.
20 PFD_DRAW_TO_WINDOW | // Window drawing support.
21 PFD_SUPPORT_OPENGL | // OpenGL support.
22 PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
23 PFD_TYPE_RGBA, // RGBA color mode (not indexed).
24 24, // 24 bit color mode.
25 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
26 8, 0, // 8 bit alpha
27 0, // No accumulation buffer.
28 0, 0, 0, 0, // Ignore accumulation bits.
29 0, // no z-buffer.
30 0, // no stencil buffer.
31 0, // No aux buffer.
32 PFD_MAIN_PLANE, // Main drawing plane (not overlay).
33 0, // Reserved.
34 0, 0, 0, // Layer masks ignored.
37 LRESULT CALLBACK IntermediateWindowProc(HWND window,
38 UINT message,
39 WPARAM w_param,
40 LPARAM l_param) {
41 switch (message) {
42 case WM_ERASEBKGND:
43 // Prevent windows from erasing the background.
44 return 1;
45 case WM_PAINT:
46 // Do not paint anything.
47 PAINTSTRUCT paint;
48 if (BeginPaint(window, &paint))
49 EndPaint(window, &paint);
50 return 0;
51 default:
52 return DefWindowProc(window, message, w_param, l_param);
56 class DisplayWGL {
57 public:
58 DisplayWGL()
59 : module_handle_(0),
60 window_class_(0),
61 window_handle_(0),
62 device_context_(0),
63 pixel_format_(0) {
66 ~DisplayWGL() {
67 if (window_handle_)
68 DestroyWindow(window_handle_);
69 if (window_class_)
70 UnregisterClass(reinterpret_cast<wchar_t*>(window_class_),
71 module_handle_);
74 bool Init() {
75 // We must initialize a GL context before we can bind to extension entry
76 // points. This requires the device context for a window.
77 if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
78 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
79 reinterpret_cast<wchar_t*>(IntermediateWindowProc),
80 &module_handle_)) {
81 LOG(ERROR) << "GetModuleHandleEx failed.";
82 return false;
85 WNDCLASS intermediate_class;
86 intermediate_class.style = CS_OWNDC;
87 intermediate_class.lpfnWndProc = IntermediateWindowProc;
88 intermediate_class.cbClsExtra = 0;
89 intermediate_class.cbWndExtra = 0;
90 intermediate_class.hInstance = module_handle_;
91 intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
92 intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
93 intermediate_class.hbrBackground = NULL;
94 intermediate_class.lpszMenuName = NULL;
95 intermediate_class.lpszClassName = L"Intermediate GL Window";
96 window_class_ = RegisterClass(&intermediate_class);
97 if (!window_class_) {
98 LOG(ERROR) << "RegisterClass failed.";
99 return false;
102 window_handle_ = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
103 reinterpret_cast<wchar_t*>(window_class_),
104 L"",
105 WS_OVERLAPPEDWINDOW,
108 100,
109 100,
110 NULL,
111 NULL,
112 NULL,
113 NULL);
114 if (!window_handle_) {
115 LOG(ERROR) << "CreateWindow failed.";
116 return false;
119 device_context_ = GetDC(window_handle_);
120 pixel_format_ = ChoosePixelFormat(device_context_,
121 &kPixelFormatDescriptor);
122 if (pixel_format_ == 0) {
123 LOG(ERROR) << "Unable to get the pixel format for GL context.";
124 return false;
126 if (!SetPixelFormat(device_context_,
127 pixel_format_,
128 &kPixelFormatDescriptor)) {
129 LOG(ERROR) << "Unable to set the pixel format for temporary GL context.";
130 return false;
133 return true;
136 ATOM window_class() const { return window_class_; }
137 HDC device_context() const { return device_context_; }
138 int pixel_format() const { return pixel_format_; }
140 private:
141 HINSTANCE module_handle_;
142 ATOM window_class_;
143 HWND window_handle_;
144 HDC device_context_;
145 int pixel_format_;
147 DisplayWGL* g_display;
148 } // namespace
150 GLSurfaceWGL::GLSurfaceWGL() {
153 GLSurfaceWGL::~GLSurfaceWGL() {
156 void* GLSurfaceWGL::GetDisplay() {
157 return GetDisplayDC();
160 bool GLSurfaceWGL::InitializeOneOff() {
161 static bool initialized = false;
162 if (initialized)
163 return true;
165 DCHECK(g_display == NULL);
166 scoped_ptr<DisplayWGL> wgl_display(new DisplayWGL);
167 if (!wgl_display->Init())
168 return false;
170 g_display = wgl_display.release();
171 initialized = true;
172 return true;
175 HDC GLSurfaceWGL::GetDisplayDC() {
176 return g_display->device_context();
179 NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window)
180 : window_(window), child_window_(NULL), device_context_(NULL) {
181 DCHECK(window);
184 NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
185 Destroy();
188 bool NativeViewGLSurfaceWGL::Initialize() {
189 DCHECK(!device_context_);
191 RECT rect;
192 if (!GetClientRect(window_, &rect)) {
193 LOG(ERROR) << "GetClientRect failed.\n";
194 Destroy();
195 return false;
198 // Create a child window. WGL has problems using a window handle owned by
199 // another process.
200 child_window_ =
201 CreateWindowEx(WS_EX_NOPARENTNOTIFY,
202 reinterpret_cast<wchar_t*>(g_display->window_class()),
203 L"",
204 WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
207 rect.right - rect.left,
208 rect.bottom - rect.top,
209 window_,
210 NULL,
211 NULL,
212 NULL);
213 if (!child_window_) {
214 LOG(ERROR) << "CreateWindow failed.\n";
215 Destroy();
216 return false;
219 // The GL context will render to this window.
220 device_context_ = GetDC(child_window_);
221 if (!device_context_) {
222 LOG(ERROR) << "Unable to get device context for window.";
223 Destroy();
224 return false;
227 if (!SetPixelFormat(device_context_,
228 g_display->pixel_format(),
229 &kPixelFormatDescriptor)) {
230 LOG(ERROR) << "Unable to set the pixel format for GL context.";
231 Destroy();
232 return false;
235 return true;
238 void NativeViewGLSurfaceWGL::Destroy() {
239 if (child_window_ && device_context_)
240 ReleaseDC(child_window_, device_context_);
242 if (child_window_)
243 DestroyWindow(child_window_);
245 child_window_ = NULL;
246 device_context_ = NULL;
249 bool NativeViewGLSurfaceWGL::IsOffscreen() {
250 return false;
253 gfx::SwapResult NativeViewGLSurfaceWGL::SwapBuffers() {
254 TRACE_EVENT2("gpu", "NativeViewGLSurfaceWGL:RealSwapBuffers",
255 "width", GetSize().width(),
256 "height", GetSize().height());
258 // Resize the child window to match the parent before swapping. Do not repaint
259 // it as it moves.
260 RECT rect;
261 if (!GetClientRect(window_, &rect))
262 return gfx::SwapResult::SWAP_FAILED;
263 if (!MoveWindow(child_window_,
266 rect.right - rect.left,
267 rect.bottom - rect.top,
268 FALSE)) {
269 return gfx::SwapResult::SWAP_FAILED;
272 DCHECK(device_context_);
273 return ::SwapBuffers(device_context_) == TRUE ? gfx::SwapResult::SWAP_ACK
274 : gfx::SwapResult::SWAP_FAILED;
277 gfx::Size NativeViewGLSurfaceWGL::GetSize() {
278 RECT rect;
279 BOOL result = GetClientRect(child_window_, &rect);
280 DCHECK(result);
281 return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
284 void* NativeViewGLSurfaceWGL::GetHandle() {
285 return device_context_;
288 PbufferGLSurfaceWGL::PbufferGLSurfaceWGL(const gfx::Size& size)
289 : size_(size),
290 device_context_(NULL),
291 pbuffer_(NULL) {
292 // Some implementations of Pbuffer do not support having a 0 size. For such
293 // cases use a (1, 1) surface.
294 if (size_.GetArea() == 0)
295 size_.SetSize(1, 1);
298 PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
299 Destroy();
302 bool PbufferGLSurfaceWGL::Initialize() {
303 DCHECK(!device_context_);
305 if (!gfx::g_driver_wgl.fn.wglCreatePbufferARBFn) {
306 LOG(ERROR) << "wglCreatePbufferARB not available.";
307 Destroy();
308 return false;
311 const int kNoAttributes[] = { 0 };
312 pbuffer_ = wglCreatePbufferARB(g_display->device_context(),
313 g_display->pixel_format(),
314 size_.width(), size_.height(),
315 kNoAttributes);
317 if (!pbuffer_) {
318 LOG(ERROR) << "Unable to create pbuffer.";
319 Destroy();
320 return false;
323 device_context_ = wglGetPbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_));
324 if (!device_context_) {
325 LOG(ERROR) << "Unable to get pbuffer device context.";
326 Destroy();
327 return false;
330 return true;
333 void PbufferGLSurfaceWGL::Destroy() {
334 if (pbuffer_ && device_context_)
335 wglReleasePbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_), device_context_);
337 device_context_ = NULL;
339 if (pbuffer_) {
340 wglDestroyPbufferARB(static_cast<HPBUFFERARB>(pbuffer_));
341 pbuffer_ = NULL;
345 bool PbufferGLSurfaceWGL::IsOffscreen() {
346 return true;
349 gfx::SwapResult PbufferGLSurfaceWGL::SwapBuffers() {
350 NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
351 return gfx::SwapResult::SWAP_FAILED;
354 gfx::Size PbufferGLSurfaceWGL::GetSize() {
355 return size_;
358 void* PbufferGLSurfaceWGL::GetHandle() {
359 return device_context_;
362 } // namespace gfx