1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
// Copyright 2012 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 "config.h"
#include "cc/software_renderer.h"
#include "cc/quad_sink.h"
#include "cc/render_pass.h"
#include "cc/render_pass_draw_quad.h"
#include "cc/settings.h"
#include "cc/single_thread_proxy.h" // For DebugScopedSetImplThread
#include "cc/solid_color_draw_quad.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/fake_web_compositor_output_surface.h"
#include "cc/test/fake_web_compositor_software_output_device.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/render_pass_test_common.h"
#include "cc/test/test_common.h"
#include "cc/tile_draw_quad.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using namespace cc;
using namespace WebKit;
using namespace WebKitTests;
namespace {
class SoftwareRendererTest : public testing::Test, public RendererClient {
public:
void initializeRenderer() {
m_outputSurface = FakeWebCompositorOutputSurface::createSoftware(scoped_ptr<WebKit::WebCompositorSoftwareOutputDevice>(new FakeWebCompositorSoftwareOutputDevice));
m_resourceProvider = ResourceProvider::create(m_outputSurface.get());
m_renderer = SoftwareRenderer::create(this, resourceProvider(), softwareDevice());
}
WebCompositorSoftwareOutputDevice* softwareDevice() const { return m_outputSurface->softwareDevice(); }
FakeWebCompositorOutputSurface* outputSurface() const { return m_outputSurface.get(); }
ResourceProvider* resourceProvider() const { return m_resourceProvider.get(); }
SoftwareRenderer* renderer() const { return m_renderer.get(); }
void setViewportSize(IntSize viewportSize) { m_viewportSize = viewportSize; }
// RendererClient implementation.
virtual const IntSize& deviceViewportSize() const OVERRIDE { return m_viewportSize; }
virtual const LayerTreeSettings& settings() const OVERRIDE { return m_settings; }
virtual void didLoseContext() OVERRIDE { }
virtual void onSwapBuffersComplete() OVERRIDE { }
virtual void setFullRootLayerDamage() OVERRIDE { }
virtual void setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { };
virtual void enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { };
protected:
DebugScopedSetImplThread m_alwaysImplThread;
scoped_ptr<FakeWebCompositorOutputSurface> m_outputSurface;
scoped_ptr<ResourceProvider> m_resourceProvider;
scoped_ptr<SoftwareRenderer> m_renderer;
IntSize m_viewportSize;
LayerTreeSettings m_settings;
};
TEST_F(SoftwareRendererTest, solidColorQuad)
{
IntSize outerSize(100, 100);
int outerPixels = outerSize.width() * outerSize.height();
IntSize innerSize(98, 98);
IntRect outerRect(IntPoint(), outerSize);
IntRect innerRect(IntPoint(1, 1), innerSize);
setViewportSize(outerSize);
initializeRenderer();
scoped_ptr<SharedQuadState> sharedQuadState = SharedQuadState::create(WebTransformationMatrix(), outerRect, outerRect, 1.0, true);
RenderPass::Id rootRenderPassId = RenderPass::Id(1, 1);
scoped_ptr<TestRenderPass> rootRenderPass = TestRenderPass::create(rootRenderPassId, outerRect, WebTransformationMatrix());
scoped_ptr<DrawQuad> outerQuad = SolidColorDrawQuad::create(sharedQuadState.get(), outerRect, SK_ColorYELLOW).PassAs<DrawQuad>();
scoped_ptr<DrawQuad> innerQuad = SolidColorDrawQuad::create(sharedQuadState.get(), innerRect, SK_ColorCYAN).PassAs<DrawQuad>();
rootRenderPass->appendQuad(innerQuad.Pass());
rootRenderPass->appendQuad(outerQuad.Pass());
RenderPassList list;
RenderPassIdHashMap hashmap;
list.push_back(rootRenderPass.get());
hashmap.add(rootRenderPassId, rootRenderPass.PassAs<RenderPass>());
renderer()->drawFrame(list, hashmap);
scoped_array<SkColor> pixels(new SkColor[deviceViewportSize().width() * deviceViewportSize().height()]);
renderer()->getFramebufferPixels(pixels.get(), outerRect);
// FIXME: This fails on Android. Endianness maybe?
// Yellow: expects 0xFFFFFF00, was 0xFF00FFFF on android.
// Cyan: expects 0xFF00FFFF, was 0xFFFFFF00 on android.
// http://crbug.com/154528
#ifndef OS_ANDROID
EXPECT_EQ(SK_ColorYELLOW, pixels[0]);
EXPECT_EQ(SK_ColorYELLOW, pixels[outerPixels - 1]);
EXPECT_EQ(SK_ColorCYAN, pixels[outerSize.width() + 1]);
EXPECT_EQ(SK_ColorCYAN, pixels[outerPixels - outerSize.width() - 2]);
#endif
}
TEST_F(SoftwareRendererTest, tileQuad)
{
IntSize outerSize(100, 100);
int outerPixels = outerSize.width() * outerSize.height();
IntSize innerSize(98, 98);
int innerPixels = innerSize.width() * innerSize.height();
IntRect outerRect(IntPoint(), outerSize);
IntRect innerRect(IntPoint(1, 1), innerSize);
setViewportSize(outerSize);
initializeRenderer();
ResourceProvider::ResourceId resourceYellow = resourceProvider()->createResource(1, outerSize, GL_RGBA, ResourceProvider::TextureUsageAny);
ResourceProvider::ResourceId resourceCyan = resourceProvider()->createResource(1, innerSize, GL_RGBA, ResourceProvider::TextureUsageAny);
SkColor yellow = SK_ColorYELLOW;
SkColor cyan = SK_ColorCYAN;
scoped_array<SkColor> yellowPixels(new SkColor[outerPixels]);
scoped_array<SkColor> cyanPixels(new SkColor[innerPixels]);
for (int i = 0; i < outerPixels; i++)
yellowPixels[i] = yellow;
for (int i = 0; i < innerPixels; i++)
cyanPixels[i] = cyan;
resourceProvider()->upload(resourceYellow, reinterpret_cast<uint8_t*>(yellowPixels.get()), IntRect(IntPoint(), outerSize), IntRect(IntPoint(), outerSize), IntSize());
resourceProvider()->upload(resourceCyan, reinterpret_cast<uint8_t*>(cyanPixels.get()), IntRect(IntPoint(), innerSize), IntRect(IntPoint(), innerSize), IntSize());
IntRect rect = IntRect(IntPoint(), deviceViewportSize());
scoped_ptr<SharedQuadState> sharedQuadState = SharedQuadState::create(WebTransformationMatrix(), outerRect, outerRect, 1.0, true);
RenderPass::Id rootRenderPassId = RenderPass::Id(1, 1);
scoped_ptr<TestRenderPass> rootRenderPass = TestRenderPass::create(rootRenderPassId, IntRect(IntPoint(), deviceViewportSize()), WebTransformationMatrix());
scoped_ptr<DrawQuad> outerQuad = TileDrawQuad::create(sharedQuadState.get(), outerRect, outerRect, resourceYellow, IntPoint(), outerSize, 0, false, false, false, false, false).PassAs<DrawQuad>();
scoped_ptr<DrawQuad> innerQuad = TileDrawQuad::create(sharedQuadState.get(), innerRect, innerRect, resourceCyan, IntPoint(), innerSize, 0, false, false, false, false, false).PassAs<DrawQuad>();
rootRenderPass->appendQuad(innerQuad.Pass());
rootRenderPass->appendQuad(outerQuad.Pass());
RenderPassList list;
RenderPassIdHashMap hashmap;
list.push_back(rootRenderPass.get());
hashmap.add(rootRenderPassId, rootRenderPass.PassAs<RenderPass>());
renderer()->drawFrame(list, hashmap);
scoped_array<SkColor> pixels(new SkColor[deviceViewportSize().width() * deviceViewportSize().height()]);
renderer()->getFramebufferPixels(pixels.get(), outerRect);
EXPECT_EQ(SK_ColorYELLOW, pixels[0]);
EXPECT_EQ(SK_ColorYELLOW, pixels[outerPixels - 1]);
EXPECT_EQ(SK_ColorCYAN, pixels[outerSize.width() + 1]);
EXPECT_EQ(SK_ColorCYAN, pixels[outerPixels - outerSize.width() - 2]);
}
} // namespace
|