1 // Copyright 2018 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "tests/cefclient/browser/osr_render_handler_win_gl.h"
6
7 #include "include/base/cef_callback.h"
8 #include "include/wrapper/cef_closure_task.h"
9 #include "include/wrapper/cef_helpers.h"
10 #include "tests/shared/browser/util_win.h"
11
12 namespace client {
13
14 namespace {
15
16 // Helper that calls wglMakeCurrent.
17 class ScopedGLContext {
18 public:
ScopedGLContext(HDC hdc,HGLRC hglrc,bool swap_buffers)19 ScopedGLContext(HDC hdc, HGLRC hglrc, bool swap_buffers)
20 : hdc_(hdc), swap_buffers_(swap_buffers) {
21 BOOL result = wglMakeCurrent(hdc, hglrc);
22 ALLOW_UNUSED_LOCAL(result);
23 DCHECK(result);
24 }
~ScopedGLContext()25 ~ScopedGLContext() {
26 BOOL result = wglMakeCurrent(nullptr, nullptr);
27 DCHECK(result);
28 if (swap_buffers_) {
29 result = SwapBuffers(hdc_);
30 DCHECK(result);
31 }
32 }
33
34 private:
35 const HDC hdc_;
36 const bool swap_buffers_;
37 };
38
39 } // namespace
40
OsrRenderHandlerWinGL(const OsrRendererSettings & settings,HWND hwnd)41 OsrRenderHandlerWinGL::OsrRenderHandlerWinGL(
42 const OsrRendererSettings& settings,
43 HWND hwnd)
44 : OsrRenderHandlerWin(settings, hwnd),
45 renderer_(settings),
46 hdc_(nullptr),
47 hrc_(nullptr),
48 painting_popup_(false) {}
49
Initialize(CefRefPtr<CefBrowser> browser)50 void OsrRenderHandlerWinGL::Initialize(CefRefPtr<CefBrowser> browser) {
51 CEF_REQUIRE_UI_THREAD();
52 SetBrowser(browser);
53 }
54
~OsrRenderHandlerWinGL()55 OsrRenderHandlerWinGL::~OsrRenderHandlerWinGL() {
56 CEF_REQUIRE_UI_THREAD();
57 DisableGL();
58 }
59
SetSpin(float spinX,float spinY)60 void OsrRenderHandlerWinGL::SetSpin(float spinX, float spinY) {
61 CEF_REQUIRE_UI_THREAD();
62 renderer_.SetSpin(spinX, spinY);
63 Invalidate();
64 }
65
IncrementSpin(float spinDX,float spinDY)66 void OsrRenderHandlerWinGL::IncrementSpin(float spinDX, float spinDY) {
67 CEF_REQUIRE_UI_THREAD();
68 renderer_.IncrementSpin(spinDX, spinDY);
69 Invalidate();
70 }
71
IsOverPopupWidget(int x,int y) const72 bool OsrRenderHandlerWinGL::IsOverPopupWidget(int x, int y) const {
73 CEF_REQUIRE_UI_THREAD();
74 const CefRect& rc = renderer_.popup_rect();
75 int popup_right = rc.x + rc.width;
76 int popup_bottom = rc.y + rc.height;
77 return (x >= rc.x) && (x < popup_right) && (y >= rc.y) && (y < popup_bottom);
78 }
79
GetPopupXOffset() const80 int OsrRenderHandlerWinGL::GetPopupXOffset() const {
81 CEF_REQUIRE_UI_THREAD();
82 return renderer_.original_popup_rect().x - renderer_.popup_rect().x;
83 }
84
GetPopupYOffset() const85 int OsrRenderHandlerWinGL::GetPopupYOffset() const {
86 CEF_REQUIRE_UI_THREAD();
87 return renderer_.original_popup_rect().y - renderer_.popup_rect().y;
88 }
89
OnPopupShow(CefRefPtr<CefBrowser> browser,bool show)90 void OsrRenderHandlerWinGL::OnPopupShow(CefRefPtr<CefBrowser> browser,
91 bool show) {
92 CEF_REQUIRE_UI_THREAD();
93
94 if (!show) {
95 renderer_.ClearPopupRects();
96 browser->GetHost()->Invalidate(PET_VIEW);
97 }
98
99 renderer_.OnPopupShow(browser, show);
100 }
101
OnPopupSize(CefRefPtr<CefBrowser> browser,const CefRect & rect)102 void OsrRenderHandlerWinGL::OnPopupSize(CefRefPtr<CefBrowser> browser,
103 const CefRect& rect) {
104 CEF_REQUIRE_UI_THREAD();
105 renderer_.OnPopupSize(browser, rect);
106 }
107
OnPaint(CefRefPtr<CefBrowser> browser,CefRenderHandler::PaintElementType type,const CefRenderHandler::RectList & dirtyRects,const void * buffer,int width,int height)108 void OsrRenderHandlerWinGL::OnPaint(
109 CefRefPtr<CefBrowser> browser,
110 CefRenderHandler::PaintElementType type,
111 const CefRenderHandler::RectList& dirtyRects,
112 const void* buffer,
113 int width,
114 int height) {
115 CEF_REQUIRE_UI_THREAD();
116
117 if (painting_popup_) {
118 renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height);
119 return;
120 }
121 if (!hdc_) {
122 EnableGL();
123 }
124
125 ScopedGLContext scoped_gl_context(hdc_, hrc_, true);
126 renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height);
127 if (type == PET_VIEW && !renderer_.popup_rect().IsEmpty()) {
128 painting_popup_ = true;
129 browser->GetHost()->Invalidate(PET_POPUP);
130 painting_popup_ = false;
131 }
132 renderer_.Render();
133 }
134
OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,CefRenderHandler::PaintElementType type,const CefRenderHandler::RectList & dirtyRects,void * share_handle)135 void OsrRenderHandlerWinGL::OnAcceleratedPaint(
136 CefRefPtr<CefBrowser> browser,
137 CefRenderHandler::PaintElementType type,
138 const CefRenderHandler::RectList& dirtyRects,
139 void* share_handle) {
140 // Not used with this implementation.
141 NOTREACHED();
142 }
143
Render()144 void OsrRenderHandlerWinGL::Render() {
145 if (!hdc_) {
146 EnableGL();
147 }
148
149 ScopedGLContext scoped_gl_context(hdc_, hrc_, true);
150 renderer_.Render();
151 }
152
EnableGL()153 void OsrRenderHandlerWinGL::EnableGL() {
154 PIXELFORMATDESCRIPTOR pfd;
155 int format;
156
157 // Get the device context.
158 hdc_ = GetDC(hwnd());
159
160 // Set the pixel format for the DC.
161 ZeroMemory(&pfd, sizeof(pfd));
162 pfd.nSize = sizeof(pfd);
163 pfd.nVersion = 1;
164 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
165 pfd.iPixelType = PFD_TYPE_RGBA;
166 pfd.cColorBits = 24;
167 pfd.cDepthBits = 16;
168 pfd.iLayerType = PFD_MAIN_PLANE;
169 format = ChoosePixelFormat(hdc_, &pfd);
170 SetPixelFormat(hdc_, format, &pfd);
171
172 // Create and enable the render context.
173 hrc_ = wglCreateContext(hdc_);
174
175 ScopedGLContext scoped_gl_context(hdc_, hrc_, false);
176 renderer_.Initialize();
177 }
178
DisableGL()179 void OsrRenderHandlerWinGL::DisableGL() {
180 if (!hdc_) {
181 return;
182 }
183
184 {
185 ScopedGLContext scoped_gl_context(hdc_, hrc_, false);
186 renderer_.Cleanup();
187 }
188
189 if (IsWindow(hwnd())) {
190 // wglDeleteContext will make the context not current before deleting it.
191 BOOL result = wglDeleteContext(hrc_);
192 ALLOW_UNUSED_LOCAL(result);
193 DCHECK(result);
194 ReleaseDC(hwnd(), hdc_);
195 }
196
197 hdc_ = nullptr;
198 hrc_ = nullptr;
199 }
200
201 } // namespace client
202