Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / gl / gl_surface_wgl.cc
blob6495686f872cc5d576fbbb0460f9ea761b8dbdb5
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 void GLSurfaceWGL::InitializeOneOffForTesting() {
176 if (g_display == NULL) {
177 g_display = new DisplayWGL;
181 HDC GLSurfaceWGL::GetDisplayDC() {
182 return g_display->device_context();
185 NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window)
186 : window_(window), child_window_(NULL), device_context_(NULL) {
187 DCHECK(window);
190 NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
191 Destroy();
194 bool NativeViewGLSurfaceWGL::Initialize() {
195 DCHECK(!device_context_);
197 RECT rect;
198 if (!GetClientRect(window_, &rect)) {
199 LOG(ERROR) << "GetClientRect failed.\n";
200 Destroy();
201 return false;
204 // Create a child window. WGL has problems using a window handle owned by
205 // another process.
206 child_window_ =
207 CreateWindowEx(WS_EX_NOPARENTNOTIFY,
208 reinterpret_cast<wchar_t*>(g_display->window_class()),
209 L"",
210 WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
213 rect.right - rect.left,
214 rect.bottom - rect.top,
215 window_,
216 NULL,
217 NULL,
218 NULL);
219 if (!child_window_) {
220 LOG(ERROR) << "CreateWindow failed.\n";
221 Destroy();
222 return false;
225 // The GL context will render to this window.
226 device_context_ = GetDC(child_window_);
227 if (!device_context_) {
228 LOG(ERROR) << "Unable to get device context for window.";
229 Destroy();
230 return false;
233 if (!SetPixelFormat(device_context_,
234 g_display->pixel_format(),
235 &kPixelFormatDescriptor)) {
236 LOG(ERROR) << "Unable to set the pixel format for GL context.";
237 Destroy();
238 return false;
241 return true;
244 void NativeViewGLSurfaceWGL::Destroy() {
245 if (child_window_ && device_context_)
246 ReleaseDC(child_window_, device_context_);
248 if (child_window_)
249 DestroyWindow(child_window_);
251 child_window_ = NULL;
252 device_context_ = NULL;
255 bool NativeViewGLSurfaceWGL::IsOffscreen() {
256 return false;
259 gfx::SwapResult NativeViewGLSurfaceWGL::SwapBuffers() {
260 TRACE_EVENT2("gpu", "NativeViewGLSurfaceWGL:RealSwapBuffers",
261 "width", GetSize().width(),
262 "height", GetSize().height());
264 // Resize the child window to match the parent before swapping. Do not repaint
265 // it as it moves.
266 RECT rect;
267 if (!GetClientRect(window_, &rect))
268 return gfx::SwapResult::SWAP_FAILED;
269 if (!MoveWindow(child_window_,
272 rect.right - rect.left,
273 rect.bottom - rect.top,
274 FALSE)) {
275 return gfx::SwapResult::SWAP_FAILED;
278 DCHECK(device_context_);
279 return ::SwapBuffers(device_context_) == TRUE ? gfx::SwapResult::SWAP_ACK
280 : gfx::SwapResult::SWAP_FAILED;
283 gfx::Size NativeViewGLSurfaceWGL::GetSize() {
284 RECT rect;
285 BOOL result = GetClientRect(child_window_, &rect);
286 DCHECK(result);
287 return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
290 void* NativeViewGLSurfaceWGL::GetHandle() {
291 return device_context_;
294 PbufferGLSurfaceWGL::PbufferGLSurfaceWGL(const gfx::Size& size)
295 : size_(size),
296 device_context_(NULL),
297 pbuffer_(NULL) {
298 // Some implementations of Pbuffer do not support having a 0 size. For such
299 // cases use a (1, 1) surface.
300 if (size_.GetArea() == 0)
301 size_.SetSize(1, 1);
304 PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
305 Destroy();
308 bool PbufferGLSurfaceWGL::Initialize() {
309 DCHECK(!device_context_);
311 if (!gfx::g_driver_wgl.fn.wglCreatePbufferARBFn) {
312 LOG(ERROR) << "wglCreatePbufferARB not available.";
313 Destroy();
314 return false;
317 const int kNoAttributes[] = { 0 };
318 pbuffer_ = wglCreatePbufferARB(g_display->device_context(),
319 g_display->pixel_format(),
320 size_.width(), size_.height(),
321 kNoAttributes);
323 if (!pbuffer_) {
324 LOG(ERROR) << "Unable to create pbuffer.";
325 Destroy();
326 return false;
329 device_context_ = wglGetPbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_));
330 if (!device_context_) {
331 LOG(ERROR) << "Unable to get pbuffer device context.";
332 Destroy();
333 return false;
336 return true;
339 void PbufferGLSurfaceWGL::Destroy() {
340 if (pbuffer_ && device_context_)
341 wglReleasePbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_), device_context_);
343 device_context_ = NULL;
345 if (pbuffer_) {
346 wglDestroyPbufferARB(static_cast<HPBUFFERARB>(pbuffer_));
347 pbuffer_ = NULL;
351 bool PbufferGLSurfaceWGL::IsOffscreen() {
352 return true;
355 gfx::SwapResult PbufferGLSurfaceWGL::SwapBuffers() {
356 NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
357 return gfx::SwapResult::SWAP_FAILED;
360 gfx::Size PbufferGLSurfaceWGL::GetSize() {
361 return size_;
364 void* PbufferGLSurfaceWGL::GetHandle() {
365 return device_context_;
368 } // namespace gfx