1 // Copyright 2014 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. 4 5 6 // This plugin is intended to be used in a telemetry test for tracing touch 7 // input latency. It is a simple touch drawing app, that for each touch move 8 // event, it draws a square with fix size. 9 // When the plugin instance is initialized, we call 10 // InputEventPrivate::StartTrackingLatency to enable latency tracking. 11 // And for each touch move event, we call 12 // InputEventPrivate::TraceInputLatency(true) to indicate the touch event 13 // causes rendering effect and its input latency should be tracked. 14 // The plugin is built as a pexe and bundled with a telemetry test page. 15 // For how to build the pexe, see the accompanying README file. 16 17 #include <algorithm> 18 19 #include "ppapi/c/pp_input_event.h" 20 #include "ppapi/cpp/graphics_2d.h" 21 #include "ppapi/cpp/image_data.h" 22 #include "ppapi/cpp/input_event.h" 23 #include "ppapi/cpp/instance.h" 24 #include "ppapi/cpp/module.h" 25 #include "ppapi/cpp/private/input_event_private.h" 26 #include "ppapi/cpp/size.h" 27 #include "ppapi/cpp/view.h" 28 #include "ppapi/utility/graphics/paint_manager.h" 29 30 pp::Rect SquareForTouchPoint(int x, int y) { 31 return PP_MakeRectFromXYWH(x - 30, y - 30, 32 30 * 2 + 1, 30 * 2 + 1); 33 } 34 35 static void FillRect(pp::ImageData* image, 36 int left, 37 int top, 38 int width, 39 int height, 40 uint32_t color) { 41 for (int y = std::max(0, top); 42 y < std::min(image->size().height() - 1, top + height); 43 y++) { 44 for (int x = std::max(0, left); 45 x < std::min(image->size().width() - 1, left + width); 46 x++) { 47 *image->GetAddr32(pp::Point(x, y)) = color; 48 } 49 } 50 } 51 52 class MyInstance : public pp::Instance, public pp::PaintManager::Client { 53 public: 54 explicit MyInstance(PP_Instance instance) 55 : pp::Instance(instance), 56 paint_manager_() { 57 paint_manager_.Initialize(this, this, false); 58 RequestInputEvents(PP_INPUTEVENT_CLASS_TOUCH); 59 pp::InputEventPrivate::StartTrackingLatency(pp::InstanceHandle(instance)); 60 } 61 62 virtual bool HandleInputEvent(const pp::InputEvent& event) { 63 switch (event.GetType()) { 64 case PP_INPUTEVENT_TYPE_TOUCHSTART: 65 case PP_INPUTEVENT_TYPE_TOUCHEND: 66 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: { 67 pp::InputEventPrivate private_event(event); 68 private_event.TraceInputLatency(false); 69 return true; 70 } 71 72 case PP_INPUTEVENT_TYPE_TOUCHMOVE: { 73 pp::TouchInputEvent touch(event); 74 uint32_t count = touch.GetTouchCount(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES); 75 if (count > 0) { 76 pp::TouchPoint point = touch.GetTouchByIndex( 77 PP_TOUCHLIST_TYPE_CHANGEDTOUCHES, 0); 78 UpdateSquareTouch(static_cast<int>(point.position().x()), 79 static_cast<int>(point.position().y())); 80 pp::InputEventPrivate private_event(event); 81 private_event.TraceInputLatency(true); 82 } else { 83 pp::InputEventPrivate private_event(event); 84 private_event.TraceInputLatency(false); 85 } 86 return true; 87 } 88 default: 89 return false; 90 } 91 } 92 93 virtual void DidChangeView(const pp::View& view) { 94 paint_manager_.SetSize(view.GetRect().size()); 95 } 96 97 // PaintManager::Client implementation. 98 virtual bool OnPaint(pp::Graphics2D& graphics_2d, 99 const std::vector<pp::Rect>& paint_rects, 100 const pp::Rect& paint_bounds) { 101 pp::ImageData updated_image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, 102 paint_bounds.size(), false); 103 104 for (size_t i = 0; i < paint_rects.size(); i++) { 105 // Since our image is just the invalid region, we need to offset the 106 // areas we paint by that much. This is just a light blue background. 107 FillRect(&updated_image, 108 paint_rects[i].x(), 109 paint_rects[i].y(), 110 paint_rects[i].width(), 111 paint_rects[i].height(), 112 0xFF000000); 113 } 114 115 graphics_2d.PaintImageData(updated_image, paint_bounds.point()); 116 return true; 117 } 118 119 private: 120 void UpdateSquareTouch(int x, int y) { 121 paint_manager_.InvalidateRect(SquareForTouchPoint(x, y)); 122 } 123 124 pp::PaintManager paint_manager_; 125 }; 126 127 class MyModule : public pp::Module { 128 public: 129 virtual pp::Instance* CreateInstance(PP_Instance instance) { 130 return new MyInstance(instance); 131 } 132 }; 133 134 namespace pp { 135 136 Module* CreateModule() { 137 return new MyModule(); 138 } 139 140 } // namespace pp 141