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

Side by Side Diff: ui/surface/accelerated_surface_transformer_win_unittest.cc

Issue 11280318: YUV conversion on the GPU. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Test improvements. Created 7 years, 12 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 <d3d9.h> 5 #include <d3d9.h>
6 #include <random> 6 #include <random>
7 7
8 #include "base/basictypes.h" 8 #include "base/basictypes.h"
9 #include "base/file_util.h"
9 #include "base/hash.h" 10 #include "base/hash.h"
10 #include "base/scoped_native_library.h" 11 #include "base/scoped_native_library.h"
11 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/time.h"
12 #include "base/win/scoped_comptr.h" 14 #include "base/win/scoped_comptr.h"
13 #include "base/win/windows_version.h" 15 #include "base/win/windows_version.h"
16 #include "media/base/simd/convert_rgb_to_yuv.h"
17 #include "media/base/yuv_convert.h"
14 #include "testing/gtest/include/gtest/gtest-param-test.h" 18 #include "testing/gtest/include/gtest/gtest-param-test.h"
15 #include "testing/gtest/include/gtest/gtest.h" 19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "third_party/skia/include/core/SkColor.h"
22 #include "ui/gfx/codec/png_codec.h"
16 #include "ui/gfx/rect.h" 23 #include "ui/gfx/rect.h"
17 #include "ui/surface/accelerated_surface_transformer_win.h" 24 #include "ui/surface/accelerated_surface_transformer_win.h"
18 #include "ui/surface/accelerated_surface_win.h" 25 #include "ui/surface/accelerated_surface_win.h"
19 #include "ui/surface/d3d9_utils_win.h" 26 #include "ui/surface/d3d9_utils_win.h"
20 27
21 namespace d3d_utils = ui_surface_d3d9_utils; 28 namespace d3d_utils = ui_surface_d3d9_utils;
22 29
23 using base::win::ScopedComPtr; 30 using base::win::ScopedComPtr;
24 using std::uniform_int_distribution; 31 using std::uniform_int_distribution;
25 32
26 // Provides a reference rasterizer (all rendering done by software emulation) 33 namespace {
27 // Direct3D device, for use by unit tests. 34
35 // Debug flag, useful when hacking on tests.
36 const bool kDumpImagesOnFailure = false;
37
38 SkBitmap ToSkBitmap(IDirect3DSurface9* surface, bool is_single_channel) {
39 D3DLOCKED_RECT locked_rect;
40 EXPECT_HRESULT_SUCCEEDED(
41 surface->LockRect(&locked_rect, NULL, D3DLOCK_READONLY));
42
43 SkBitmap result;
44 gfx::Size size = d3d_utils::GetSize(surface);
45 if (is_single_channel)
46 size = gfx::Size(size.width() * 4, size.height());
47 result.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
48 result.setIsOpaque(true);
49 result.allocPixels();
50 result.lockPixels();
51 for (int y = 0; y < size.height(); ++y) {
52 if (is_single_channel) {
53 byte* row = y * locked_rect.Pitch +
miu 2012/12/27 21:40:17 nit: indent is one off
ncarter (slow) 2013/01/07 22:49:10 Done.
54 reinterpret_cast<byte*>(locked_rect.pBits);
apatrick_chromium 2013/01/07 22:56:53 Where is byte defined? basictypes.h has int8 and u
ncarter (slow) 2013/01/07 23:24:52 Apparently byte comes from a windows header: rpcnd
55 for (int x = 0; x < size.width(); ++x) {
56 *result.getAddr32(x, y) = SkColorSetRGB(row[x], row[x], row[x]);
57 }
58 } else {
59 uint32* row = reinterpret_cast<uint32*>(y * locked_rect.Pitch +
miu 2012/12/27 21:40:17 nit: This is the same calculation as a few lines a
ncarter (slow) 2013/01/07 22:49:10 Done.
60 reinterpret_cast<byte*>(locked_rect.pBits));
61 for (int x = 0; x < size.width(); ++x) {
62 *result.getAddr32(x, y) = row[x] | 0xFF000000;
63 }
64 }
65 }
66 result.unlockPixels();
67 result.setImmutable();
68 surface->UnlockRect();
69 return result;
70 }
71
72 bool WritePNGFile(const SkBitmap& bitmap, const FilePath& file_path) {
73 std::vector<unsigned char> png_data;
74 const bool discard_transparency = true;
75 if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap,
76 discard_transparency,
77 &png_data) &&
78 file_util::CreateDirectory(file_path.DirName())) {
79 char* data = reinterpret_cast<char*>(&png_data[0]);
80 int size = static_cast<int>(png_data.size());
81 return file_util::WriteFile(file_path, data, size) == size;
82 }
83 return false;
84 }
85
86 } // namespace
87
88 // Test fixture for AcceleratedSurfaceTransformer.
28 // 89 //
29 // This class is parameterized so that it runs only on Vista+. See 90 // This class is parameterized so that it runs only on Vista+. See
30 // WindowsVersionIfVistaOrBetter() for details on this works. 91 // WindowsVersionIfVistaOrBetter() for details on this works.
31 class AcceleratedSurfaceTransformerTest : public testing::TestWithParam<int> { 92 class AcceleratedSurfaceTransformerTest : public testing::TestWithParam<int> {
32 public: 93 public:
33 AcceleratedSurfaceTransformerTest() {}; 94 AcceleratedSurfaceTransformerTest() : color_error_tolerance_(0) {};
34 95
35 IDirect3DDevice9Ex* device() { return device_.get(); } 96 IDirect3DDevice9Ex* device() { return device_.get(); }
36 97
37 virtual void SetUp() { 98 virtual void SetUp() {
38 if (!d3d_module_.is_valid()) { 99 if (!d3d_module_.is_valid()) {
39 if (!d3d_utils::LoadD3D9(&d3d_module_)) { 100 if (!d3d_utils::LoadD3D9(&d3d_module_)) {
40 GTEST_FAIL() << "Could not load d3d9.dll"; 101 GTEST_FAIL() << "Could not load d3d9.dll";
41 return; 102 return;
42 } 103 }
43 } 104 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 const gfx::Size& size, 148 const gfx::Size& size,
88 int checker_square_size) { 149 int checker_square_size) {
89 150
90 D3DLOCKED_RECT locked_rect; 151 D3DLOCKED_RECT locked_rect;
91 ASSERT_HRESULT_SUCCEEDED( 152 ASSERT_HRESULT_SUCCEEDED(
92 lockable_surface->LockRect(&locked_rect, NULL, D3DLOCK_DISCARD)); 153 lockable_surface->LockRect(&locked_rect, NULL, D3DLOCK_DISCARD));
93 DWORD* surface = reinterpret_cast<DWORD*>(locked_rect.pBits); 154 DWORD* surface = reinterpret_cast<DWORD*>(locked_rect.pBits);
94 ASSERT_EQ(0, locked_rect.Pitch % sizeof(DWORD)); 155 ASSERT_EQ(0, locked_rect.Pitch % sizeof(DWORD));
95 int pitch = locked_rect.Pitch / sizeof(DWORD); 156 int pitch = locked_rect.Pitch / sizeof(DWORD);
96 157
97 for (int y = 0; y <= size.height() / 2; y += checker_square_size) { 158 for (int y = 0; y < (size.height() + 1) / 2; y += checker_square_size) {
98 for (int x = 0; x <= size.width() / 2; x += checker_square_size) { 159 for (int x = 0; x < (size.width() + 1) / 2; x += checker_square_size) {
99 DWORD color = RandomColor(); 160 DWORD color = RandomColor();
100 int y_limit = std::min(size.height() / 2, y + checker_square_size - 1); 161 int y_limit = std::min(size.height() / 2, y + checker_square_size - 1);
101 int x_limit = std::min(size.width() / 2, x + checker_square_size - 1); 162 int x_limit = std::min(size.width() / 2, x + checker_square_size - 1);
102 for (int y_lo = y; y_lo <= y_limit; y_lo++) { 163 for (int y_lo = y; y_lo <= y_limit; y_lo++) {
103 for (int x_lo = x; x_lo <= x_limit; x_lo++) { 164 for (int x_lo = x; x_lo <= x_limit; x_lo++) {
104 int y_hi = size.height() - 1 - y_lo; 165 int y_hi = size.height() - 1 - y_lo;
105 int x_hi = size.width() - 1 - x_lo; 166 int x_hi = size.width() - 1 - x_lo;
106 surface[x_lo + y_lo*pitch] = color; 167 surface[x_lo + y_lo*pitch] = color;
107 surface[x_lo + y_hi*pitch] = color; 168 surface[x_lo + y_hi*pitch] = color;
108 surface[x_hi + y_lo*pitch] = color; 169 surface[x_hi + y_lo*pitch] = color;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 bool AssertSameColor(DWORD color_a, DWORD color_b) { 208 bool AssertSameColor(DWORD color_a, DWORD color_b) {
148 if (color_a == color_b) 209 if (color_a == color_b)
149 return true; 210 return true;
150 uint8* a = reinterpret_cast<uint8*>(&color_a); 211 uint8* a = reinterpret_cast<uint8*>(&color_a);
151 uint8* b = reinterpret_cast<uint8*>(&color_b); 212 uint8* b = reinterpret_cast<uint8*>(&color_b);
152 int max_error = 0; 213 int max_error = 0;
153 for (int i = 0; i < 4; i++) 214 for (int i = 0; i < 4; i++)
154 max_error = std::max(max_error, 215 max_error = std::max(max_error,
155 std::abs(static_cast<int>(a[i]) - b[i])); 216 std::abs(static_cast<int>(a[i]) - b[i]));
156 217
157 if (max_error <= kAbsoluteColorErrorTolerance) 218 if (max_error <= color_error_tolerance())
158 return true; 219 return true;
159 220
160 std::string expected_color = 221 std::string expected_color =
161 StringPrintf("%3d, %3d, %3d, %3d", a[0], a[1], a[2], a[3]); 222 StringPrintf("%3d, %3d, %3d, %3d", a[0], a[1], a[2], a[3]);
162 std::string actual_color = 223 std::string actual_color =
163 StringPrintf("%3d, %3d, %3d, %3d", b[0], b[1], b[2], b[3]); 224 StringPrintf("%3d, %3d, %3d, %3d", b[0], b[1], b[2], b[3]);
164 EXPECT_EQ(expected_color, actual_color) 225 EXPECT_EQ(expected_color, actual_color)
165 << "Componentwise color difference was " 226 << "Componentwise color difference was "
166 << max_error << "; max allowed is " << kAbsoluteColorErrorTolerance; 227 << max_error << "; max allowed is " << color_error_tolerance();
167 228
229 return false;
230 }
231
232 bool AssertSameColor(byte color_a, byte color_b) {
233 if (color_a == color_b)
234 return true;
235 int max_error = std::abs((int) color_a - (int) color_b);
236 if (max_error <= color_error_tolerance())
237 return true;
238 ADD_FAILURE() << "Colors not equal: " << StringPrintf("0x%x", color_a)
239 << " vs. " << StringPrintf("0x%x", color_b);
168 return false; 240 return false;
169 } 241 }
170 242
171 // Asserts that an image is symmetric with respect to itself: both 243 // Asserts that an image is symmetric with respect to itself: both
172 // horizontally and vertically, within the tolerance of AssertSameColor. 244 // horizontally and vertically, within the tolerance of AssertSameColor.
173 void AssertSymmetry(IDirect3DSurface9* lockable_surface, 245 void AssertSymmetry(IDirect3DSurface9* lockable_surface,
174 const gfx::Size& size) { 246 const gfx::Size& size) {
175 BeforeLockWorkaround(); 247 BeforeLockWorkaround();
176 248
177 D3DLOCKED_RECT locked_rect; 249 D3DLOCKED_RECT locked_rect;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 actual->UnlockRect(); 304 actual->UnlockRect();
233 GTEST_FAIL() << "Pixels (" << x << ", " << y << ") vs. " 305 GTEST_FAIL() << "Pixels (" << x << ", " << y << ") vs. "
234 << "(" << x << ", " << y_actual << ")"; 306 << "(" << x << ", " << y_actual << ")";
235 } 307 }
236 } 308 }
237 expected->UnlockRect(); 309 expected->UnlockRect();
238 actual->UnlockRect(); 310 actual->UnlockRect();
239 } 311 }
240 312
241 protected: 313 protected:
242 static const int kAbsoluteColorErrorTolerance = 5;
243
244 DWORD RandomColor() { 314 DWORD RandomColor() {
245 return random_dword_(rng_); 315 return random_dword_(rng_);
246 } 316 }
247 317
318 void set_color_error_tolerance(int value) {
319 color_error_tolerance_ = value;
320 }
321
322 int color_error_tolerance() {
323 return color_error_tolerance_;
324 }
325
248 void DoResizeBilinearTest(AcceleratedSurfaceTransformer* gpu_ops, 326 void DoResizeBilinearTest(AcceleratedSurfaceTransformer* gpu_ops,
249 const gfx::Size& src_size, 327 const gfx::Size& src_size,
250 const gfx::Size& dst_size, 328 const gfx::Size& dst_size,
251 int checkerboard_size) { 329 int checkerboard_size) {
252 330
253 SCOPED_TRACE( 331 SCOPED_TRACE(
254 StringPrintf("Resizing %dx%d -> %dx%d at checkerboard size of %d", 332 StringPrintf("Resizing %dx%d -> %dx%d at checkerboard size of %d",
255 src_size.width(), src_size.height(), 333 src_size.width(), src_size.height(),
256 dst_size.width(), dst_size.height(), 334 dst_size.width(), dst_size.height(),
257 checkerboard_size)); 335 checkerboard_size));
258 336
337 set_color_error_tolerance(4);
338
259 base::win::ScopedComPtr<IDirect3DSurface9> src, dst; 339 base::win::ScopedComPtr<IDirect3DSurface9> src, dst;
260 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface( 340 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(
261 device(), src_size, src.Receive())) 341 device(), src_size, src.Receive()))
262 << "Could not create src render target"; 342 << "Could not create src render target";
263 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface( 343 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(
264 device(), dst_size, dst.Receive())) 344 device(), dst_size, dst.Receive()))
265 << "Could not create dst render target"; 345 << "Could not create dst render target";
266 346
267 FillSymmetricRandomCheckerboard(src, src_size, checkerboard_size); 347 FillSymmetricRandomCheckerboard(src, src_size, checkerboard_size);
268 348
269 ASSERT_TRUE(gpu_ops->ResizeBilinear(src, gfx::Rect(src_size), dst)); 349 ASSERT_TRUE(gpu_ops->ResizeBilinear(src, gfx::Rect(src_size), dst));
270 350
271 AssertSymmetry(dst, dst_size); 351 AssertSymmetry(dst, dst_size);
272 } 352 }
273 353
354 void CreateRandomCheckerboardTexture(
355 const gfx::Size& size,
356 int checkerboard_size,
357 IDirect3DSurface9** reference_surface,
358 IDirect3DTexture9** result) {
359 base::win::ScopedComPtr<IDirect3DSurface9> dst;
360 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(device(), size,
361 reference_surface));
362 ASSERT_TRUE(d3d_utils::CreateTemporaryRenderTargetTexture(device(), size,
363 result, dst.Receive()));
364 FillRandomCheckerboard(*reference_surface, size, checkerboard_size);
365 ASSERT_HRESULT_SUCCEEDED(
366 device()->StretchRect(
367 *reference_surface, NULL, dst, NULL, D3DTEXF_NONE));
368 }
369
370 void CreateSymmetricRandomCheckerboardTexture(
371 const gfx::Size& size,
372 int checkerboard_size,
373 IDirect3DTexture9** result) {
374 base::win::ScopedComPtr<IDirect3DSurface9> checkerboard, dst;
375 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(device(), size,
376 checkerboard.Receive()));
377 ASSERT_TRUE(d3d_utils::CreateTemporaryRenderTargetTexture(device(), size,
378 result, dst.Receive()));
379 FillSymmetricRandomCheckerboard(checkerboard, size, checkerboard_size);
380 ASSERT_HRESULT_SUCCEEDED(
381 device()->StretchRect(checkerboard, NULL, dst, NULL, D3DTEXF_NONE));
382 }
383
384 void AssertSame(int widthInBytes, int height, uint8* reference,
apatrick_chromium 2013/01/07 22:56:53 widthInBytes -> width_in_bytes
ncarter (slow) 2013/01/07 23:24:52 Done.
385 IDirect3DSurface9* lockable) {
386 BeforeLockWorkaround();
387
388 D3DLOCKED_RECT locked_rect;
389 ASSERT_HRESULT_SUCCEEDED(
390 lockable->LockRect(&locked_rect, NULL, D3DLOCK_READONLY));
391 uint8* actual = reinterpret_cast<uint8*>(locked_rect.pBits);
392 for (int y = 0; y < height; ++y) {
393 for (int x = 0; x < widthInBytes; ++x) {
394 if (!AssertSameColor(reference[y * widthInBytes + x],
395 actual[y * locked_rect.Pitch + x])) {
396 lockable->UnlockRect();
397 GTEST_FAIL() << "At pixel (" << x << ", " << y << ")";
398 }
399 }
400 }
401 lockable->UnlockRect();
402 }
403
274 void DoCopyInvertedTest(AcceleratedSurfaceTransformer* gpu_ops, 404 void DoCopyInvertedTest(AcceleratedSurfaceTransformer* gpu_ops,
275 const gfx::Size& size) { 405 const gfx::Size& size) {
276 406
277 SCOPED_TRACE( 407 SCOPED_TRACE(
278 StringPrintf("CopyInverted @ %dx%d", size.width(), size.height())); 408 StringPrintf("CopyInverted @ %dx%d", size.width(), size.height()));
279 409
280 base::win::ScopedComPtr<IDirect3DSurface9> checkerboard, src, dst; 410 set_color_error_tolerance(0);
281 base::win::ScopedComPtr<IDirect3DTexture9> src_texture; 411
282 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(device(), size, 412 base::win::ScopedComPtr<IDirect3DSurface9> dst, reference_pattern;
283 checkerboard.Receive())) << "Could not create src render target";; 413 base::win::ScopedComPtr<IDirect3DTexture9> src;
284 ASSERT_TRUE(d3d_utils::CreateTemporaryRenderTargetTexture(device(), size, 414
285 src_texture.Receive(), src.Receive())) 415 CreateRandomCheckerboardTexture(size, 1, reference_pattern.Receive(),
286 << "Could not create src texture."; 416 src.Receive());
417
287 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(device(), size, 418 ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(device(), size,
288 dst.Receive())) << "Could not create dst render target."; 419 dst.Receive())) << "Could not create dst render target.";
289 420
290 FillRandomCheckerboard(checkerboard, size, 1); 421 ASSERT_TRUE(gpu_ops->CopyInverted(src, dst, size));
291 ASSERT_HRESULT_SUCCEEDED( 422 AssertIsInvertedCopy(size, reference_pattern, dst);
292 device()->StretchRect(checkerboard, NULL, src, NULL, D3DTEXF_NONE)); 423 }
293 ASSERT_TRUE(gpu_ops->CopyInverted(src_texture, dst, size)); 424
294 AssertIsInvertedCopy(size, checkerboard, dst); 425
295 } 426 void DoYUVConversionTest(AcceleratedSurfaceTransformer* gpu_ops,
296 427 const gfx::Size& src_size,
428 int checkerboard_size) {
429 // Test the non-MRT implementation, and the MRT implementation as well
430 // (if supported by the device).
431 ASSERT_NO_FATAL_FAILURE(
432 DoYUVConversionTest(gpu_ops, src_size, checkerboard_size, false));
433 if (gpu_ops->device_supports_multiple_render_targets()) {
434 ASSERT_NO_FATAL_FAILURE(
435 DoYUVConversionTest(gpu_ops, src_size, checkerboard_size, true));
436 }
miu 2012/12/27 21:40:17 else LOG(WARNING) << "MRT path not tested (due to
ncarter (slow) 2013/01/07 22:49:10 Added, but only to the Init test so that the warni
437 }
438
439 void DoYUVConversionTest(AcceleratedSurfaceTransformer* gpu_ops,
440 const gfx::Size& src_size,
441 int checkerboard_size,
442 boolean use_multi_render_targets) {
443 SCOPED_TRACE(
444 StringPrintf("YUV Converting %dx%d at checkerboard size of %d; MRT %s",
445 src_size.width(), src_size.height(),
446 checkerboard_size,
447 use_multi_render_targets ? "enabled" : "disabled"));
448
449 // TODO(ncarter): Use a better error metric that measures aggregate error
450 // rather than simply max error. There seems to be slightly more error at
451 // higher resolutions, maybe due to precision issues during rasterization
452 // (or maybe more pixels = more test trials). Results are usually to an
453 // error of 1, but we must use a tolerance of 3 here.
454 set_color_error_tolerance(3);
455
456 base::win::ScopedComPtr<IDirect3DTexture9> src;
457 base::win::ScopedComPtr<IDirect3DSurface9> reference;
458 base::win::ScopedComPtr<IDirect3DSurface9> dst_y, dst_u, dst_v;
459
460 CreateRandomCheckerboardTexture(
461 src_size, checkerboard_size, reference.Receive(), src.Receive());
462
463 gfx::Size dst_size = src_size;
miu 2012/12/27 21:40:17 Might it necessary to test some dst_size != src_si
ncarter (slow) 2013/01/07 22:49:10 Done. Good call. Turns out StretchRect has a sligh
464 gfx::Size packed_y_size, packed_uv_size;
465
466 ASSERT_TRUE(gpu_ops->AllocYUVBuffers(dst_size,
467 &packed_y_size,
468 &packed_uv_size,
469 dst_y.Receive(),
470 dst_u.Receive(),
471 dst_v.Receive()));
472
473 // Actually do the conversion.
474 if (use_multi_render_targets) {
475 ASSERT_TRUE(gpu_ops->TransformRGBToYV12_MRT(src,
476 dst_size,
477 packed_y_size,
478 packed_uv_size,
479 dst_y,
480 dst_u,
481 dst_v));
482 } else {
483 ASSERT_TRUE(gpu_ops->TransformRGBToYV12_WithoutMRT(src,
484 dst_size,
485 packed_y_size,
486 packed_uv_size,
487 dst_y,
488 dst_u,
489 dst_v));
490 }
491
492 // UV size (in bytes/samples) is half, rounded up.
493 gfx::Size uv_size((dst_size.width() + 1) / 2,
494 (dst_size.height() + 1) / 2);
495
496 // Generate a reference bitmap by calling a software implementation.
497 SkBitmap reference_rgb = ToSkBitmap(reference, false);
498 scoped_array<uint8> reference_y(new uint8[dst_size.GetArea()]);
apatrick_chromium 2013/01/07 22:56:53 I think this is preferred now: scoped_ptr<uint8[]
ncarter (slow) 2013/01/07 23:24:52 Done. Good to know.
499 scoped_array<uint8> reference_u(new uint8[uv_size.GetArea()]);
500 scoped_array<uint8> reference_v(new uint8[uv_size.GetArea()]);
501 reference_rgb.lockPixels();
502 media::ConvertRGB32ToYUV_SSE2_Reference(
503 reinterpret_cast<uint8*>(reference_rgb.getAddr32(0, 0)),
504 &reference_y[0],
505 &reference_u[0],
506 &reference_v[0],
507 dst_size.width(),
508 dst_size.height(),
509 reference_rgb.rowBytes(),
510 dst_size.width(),
511 uv_size.width());
512 reference_rgb.unlockPixels();
513
514 // Check for equality of the reference and the actual.
515 AssertSame(dst_size.width(), dst_size.height(), &reference_y[0], dst_y);
516 AssertSame(uv_size.width(), uv_size.height(), &reference_u[0], dst_u);
517 AssertSame(uv_size.width(), uv_size.height(), &reference_v[0], dst_v);
518
519 if (kDumpImagesOnFailure && HasFatalFailure()) {
520 // Note that this will dump the full u and v buffers, including
521 // extra columns added due to packing. That means up to 7 extra
522 // columns for uv, and up to 3 extra columns for y.
523 WritePNGFile(reference_rgb,
524 FilePath(FILE_PATH_LITERAL("test_fail_src.png")));
525 WritePNGFile(ToSkBitmap(dst_y, true),
526 FilePath(FILE_PATH_LITERAL("test_fail_y.png")));
527 WritePNGFile(ToSkBitmap(dst_u, true),
528 FilePath(FILE_PATH_LITERAL("test_fail_u.png")));
529 WritePNGFile(ToSkBitmap(dst_v, true),
530 FilePath(FILE_PATH_LITERAL("test_fail_v.png")));
531 }
532 }
533
534 int color_error_tolerance_;
297 uniform_int_distribution<DWORD> random_dword_; 535 uniform_int_distribution<DWORD> random_dword_;
298 std::mt19937 rng_; 536 std::mt19937 rng_;
299 base::ScopedNativeLibrary d3d_module_; 537 base::ScopedNativeLibrary d3d_module_;
300 base::win::ScopedComPtr<IDirect3DDevice9Ex> device_; 538 base::win::ScopedComPtr<IDirect3DDevice9Ex> device_;
301 }; 539 };
302 540
303 // Fails on some bots because Direct3D isn't allowed. 541 // Fails on some bots because Direct3D isn't allowed.
304 TEST_P(AcceleratedSurfaceTransformerTest, FAILS_Init) { 542 TEST_P(AcceleratedSurfaceTransformerTest, FAILS_Init) {
305 SCOPED_TRACE(GetAdapterInfo()); 543 SCOPED_TRACE(GetAdapterInfo());
306 AcceleratedSurfaceTransformer gpu_ops; 544 AcceleratedSurfaceTransformer gpu_ops;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 1)); 594 DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 1));
357 ASSERT_NO_FATAL_FAILURE( 595 ASSERT_NO_FATAL_FAILURE(
358 DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 2)); 596 DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 2));
359 ASSERT_NO_FATAL_FAILURE( 597 ASSERT_NO_FATAL_FAILURE(
360 DoCopyInvertedTest(&t, gfx::Size(20, 107))); 598 DoCopyInvertedTest(&t, gfx::Size(20, 107)));
361 ASSERT_NO_FATAL_FAILURE( 599 ASSERT_NO_FATAL_FAILURE(
362 DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 5)); 600 DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(255, 255), 5));
363 ASSERT_NO_FATAL_FAILURE( 601 ASSERT_NO_FATAL_FAILURE(
364 DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(64, 64), 5)); 602 DoResizeBilinearTest(&t, gfx::Size(256, 256), gfx::Size(64, 64), 5));
365 ASSERT_NO_FATAL_FAILURE( 603 ASSERT_NO_FATAL_FAILURE(
604 DoYUVConversionTest(&t, gfx::Size(128, 128), 1));
605 ASSERT_NO_FATAL_FAILURE(
366 DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(3, 3), 1)); 606 DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(3, 3), 1));
367 ASSERT_NO_FATAL_FAILURE( 607 ASSERT_NO_FATAL_FAILURE(
368 DoCopyInvertedTest(&t, gfx::Size(1412, 124))); 608 DoCopyInvertedTest(&t, gfx::Size(1412, 124)));
369 ASSERT_NO_FATAL_FAILURE( 609 ASSERT_NO_FATAL_FAILURE(
610 DoYUVConversionTest(&t, gfx::Size(100, 200), 1));
611 ASSERT_NO_FATAL_FAILURE(
370 DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 1)); 612 DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 1));
371 ASSERT_NO_FATAL_FAILURE( 613 ASSERT_NO_FATAL_FAILURE(
372 DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 2)); 614 DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 2));
373 615
374 ASSERT_NO_FATAL_FAILURE( 616 ASSERT_NO_FATAL_FAILURE(
375 DoCopyInvertedTest(&t, gfx::Size(1512, 7))); 617 DoCopyInvertedTest(&t, gfx::Size(1512, 7)));
376 ASSERT_NO_FATAL_FAILURE( 618 ASSERT_NO_FATAL_FAILURE(
377 DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 5)); 619 DoResizeBilinearTest(&t, gfx::Size(255, 255), gfx::Size(257, 257), 5));
378 ASSERT_NO_FATAL_FAILURE( 620 ASSERT_NO_FATAL_FAILURE(
379 DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 256), 8)); 621 DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 256), 8));
380 ASSERT_NO_FATAL_FAILURE( 622 ASSERT_NO_FATAL_FAILURE(
381 DoCopyInvertedTest(&t, gfx::Size(1521, 3))); 623 DoCopyInvertedTest(&t, gfx::Size(1521, 3)));
382 ASSERT_NO_FATAL_FAILURE( 624 ASSERT_NO_FATAL_FAILURE(
625 DoYUVConversionTest(&t, gfx::Size(140, 181), 1));
626 ASSERT_NO_FATAL_FAILURE(
383 DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 256), 1)); 627 DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 256), 1));
384 ASSERT_NO_FATAL_FAILURE( 628 ASSERT_NO_FATAL_FAILURE(
385 DoCopyInvertedTest(&t, gfx::Size(33, 712))); 629 DoCopyInvertedTest(&t, gfx::Size(33, 712)));
386 ASSERT_NO_FATAL_FAILURE( 630 ASSERT_NO_FATAL_FAILURE(
387 DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 8), 8)); 631 DoResizeBilinearTest(&t, gfx::Size(150, 256), gfx::Size(126, 8), 8));
388 ASSERT_NO_FATAL_FAILURE( 632 ASSERT_NO_FATAL_FAILURE(
389 DoCopyInvertedTest(&t, gfx::Size(33, 2))); 633 DoCopyInvertedTest(&t, gfx::Size(33, 2)));
390 ASSERT_NO_FATAL_FAILURE( 634 ASSERT_NO_FATAL_FAILURE(
391 DoResizeBilinearTest(&t, gfx::Size(200, 256), gfx::Size(126, 8), 8)); 635 DoResizeBilinearTest(&t, gfx::Size(200, 256), gfx::Size(126, 8), 8));
392 } 636 }
(...skipping 26 matching lines...) Expand all
419 ASSERT_NO_FATAL_FAILURE( 663 ASSERT_NO_FATAL_FAILURE(
420 DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, h), gfx::Size(lo, lo), 1)); 664 DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, h), gfx::Size(lo, lo), 1));
421 ASSERT_NO_FATAL_FAILURE( 665 ASSERT_NO_FATAL_FAILURE(
422 DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, lo), gfx::Size(w, lo), lo)); 666 DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, lo), gfx::Size(w, lo), lo));
423 ASSERT_NO_FATAL_FAILURE( 667 ASSERT_NO_FATAL_FAILURE(
424 DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, lo), gfx::Size(lo, h), lo)); 668 DoResizeBilinearTest(&gpu_ops, gfx::Size(lo, lo), gfx::Size(lo, h), lo));
425 ASSERT_NO_FATAL_FAILURE( 669 ASSERT_NO_FATAL_FAILURE(
426 DoCopyInvertedTest(&gpu_ops, gfx::Size(w, lo))); 670 DoCopyInvertedTest(&gpu_ops, gfx::Size(w, lo)));
427 ASSERT_NO_FATAL_FAILURE( 671 ASSERT_NO_FATAL_FAILURE(
428 DoCopyInvertedTest(&gpu_ops, gfx::Size(lo, h))); 672 DoCopyInvertedTest(&gpu_ops, gfx::Size(lo, h)));
673
674 ASSERT_NO_FATAL_FAILURE(
675 DoYUVConversionTest(&gpu_ops, gfx::Size(w, lo), 1));
676 ASSERT_NO_FATAL_FAILURE(
677 DoYUVConversionTest(&gpu_ops, gfx::Size(lo, h), 1));
678
429 } 679 }
430 680
431 // Exercises ResizeBilinear with random minification cases where the 681 // Exercises ResizeBilinear with random minification cases where the
432 // aspect ratio does not change. 682 // aspect ratio does not change.
433 // 683 //
434 // Fails on some bots because Direct3D isn't allowed. 684 // Fails on some bots because Direct3D isn't allowed.
435 // Fails on other bots because of ResizeBilinear symmetry failures. 685 // Fails on other bots because of ResizeBilinear symmetry failures.
436 // Should pass, at least, on NVIDIA Quadro 600. 686 // Should pass, at least, on NVIDIA Quadro 600.
437 TEST_P(AcceleratedSurfaceTransformerTest, FAILS_MinifyUniform) { 687 TEST_P(AcceleratedSurfaceTransformerTest, FAILS_MinifyUniform) {
438 SCOPED_TRACE(GetAdapterInfo()); 688 SCOPED_TRACE(GetAdapterInfo());
439 SeedRandom("MinifyUniform"); 689 SeedRandom("MinifyUniform");
440 690
441 AcceleratedSurfaceTransformer gpu_ops; 691 AcceleratedSurfaceTransformer gpu_ops;
442 ASSERT_TRUE(gpu_ops.Init(device())); 692 ASSERT_TRUE(gpu_ops.Init(device()));
443 693
444 int dims[] = { 21, 63, 64, 65, 99, 127, 128, 129, 192, 255, 256, 257}; 694 const int dims[] = {21, 63, 64, 65, 99, 127, 128, 129, 192, 255, 256, 257};
445 int checkerboards[] = {1, 2, 3, 9}; 695 const int checkerboards[] = {1, 2, 3, 9};
446 uniform_int_distribution<int> dim(0, arraysize(dims) - 1); 696 uniform_int_distribution<int> dim(0, arraysize(dims) - 1);
447 uniform_int_distribution<int> checkerboard(0, arraysize(checkerboards) - 1); 697 uniform_int_distribution<int> checkerboard(0, arraysize(checkerboards) - 1);
448 698
449 for (int i = 0; i < 300; i++) { 699 for (int i = 0; i < 300; i++) {
450 // Widths are picked so that dst is smaller than src. 700 // Widths are picked so that dst is smaller than src.
451 int dst_width = dims[dim(rng_)]; 701 int dst_width = dims[dim(rng_)];
452 int src_width = dims[dim(rng_)]; 702 int src_width = dims[dim(rng_)];
453 if (src_width < dst_width) 703 if (src_width < dst_width)
454 std::swap(dst_width, src_width); 704 std::swap(dst_width, src_width);
455 705
(...skipping 19 matching lines...) Expand all
475 // image, but for the current implementation of ResizeBilinear, this does not 725 // image, but for the current implementation of ResizeBilinear, this does not
476 // seem to be true (fails on NVIDIA Quadro 600; passes on 726 // seem to be true (fails on NVIDIA Quadro 600; passes on
477 // Intel Mobile 965 Express) 727 // Intel Mobile 965 Express)
478 TEST_P(AcceleratedSurfaceTransformerTest, FAILS_MagnifyUniform) { 728 TEST_P(AcceleratedSurfaceTransformerTest, FAILS_MagnifyUniform) {
479 SCOPED_TRACE(GetAdapterInfo()); 729 SCOPED_TRACE(GetAdapterInfo());
480 SeedRandom("MagnifyUniform"); 730 SeedRandom("MagnifyUniform");
481 731
482 AcceleratedSurfaceTransformer gpu_ops; 732 AcceleratedSurfaceTransformer gpu_ops;
483 ASSERT_TRUE(gpu_ops.Init(device())); 733 ASSERT_TRUE(gpu_ops.Init(device()));
484 734
485 int dims[] = {63, 64, 65, 99, 127, 128, 129, 192, 255, 256, 257}; 735 const int dims[] = {63, 64, 65, 99, 127, 128, 129, 192, 255, 256, 257};
486 int checkerboards[] = {1, 2, 3, 9}; 736 const int checkerboards[] = {1, 2, 3, 9};
487 uniform_int_distribution<int> dim(0, arraysize(dims) - 1); 737 uniform_int_distribution<int> dim(0, arraysize(dims) - 1);
488 uniform_int_distribution<int> checkerboard(0, arraysize(checkerboards) - 1); 738 uniform_int_distribution<int> checkerboard(0, arraysize(checkerboards) - 1);
489 739
490 for (int i = 0; i < 50; i++) { 740 for (int i = 0; i < 50; i++) {
491 // Widths are picked so that b is smaller than a. 741 // Widths are picked so that b is smaller than a.
492 int dst_width = dims[dim(rng_)]; 742 int dst_width = dims[dim(rng_)];
493 int src_width = dims[dim(rng_)]; 743 int src_width = dims[dim(rng_)];
494 if (dst_width < src_width) 744 if (dst_width < src_width)
495 std::swap(src_width, dst_width); 745 std::swap(src_width, dst_width);
496 746
497 int dst_height = dims[dim(rng_)]; 747 int dst_height = dims[dim(rng_)];
498 int src_height = static_cast<int>( 748 int src_height = static_cast<int>(
499 static_cast<int64>(src_width) * dst_height / dst_width); 749 static_cast<int64>(src_width) * dst_height / dst_width);
500 750
501 int checkerboard_size = checkerboards[checkerboard(rng_)]; 751 int checkerboard_size = checkerboards[checkerboard(rng_)];
502 752
503 ASSERT_NO_FATAL_FAILURE( 753 ASSERT_NO_FATAL_FAILURE(
504 DoResizeBilinearTest(&gpu_ops, 754 DoResizeBilinearTest(&gpu_ops,
505 gfx::Size(src_width, src_height), // Src size (smaller) 755 gfx::Size(src_width, src_height), // Src size (smaller)
506 gfx::Size(dst_width, dst_height), // Dst size (larger) 756 gfx::Size(dst_width, dst_height), // Dst size (larger)
507 checkerboard_size)) << "Failed on iteration " << i; 757 checkerboard_size)) << "Failed on iteration " << i;
508 } 758 }
509 }; 759 };
510 760
761 TEST_P(AcceleratedSurfaceTransformerTest, RGBtoYUV) {
762 SeedRandom("RGBtoYUV");
763
764 AcceleratedSurfaceTransformer gpu_ops;
765 ASSERT_TRUE(gpu_ops.Init(device()));
766
767 // Start with some easy-to-debug cases. A checkerboard size of 1 is the
768 // best test, but larger checkerboard sizes give more insight into where
769 // a bug might be.
770 ASSERT_NO_FATAL_FAILURE(
771 DoYUVConversionTest(&gpu_ops, gfx::Size(32, 32), 4));
772 ASSERT_NO_FATAL_FAILURE(
773 DoYUVConversionTest(&gpu_ops, gfx::Size(32, 32), 2));
774 ASSERT_NO_FATAL_FAILURE(
775 DoYUVConversionTest(&gpu_ops, gfx::Size(32, 32), 3));
776
777 // All cases of width (mod 8) and height (mod 8), using 1x1 checkerboard.
778 for (int w = 32; w < 40; ++w) {
779 for (int h = 32; h < 40; ++h) {
780 ASSERT_NO_FATAL_FAILURE(
781 DoYUVConversionTest(&gpu_ops, gfx::Size(w, h), 1));
782 }
783 }
784
785 // All the very small sizes which require the most shifting in the
786 // texture coordinates when doing alignment.
787 for (int w = 1; w <= 9; ++w) {
788 for (int h = 1; h <= 9; ++h) {
789 ASSERT_NO_FATAL_FAILURE(
790 DoYUVConversionTest(&gpu_ops, gfx::Size(w, h), 1));
791 }
792 }
793
794 // Random medium dimensions.
795 ASSERT_NO_FATAL_FAILURE(
796 DoYUVConversionTest(&gpu_ops, gfx::Size(10, 142), 1));
797 ASSERT_NO_FATAL_FAILURE(
798 DoYUVConversionTest(&gpu_ops, gfx::Size(124, 333), 1));
799 ASSERT_NO_FATAL_FAILURE(
800 DoYUVConversionTest(&gpu_ops, gfx::Size(853, 225), 1));
801 ASSERT_NO_FATAL_FAILURE(
802 DoYUVConversionTest(&gpu_ops, gfx::Size(231, 412), 1));
803 ASSERT_NO_FATAL_FAILURE(
804 DoYUVConversionTest(&gpu_ops, gfx::Size(512, 128), 1));
805 ASSERT_NO_FATAL_FAILURE(
806 DoYUVConversionTest(&gpu_ops, gfx::Size(1024, 768), 1));
807
808 // Common video/monitor resolutions
809 ASSERT_NO_FATAL_FAILURE(
810 DoYUVConversionTest(&gpu_ops, gfx::Size(800, 768), 1));
811 ASSERT_NO_FATAL_FAILURE(
812 DoYUVConversionTest(&gpu_ops, gfx::Size(1024, 768), 1));
813 ASSERT_NO_FATAL_FAILURE(
814 DoYUVConversionTest(&gpu_ops, gfx::Size(1280, 720), 1));
815 ASSERT_NO_FATAL_FAILURE(
816 DoYUVConversionTest(&gpu_ops, gfx::Size(1280, 720), 2));
817 ASSERT_NO_FATAL_FAILURE(
818 DoYUVConversionTest(&gpu_ops, gfx::Size(1920, 1080), 1));
819 ASSERT_NO_FATAL_FAILURE(
820 DoYUVConversionTest(&gpu_ops, gfx::Size(1920, 1080), 2));
821 ASSERT_NO_FATAL_FAILURE(
822 DoYUVConversionTest(&gpu_ops, gfx::Size(2048, 1536), 1));
823 }
824
511 namespace { 825 namespace {
512 826
513 // Used to suppress test on Windows versions prior to Vista. 827 // Used to suppress test on Windows versions prior to Vista.
514 std::vector<int> WindowsVersionIfVistaOrBetter() { 828 std::vector<int> WindowsVersionIfVistaOrBetter() {
515 std::vector<int> result; 829 std::vector<int> result;
516 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 830 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
517 result.push_back(base::win::GetVersion()); 831 result.push_back(base::win::GetVersion());
518 } 832 }
519 return result; 833 return result;
520 } 834 }
521 835
522 } // namespace 836 } // namespace
523 837
524 INSTANTIATE_TEST_CASE_P(VistaAndUp, 838 INSTANTIATE_TEST_CASE_P(VistaAndUp,
525 AcceleratedSurfaceTransformerTest, 839 AcceleratedSurfaceTransformerTest,
526 ::testing::ValuesIn(WindowsVersionIfVistaOrBetter())); 840 ::testing::ValuesIn(WindowsVersionIfVistaOrBetter()));
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698