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"
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.
26 0, // No accumulation buffer.
27 0, 0, 0, 0, // Ignore accumulation bits.
29 0, // no stencil buffer.
31 PFD_MAIN_PLANE
, // Main drawing plane (not overlay).
33 0, 0, 0, // Layer masks ignored.
36 LRESULT CALLBACK
IntermediateWindowProc(HWND window
,
42 // Prevent windows from erasing the background.
45 // Do not paint anything.
47 if (BeginPaint(window
, &paint
))
48 EndPaint(window
, &paint
);
51 return DefWindowProc(window
, message
, w_param
, l_param
);
67 DestroyWindow(window_handle_
);
69 UnregisterClass(reinterpret_cast<wchar_t*>(window_class_
),
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
),
80 LOG(ERROR
) << "GetModuleHandleEx failed.";
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
);
97 LOG(ERROR
) << "RegisterClass failed.";
101 window_handle_
= CreateWindow(
102 reinterpret_cast<wchar_t*>(window_class_
),
111 if (!window_handle_
) {
112 LOG(ERROR
) << "CreateWindow failed.";
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.";
123 if (!SetPixelFormat(device_context_
,
125 &kPixelFormatDescriptor
)) {
126 LOG(ERROR
) << "Unable to set the pixel format for temporary GL context.";
133 ATOM
window_class() const { return window_class_
; }
134 HDC
device_context() const { return device_context_
; }
135 int pixel_format() const { return pixel_format_
; }
138 HINSTANCE module_handle_
;
144 DisplayWGL
* g_display
;
147 GLSurfaceWGL::GLSurfaceWGL() {
150 GLSurfaceWGL::~GLSurfaceWGL() {
153 void* GLSurfaceWGL::GetDisplay() {
154 return GetDisplayDC();
157 bool GLSurfaceWGL::InitializeOneOff() {
158 static bool initialized
= false;
162 DCHECK(g_display
== NULL
);
163 scoped_ptr
<DisplayWGL
> wgl_display(new DisplayWGL
);
164 if (!wgl_display
->Init())
167 // Create a temporary GL context to bind to extension entry points.
168 HGLRC gl_context
= wglCreateContext(wgl_display
->device_context());
170 LOG(ERROR
) << "Failed to create temporary context.";
173 if (!wglMakeCurrent(wgl_display
->device_context(), gl_context
)) {
174 LOG(ERROR
) << "Failed to make temporary GL context current.";
175 wglDeleteContext(gl_context
);
178 // Get bindings to extension functions that cannot be acquired without a
180 InitializeGLBindingsGL();
181 InitializeGLBindingsWGL();
183 wglMakeCurrent(NULL
, NULL
);
184 wglDeleteContext(gl_context
);
186 g_display
= wgl_display
.release();
191 HDC
GLSurfaceWGL::GetDisplayDC() {
192 return g_display
->device_context();
195 NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window
)
198 device_context_(NULL
) {
202 NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
206 bool NativeViewGLSurfaceWGL::Initialize() {
207 DCHECK(!device_context_
);
210 if (!GetClientRect(window_
, &rect
)) {
211 LOG(ERROR
) << "GetClientRect failed.\n";
216 // Create a child window. WGL has problems using a window handle owned by
218 child_window_
= CreateWindow(
219 reinterpret_cast<wchar_t*>(g_display
->window_class()),
221 WS_CHILDWINDOW
| WS_DISABLED
| WS_VISIBLE
,
223 rect
.right
- rect
.left
,
224 rect
.bottom
- rect
.top
,
229 if (!child_window_
) {
230 LOG(ERROR
) << "CreateWindow failed.\n";
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.";
243 if (!SetPixelFormat(device_context_
,
244 g_display
->pixel_format(),
245 &kPixelFormatDescriptor
)) {
246 LOG(ERROR
) << "Unable to set the pixel format for GL context.";
254 void NativeViewGLSurfaceWGL::Destroy() {
255 if (child_window_
&& device_context_
)
256 ReleaseDC(child_window_
, device_context_
);
259 DestroyWindow(child_window_
);
261 child_window_
= NULL
;
262 device_context_
= NULL
;
265 bool NativeViewGLSurfaceWGL::IsOffscreen() {
269 bool NativeViewGLSurfaceWGL::SwapBuffers() {
270 // Resize the child window to match the parent before swapping. Do not repaint
273 if (!GetClientRect(window_
, &rect
))
275 if (!MoveWindow(child_window_
,
277 rect
.right
- rect
.left
,
278 rect
.bottom
- rect
.top
,
283 DCHECK(device_context_
);
284 return ::SwapBuffers(device_context_
) == TRUE
;
287 gfx::Size
NativeViewGLSurfaceWGL::GetSize() {
289 BOOL result
= GetClientRect(child_window_
, &rect
);
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
)
300 device_context_(NULL
),
304 PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
308 bool PbufferGLSurfaceWGL::Initialize() {
309 DCHECK(!device_context_
);
311 if (!gfx::g_driver_wgl
.fn
.wglCreatePbufferARBFn
) {
312 LOG(ERROR
) << "wglCreatePbufferARB not available.";
317 const int kNoAttributes
[] = { 0 };
318 pbuffer_
= wglCreatePbufferARB(g_display
->device_context(),
319 g_display
->pixel_format(),
320 size_
.width(), size_
.height(),
324 LOG(ERROR
) << "Unable to create pbuffer.";
329 device_context_
= wglGetPbufferDCARB(static_cast<HPBUFFERARB
>(pbuffer_
));
330 if (!device_context_
) {
331 LOG(ERROR
) << "Unable to get pbuffer device context.";
339 void PbufferGLSurfaceWGL::Destroy() {
340 if (pbuffer_
&& device_context_
)
341 wglReleasePbufferDCARB(static_cast<HPBUFFERARB
>(pbuffer_
), device_context_
);
343 device_context_
= NULL
;
346 wglDestroyPbufferARB(static_cast<HPBUFFERARB
>(pbuffer_
));
351 bool PbufferGLSurfaceWGL::IsOffscreen() {
355 bool PbufferGLSurfaceWGL::SwapBuffers() {
356 NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
360 gfx::Size
PbufferGLSurfaceWGL::GetSize() {
364 void* PbufferGLSurfaceWGL::GetHandle() {
365 return device_context_
;