Revert 233039 "Blink roll 161254:161319"
[chromium-blink-merge.git] / ui / gl / gl_surface_wgl.cc
blob7e1c3a7ad1fe9f2ec1cf127ba6eeadfb1f80b0b3
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 "ui/gl/gl_bindings.h"
10 #include "ui/gl/gl_gl_api_implementation.h"
11 #include "ui/gl/gl_wgl_api_implementation.h"
13 namespace gfx {
15 namespace {
16 const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
17 sizeof(kPixelFormatDescriptor), // Size of structure.
18 1, // Default version.
19 PFD_DRAW_TO_WINDOW | // Window drawing support.
20 PFD_SUPPORT_OPENGL | // OpenGL support.
21 PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
22 PFD_TYPE_RGBA, // RGBA color mode (not indexed).
23 24, // 24 bit color mode.
24 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
25 8, 0, // 8 bit alpha
26 0, // No accumulation buffer.
27 0, 0, 0, 0, // Ignore accumulation bits.
28 0, // no z-buffer.
29 0, // no stencil buffer.
30 0, // No aux buffer.
31 PFD_MAIN_PLANE, // Main drawing plane (not overlay).
32 0, // Reserved.
33 0, 0, 0, // Layer masks ignored.
36 LRESULT CALLBACK IntermediateWindowProc(HWND window,
37 UINT message,
38 WPARAM w_param,
39 LPARAM l_param) {
40 switch (message) {
41 case WM_ERASEBKGND:
42 // Prevent windows from erasing the background.
43 return 1;
44 case WM_PAINT:
45 // Do not paint anything.
46 PAINTSTRUCT paint;
47 if (BeginPaint(window, &paint))
48 EndPaint(window, &paint);
49 return 0;
50 default:
51 return DefWindowProc(window, message, w_param, l_param);
55 class DisplayWGL {
56 public:
57 DisplayWGL()
58 : module_handle_(0),
59 window_class_(0),
60 window_handle_(0),
61 device_context_(0),
62 pixel_format_(0) {
65 ~DisplayWGL() {
66 if (window_handle_)
67 DestroyWindow(window_handle_);
68 if (window_class_)
69 UnregisterClass(reinterpret_cast<wchar_t*>(window_class_),
70 module_handle_);
73 bool Init() {
74 // We must initialize a GL context before we can bind to extension entry
75 // points. This requires the device context for a window.
76 if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
77 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
78 reinterpret_cast<wchar_t*>(IntermediateWindowProc),
79 &module_handle_)) {
80 LOG(ERROR) << "GetModuleHandleEx failed.";
81 return false;
84 WNDCLASS intermediate_class;
85 intermediate_class.style = CS_OWNDC;
86 intermediate_class.lpfnWndProc = IntermediateWindowProc;
87 intermediate_class.cbClsExtra = 0;
88 intermediate_class.cbWndExtra = 0;
89 intermediate_class.hInstance = module_handle_;
90 intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
91 intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
92 intermediate_class.hbrBackground = NULL;
93 intermediate_class.lpszMenuName = NULL;
94 intermediate_class.lpszClassName = L"Intermediate GL Window";
95 window_class_ = RegisterClass(&intermediate_class);
96 if (!window_class_) {
97 LOG(ERROR) << "RegisterClass failed.";
98 return false;
101 window_handle_ = CreateWindow(
102 reinterpret_cast<wchar_t*>(window_class_),
103 L"",
104 WS_OVERLAPPEDWINDOW,
105 0, 0,
106 100, 100,
107 NULL,
108 NULL,
109 NULL,
110 NULL);
111 if (!window_handle_) {
112 LOG(ERROR) << "CreateWindow failed.";
113 return false;
116 device_context_ = GetDC(window_handle_);
117 pixel_format_ = ChoosePixelFormat(device_context_,
118 &kPixelFormatDescriptor);
119 if (pixel_format_ == 0) {
120 LOG(ERROR) << "Unable to get the pixel format for GL context.";
121 return false;
123 if (!SetPixelFormat(device_context_,
124 pixel_format_,
125 &kPixelFormatDescriptor)) {
126 LOG(ERROR) << "Unable to set the pixel format for temporary GL context.";
127 return false;
130 return true;
133 ATOM window_class() const { return window_class_; }
134 HDC device_context() const { return device_context_; }
135 int pixel_format() const { return pixel_format_; }
137 private:
138 HINSTANCE module_handle_;
139 ATOM window_class_;
140 HWND window_handle_;
141 HDC device_context_;
142 int pixel_format_;
144 DisplayWGL* g_display;
145 } // namespace
147 GLSurfaceWGL::GLSurfaceWGL() {
150 GLSurfaceWGL::~GLSurfaceWGL() {
153 void* GLSurfaceWGL::GetDisplay() {
154 return GetDisplayDC();
157 bool GLSurfaceWGL::InitializeOneOff() {
158 static bool initialized = false;
159 if (initialized)
160 return true;
162 DCHECK(g_display == NULL);
163 scoped_ptr<DisplayWGL> wgl_display(new DisplayWGL);
164 if (!wgl_display->Init())
165 return false;
167 // Create a temporary GL context to bind to extension entry points.
168 HGLRC gl_context = wglCreateContext(wgl_display->device_context());
169 if (!gl_context) {
170 LOG(ERROR) << "Failed to create temporary context.";
171 return false;
173 if (!wglMakeCurrent(wgl_display->device_context(), gl_context)) {
174 LOG(ERROR) << "Failed to make temporary GL context current.";
175 wglDeleteContext(gl_context);
176 return false;
178 // Get bindings to extension functions that cannot be acquired without a
179 // current context.
180 InitializeGLBindingsGL();
181 InitializeGLBindingsWGL();
183 wglMakeCurrent(NULL, NULL);
184 wglDeleteContext(gl_context);
186 g_display = wgl_display.release();
187 initialized = true;
188 return true;
191 HDC GLSurfaceWGL::GetDisplayDC() {
192 return g_display->device_context();
195 NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window)
196 : window_(window),
197 child_window_(NULL),
198 device_context_(NULL) {
199 DCHECK(window);
202 NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
203 Destroy();
206 bool NativeViewGLSurfaceWGL::Initialize() {
207 DCHECK(!device_context_);
209 RECT rect;
210 if (!GetClientRect(window_, &rect)) {
211 LOG(ERROR) << "GetClientRect failed.\n";
212 Destroy();
213 return false;
216 // Create a child window. WGL has problems using a window handle owned by
217 // another process.
218 child_window_ = CreateWindow(
219 reinterpret_cast<wchar_t*>(g_display->window_class()),
220 L"",
221 WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
222 0, 0,
223 rect.right - rect.left,
224 rect.bottom - rect.top,
225 window_,
226 NULL,
227 NULL,
228 NULL);
229 if (!child_window_) {
230 LOG(ERROR) << "CreateWindow failed.\n";
231 Destroy();
232 return false;
235 // The GL context will render to this window.
236 device_context_ = GetDC(child_window_);
237 if (!device_context_) {
238 LOG(ERROR) << "Unable to get device context for window.";
239 Destroy();
240 return false;
243 if (!SetPixelFormat(device_context_,
244 g_display->pixel_format(),
245 &kPixelFormatDescriptor)) {
246 LOG(ERROR) << "Unable to set the pixel format for GL context.";
247 Destroy();
248 return false;
251 return true;
254 void NativeViewGLSurfaceWGL::Destroy() {
255 if (child_window_ && device_context_)
256 ReleaseDC(child_window_, device_context_);
258 if (child_window_)
259 DestroyWindow(child_window_);
261 child_window_ = NULL;
262 device_context_ = NULL;
265 bool NativeViewGLSurfaceWGL::IsOffscreen() {
266 return false;
269 bool NativeViewGLSurfaceWGL::SwapBuffers() {
270 // Resize the child window to match the parent before swapping. Do not repaint
271 // it as it moves.
272 RECT rect;
273 if (!GetClientRect(window_, &rect))
274 return false;
275 if (!MoveWindow(child_window_,
276 0, 0,
277 rect.right - rect.left,
278 rect.bottom - rect.top,
279 FALSE)) {
280 return false;
283 DCHECK(device_context_);
284 return ::SwapBuffers(device_context_) == TRUE;
287 gfx::Size NativeViewGLSurfaceWGL::GetSize() {
288 RECT rect;
289 BOOL result = GetClientRect(child_window_, &rect);
290 DCHECK(result);
291 return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
294 void* NativeViewGLSurfaceWGL::GetHandle() {
295 return device_context_;
298 PbufferGLSurfaceWGL::PbufferGLSurfaceWGL(const gfx::Size& size)
299 : size_(size),
300 device_context_(NULL),
301 pbuffer_(NULL) {
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 bool PbufferGLSurfaceWGL::SwapBuffers() {
356 NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
357 return false;
360 gfx::Size PbufferGLSurfaceWGL::GetSize() {
361 return size_;
364 void* PbufferGLSurfaceWGL::GetHandle() {
365 return device_context_;
368 } // namespace gfx