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/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.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"
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.
27 0, // No accumulation buffer.
28 0, 0, 0, 0, // Ignore accumulation bits.
30 0, // no stencil buffer.
32 PFD_MAIN_PLANE
, // Main drawing plane (not overlay).
34 0, 0, 0, // Layer masks ignored.
37 LRESULT CALLBACK
IntermediateWindowProc(HWND window
,
43 // Prevent windows from erasing the background.
46 // Do not paint anything.
48 if (BeginPaint(window
, &paint
))
49 EndPaint(window
, &paint
);
52 return DefWindowProc(window
, message
, w_param
, l_param
);
68 DestroyWindow(window_handle_
);
70 UnregisterClass(reinterpret_cast<wchar_t*>(window_class_
),
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
),
81 LOG(ERROR
) << "GetModuleHandleEx failed.";
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
);
98 LOG(ERROR
) << "RegisterClass failed.";
102 window_handle_
= CreateWindow(
103 reinterpret_cast<wchar_t*>(window_class_
),
112 if (!window_handle_
) {
113 LOG(ERROR
) << "CreateWindow failed.";
117 device_context_
= GetDC(window_handle_
);
118 pixel_format_
= ChoosePixelFormat(device_context_
,
119 &kPixelFormatDescriptor
);
120 if (pixel_format_
== 0) {
121 LOG(ERROR
) << "Unable to get the pixel format for GL context.";
124 if (!SetPixelFormat(device_context_
,
126 &kPixelFormatDescriptor
)) {
127 LOG(ERROR
) << "Unable to set the pixel format for temporary GL context.";
134 ATOM
window_class() const { return window_class_
; }
135 HDC
device_context() const { return device_context_
; }
136 int pixel_format() const { return pixel_format_
; }
139 HINSTANCE module_handle_
;
145 DisplayWGL
* g_display
;
148 GLSurfaceWGL::GLSurfaceWGL() {
151 GLSurfaceWGL::~GLSurfaceWGL() {
154 void* GLSurfaceWGL::GetDisplay() {
155 return GetDisplayDC();
158 bool GLSurfaceWGL::InitializeOneOff() {
159 static bool initialized
= false;
163 DCHECK(g_display
== NULL
);
164 scoped_ptr
<DisplayWGL
> wgl_display(new DisplayWGL
);
165 if (!wgl_display
->Init())
168 g_display
= wgl_display
.release();
173 HDC
GLSurfaceWGL::GetDisplayDC() {
174 return g_display
->device_context();
177 NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window
)
180 device_context_(NULL
) {
184 NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
188 bool NativeViewGLSurfaceWGL::Initialize() {
189 DCHECK(!device_context_
);
192 if (!GetClientRect(window_
, &rect
)) {
193 LOG(ERROR
) << "GetClientRect failed.\n";
198 // Create a child window. WGL has problems using a window handle owned by
200 child_window_
= CreateWindow(
201 reinterpret_cast<wchar_t*>(g_display
->window_class()),
203 WS_CHILDWINDOW
| WS_DISABLED
| WS_VISIBLE
,
205 rect
.right
- rect
.left
,
206 rect
.bottom
- rect
.top
,
211 if (!child_window_
) {
212 LOG(ERROR
) << "CreateWindow failed.\n";
217 // The GL context will render to this window.
218 device_context_
= GetDC(child_window_
);
219 if (!device_context_
) {
220 LOG(ERROR
) << "Unable to get device context for window.";
225 if (!SetPixelFormat(device_context_
,
226 g_display
->pixel_format(),
227 &kPixelFormatDescriptor
)) {
228 LOG(ERROR
) << "Unable to set the pixel format for GL context.";
236 void NativeViewGLSurfaceWGL::Destroy() {
237 if (child_window_
&& device_context_
)
238 ReleaseDC(child_window_
, device_context_
);
241 DestroyWindow(child_window_
);
243 child_window_
= NULL
;
244 device_context_
= NULL
;
247 bool NativeViewGLSurfaceWGL::IsOffscreen() {
251 bool NativeViewGLSurfaceWGL::SwapBuffers() {
252 TRACE_EVENT2("gpu", "NativeViewGLSurfaceWGL:RealSwapBuffers",
253 "width", GetSize().width(),
254 "height", GetSize().height());
256 // Resize the child window to match the parent before swapping. Do not repaint
259 if (!GetClientRect(window_
, &rect
))
261 if (!MoveWindow(child_window_
,
263 rect
.right
- rect
.left
,
264 rect
.bottom
- rect
.top
,
269 DCHECK(device_context_
);
270 return ::SwapBuffers(device_context_
) == TRUE
;
273 gfx::Size
NativeViewGLSurfaceWGL::GetSize() {
275 BOOL result
= GetClientRect(child_window_
, &rect
);
277 return gfx::Size(rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
280 void* NativeViewGLSurfaceWGL::GetHandle() {
281 return device_context_
;
284 PbufferGLSurfaceWGL::PbufferGLSurfaceWGL(const gfx::Size
& size
)
286 device_context_(NULL
),
290 PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
294 bool PbufferGLSurfaceWGL::Initialize() {
295 DCHECK(!device_context_
);
297 if (!gfx::g_driver_wgl
.fn
.wglCreatePbufferARBFn
) {
298 LOG(ERROR
) << "wglCreatePbufferARB not available.";
303 const int kNoAttributes
[] = { 0 };
304 pbuffer_
= wglCreatePbufferARB(g_display
->device_context(),
305 g_display
->pixel_format(),
306 size_
.width(), size_
.height(),
310 LOG(ERROR
) << "Unable to create pbuffer.";
315 device_context_
= wglGetPbufferDCARB(static_cast<HPBUFFERARB
>(pbuffer_
));
316 if (!device_context_
) {
317 LOG(ERROR
) << "Unable to get pbuffer device context.";
325 void PbufferGLSurfaceWGL::Destroy() {
326 if (pbuffer_
&& device_context_
)
327 wglReleasePbufferDCARB(static_cast<HPBUFFERARB
>(pbuffer_
), device_context_
);
329 device_context_
= NULL
;
332 wglDestroyPbufferARB(static_cast<HPBUFFERARB
>(pbuffer_
));
337 bool PbufferGLSurfaceWGL::IsOffscreen() {
341 bool PbufferGLSurfaceWGL::SwapBuffers() {
342 NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
346 gfx::Size
PbufferGLSurfaceWGL::GetSize() {
350 void* PbufferGLSurfaceWGL::GetHandle() {
351 return device_context_
;