cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / ppapi / tests / test_fullscreen.cc
blob2fddbdf9371e3234fffe64722913c2b1044249c2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/tests/test_fullscreen.h"
7 #include <stdio.h>
8 #include <string.h>
9 #include <string>
11 #include "ppapi/c/dev/ppb_testing_dev.h"
12 #include "ppapi/c/ppb_fullscreen.h"
13 #include "ppapi/cpp/image_data.h"
14 #include "ppapi/cpp/input_event.h"
15 #include "ppapi/cpp/instance.h"
16 #include "ppapi/cpp/module.h"
17 #include "ppapi/cpp/point.h"
18 #include "ppapi/tests/test_utils.h"
19 #include "ppapi/tests/testing_instance.h"
21 REGISTER_TEST_CASE(Fullscreen);
23 namespace {
25 const ColorPremul kOpaqueWhite = { 0xFF, 0xFF, 0xFF, 0xFF };
26 const ColorPremul kSheerRed = { 0x88, 0x88, 0x00, 0x00 };
27 const ColorPremul kSheerBlue = { 0x88, 0x00, 0x00, 0x88 };
28 const ColorPremul kOpaqueYellow = { 0xFF, 0xFF, 0xFF, 0x00 };
29 const int kBytesPerPixel = sizeof(uint32_t); // 4 bytes for BGRA or RGBA.
31 uint32_t FormatColor(PP_ImageDataFormat format, ColorPremul color) {
32 if (format == PP_IMAGEDATAFORMAT_BGRA_PREMUL)
33 return (color.A << 24) | (color.R << 16) | (color.G << 8) | (color.B);
34 else if (format == PP_IMAGEDATAFORMAT_RGBA_PREMUL)
35 return (color.A << 24) | (color.B << 16) | (color.G << 8) | (color.R);
36 else
37 return 0;
40 bool HasMidScreen(const pp::Rect& position, const pp::Size& screen_size) {
41 static int32_t mid_x = screen_size.width() / 2;
42 static int32_t mid_y = screen_size.height() / 2;
43 return (position.Contains(mid_x, mid_y));
46 void FlushCallbackCheckImageData(void* data, int32_t result) {
47 static_cast<TestFullscreen*>(data)->CheckPluginPaint();
50 } // namespace
52 TestFullscreen::TestFullscreen(TestingInstance* instance)
53 : TestCase(instance),
54 error_(),
55 screen_mode_(instance),
56 painted_color_(0),
57 fullscreen_pending_(false),
58 normal_pending_(false),
59 fullscreen_event_(instance->pp_instance()),
60 normal_event_(instance->pp_instance()) {
61 screen_mode_.GetScreenSize(&screen_size_);
64 bool TestFullscreen::Init() {
65 if (screen_size_.IsEmpty()) {
66 instance_->AppendError("Failed to initialize screen_size_");
67 return false;
69 graphics2d_ = pp::Graphics2D(instance_, screen_size_, true);
70 if (!instance_->BindGraphics(graphics2d_)) {
71 instance_->AppendError("Failed to initialize graphics2d_");
72 return false;
74 return CheckTestingInterface();
77 void TestFullscreen::RunTests(const std::string& filter) {
78 RUN_TEST(GetScreenSize, filter);
79 RUN_TEST(NormalToFullscreenToNormal, filter);
82 bool TestFullscreen::GotError() {
83 return !error_.empty();
86 std::string TestFullscreen::Error() {
87 std::string last_error = error_;
88 error_.clear();
89 return last_error;
92 // TODO(polina): consider adding custom logic to JS for this test to
93 // get screen.width and screen.height and postMessage those to this code,
94 // so the dimensions can be checked exactly.
95 std::string TestFullscreen::TestGetScreenSize() {
96 if (screen_size_.width() < 320 || screen_size_.width() > 2560)
97 return ReportError("screen_size.width()", screen_size_.width());
98 if (screen_size_.height() < 200 || screen_size_.height() > 2048)
99 return ReportError("screen_size.height()", screen_size_.height());
100 PASS();
103 std::string TestFullscreen::TestNormalToFullscreenToNormal() {
104 // 0. Start in normal mode.
105 if (screen_mode_.IsFullscreen())
106 return ReportError("IsFullscreen() at start", true);
108 // 1. Switch to fullscreen.
109 // This is only allowed within a context of a user gesture (e.g. mouse click).
110 if (screen_mode_.SetFullscreen(true))
111 return ReportError("SetFullscreen(true) outside of user gesture", true);
112 // Trigger another call to SetFullscreen(true) from HandleInputEvent().
113 // The transition is asynchronous and ends at the next DidChangeView().
114 instance_->RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
115 SimulateUserGesture();
116 // DidChangeView() will call the callback once in fullscreen mode.
117 fullscreen_event_.Wait();
118 if (GotError())
119 return Error();
120 if (fullscreen_pending_)
121 return "fullscreen_pending_ has not been reset";
122 if (!screen_mode_.IsFullscreen())
123 return ReportError("IsFullscreen() in fullscreen", false);
125 // 2. Stay in fullscreen. No change.
126 if (screen_mode_.SetFullscreen(true))
127 return ReportError("SetFullscreen(true) in fullscreen", true);
128 if (!screen_mode_.IsFullscreen())
129 return ReportError("IsFullscreen() in fullscreen^2", false);
131 // 3. Switch to normal.
132 // The transition is asynchronous and ends at DidChangeView().
133 // No graphics devices can be bound while in transition.
134 normal_pending_ = true;
135 if (!screen_mode_.SetFullscreen(false))
136 return ReportError("SetFullscreen(false) in fullscreen", false);
137 // DidChangeView() will signal once out of fullscreen mode.
138 normal_event_.Wait();
139 if (GotError())
140 return Error();
141 if (normal_pending_)
142 return "normal_pending_ has not been reset";
143 if (screen_mode_.IsFullscreen())
144 return ReportError("IsFullscreen() in normal", true);
146 // 4. Stay in normal. No change.
147 if (screen_mode_.SetFullscreen(false))
148 return ReportError("SetFullscreen(false) in normal", true);
149 if (screen_mode_.IsFullscreen())
150 return ReportError("IsFullscreen() in normal^2", true);
152 PASS();
155 void TestFullscreen::SimulateUserGesture() {
156 pp::Point plugin_center(
157 normal_position_.x() + normal_position_.width() / 2,
158 normal_position_.y() + normal_position_.height() / 2);
159 pp::Point mouse_movement;
160 pp::MouseInputEvent input_event(
161 instance_,
162 PP_INPUTEVENT_TYPE_MOUSEDOWN,
163 0, // time_stamp
164 0, // modifiers
165 PP_INPUTEVENT_MOUSEBUTTON_LEFT,
166 plugin_center,
167 1, // click_count
168 mouse_movement);
170 testing_interface_->SimulateInputEvent(instance_->pp_instance(),
171 input_event.pp_resource());
174 void TestFullscreen::FailFullscreenTest(const std::string& error) {
175 error_ = error;
176 fullscreen_event_.Signal();
179 void TestFullscreen::FailNormalTest(const std::string& error) {
180 error_ = error;
181 normal_event_.Signal();
184 void TestFullscreen::PassFullscreenTest() {
185 fullscreen_event_.Signal();
188 void TestFullscreen::PassNormalTest() {
189 normal_event_.Signal();
192 // Transition to fullscreen can only happen when processing a user gesture.
193 bool TestFullscreen::HandleInputEvent(const pp::InputEvent& event) {
194 // We only let mouse events through and only mouse clicks count.
195 if (event.GetType() != PP_INPUTEVENT_TYPE_MOUSEDOWN &&
196 event.GetType() != PP_INPUTEVENT_TYPE_MOUSEUP)
197 return false;
198 // We got the gesture. No need to handle any more events.
199 instance_->ClearInputEventRequest(PP_INPUTEVENT_CLASS_MOUSE);
200 if (screen_mode_.IsFullscreen()) {
201 FailFullscreenTest(
202 ReportError("IsFullscreen() before fullscreen transition", true));
203 return false;
205 fullscreen_pending_ = true;
206 if (!screen_mode_.SetFullscreen(true)) {
207 FailFullscreenTest(ReportError("SetFullscreen(true) in normal", false));
208 return false;
210 // DidChangeView() will complete the transition to fullscreen.
211 return false;
214 bool TestFullscreen::PaintPlugin(pp::Size size, ColorPremul color) {
215 painted_size_ = size;
216 PP_ImageDataFormat image_format = pp::ImageData::GetNativeImageDataFormat();
217 painted_color_ = FormatColor(image_format, color);
218 if (painted_color_ == 0)
219 return false;
220 pp::Point origin(0, 0);
222 pp::ImageData image(instance_, image_format, size, false);
223 if (image.is_null())
224 return false;
225 uint32_t* pixels = static_cast<uint32_t*>(image.data());
226 int num_pixels = image.stride() / kBytesPerPixel * image.size().height();
227 for (int i = 0; i < num_pixels; i++)
228 pixels[i] = painted_color_;
229 graphics2d_.PaintImageData(image, origin);
230 pp::CompletionCallback cc(FlushCallbackCheckImageData, this);
231 if (graphics2d_.Flush(cc) != PP_OK_COMPLETIONPENDING)
232 return false;
234 return true;
237 void TestFullscreen::CheckPluginPaint() {
238 PP_ImageDataFormat image_format = pp::ImageData::GetNativeImageDataFormat();
239 pp::ImageData readback(instance_, image_format, painted_size_, false);
240 pp::Point origin(0, 0);
241 if (readback.is_null() ||
242 PP_TRUE != testing_interface_->ReadImageData(graphics2d_.pp_resource(),
243 readback.pp_resource(),
244 &origin.pp_point())) {
245 error_ = "Can't read plugin image";
246 return;
248 for (int y = 0; y < painted_size_.height(); y++) {
249 for (int x = 0; x < painted_size_.width(); x++) {
250 uint32_t* readback_color = readback.GetAddr32(pp::Point(x, y));
251 if (painted_color_ != *readback_color) {
252 error_ = "Plugin image contains incorrect pixel value";
253 return;
257 if (screen_mode_.IsFullscreen())
258 PassFullscreenTest();
259 else
260 PassNormalTest();
263 // Transitions to/from fullscreen is asynchronous ending at DidChangeView.
264 // The number of calls to DidChangeView during fullscreen / normal transitions
265 // isn't specified by the API. The test waits until it the screen has
266 // transitioned to the desired state.
268 // WebKit does not change the plugin size, but Pepper does explicitly set
269 // it to screen width and height when SetFullscreen(true) is called and
270 // resets it back when ViewChanged is received indicating that we exited
271 // fullscreen.
273 // NOTE: The number of DidChangeView calls for <object> might be different.
274 // TODO(bbudge) Figure out how to test that the plugin positon eventually
275 // changes to normal_position_.
276 void TestFullscreen::DidChangeView(const pp::View& view) {
277 pp::Rect position = view.GetRect();
278 pp::Rect clip = view.GetClipRect();
280 if (normal_position_.IsEmpty())
281 normal_position_ = position;
283 bool is_fullscreen = screen_mode_.IsFullscreen();
284 if (fullscreen_pending_ && is_fullscreen) {
285 fullscreen_pending_ = false;
286 if (!HasMidScreen(position, screen_size_))
287 FailFullscreenTest("DidChangeView is not in the middle of the screen");
288 else if (position.size() != screen_size_)
289 FailFullscreenTest("DidChangeView does not have screen size");
290 // NOTE: we cannot reliably test for clip size being equal to the screen
291 // because it might be affected by JS console, info bars, etc.
292 else if (!instance_->BindGraphics(graphics2d_))
293 FailFullscreenTest("Failed to BindGraphics() in fullscreen");
294 else if (!PaintPlugin(position.size(), kOpaqueYellow))
295 FailFullscreenTest("Failed to paint plugin image in fullscreen");
296 } else if (normal_pending_ && !is_fullscreen) {
297 normal_pending_ = false;
298 if (screen_mode_.IsFullscreen())
299 FailNormalTest("DidChangeview is in fullscreen");
300 else if (!instance_->BindGraphics(graphics2d_))
301 FailNormalTest("Failed to BindGraphics() in normal");
302 else if (!PaintPlugin(position.size(), kSheerBlue))
303 FailNormalTest("Failed to paint plugin image in normal");