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. 4 5 #include "ppapi/cpp/graphics_2d.h" 6 #include "ppapi/cpp/image_data.h" 7 #include "ppapi/cpp/instance.h" 8 #include "ppapi/cpp/logging.h" 9 #include "ppapi/cpp/module.h" 10 #include "ppapi/cpp/private/flash.h" 11 #include "ppapi/cpp/rect.h" 12 #include "ppapi/cpp/size.h" 13 #include "ppapi/utility/completion_callback_factory.h" 14 15 const int32_t kTimerInterval = 200; 16 17 class MyInstance : public pp::Instance { 18 public: 19 explicit MyInstance(PP_Instance instance) 20 : pp::Instance(instance), 21 callback_factory_(this), 22 pending_paint_(false), 23 waiting_for_flush_completion_(false) { 24 } 25 virtual ~MyInstance() { 26 } 27 28 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { 29 ScheduleNextTimer(); 30 return true; 31 } 32 33 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { 34 if (position.size() != size_) { 35 size_ = position.size(); 36 device_context_ = pp::Graphics2D(this, size_, false); 37 if (!BindGraphics(device_context_)) 38 return; 39 } 40 41 Paint(); 42 } 43 44 private: 45 void ScheduleNextTimer() { 46 pp::Module::Get()->core()->CallOnMainThread( 47 kTimerInterval, 48 callback_factory_.NewCallback(&MyInstance::OnTimer), 49 0); 50 } 51 52 void OnTimer(int32_t) { 53 ScheduleNextTimer(); 54 Paint(); 55 } 56 57 void DidFlush(int32_t result) { 58 waiting_for_flush_completion_ = false; 59 if (pending_paint_) 60 Paint(); 61 } 62 63 void Paint() { 64 if (waiting_for_flush_completion_) { 65 pending_paint_ = true; 66 return; 67 } 68 69 pending_paint_ = false; 70 71 if (size_.IsEmpty()) 72 return; // Nothing to do. 73 74 pp::ImageData image = PaintImage(size_); 75 if (!image.is_null()) { 76 device_context_.ReplaceContents(&image); 77 waiting_for_flush_completion_ = true; 78 device_context_.Flush( 79 callback_factory_.NewCallback(&MyInstance::DidFlush)); 80 } 81 } 82 83 pp::ImageData PaintImage(const pp::Size& size) { 84 pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false); 85 if (image.is_null()) 86 return image; 87 88 pp::Rect rect(size.width() / 8, size.height() / 4, 89 3 * size.width() / 4, size.height() / 2); 90 uint32_t fill_color = pp::flash::Flash::IsRectTopmost(this, rect) ? 91 0xff00ff00 : 0xffff0000; 92 93 for (int y = 0; y < size.height(); y++) { 94 for (int x = 0; x < size.width(); x++) 95 *image.GetAddr32(pp::Point(x, y)) = fill_color; 96 } 97 98 for (int x = rect.x(); x < rect.x() + rect.width(); x++) { 99 *image.GetAddr32(pp::Point(x, rect.y())) = 0xff202020; 100 *image.GetAddr32(pp::Point(x, rect.y() + rect.height() - 1)) = 0xff202020; 101 } 102 for (int y = rect.y(); y < rect.y() + rect.height(); y++) { 103 *image.GetAddr32(pp::Point(rect.x(), y)) = 0xff202020; 104 *image.GetAddr32(pp::Point(rect.x() + rect.width() - 1, y)) = 0xff202020; 105 } 106 107 return image; 108 } 109 110 pp::CompletionCallbackFactory<MyInstance> callback_factory_; 111 112 // Painting stuff. 113 pp::Size size_; 114 pp::Graphics2D device_context_; 115 bool pending_paint_; 116 bool waiting_for_flush_completion_; 117 }; 118 119 class MyModule : public pp::Module { 120 public: 121 virtual pp::Instance* CreateInstance(PP_Instance instance) { 122 return new MyInstance(instance); 123 } 124 }; 125 126 namespace pp { 127 128 // Factory function for your specialization of the Module object. 129 Module* CreateModule() { 130 return new MyModule(); 131 } 132 133 } // namespace pp 134