Make reftests work for sky.
-Add a --testing flag to sky_viewer and cause it to paint into an SkBitmap instead of a ganesh surface so we can get the pixels out. -Add GetPixelsForTesting to layer.cc to actually grab out the pixels. -Add a reftest and a mismatch reftest. They need a setTimeout after the load event. Unclear why or what the right fix is. Maybe we should give internals some way to force the paint? If we don't have the setTimeout, we paint a white page (so we do a paint, but with no content). -Add a DisplayDelegate to Layer so that Viewer can decide whether to use the real ganesh backend or the SkBitmap one without littering the whole code-base with is_testing bools and logic. R=esprehn@chromium.org Review URL: https://codereview.chromium.org/797063002
This commit is contained in:
parent
70a7a3a0ee
commit
8673d5e31d
@ -4,6 +4,12 @@
|
||||
|
||||
source_set("compositor") {
|
||||
sources = [
|
||||
"display_delegate.cc",
|
||||
"display_delegate.h",
|
||||
"display_delegate_bitmap.cc",
|
||||
"display_delegate_bitmap.h",
|
||||
"display_delegate_ganesh.cc",
|
||||
"display_delegate_ganesh.h",
|
||||
"layer.cc",
|
||||
"layer.h",
|
||||
"layer_client.cc",
|
||||
|
24
engine/src/flutter/compositor/display_delegate.cc
Normal file
24
engine/src/flutter/compositor/display_delegate.cc
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2014 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 "sky/compositor/display_delegate.h"
|
||||
|
||||
namespace sky {
|
||||
|
||||
static CreateDisplayDelegate createDisplayDelegateFunction = 0;
|
||||
|
||||
void DisplayDelegate::setDisplayDelegateCreateFunction(CreateDisplayDelegate createFunction)
|
||||
{
|
||||
DCHECK(createFunction);
|
||||
DCHECK(!createDisplayDelegateFunction);
|
||||
createDisplayDelegateFunction = createFunction;
|
||||
}
|
||||
|
||||
DisplayDelegate* DisplayDelegate::create(LayerClient* client)
|
||||
{
|
||||
DCHECK(createDisplayDelegateFunction);
|
||||
return createDisplayDelegateFunction(client);
|
||||
}
|
||||
|
||||
} // namespace sky
|
43
engine/src/flutter/compositor/display_delegate.h
Normal file
43
engine/src/flutter/compositor/display_delegate.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef SKY_COMPOSITOR_DISPLAY_DELEGATE_H_
|
||||
#define SKY_COMPOSITOR_DISPLAY_DELEGATE_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "mojo/skia/ganesh_surface.h"
|
||||
|
||||
class SkCanvas;
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
}
|
||||
|
||||
namespace sky {
|
||||
|
||||
class DisplayDelegate;
|
||||
class LayerClient;
|
||||
|
||||
typedef DisplayDelegate* (*CreateDisplayDelegate)(LayerClient*);
|
||||
|
||||
class DisplayDelegate {
|
||||
public:
|
||||
DisplayDelegate() {}
|
||||
virtual ~DisplayDelegate() {}
|
||||
|
||||
static DisplayDelegate* create(LayerClient*);
|
||||
static void setDisplayDelegateCreateFunction(CreateDisplayDelegate);
|
||||
|
||||
virtual void GetPixelsForTesting(std::vector<unsigned char>* pixels) = 0;
|
||||
virtual void Paint(mojo::GaneshSurface& surface, const gfx::Rect& size) = 0;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DisplayDelegate);
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace sky
|
||||
|
||||
#endif // SKY_COMPOSITOR_DISPLAY_DELEGATE_H_
|
39
engine/src/flutter/compositor/display_delegate_bitmap.cc
Normal file
39
engine/src/flutter/compositor/display_delegate_bitmap.cc
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2014 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 "sky/compositor/display_delegate_bitmap.h"
|
||||
|
||||
#include "sky/compositor/layer_client.h"
|
||||
#include "third_party/skia/include/core/SkBitmapDevice.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "ui/gfx/codec/png_codec.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
namespace sky {
|
||||
|
||||
DisplayDelegateBitmap::DisplayDelegateBitmap(LayerClient* client)
|
||||
: client_(client) {}
|
||||
|
||||
DisplayDelegateBitmap::~DisplayDelegateBitmap() {}
|
||||
|
||||
DisplayDelegate* DisplayDelegateBitmap::create(LayerClient* client) {
|
||||
return new DisplayDelegateBitmap(client);
|
||||
}
|
||||
|
||||
void DisplayDelegateBitmap::GetPixelsForTesting(std::vector<unsigned char>* pixels) {
|
||||
gfx::PNGCodec::EncodeBGRASkBitmap(bitmap_, false, pixels);
|
||||
}
|
||||
|
||||
void DisplayDelegateBitmap::Paint(mojo::GaneshSurface& surface, const gfx::Rect& size) {
|
||||
bitmap_.allocN32Pixels(size.width(), size.height());
|
||||
SkBitmapDevice device(bitmap_);
|
||||
SkCanvas canvas(&device);
|
||||
// Draw red so we can see when we fail to paint.
|
||||
canvas.drawColor(SK_ColorRED);
|
||||
|
||||
client_->PaintContents(&canvas, size);
|
||||
canvas.flush();
|
||||
}
|
||||
|
||||
} // namespace sky
|
33
engine/src/flutter/compositor/display_delegate_bitmap.h
Normal file
33
engine/src/flutter/compositor/display_delegate_bitmap.h
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef SKY_COMPOSITOR_DISPLAY_DELEGATE_BITMAP_H_
|
||||
#define SKY_COMPOSITOR_DISPLAY_DELEGATE_BITMAP_H_
|
||||
|
||||
#include "sky/compositor/display_delegate.h"
|
||||
|
||||
namespace sky {
|
||||
|
||||
class LayerClient;
|
||||
|
||||
class DisplayDelegateBitmap final : public DisplayDelegate {
|
||||
public:
|
||||
explicit DisplayDelegateBitmap(LayerClient* client);
|
||||
~DisplayDelegateBitmap() override;
|
||||
|
||||
static DisplayDelegate* create(LayerClient* client);
|
||||
|
||||
void GetPixelsForTesting(std::vector<unsigned char>* pixels) override;
|
||||
void Paint(mojo::GaneshSurface& surface, const gfx::Rect& size) override;
|
||||
|
||||
private:
|
||||
SkBitmap bitmap_;
|
||||
LayerClient* client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DisplayDelegateBitmap);
|
||||
};
|
||||
|
||||
} // namespace sky
|
||||
|
||||
#endif // SKY_COMPOSITOR_DISPLAY_DELEGATE_BITMAP_H_
|
27
engine/src/flutter/compositor/display_delegate_ganesh.cc
Normal file
27
engine/src/flutter/compositor/display_delegate_ganesh.cc
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2014 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 "sky/compositor/display_delegate_ganesh.h"
|
||||
|
||||
#include "sky/compositor/layer_client.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace sky {
|
||||
|
||||
DisplayDelegate* DisplayDelegateGanesh::create(LayerClient* client) {
|
||||
return new DisplayDelegateGanesh(client);
|
||||
}
|
||||
|
||||
void DisplayDelegateGanesh::GetPixelsForTesting(std::vector<unsigned char>* pixels) {
|
||||
// TODO(ojan): When we change notifyTestComplete to only GetPixelsForTesting
|
||||
// in pixel/ref tests, add a NOTREACHED() here.
|
||||
}
|
||||
|
||||
void DisplayDelegateGanesh::Paint(mojo::GaneshSurface& surface, const gfx::Rect& size) {
|
||||
SkCanvas* canvas = surface.canvas();
|
||||
client_->PaintContents(canvas, size);
|
||||
canvas->flush();
|
||||
}
|
||||
|
||||
} // namespace sky
|
31
engine/src/flutter/compositor/display_delegate_ganesh.h
Normal file
31
engine/src/flutter/compositor/display_delegate_ganesh.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#ifndef SKY_COMPOSITOR_DISPLAY_DELEGATE_GANESH_H_
|
||||
#define SKY_COMPOSITOR_DISPLAY_DELEGATE_GANESH_H_
|
||||
|
||||
#include "sky/compositor/display_delegate.h"
|
||||
|
||||
namespace sky {
|
||||
|
||||
class LayerClient;
|
||||
|
||||
class DisplayDelegateGanesh final : public DisplayDelegate {
|
||||
public:
|
||||
explicit DisplayDelegateGanesh(LayerClient* client) : client_(client) {}
|
||||
~DisplayDelegateGanesh() override {}
|
||||
|
||||
static DisplayDelegate* create(LayerClient* client);
|
||||
|
||||
void GetPixelsForTesting(std::vector<unsigned char>* pixels) override;
|
||||
void Paint(mojo::GaneshSurface& surface, const gfx::Rect& size) override;
|
||||
|
||||
private:
|
||||
LayerClient* client_;
|
||||
DISALLOW_COPY_AND_ASSIGN(DisplayDelegateGanesh);
|
||||
};
|
||||
|
||||
} // namespace sky
|
||||
|
||||
#endif // SKY_COMPOSITOR_DISPLAY_DELEGATE_GANESH_H_
|
@ -6,25 +6,29 @@
|
||||
|
||||
#include "base/debug/trace_event.h"
|
||||
#include "mojo/skia/ganesh_surface.h"
|
||||
#include "sky/compositor/display_delegate.h"
|
||||
#include "sky/compositor/layer_host.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
|
||||
namespace sky {
|
||||
|
||||
Layer::Layer(LayerClient* client) : client_(client), host_(nullptr) {
|
||||
Layer::Layer(LayerClient* client)
|
||||
: client_(client),
|
||||
host_(nullptr) {
|
||||
delegate_.reset(DisplayDelegate::create(client));
|
||||
}
|
||||
|
||||
Layer::~Layer() {
|
||||
}
|
||||
|
||||
void Layer::ClearClient() {
|
||||
client_ = nullptr;
|
||||
}
|
||||
|
||||
void Layer::SetSize(const gfx::Size& size) {
|
||||
size_ = size;
|
||||
}
|
||||
|
||||
void Layer::GetPixelsForTesting(std::vector<unsigned char>* pixels) {
|
||||
delegate_->GetPixelsForTesting(pixels);
|
||||
}
|
||||
|
||||
void Layer::Display() {
|
||||
TRACE_EVENT0("sky", "Layer::Display");
|
||||
|
||||
@ -33,11 +37,8 @@ void Layer::Display() {
|
||||
mojo::GaneshSurface surface(host_->ganesh_context(),
|
||||
host_->resource_manager()->CreateTexture(size_));
|
||||
|
||||
SkCanvas* canvas = surface.canvas();
|
||||
|
||||
gfx::Rect rect(size_);
|
||||
client_->PaintContents(canvas, rect);
|
||||
canvas->flush();
|
||||
delegate_->Paint(surface, rect);
|
||||
|
||||
texture_ = surface.TakeTexture();
|
||||
}
|
||||
|
@ -11,15 +11,16 @@
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
namespace sky {
|
||||
|
||||
class DisplayDelegate;
|
||||
class LayerHost;
|
||||
|
||||
class Layer : public base::RefCounted<Layer> {
|
||||
public:
|
||||
explicit Layer(LayerClient* client);
|
||||
|
||||
void ClearClient();
|
||||
|
||||
void SetSize(const gfx::Size& size);
|
||||
void GetPixelsForTesting(std::vector<unsigned char>* pixels);
|
||||
void Display();
|
||||
|
||||
scoped_ptr<mojo::GLTexture> GetTexture();
|
||||
@ -35,8 +36,8 @@ class Layer : public base::RefCounted<Layer> {
|
||||
LayerClient* client_;
|
||||
LayerHost* host_;
|
||||
gfx::Size size_;
|
||||
|
||||
scoped_ptr<mojo::GLTexture> texture_;
|
||||
scoped_ptr<DisplayDelegate> delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Layer);
|
||||
};
|
||||
|
@ -42,6 +42,10 @@ void LayerHost::SetRootLayer(scoped_refptr<Layer> layer) {
|
||||
root_layer_->set_host(this);
|
||||
}
|
||||
|
||||
void LayerHost::GetPixelsForTesting(std::vector<unsigned char>* pixels) {
|
||||
return root_layer_->GetPixelsForTesting(pixels);
|
||||
}
|
||||
|
||||
void LayerHost::OnSurfaceConnectionCreated() {
|
||||
DCHECK_EQ(state_, kWaitingForSurfaceService);
|
||||
state_ = kReadyForFrame;
|
||||
|
@ -41,6 +41,8 @@ class LayerHost : public SurfaceHolder::Client {
|
||||
void SetNeedsAnimate();
|
||||
void SetRootLayer(scoped_refptr<Layer> layer);
|
||||
|
||||
void GetPixelsForTesting(std::vector<unsigned char>* pixels);
|
||||
|
||||
private:
|
||||
enum State {
|
||||
kWaitingForSurfaceService,
|
||||
|
12
engine/src/flutter/tests/harness/reftest-expected.sky
Normal file
12
engine/src/flutter/tests/harness/reftest-expected.sky
Normal file
@ -0,0 +1,12 @@
|
||||
<foo>
|
||||
This is a reftest.
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
// TODO(ojan): requestAnimationFrame once we properly pump frames.
|
||||
// https://github.com/domokit/mojo/issues/32
|
||||
setTimeout(function() {
|
||||
internals.notifyTestComplete("");
|
||||
}, 100);
|
||||
})
|
||||
</script>
|
||||
</foo>
|
@ -0,0 +1,12 @@
|
||||
<foo>
|
||||
This is a mismatch reftest.
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
// TODO(ojan): requestAnimationFrame once we properly pump frames.
|
||||
// https://github.com/domokit/mojo/issues/32
|
||||
setTimeout(function() {
|
||||
internals.notifyTestComplete("");
|
||||
}, 100);
|
||||
})
|
||||
</script>
|
||||
</foo>
|
12
engine/src/flutter/tests/harness/reftest-mismatch.sky
Normal file
12
engine/src/flutter/tests/harness/reftest-mismatch.sky
Normal file
@ -0,0 +1,12 @@
|
||||
<foo>
|
||||
This is a mismatch reftest. Should not match.
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
// TODO(ojan): requestAnimationFrame once we properly pump frames.
|
||||
// https://github.com/domokit/mojo/issues/32
|
||||
setTimeout(function() {
|
||||
internals.notifyTestComplete("");
|
||||
}, 100);
|
||||
})
|
||||
</script>
|
||||
</foo>
|
12
engine/src/flutter/tests/harness/reftest.sky
Normal file
12
engine/src/flutter/tests/harness/reftest.sky
Normal file
@ -0,0 +1,12 @@
|
||||
<foo>
|
||||
This is a reftest.
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
// TODO(ojan): requestAnimationFrame once we properly pump frames.
|
||||
// https://github.com/domokit/mojo/issues/32
|
||||
setTimeout(function() {
|
||||
internals.notifyTestComplete("");
|
||||
}, 100);
|
||||
})
|
||||
</script>
|
||||
</foo>
|
@ -20,9 +20,10 @@ TestHarnessImpl::TestHarnessImpl(TestRunner* test_runner)
|
||||
TestHarnessImpl::~TestHarnessImpl() {
|
||||
}
|
||||
|
||||
void TestHarnessImpl::OnTestComplete(const mojo::String& test_result) {
|
||||
void TestHarnessImpl::OnTestComplete(const mojo::String& test_result,
|
||||
const mojo::Array<uint8_t> pixels) {
|
||||
if (test_runner_)
|
||||
test_runner_->OnTestComplete(test_result);
|
||||
test_runner_->OnTestComplete(test_result, pixels);
|
||||
}
|
||||
|
||||
void TestHarnessImpl::DispatchInputEvent(mojo::EventPtr event) {
|
||||
|
@ -21,7 +21,8 @@ class TestHarnessImpl : public mojo::InterfaceImpl<TestHarness> {
|
||||
|
||||
private:
|
||||
// TestHarness implementation.
|
||||
void OnTestComplete(const mojo::String& test_result) override;
|
||||
void OnTestComplete(const mojo::String& test_result,
|
||||
const mojo::Array<uint8_t> pixels) override;
|
||||
void DispatchInputEvent(mojo::EventPtr event) override;
|
||||
|
||||
base::WeakPtr<TestRunner> test_runner_;
|
||||
|
@ -17,10 +17,11 @@ TestRunnerClient::~TestRunnerClient() {
|
||||
}
|
||||
|
||||
TestRunner::TestRunner(TestRunnerClient* client, mojo::View* container,
|
||||
const std::string& url)
|
||||
const std::string& url, bool enable_pixel_dumping)
|
||||
: test_harness_factory_(this),
|
||||
client_(client),
|
||||
weak_ptr_factory_(this) {
|
||||
weak_ptr_factory_(this),
|
||||
enable_pixel_dumping_(enable_pixel_dumping) {
|
||||
CHECK(client);
|
||||
|
||||
scoped_ptr<mojo::ServiceProviderImpl> exported_services(
|
||||
@ -42,10 +43,22 @@ void TestRunner::OnTestStart() {
|
||||
std::cout.flush();
|
||||
}
|
||||
|
||||
void TestRunner::OnTestComplete(const std::string& test_result) {
|
||||
void TestRunner::OnTestComplete(const std::string& test_result,
|
||||
const mojo::Array<uint8_t>& pixels) {
|
||||
std::cout << "Content-Type: text/plain\n";
|
||||
std::cout << test_result << "\n";
|
||||
std::cout << "#EOF\n";
|
||||
|
||||
// TODO(ojan): Don't generate the pixels if enable_pixel_dumping_ is false.
|
||||
if (enable_pixel_dumping_) {
|
||||
// TODO(ojan): Add real hashes here once we want to do pixel tests.
|
||||
std::cout << "\nActualHash: FAKEHASHSTUB\n";
|
||||
std::cout << "Content-Type: image/png\n";
|
||||
std::cout << "Content-Length: " << pixels.size() << "\n";
|
||||
std::cout.write(
|
||||
reinterpret_cast<const char*>(&pixels[0]), pixels.size());
|
||||
}
|
||||
|
||||
std::cout << "#EOF\n";
|
||||
std::cout.flush();
|
||||
std::cerr << "#EOF\n";
|
||||
|
@ -27,7 +27,7 @@ class TestRunnerClient {
|
||||
class TestRunner {
|
||||
public:
|
||||
TestRunner(TestRunnerClient* client, mojo::View* container,
|
||||
const std::string& url);
|
||||
const std::string& url, bool enable_pixel_dumping);
|
||||
virtual ~TestRunner();
|
||||
|
||||
TestRunnerClient* client() const { return client_; }
|
||||
@ -35,12 +35,14 @@ class TestRunner {
|
||||
|
||||
base::WeakPtr<TestRunner> GetWeakPtr();
|
||||
void OnTestStart();
|
||||
void OnTestComplete(const std::string& test_result);
|
||||
void OnTestComplete(const std::string& test_result,
|
||||
const mojo::Array<uint8_t>& pixels);
|
||||
|
||||
private:
|
||||
TestHarnessFactory test_harness_factory_;
|
||||
TestRunnerClient* client_;
|
||||
base::WeakPtrFactory<TestRunner> weak_ptr_factory_;
|
||||
bool enable_pixel_dumping_;
|
||||
|
||||
MOJO_DISALLOW_COPY_AND_ASSIGN(TestRunner);
|
||||
};
|
||||
|
@ -23,10 +23,32 @@ namespace sky {
|
||||
namespace tester {
|
||||
namespace {
|
||||
|
||||
std::string WaitForURL() {
|
||||
struct UrlData {
|
||||
std::string url;
|
||||
std::cin >> url;
|
||||
return url;
|
||||
std::string expected_pixel_hash;
|
||||
bool enable_pixel_dumping = false;
|
||||
};
|
||||
|
||||
void WaitForURL(UrlData& data) {
|
||||
// A test name is formated like file:///path/to/test'--pixel-test'pixelhash
|
||||
std::cin >> data.url;
|
||||
|
||||
std::string pixel_switch;
|
||||
std::string::size_type separator_position = data.url.find('\'');
|
||||
if (separator_position != std::string::npos) {
|
||||
pixel_switch = data.url.substr(separator_position + 1);
|
||||
data.url.erase(separator_position);
|
||||
}
|
||||
|
||||
std::string pixel_hash;
|
||||
separator_position = pixel_switch.find('\'');
|
||||
if (separator_position != std::string::npos) {
|
||||
pixel_hash = pixel_switch.substr(separator_position + 1);
|
||||
pixel_switch.erase(separator_position);
|
||||
}
|
||||
|
||||
data.enable_pixel_dumping = pixel_switch == "--pixel-test";
|
||||
data.expected_pixel_hash = pixel_hash;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -110,8 +132,16 @@ class SkyTester : public mojo::ApplicationDelegate,
|
||||
|
||||
void Run() {
|
||||
DCHECK(!test_runner_);
|
||||
std::string url = url_from_args_.length() ? url_from_args_ : WaitForURL();
|
||||
test_runner_.reset(new TestRunner(this, content_, url));
|
||||
|
||||
UrlData data;
|
||||
if (url_from_args_.length()) {
|
||||
data.url = url_from_args_;
|
||||
} else {
|
||||
WaitForURL(data);
|
||||
}
|
||||
|
||||
test_runner_.reset(new TestRunner(this, content_, data.url,
|
||||
data.enable_pixel_dumping));
|
||||
}
|
||||
|
||||
void OnTestComplete() override {
|
||||
|
Loading…
x
Reference in New Issue
Block a user