Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: gpu/ipc/service/direct_composition_surface_win_unittest.cc

Issue 2749023011: Add DirectComposition overlay support. (Closed)
Patch Set: remove unused method Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/ipc/service/direct_composition_surface_win.h" 5 #include "gpu/ipc/service/direct_composition_surface_win.h"
6 #include "base/memory/weak_ptr.h" 6 #include "base/memory/weak_ptr.h"
7 #include "base/run_loop.h" 7 #include "base/run_loop.h"
8 #include "base/synchronization/waitable_event.h" 8 #include "base/synchronization/waitable_event.h"
9 #include "base/threading/thread_task_runner_handle.h"
10 #include "skia/ext/platform_canvas.h"
11 #include "skia/ext/skia_utils_win.h"
9 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/base/win/hidden_window.h" 13 #include "ui/base/win/hidden_window.h"
14 #include "ui/gfx/skia_util.h"
15 #include "ui/gfx/transform.h"
16 #include "ui/gl/dc_renderer_layer_params.h"
11 #include "ui/gl/gl_angle_util_win.h" 17 #include "ui/gl/gl_angle_util_win.h"
12 #include "ui/gl/gl_context.h" 18 #include "ui/gl/gl_context.h"
19 #include "ui/gl/gl_image_dxgi.h"
13 #include "ui/gl/init/gl_factory.h" 20 #include "ui/gl/init/gl_factory.h"
21 #include "ui/platform_window/platform_window_delegate.h"
22 #include "ui/platform_window/win/win_window.h"
14 23
15 namespace gpu { 24 namespace gpu {
16 namespace { 25 namespace {
17 26
18 class TestImageTransportSurfaceDelegate 27 class TestImageTransportSurfaceDelegate
19 : public ImageTransportSurfaceDelegate, 28 : public ImageTransportSurfaceDelegate,
20 public base::SupportsWeakPtr<TestImageTransportSurfaceDelegate> { 29 public base::SupportsWeakPtr<TestImageTransportSurfaceDelegate> {
21 public: 30 public:
22 ~TestImageTransportSurfaceDelegate() override {} 31 ~TestImageTransportSurfaceDelegate() override {}
23 32
24 // ImageTransportSurfaceDelegate implementation. 33 // ImageTransportSurfaceDelegate implementation.
25 void DidCreateAcceleratedSurfaceChildWindow( 34 void DidCreateAcceleratedSurfaceChildWindow(
26 SurfaceHandle parent_window, 35 SurfaceHandle parent_window,
27 SurfaceHandle child_window) override {} 36 SurfaceHandle child_window) override {
37 if (parent_window)
38 ::SetParent(child_window, parent_window);
39 }
28 void DidSwapBuffersComplete(SwapBuffersCompleteParams params) override {} 40 void DidSwapBuffersComplete(SwapBuffersCompleteParams params) override {}
29 const gles2::FeatureInfo* GetFeatureInfo() const override { return nullptr; } 41 const gles2::FeatureInfo* GetFeatureInfo() const override { return nullptr; }
30 void SetLatencyInfoCallback(const LatencyInfoCallback& callback) override {} 42 void SetLatencyInfoCallback(const LatencyInfoCallback& callback) override {}
31 void UpdateVSyncParameters(base::TimeTicks timebase, 43 void UpdateVSyncParameters(base::TimeTicks timebase,
32 base::TimeDelta interval) override {} 44 base::TimeDelta interval) override {}
33 void AddFilter(IPC::MessageFilter* message_filter) override {} 45 void AddFilter(IPC::MessageFilter* message_filter) override {}
34 int32_t GetRouteID() const override { return 0; } 46 int32_t GetRouteID() const override { return 0; }
35 }; 47 };
36 48
49 class TestPlatformDelegate : public ui::PlatformWindowDelegate {
50 public:
51 // ui::PlatformWindowDelegate implementation.
52 void OnBoundsChanged(const gfx::Rect& new_bounds) override {}
53 void OnDamageRect(const gfx::Rect& damaged_region) override {}
54 void DispatchEvent(ui::Event* event) override {}
55 void OnCloseRequest() override {}
56 void OnClosed() override {}
57 void OnWindowStateChanged(ui::PlatformWindowState new_state) override {}
58 void OnLostCapture() override {}
59 void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget,
60 float device_pixel_ratio) override {}
61 void OnAcceleratedWidgetDestroyed() override {}
62 void OnActivationChanged(bool active) override {}
63 };
64
37 void RunPendingTasks(scoped_refptr<base::TaskRunner> task_runner) { 65 void RunPendingTasks(scoped_refptr<base::TaskRunner> task_runner) {
38 base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, 66 base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
39 base::WaitableEvent::InitialState::NOT_SIGNALED); 67 base::WaitableEvent::InitialState::NOT_SIGNALED);
40 task_runner->PostTask(FROM_HERE, 68 task_runner->PostTask(FROM_HERE,
41 Bind(&base::WaitableEvent::Signal, Unretained(&done))); 69 Bind(&base::WaitableEvent::Signal, Unretained(&done)));
42 done.Wait(); 70 done.Wait();
43 } 71 }
44 72
45 void DestroySurface(scoped_refptr<DirectCompositionSurfaceWin> surface) { 73 void DestroySurface(scoped_refptr<DirectCompositionSurfaceWin> surface) {
46 scoped_refptr<base::TaskRunner> task_runner = 74 scoped_refptr<base::TaskRunner> task_runner =
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 202
175 // Surface switched to use IDXGISwapChain, so must draw to entire 203 // Surface switched to use IDXGISwapChain, so must draw to entire
176 // surface. 204 // surface.
177 EXPECT_FALSE(surface->SetDrawRectangle(gfx::Rect(0, 0, 50, 50))); 205 EXPECT_FALSE(surface->SetDrawRectangle(gfx::Rect(0, 0, 50, 50)));
178 EXPECT_TRUE(surface->SetDrawRectangle(gfx::Rect(0, 0, 100, 100))); 206 EXPECT_TRUE(surface->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
179 EXPECT_TRUE(surface->swap_chain()); 207 EXPECT_TRUE(surface->swap_chain());
180 208
181 context = nullptr; 209 context = nullptr;
182 DestroySurface(std::move(surface)); 210 DestroySurface(std::move(surface));
183 } 211 }
212
213 SkBitmap ReadBackWindow(HWND window, const gfx::Rect& snapshot_bounds) {
214 std::unique_ptr<SkCanvas> canvas = skia::CreatePlatformCanvas(
215 snapshot_bounds.right(), snapshot_bounds.bottom(), false);
216 HDC mem_hdc = skia::GetNativeDrawingContext(canvas.get());
217
218 // Grab a copy of the window. Use PrintWindow because it works even when the
219 // window's partially occluded. The PW_RENDERFULLCONTENT flag is undocumented,
220 // but works starting in Windows 8.1. It allows for capturing the contents of
221 // the window that are drawn using DirectComposition.
222 UINT flags = PW_CLIENTONLY | PW_RENDERFULLCONTENT;
223
224 BOOL result = PrintWindow(window, mem_hdc, flags);
225 if (!result)
226 PLOG(ERROR) << "Failed to print window";
227
228 SkBitmap bitmap;
229 canvas->readPixels(gfx::RectToSkIRect(snapshot_bounds), &bitmap);
230
231 return bitmap;
232 }
233
234 class DirectCompositionPixelTest : public testing::Test {
235 public:
236 DirectCompositionPixelTest()
237 : window_(&platform_delegate_, gfx::Rect(0, 0, 100, 100)) {}
238
239 protected:
240 bool CheckIfSupported() {
241 if (!gl::QueryDirectCompositionDevice(
242 gl::QueryD3D11DeviceObjectFromANGLE())) {
243 LOG(WARNING)
244 << "GL implementation not using DirectComposition, skipping test.";
245 return false;
246 }
247 return true;
248 }
249
250 void InitializeSurface() {
251 static_cast<ui::PlatformWindow*>(&window_)->Show();
252
253 surface_ =
254 new DirectCompositionSurfaceWin(delegate_.AsWeakPtr(), window_.hwnd());
255 EXPECT_TRUE(surface_->Initialize());
256 }
257
258 TestPlatformDelegate platform_delegate_;
259 TestImageTransportSurfaceDelegate delegate_;
260 ui::WinWindow window_;
261 scoped_refptr<DirectCompositionSurfaceWin> surface_;
262 };
263
264 TEST_F(DirectCompositionPixelTest, PixelTest) {
265 if (!CheckIfSupported())
266 return;
267 for (int i = 0; i < 2; i++) {
268 InitializeSurface();
269
270 surface_->SetEnableDCLayers(i > 0);
271 gfx::Size window_size(100, 100);
272
273 scoped_refptr<gl::GLContext> context = gl::init::CreateGLContext(
274 nullptr, surface_.get(), gl::GLContextAttribs());
275 EXPECT_TRUE(surface_->Resize(window_size, 1.0, true));
276 EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size)));
277 EXPECT_TRUE(context->MakeCurrent(surface_.get()));
278
279 glClearColor(1.0, 0.0, 0.0, 1.0);
280 glClear(GL_COLOR_BUFFER_BIT);
281
282 EXPECT_EQ(gfx::SwapResult::SWAP_ACK, surface_->SwapBuffers());
283 Sleep(1000);
284
285 SkBitmap bitmap = ReadBackWindow(window_.hwnd(), gfx::Rect(window_size));
286 EXPECT_EQ(SK_ColorRED, bitmap.getColor(50, 50));
287
288 EXPECT_TRUE(context->IsCurrent(surface_.get()));
289
290 context = nullptr;
291 DestroySurface(std::move(surface_));
292 }
293 }
294
295 base::win::ScopedComPtr<ID3D11Texture2D> CreateNV12Texture(
296 const base::win::ScopedComPtr<ID3D11Device>& d3d11_device,
297 const gfx::Size& size) {
298 D3D11_TEXTURE2D_DESC desc = {};
299 desc.Width = size.width();
300 desc.Height = size.height();
301 desc.MipLevels = 1;
302 desc.ArraySize = 1;
303 desc.Format = DXGI_FORMAT_NV12;
304 desc.Usage = D3D11_USAGE_DEFAULT;
305 desc.SampleDesc.Count = 1;
306 desc.BindFlags = 0;
307
308 std::vector<char> image_data(size.width() * size.height() * 3 / 2);
309 // Y, U, and V should all be Oxff. Output color should be pink.
310 memset(&image_data[0], 0xff, size.width() * size.height() * 3 / 2);
311
312 D3D11_SUBRESOURCE_DATA data = {};
313 data.pSysMem = (const void*)&image_data[0];
314 data.SysMemPitch = size.width();
315
316 base::win::ScopedComPtr<ID3D11Texture2D> texture;
317 HRESULT hr = d3d11_device->CreateTexture2D(&desc, &data, texture.Receive());
318 CHECK(SUCCEEDED(hr));
319 return texture;
320 }
321
322 bool AreColorsSimilar(int a, int b) {
323 const int kMargin = 10;
324 return abs(SkColorGetA(a) - SkColorGetA(b)) < kMargin &&
325 abs(SkColorGetR(a) - SkColorGetR(b)) < kMargin &&
326 abs(SkColorGetG(a) - SkColorGetG(b)) < kMargin &&
327 abs(SkColorGetB(a) - SkColorGetB(b)) < kMargin;
328 }
329
330 TEST_F(DirectCompositionPixelTest, PixelTestVideoSwapchain) {
331 if (!CheckIfSupported())
332 return;
333 InitializeSurface();
334 surface_->SetEnableDCLayers(true);
335 gfx::Size window_size(100, 100);
336
337 scoped_refptr<gl::GLContext> context = gl::init::CreateGLContext(
338 nullptr, surface_.get(), gl::GLContextAttribs());
339 EXPECT_TRUE(surface_->Resize(window_size, 1.0, true));
340
341 base::win::ScopedComPtr<ID3D11Device> d3d11_device =
342 gl::QueryD3D11DeviceObjectFromANGLE();
343
344 gfx::Size texture_size(50, 50);
345 base::win::ScopedComPtr<ID3D11Texture2D> texture =
346 CreateNV12Texture(d3d11_device, texture_size);
347
348 scoped_refptr<gl::GLImageDXGI> image_dxgi(
349 new gl::GLImageDXGI(texture_size, nullptr));
350 image_dxgi->SetTexture(texture, 0);
351
352 ui::DCRendererLayerParams params(false, gfx::Rect(), 1, gfx::Transform(),
353 image_dxgi.get(),
354 gfx::RectF(gfx::Rect(texture_size)),
355 gfx::Rect(window_size), 0, 0, 1.0, 0);
356 surface_->ScheduleDCLayer(params);
357
358 EXPECT_EQ(gfx::SwapResult::SWAP_ACK, surface_->SwapBuffers());
359 Sleep(1000);
360
361 SkBitmap bitmap = ReadBackWindow(window_.hwnd(), gfx::Rect(window_size));
362 SkColor expected_color = SkColorSetRGB(0xff, 0xb7, 0xff);
363 SkColor actual_color = bitmap.getColor(75, 75);
364 EXPECT_TRUE(AreColorsSimilar(expected_color, actual_color))
365 << std::hex << "Expected " << expected_color << " Actual "
366 << actual_color;
367
368 context = nullptr;
369 DestroySurface(std::move(surface_));
370 }
371
184 } // namespace 372 } // namespace
185 } // namespace gpu 373 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698