Obey renderer-supplied quota in the browser.
[chromium-blink-merge.git] / ui / gl / gl_surface_wgl.cc
blobe301bce6b037a0bdbd28dde06995d403481c09c9
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"
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_ = CreateWindow(
103 reinterpret_cast<wchar_t*>(window_class_),
104 L"",
105 WS_OVERLAPPEDWINDOW,
106 0, 0,
107 100, 100,
108 NULL,
109 NULL,
110 NULL,
111 NULL);
112 if (!window_handle_) {
113 LOG(ERROR) << "CreateWindow failed.";
114 return false;
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.";
122 return false;
124 if (!SetPixelFormat(device_context_,
125 pixel_format_,
126 &kPixelFormatDescriptor)) {
127 LOG(ERROR) << "Unable to set the pixel format for temporary GL context.";
128 return false;
131 return true;
134 ATOM window_class() const { return window_class_; }
135 HDC device_context() const { return device_context_; }
136 int pixel_format() const { return pixel_format_; }
138 private:
139 HINSTANCE module_handle_;
140 ATOM window_class_;
141 HWND window_handle_;
142 HDC device_context_;
143 int pixel_format_;
145 DisplayWGL* g_display;
146 } // namespace
148 GLSurfaceWGL::GLSurfaceWGL() {
151 GLSurfaceWGL::~GLSurfaceWGL() {
154 void* GLSurfaceWGL::GetDisplay() {
155 return GetDisplayDC();
158 bool GLSurfaceWGL::InitializeOneOff() {
159 static bool initialized = false;
160 if (initialized)
161 return true;
163 DCHECK(g_display == NULL);
164 scoped_ptr<DisplayWGL> wgl_display(new DisplayWGL);
165 if (!wgl_display->Init())
166 return false;
168 g_display = wgl_display.release();
169 initialized = true;
170 return true;
173 HDC GLSurfaceWGL::GetDisplayDC() {
174 return g_display->device_context();
177 NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window)
178 : window_(window),
179 child_window_(NULL),
180 device_context_(NULL) {
181 DCHECK(window);
184 NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
185 Destroy();
188 bool NativeViewGLSurfaceWGL::Initialize() {
189 DCHECK(!device_context_);
191 RECT rect;
192 if (!GetClientRect(window_, &rect)) {
193 LOG(ERROR) << "GetClientRect failed.\n";
194 Destroy();
195 return false;
198 // Create a child window. WGL has problems using a window handle owned by
199 // another process.
200 child_window_ = CreateWindow(
201 reinterpret_cast<wchar_t*>(g_display->window_class()),
202 L"",
203 WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
204 0, 0,
205 rect.right - rect.left,
206 rect.bottom - rect.top,
207 window_,
208 NULL,
209 NULL,
210 NULL);
211 if (!child_window_) {
212 LOG(ERROR) << "CreateWindow failed.\n";
213 Destroy();
214 return false;
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.";
221 Destroy();
222 return false;
225 if (!SetPixelFormat(device_context_,
226 g_display->pixel_format(),
227 &kPixelFormatDescriptor)) {
228 LOG(ERROR) << "Unable to set the pixel format for GL context.";
229 Destroy();
230 return false;
233 return true;
236 void NativeViewGLSurfaceWGL::Destroy() {
237 if (child_window_ && device_context_)
238 ReleaseDC(child_window_, device_context_);
240 if (child_window_)
241 DestroyWindow(child_window_);
243 child_window_ = NULL;
244 device_context_ = NULL;
247 bool NativeViewGLSurfaceWGL::IsOffscreen() {
248 return false;
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
257 // it as it moves.
258 RECT rect;
259 if (!GetClientRect(window_, &rect))
260 return false;
261 if (!MoveWindow(child_window_,
262 0, 0,
263 rect.right - rect.left,
264 rect.bottom - rect.top,
265 FALSE)) {
266 return false;
269 DCHECK(device_context_);
270 return ::SwapBuffers(device_context_) == TRUE;
273 gfx::Size NativeViewGLSurfaceWGL::GetSize() {
274 RECT rect;
275 BOOL result = GetClientRect(child_window_, &rect);
276 DCHECK(result);
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)
285 : size_(size),
286 device_context_(NULL),
287 pbuffer_(NULL) {
290 PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
291 Destroy();
294 bool PbufferGLSurfaceWGL::Initialize() {
295 DCHECK(!device_context_);
297 if (!gfx::g_driver_wgl.fn.wglCreatePbufferARBFn) {
298 LOG(ERROR) << "wglCreatePbufferARB not available.";
299 Destroy();
300 return false;
303 const int kNoAttributes[] = { 0 };
304 pbuffer_ = wglCreatePbufferARB(g_display->device_context(),
305 g_display->pixel_format(),
306 size_.width(), size_.height(),
307 kNoAttributes);
309 if (!pbuffer_) {
310 LOG(ERROR) << "Unable to create pbuffer.";
311 Destroy();
312 return false;
315 device_context_ = wglGetPbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_));
316 if (!device_context_) {
317 LOG(ERROR) << "Unable to get pbuffer device context.";
318 Destroy();
319 return false;
322 return true;
325 void PbufferGLSurfaceWGL::Destroy() {
326 if (pbuffer_ && device_context_)
327 wglReleasePbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_), device_context_);
329 device_context_ = NULL;
331 if (pbuffer_) {
332 wglDestroyPbufferARB(static_cast<HPBUFFERARB>(pbuffer_));
333 pbuffer_ = NULL;
337 bool PbufferGLSurfaceWGL::IsOffscreen() {
338 return true;
341 bool PbufferGLSurfaceWGL::SwapBuffers() {
342 NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
343 return false;
346 gfx::Size PbufferGLSurfaceWGL::GetSize() {
347 return size_;
350 void* PbufferGLSurfaceWGL::GetHandle() {
351 return device_context_;
354 } // namespace gfx