• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_d3d11.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 
BrowserLayer(const std::shared_ptr<d3d11::Device> & device)14 BrowserLayer::BrowserLayer(const std::shared_ptr<d3d11::Device>& device)
15     : d3d11::Layer(device, true /* flip */) {
16   frame_buffer_ = std::make_shared<d3d11::FrameBuffer>(device_);
17 }
18 
render(const std::shared_ptr<d3d11::Context> & ctx)19 void BrowserLayer::render(const std::shared_ptr<d3d11::Context>& ctx) {
20   // Use the base class method to draw our texture.
21   render_texture(ctx, frame_buffer_->texture());
22 }
23 
on_paint(void * share_handle)24 void BrowserLayer::on_paint(void* share_handle) {
25   frame_buffer_->on_paint(share_handle);
26 }
27 
texture_size() const28 std::pair<uint32_t, uint32_t> BrowserLayer::texture_size() const {
29   const auto texture = frame_buffer_->texture();
30   return std::make_pair(texture->width(), texture->height());
31 }
32 
PopupLayer(const std::shared_ptr<d3d11::Device> & device)33 PopupLayer::PopupLayer(const std::shared_ptr<d3d11::Device>& device)
34     : BrowserLayer(device) {}
35 
set_bounds(const CefRect & bounds)36 void PopupLayer::set_bounds(const CefRect& bounds) {
37   const auto comp = composition();
38   if (!comp)
39     return;
40 
41   const auto outer_width = comp->width();
42   const auto outer_height = comp->height();
43   if (outer_width == 0 || outer_height == 0)
44     return;
45 
46   original_bounds_ = bounds;
47   bounds_ = bounds;
48 
49   // If x or y are negative, move them to 0.
50   if (bounds_.x < 0)
51     bounds_.x = 0;
52   if (bounds_.y < 0)
53     bounds_.y = 0;
54   // If popup goes outside the view, try to reposition origin
55   if (bounds_.x + bounds_.width > outer_width)
56     bounds_.x = outer_width - bounds_.width;
57   if (bounds_.y + bounds_.height > outer_height)
58     bounds_.y = outer_height - bounds_.height;
59   // If x or y became negative, move them to 0 again.
60   if (bounds_.x < 0)
61     bounds_.x = 0;
62   if (bounds_.y < 0)
63     bounds_.y = 0;
64 
65   const auto x = bounds_.x / float(outer_width);
66   const auto y = bounds_.y / float(outer_height);
67   const auto w = bounds_.width / float(outer_width);
68   const auto h = bounds_.height / float(outer_height);
69   move(x, y, w, h);
70 }
71 
OsrRenderHandlerWinD3D11(const OsrRendererSettings & settings,HWND hwnd)72 OsrRenderHandlerWinD3D11::OsrRenderHandlerWinD3D11(
73     const OsrRendererSettings& settings,
74     HWND hwnd)
75     : OsrRenderHandlerWin(settings, hwnd), start_time_(0) {}
76 
Initialize(CefRefPtr<CefBrowser> browser,int width,int height)77 bool OsrRenderHandlerWinD3D11::Initialize(CefRefPtr<CefBrowser> browser,
78                                           int width,
79                                           int height) {
80   CEF_REQUIRE_UI_THREAD();
81 
82   // Create a D3D11 device instance.
83   device_ = d3d11::Device::create();
84   DCHECK(device_);
85   if (!device_)
86     return false;
87 
88   // Create a D3D11 swapchain for the window.
89   swap_chain_ = device_->create_swapchain(hwnd());
90   DCHECK(swap_chain_);
91   if (!swap_chain_)
92     return false;
93 
94   // Create the browser layer.
95   browser_layer_ = std::make_shared<BrowserLayer>(device_);
96 
97   // Set up the composition.
98   composition_ = std::make_shared<d3d11::Composition>(device_, width, height);
99   composition_->add_layer(browser_layer_);
100 
101   // Size to the whole composition.
102   browser_layer_->move(0.0f, 0.0f, 1.0f, 1.0f);
103 
104   start_time_ = GetTimeNow();
105 
106   SetBrowser(browser);
107   return true;
108 }
109 
SetSpin(float spinX,float spinY)110 void OsrRenderHandlerWinD3D11::SetSpin(float spinX, float spinY) {
111   CEF_REQUIRE_UI_THREAD();
112   // Spin support is not implemented.
113 }
114 
IncrementSpin(float spinDX,float spinDY)115 void OsrRenderHandlerWinD3D11::IncrementSpin(float spinDX, float spinDY) {
116   CEF_REQUIRE_UI_THREAD();
117   // Spin support is not implemented.
118 }
119 
IsOverPopupWidget(int x,int y) const120 bool OsrRenderHandlerWinD3D11::IsOverPopupWidget(int x, int y) const {
121   CEF_REQUIRE_UI_THREAD();
122   return popup_layer_ && popup_layer_->contains(x, y);
123 }
124 
GetPopupXOffset() const125 int OsrRenderHandlerWinD3D11::GetPopupXOffset() const {
126   CEF_REQUIRE_UI_THREAD();
127   if (popup_layer_)
128     return popup_layer_->xoffset();
129   return 0;
130 }
131 
GetPopupYOffset() const132 int OsrRenderHandlerWinD3D11::GetPopupYOffset() const {
133   CEF_REQUIRE_UI_THREAD();
134   if (popup_layer_)
135     return popup_layer_->yoffset();
136   return 0;
137 }
138 
OnPopupShow(CefRefPtr<CefBrowser> browser,bool show)139 void OsrRenderHandlerWinD3D11::OnPopupShow(CefRefPtr<CefBrowser> browser,
140                                            bool show) {
141   CEF_REQUIRE_UI_THREAD();
142 
143   if (show) {
144     DCHECK(!popup_layer_);
145 
146     // Create a new layer.
147     popup_layer_ = std::make_shared<PopupLayer>(device_);
148     composition_->add_layer(popup_layer_);
149   } else {
150     DCHECK(popup_layer_);
151 
152     composition_->remove_layer(popup_layer_);
153     popup_layer_ = nullptr;
154 
155     Render();
156   }
157 }
158 
OnPopupSize(CefRefPtr<CefBrowser> browser,const CefRect & rect)159 void OsrRenderHandlerWinD3D11::OnPopupSize(CefRefPtr<CefBrowser> browser,
160                                            const CefRect& rect) {
161   CEF_REQUIRE_UI_THREAD();
162   popup_layer_->set_bounds(rect);
163 }
164 
OnPaint(CefRefPtr<CefBrowser> browser,CefRenderHandler::PaintElementType type,const CefRenderHandler::RectList & dirtyRects,const void * buffer,int width,int height)165 void OsrRenderHandlerWinD3D11::OnPaint(
166     CefRefPtr<CefBrowser> browser,
167     CefRenderHandler::PaintElementType type,
168     const CefRenderHandler::RectList& dirtyRects,
169     const void* buffer,
170     int width,
171     int height) {
172   // Not used with this implementation.
173   NOTREACHED();
174 }
175 
OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,CefRenderHandler::PaintElementType type,const CefRenderHandler::RectList & dirtyRects,void * share_handle)176 void OsrRenderHandlerWinD3D11::OnAcceleratedPaint(
177     CefRefPtr<CefBrowser> browser,
178     CefRenderHandler::PaintElementType type,
179     const CefRenderHandler::RectList& dirtyRects,
180     void* share_handle) {
181   CEF_REQUIRE_UI_THREAD();
182 
183   if (type == PET_POPUP) {
184     popup_layer_->on_paint(share_handle);
185   } else {
186     browser_layer_->on_paint(share_handle);
187   }
188 
189   Render();
190 }
191 
Render()192 void OsrRenderHandlerWinD3D11::Render() {
193   // Update composition + layers based on time.
194   const auto t = (GetTimeNow() - start_time_) / 1000000.0;
195   composition_->tick(t);
196 
197   auto ctx = device_->immedidate_context();
198   swap_chain_->bind(ctx);
199 
200   const auto texture_size = browser_layer_->texture_size();
201 
202   // Resize the composition and swap chain to match the texture if necessary.
203   composition_->resize(!send_begin_frame(), texture_size.first,
204                        texture_size.second);
205   swap_chain_->resize(texture_size.first, texture_size.second);
206 
207   // Clear the render target.
208   swap_chain_->clear(0.0f, 0.0f, 1.0f, 1.0f);
209 
210   // Render the scene.
211   composition_->render(ctx);
212 
213   // Present to window.
214   swap_chain_->present(send_begin_frame() ? 0 : 1);
215 }
216 
217 }  // namespace client
218