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"
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_
= CreateWindowEx(WS_EX_NOPARENTNOTIFY
,
103 reinterpret_cast<wchar_t*>(window_class_
),
114 if (!window_handle_
) {
115 LOG(ERROR
) << "CreateWindow failed.";
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.";
126 if (!SetPixelFormat(device_context_
,
128 &kPixelFormatDescriptor
)) {
129 LOG(ERROR
) << "Unable to set the pixel format for temporary GL context.";
136 ATOM
window_class() const { return window_class_
; }
137 HDC
device_context() const { return device_context_
; }
138 int pixel_format() const { return pixel_format_
; }
141 HINSTANCE module_handle_
;
147 DisplayWGL
* g_display
;
150 GLSurfaceWGL::GLSurfaceWGL() {
153 GLSurfaceWGL::~GLSurfaceWGL() {
156 void* GLSurfaceWGL::GetDisplay() {
157 return GetDisplayDC();
160 bool GLSurfaceWGL::InitializeOneOff() {
161 static bool initialized
= false;
165 DCHECK(g_display
== NULL
);
166 scoped_ptr
<DisplayWGL
> wgl_display(new DisplayWGL
);
167 if (!wgl_display
->Init())
170 g_display
= wgl_display
.release();
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
) {
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
201 CreateWindowEx(WS_EX_NOPARENTNOTIFY
,
202 reinterpret_cast<wchar_t*>(g_display
->window_class()),
204 WS_CHILDWINDOW
| WS_DISABLED
| WS_VISIBLE
,
207 rect
.right
- rect
.left
,
208 rect
.bottom
- rect
.top
,
213 if (!child_window_
) {
214 LOG(ERROR
) << "CreateWindow failed.\n";
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.";
227 if (!SetPixelFormat(device_context_
,
228 g_display
->pixel_format(),
229 &kPixelFormatDescriptor
)) {
230 LOG(ERROR
) << "Unable to set the pixel format for GL context.";
238 void NativeViewGLSurfaceWGL::Destroy() {
239 if (child_window_
&& device_context_
)
240 ReleaseDC(child_window_
, device_context_
);
243 DestroyWindow(child_window_
);
245 child_window_
= NULL
;
246 device_context_
= NULL
;
249 bool NativeViewGLSurfaceWGL::IsOffscreen() {
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
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
,
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() {
279 BOOL result
= GetClientRect(child_window_
, &rect
);
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
)
290 device_context_(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)
298 PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
302 bool PbufferGLSurfaceWGL::Initialize() {
303 DCHECK(!device_context_
);
305 if (!gfx::g_driver_wgl
.fn
.wglCreatePbufferARBFn
) {
306 LOG(ERROR
) << "wglCreatePbufferARB not available.";
311 const int kNoAttributes
[] = { 0 };
312 pbuffer_
= wglCreatePbufferARB(g_display
->device_context(),
313 g_display
->pixel_format(),
314 size_
.width(), size_
.height(),
318 LOG(ERROR
) << "Unable to create pbuffer.";
323 device_context_
= wglGetPbufferDCARB(static_cast<HPBUFFERARB
>(pbuffer_
));
324 if (!device_context_
) {
325 LOG(ERROR
) << "Unable to get pbuffer device context.";
333 void PbufferGLSurfaceWGL::Destroy() {
334 if (pbuffer_
&& device_context_
)
335 wglReleasePbufferDCARB(static_cast<HPBUFFERARB
>(pbuffer_
), device_context_
);
337 device_context_
= NULL
;
340 wglDestroyPbufferARB(static_cast<HPBUFFERARB
>(pbuffer_
));
345 bool PbufferGLSurfaceWGL::IsOffscreen() {
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() {
358 void* PbufferGLSurfaceWGL::GetHandle() {
359 return device_context_
;