Index: components/display_compositor/yuv_readback_unittest.cc |
diff --git a/components/display_compositor/yuv_readback_unittest.cc b/components/display_compositor/yuv_readback_unittest.cc |
deleted file mode 100644 |
index 4e4806ef6a5efcf9d48b1cacb6d78666c49593ff..0000000000000000000000000000000000000000 |
--- a/components/display_compositor/yuv_readback_unittest.cc |
+++ /dev/null |
@@ -1,554 +0,0 @@ |
-// Copyright 2016 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "base/json/json_reader.h" |
-#include "base/memory/ref_counted_memory.h" |
-#include "base/run_loop.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/test/launcher/unit_test_launcher.h" |
-#include "base/test/test_suite.h" |
-#include "components/display_compositor/gl_helper.h" |
-#include "gpu/command_buffer/client/gl_in_process_context.h" |
-#include "gpu/command_buffer/client/gles2_implementation.h" |
-#include "gpu/command_buffer/client/shared_memory_limits.h" |
-#include "media/base/video_frame.h" |
-#include "media/base/video_util.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
-#include "third_party/skia/include/core/SkBitmap.h" |
-#include "ui/gl/gl_implementation.h" |
- |
-namespace display_compositor { |
- |
-namespace { |
-int kYUVReadbackSizes[] = {2, 4, 14}; |
-} |
- |
-class YUVReadbackTest : public testing::Test { |
- protected: |
- void SetUp() override { |
- gpu::gles2::ContextCreationAttribHelper attributes; |
- attributes.alpha_size = 8; |
- attributes.depth_size = 24; |
- attributes.red_size = 8; |
- attributes.green_size = 8; |
- attributes.blue_size = 8; |
- attributes.stencil_size = 8; |
- attributes.samples = 4; |
- attributes.sample_buffers = 1; |
- attributes.bind_generates_resource = false; |
- |
- context_.reset(gpu::GLInProcessContext::Create( |
- nullptr, /* service */ |
- nullptr, /* surface */ |
- true, /* offscreen */ |
- gfx::kNullAcceleratedWidget, /* window */ |
- gfx::Size(1, 1), /* size */ |
- nullptr, /* share_context */ |
- attributes, gfx::PreferDiscreteGpu, gpu::SharedMemoryLimits(), |
- nullptr, /* gpu_memory_buffer_manager */ |
- nullptr /* image_factory */)); |
- gl_ = context_->GetImplementation(); |
- gpu::ContextSupport* support = context_->GetImplementation(); |
- |
- helper_.reset(new display_compositor::GLHelper(gl_, support)); |
- } |
- |
- void TearDown() override { |
- helper_.reset(NULL); |
- context_.reset(NULL); |
- } |
- |
- void StartTracing(const std::string& filter) { |
- base::trace_event::TraceLog::GetInstance()->SetEnabled( |
- base::trace_event::TraceConfig(filter, |
- base::trace_event::RECORD_UNTIL_FULL), |
- base::trace_event::TraceLog::RECORDING_MODE); |
- } |
- |
- static void TraceDataCB( |
- const base::Callback<void()>& callback, |
- std::string* output, |
- const scoped_refptr<base::RefCountedString>& json_events_str, |
- bool has_more_events) { |
- if (output->size() > 1 && !json_events_str->data().empty()) { |
- output->append(","); |
- } |
- output->append(json_events_str->data()); |
- if (!has_more_events) { |
- callback.Run(); |
- } |
- } |
- |
- // End tracing, return tracing data in a simple map |
- // of event name->counts. |
- void EndTracing(std::map<std::string, int>* event_counts) { |
- std::string json_data = "["; |
- base::trace_event::TraceLog::GetInstance()->SetDisabled(); |
- base::RunLoop run_loop; |
- base::trace_event::TraceLog::GetInstance()->Flush( |
- base::Bind(&YUVReadbackTest::TraceDataCB, run_loop.QuitClosure(), |
- base::Unretained(&json_data))); |
- run_loop.Run(); |
- json_data.append("]"); |
- |
- std::string error_msg; |
- std::unique_ptr<base::Value> trace_data = |
- base::JSONReader::ReadAndReturnError(json_data, 0, NULL, &error_msg); |
- CHECK(trace_data) << "JSON parsing failed (" << error_msg |
- << ") JSON data:" << std::endl |
- << json_data; |
- |
- base::ListValue* list; |
- CHECK(trace_data->GetAsList(&list)); |
- for (size_t i = 0; i < list->GetSize(); i++) { |
- base::Value* item = NULL; |
- if (list->Get(i, &item)) { |
- base::DictionaryValue* dict; |
- CHECK(item->GetAsDictionary(&dict)); |
- std::string name; |
- CHECK(dict->GetString("name", &name)); |
- std::string trace_type; |
- CHECK(dict->GetString("ph", &trace_type)); |
- // Count all except END traces, as they come in BEGIN/END pairs. |
- if (trace_type != "E" && trace_type != "e") |
- (*event_counts)[name]++; |
- VLOG(1) << "trace name: " << name; |
- } |
- } |
- } |
- |
- // Look up a single channel value. Works for 4-channel and single channel |
- // bitmaps. Clamp x/y. |
- int Channel(SkBitmap* pixels, int x, int y, int c) { |
- if (pixels->bytesPerPixel() == 4) { |
- uint32_t* data = |
- pixels->getAddr32(std::max(0, std::min(x, pixels->width() - 1)), |
- std::max(0, std::min(y, pixels->height() - 1))); |
- return (*data) >> (c * 8) & 0xff; |
- } else { |
- DCHECK_EQ(pixels->bytesPerPixel(), 1); |
- DCHECK_EQ(c, 0); |
- return *pixels->getAddr8(std::max(0, std::min(x, pixels->width() - 1)), |
- std::max(0, std::min(y, pixels->height() - 1))); |
- } |
- } |
- |
- // Set a single channel value. Works for 4-channel and single channel |
- // bitmaps. Clamp x/y. |
- void SetChannel(SkBitmap* pixels, int x, int y, int c, int v) { |
- DCHECK_GE(x, 0); |
- DCHECK_GE(y, 0); |
- DCHECK_LT(x, pixels->width()); |
- DCHECK_LT(y, pixels->height()); |
- if (pixels->bytesPerPixel() == 4) { |
- uint32_t* data = pixels->getAddr32(x, y); |
- v = std::max(0, std::min(v, 255)); |
- *data = (*data & ~(0xffu << (c * 8))) | (v << (c * 8)); |
- } else { |
- DCHECK_EQ(pixels->bytesPerPixel(), 1); |
- DCHECK_EQ(c, 0); |
- uint8_t* data = pixels->getAddr8(x, y); |
- v = std::max(0, std::min(v, 255)); |
- *data = v; |
- } |
- } |
- |
- // Print all the R, G, B or A values from an SkBitmap in a |
- // human-readable format. |
- void PrintChannel(SkBitmap* pixels, int c) { |
- for (int y = 0; y < pixels->height(); y++) { |
- std::string formatted; |
- for (int x = 0; x < pixels->width(); x++) { |
- formatted.append(base::StringPrintf("%3d, ", Channel(pixels, x, y, c))); |
- } |
- LOG(ERROR) << formatted; |
- } |
- } |
- |
- // Get a single R, G, B or A value as a float. |
- float ChannelAsFloat(SkBitmap* pixels, int x, int y, int c) { |
- return Channel(pixels, x, y, c) / 255.0; |
- } |
- |
- // Works like a GL_LINEAR lookup on an SkBitmap. |
- float Bilinear(SkBitmap* pixels, float x, float y, int c) { |
- x -= 0.5; |
- y -= 0.5; |
- int base_x = static_cast<int>(floorf(x)); |
- int base_y = static_cast<int>(floorf(y)); |
- x -= base_x; |
- y -= base_y; |
- return (ChannelAsFloat(pixels, base_x, base_y, c) * (1 - x) * (1 - y) + |
- ChannelAsFloat(pixels, base_x + 1, base_y, c) * x * (1 - y) + |
- ChannelAsFloat(pixels, base_x, base_y + 1, c) * (1 - x) * y + |
- ChannelAsFloat(pixels, base_x + 1, base_y + 1, c) * x * y); |
- } |
- |
- void FlipSKBitmap(SkBitmap* bitmap) { |
- int bpp = bitmap->bytesPerPixel(); |
- DCHECK(bpp == 4 || bpp == 1); |
- int top_line = 0; |
- int bottom_line = bitmap->height() - 1; |
- while (top_line < bottom_line) { |
- for (int x = 0; x < bitmap->width(); x++) { |
- bpp == 4 ? std::swap(*bitmap->getAddr32(x, top_line), |
- *bitmap->getAddr32(x, bottom_line)) |
- : std::swap(*bitmap->getAddr8(x, top_line), |
- *bitmap->getAddr8(x, bottom_line)); |
- } |
- top_line++; |
- bottom_line--; |
- } |
- } |
- |
- // Note: Left/Right means Top/Bottom when used for Y dimension. |
- enum Margin { |
- MarginLeft, |
- MarginMiddle, |
- MarginRight, |
- MarginInvalid, |
- }; |
- |
- static Margin NextMargin(Margin m) { |
- switch (m) { |
- case MarginLeft: |
- return MarginMiddle; |
- case MarginMiddle: |
- return MarginRight; |
- case MarginRight: |
- return MarginInvalid; |
- default: |
- return MarginInvalid; |
- } |
- } |
- |
- int compute_margin(int insize, int outsize, Margin m) { |
- int available = outsize - insize; |
- switch (m) { |
- default: |
- EXPECT_TRUE(false) << "This should not happen."; |
- return 0; |
- case MarginLeft: |
- return 0; |
- case MarginMiddle: |
- return (available / 2) & ~1; |
- case MarginRight: |
- return available; |
- } |
- } |
- |
- // Convert 0.0 - 1.0 to 0 - 255 |
- int float_to_byte(float v) { |
- int ret = static_cast<int>(floorf(v * 255.0f + 0.5f)); |
- if (ret < 0) { |
- return 0; |
- } |
- if (ret > 255) { |
- return 255; |
- } |
- return ret; |
- } |
- |
- static void callcallback(const base::Callback<void()>& callback, |
- bool result) { |
- callback.Run(); |
- } |
- |
- void PrintPlane(unsigned char* plane, int xsize, int stride, int ysize) { |
- for (int y = 0; y < ysize; y++) { |
- std::string formatted; |
- for (int x = 0; x < xsize; x++) { |
- formatted.append(base::StringPrintf("%3d, ", plane[y * stride + x])); |
- } |
- LOG(ERROR) << formatted << " (" << (plane + y * stride) << ")"; |
- } |
- } |
- |
- // Compare two planes make sure that each component of each pixel |
- // is no more than |maxdiff| apart. |
- void ComparePlane(unsigned char* truth, |
- int truth_stride, |
- unsigned char* other, |
- int other_stride, |
- int maxdiff, |
- int xsize, |
- int ysize, |
- SkBitmap* source, |
- std::string message) { |
- for (int x = 0; x < xsize; x++) { |
- for (int y = 0; y < ysize; y++) { |
- int a = other[y * other_stride + x]; |
- int b = truth[y * truth_stride + x]; |
- EXPECT_NEAR(a, b, maxdiff) << " x=" << x << " y=" << y << " " |
- << message; |
- if (std::abs(a - b) > maxdiff) { |
- LOG(ERROR) << "-------expected--------"; |
- PrintPlane(truth, xsize, truth_stride, ysize); |
- LOG(ERROR) << "-------actual--------"; |
- PrintPlane(other, xsize, other_stride, ysize); |
- if (source) { |
- LOG(ERROR) << "-------before yuv conversion: red--------"; |
- PrintChannel(source, 0); |
- LOG(ERROR) << "-------before yuv conversion: green------"; |
- PrintChannel(source, 1); |
- LOG(ERROR) << "-------before yuv conversion: blue-------"; |
- PrintChannel(source, 2); |
- } |
- return; |
- } |
- } |
- } |
- } |
- |
- // YUV readback test. Create a test pattern, convert to YUV |
- // with reference implementation and compare to what gl_helper |
- // returns. |
- void TestYUVReadback(int xsize, |
- int ysize, |
- int output_xsize, |
- int output_ysize, |
- int xmargin, |
- int ymargin, |
- int test_pattern, |
- bool flip, |
- bool use_mrt, |
- display_compositor::GLHelper::ScalerQuality quality) { |
- GLuint src_texture; |
- gl_->GenTextures(1, &src_texture); |
- SkBitmap input_pixels; |
- input_pixels.allocN32Pixels(xsize, ysize); |
- |
- for (int x = 0; x < xsize; ++x) { |
- for (int y = 0; y < ysize; ++y) { |
- switch (test_pattern) { |
- case 0: // Smooth test pattern |
- SetChannel(&input_pixels, x, y, 0, x * 10); |
- SetChannel(&input_pixels, x, y, 1, y * 10); |
- SetChannel(&input_pixels, x, y, 2, (x + y) * 10); |
- SetChannel(&input_pixels, x, y, 3, 255); |
- break; |
- case 1: // Small blocks |
- SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0); |
- SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0); |
- SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0); |
- SetChannel(&input_pixels, x, y, 3, 255); |
- break; |
- case 2: // Medium blocks |
- SetChannel(&input_pixels, x, y, 0, 10 + x / 2 * 50); |
- SetChannel(&input_pixels, x, y, 1, 10 + y / 3 * 50); |
- SetChannel(&input_pixels, x, y, 2, (x + y) / 5 * 50 + 5); |
- SetChannel(&input_pixels, x, y, 3, 255); |
- break; |
- } |
- } |
- } |
- |
- gl_->BindTexture(GL_TEXTURE_2D, src_texture); |
- gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsize, ysize, 0, GL_RGBA, |
- GL_UNSIGNED_BYTE, input_pixels.getPixels()); |
- |
- gpu::Mailbox mailbox; |
- gl_->GenMailboxCHROMIUM(mailbox.name); |
- EXPECT_FALSE(mailbox.IsZero()); |
- gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); |
- const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); |
- gl_->ShallowFlushCHROMIUM(); |
- |
- gpu::SyncToken sync_token; |
- gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); |
- |
- std::string message = base::StringPrintf( |
- "input size: %dx%d " |
- "output size: %dx%d " |
- "margin: %dx%d " |
- "pattern: %d %s %s", |
- xsize, ysize, output_xsize, output_ysize, xmargin, ymargin, |
- test_pattern, flip ? "flip" : "noflip", flip ? "mrt" : "nomrt"); |
- std::unique_ptr<ReadbackYUVInterface> yuv_reader( |
- helper_->CreateReadbackPipelineYUV( |
- quality, gfx::Size(xsize, ysize), gfx::Rect(0, 0, xsize, ysize), |
- gfx::Size(xsize, ysize), flip, use_mrt)); |
- |
- scoped_refptr<media::VideoFrame> output_frame = |
- media::VideoFrame::CreateFrame( |
- media::PIXEL_FORMAT_YV12, |
- // The coded size of the output frame is rounded up to the next |
- // 16-byte boundary. This tests that the readback is being |
- // positioned inside the frame's visible region, and not dependent |
- // on its coded size. |
- gfx::Size((output_xsize + 15) & ~15, (output_ysize + 15) & ~15), |
- gfx::Rect(0, 0, output_xsize, output_ysize), |
- gfx::Size(output_xsize, output_ysize), |
- base::TimeDelta::FromSeconds(0)); |
- scoped_refptr<media::VideoFrame> truth_frame = |
- media::VideoFrame::CreateFrame( |
- media::PIXEL_FORMAT_YV12, gfx::Size(output_xsize, output_ysize), |
- gfx::Rect(0, 0, output_xsize, output_ysize), |
- gfx::Size(output_xsize, output_ysize), |
- base::TimeDelta::FromSeconds(0)); |
- |
- base::RunLoop run_loop; |
- yuv_reader->ReadbackYUV(mailbox, sync_token, output_frame->visible_rect(), |
- output_frame->stride(media::VideoFrame::kYPlane), |
- output_frame->data(media::VideoFrame::kYPlane), |
- output_frame->stride(media::VideoFrame::kUPlane), |
- output_frame->data(media::VideoFrame::kUPlane), |
- output_frame->stride(media::VideoFrame::kVPlane), |
- output_frame->data(media::VideoFrame::kVPlane), |
- gfx::Point(xmargin, ymargin), |
- base::Bind(&callcallback, run_loop.QuitClosure())); |
- |
- const gfx::Rect paste_rect(gfx::Point(xmargin, ymargin), |
- gfx::Size(xsize, ysize)); |
- media::LetterboxYUV(output_frame.get(), paste_rect); |
- run_loop.Run(); |
- |
- if (flip) { |
- FlipSKBitmap(&input_pixels); |
- } |
- |
- unsigned char* Y = truth_frame->visible_data(media::VideoFrame::kYPlane); |
- unsigned char* U = truth_frame->visible_data(media::VideoFrame::kUPlane); |
- unsigned char* V = truth_frame->visible_data(media::VideoFrame::kVPlane); |
- int32_t y_stride = truth_frame->stride(media::VideoFrame::kYPlane); |
- int32_t u_stride = truth_frame->stride(media::VideoFrame::kUPlane); |
- int32_t v_stride = truth_frame->stride(media::VideoFrame::kVPlane); |
- memset(Y, 0x00, y_stride * output_ysize); |
- memset(U, 0x80, u_stride * output_ysize / 2); |
- memset(V, 0x80, v_stride * output_ysize / 2); |
- |
- const float kRGBtoYColorWeights[] = {0.257f, 0.504f, 0.098f, 0.0625f}; |
- const float kRGBtoUColorWeights[] = {-0.148f, -0.291f, 0.439f, 0.5f}; |
- const float kRGBtoVColorWeights[] = {0.439f, -0.368f, -0.071f, 0.5f}; |
- |
- for (int y = 0; y < ysize; y++) { |
- for (int x = 0; x < xsize; x++) { |
- Y[(y + ymargin) * y_stride + x + xmargin] = float_to_byte( |
- ChannelAsFloat(&input_pixels, x, y, 0) * kRGBtoYColorWeights[0] + |
- ChannelAsFloat(&input_pixels, x, y, 1) * kRGBtoYColorWeights[1] + |
- ChannelAsFloat(&input_pixels, x, y, 2) * kRGBtoYColorWeights[2] + |
- kRGBtoYColorWeights[3]); |
- } |
- } |
- |
- for (int y = 0; y < ysize / 2; y++) { |
- for (int x = 0; x < xsize / 2; x++) { |
- U[(y + ymargin / 2) * u_stride + x + xmargin / 2] = |
- float_to_byte(Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * |
- kRGBtoUColorWeights[0] + |
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * |
- kRGBtoUColorWeights[1] + |
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * |
- kRGBtoUColorWeights[2] + |
- kRGBtoUColorWeights[3]); |
- V[(y + ymargin / 2) * v_stride + x + xmargin / 2] = |
- float_to_byte(Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * |
- kRGBtoVColorWeights[0] + |
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * |
- kRGBtoVColorWeights[1] + |
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * |
- kRGBtoVColorWeights[2] + |
- kRGBtoVColorWeights[3]); |
- } |
- } |
- |
- ComparePlane( |
- Y, y_stride, output_frame->visible_data(media::VideoFrame::kYPlane), |
- output_frame->stride(media::VideoFrame::kYPlane), 2, output_xsize, |
- output_ysize, &input_pixels, message + " Y plane"); |
- ComparePlane( |
- U, u_stride, output_frame->visible_data(media::VideoFrame::kUPlane), |
- output_frame->stride(media::VideoFrame::kUPlane), 2, output_xsize / 2, |
- output_ysize / 2, &input_pixels, message + " U plane"); |
- ComparePlane( |
- V, v_stride, output_frame->visible_data(media::VideoFrame::kVPlane), |
- output_frame->stride(media::VideoFrame::kVPlane), 2, output_xsize / 2, |
- output_ysize / 2, &input_pixels, message + " V plane"); |
- |
- gl_->DeleteTextures(1, &src_texture); |
- } |
- |
- std::unique_ptr<gpu::GLInProcessContext> context_; |
- gpu::gles2::GLES2Interface* gl_; |
- std::unique_ptr<display_compositor::GLHelper> helper_; |
- gfx::DisableNullDrawGLBindings enable_pixel_output_; |
-}; |
- |
-TEST_F(YUVReadbackTest, YUVReadbackOptTest) { |
- // This test uses the gpu.service/gpu_decoder tracing events to detect how |
- // many scaling passes are actually performed by the YUV readback pipeline. |
- StartTracing(TRACE_DISABLED_BY_DEFAULT( |
- "gpu.service") "," TRACE_DISABLED_BY_DEFAULT("gpu_decoder")); |
- |
- TestYUVReadback(800, 400, 800, 400, 0, 0, 1, false, true, |
- display_compositor::GLHelper::SCALER_QUALITY_FAST); |
- |
- std::map<std::string, int> event_counts; |
- EndTracing(&event_counts); |
- int draw_buffer_calls = event_counts["kDrawBuffersEXTImmediate"]; |
- int draw_arrays_calls = event_counts["kDrawArrays"]; |
- VLOG(1) << "Draw buffer calls: " << draw_buffer_calls; |
- VLOG(1) << "DrawArrays calls: " << draw_arrays_calls; |
- |
- if (draw_buffer_calls) { |
- // When using MRT, the YUV readback code should only |
- // execute two draw arrays, and scaling should be integrated |
- // into those two calls since we are using the FAST scalign |
- // quality. |
- EXPECT_EQ(2, draw_arrays_calls); |
- } else { |
- // When not using MRT, there are three passes for the YUV, |
- // and one for the scaling. |
- EXPECT_EQ(4, draw_arrays_calls); |
- } |
-} |
- |
-class YUVReadbackPixelTest |
- : public YUVReadbackTest, |
- public ::testing::WithParamInterface< |
- std::tr1::tuple<bool, bool, unsigned int, unsigned int>> {}; |
- |
-TEST_P(YUVReadbackPixelTest, Test) { |
- bool flip = std::tr1::get<0>(GetParam()); |
- bool use_mrt = std::tr1::get<1>(GetParam()); |
- unsigned int x = std::tr1::get<2>(GetParam()); |
- unsigned int y = std::tr1::get<3>(GetParam()); |
- |
- for (unsigned int ox = x; ox < arraysize(kYUVReadbackSizes); ox++) { |
- for (unsigned int oy = y; oy < arraysize(kYUVReadbackSizes); oy++) { |
- // If output is a subsection of the destination frame, (letterbox) |
- // then try different variations of where the subsection goes. |
- for (Margin xm = x < ox ? MarginLeft : MarginRight; xm <= MarginRight; |
- xm = NextMargin(xm)) { |
- for (Margin ym = y < oy ? MarginLeft : MarginRight; ym <= MarginRight; |
- ym = NextMargin(ym)) { |
- for (int pattern = 0; pattern < 3; pattern++) { |
- TestYUVReadback( |
- kYUVReadbackSizes[x], kYUVReadbackSizes[y], |
- kYUVReadbackSizes[ox], kYUVReadbackSizes[oy], |
- compute_margin(kYUVReadbackSizes[x], kYUVReadbackSizes[ox], xm), |
- compute_margin(kYUVReadbackSizes[y], kYUVReadbackSizes[oy], ym), |
- pattern, flip, use_mrt, |
- display_compositor::GLHelper::SCALER_QUALITY_GOOD); |
- if (HasFailure()) { |
- return; |
- } |
- } |
- } |
- } |
- } |
- } |
-} |
- |
-// First argument is intentionally empty. |
-INSTANTIATE_TEST_CASE_P( |
- , |
- YUVReadbackPixelTest, |
- ::testing::Combine( |
- ::testing::Bool(), |
- ::testing::Bool(), |
- ::testing::Range<unsigned int>(0, arraysize(kYUVReadbackSizes)), |
- ::testing::Range<unsigned int>(0, arraysize(kYUVReadbackSizes)))); |
- |
-} // namespace display_compositor |