15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/graphics_2d.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/image_data.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/private/flash.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/rect.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/size.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32_t kTimerInterval = 200;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MyInstance : public pp::Instance {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MyInstance(PP_Instance instance)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : pp::Instance(instance),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_factory_(this),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_paint_(false),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        waiting_for_flush_completion_(false) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MyInstance() {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleNextTimer();
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (position.size() != size_) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_ = position.size();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_context_ = pp::Graphics2D(this, size_, false);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!BindGraphics(device_context_))
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Paint();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ScheduleNextTimer() {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Module::Get()->core()->CallOnMainThread(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kTimerInterval,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_factory_.NewCallback(&MyInstance::OnTimer),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnTimer(int32_t) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleNextTimer();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Paint();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DidFlush(int32_t result) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_for_flush_completion_ = false;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending_paint_)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Paint();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Paint() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (waiting_for_flush_completion_) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_paint_ = true;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_paint_ = false;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_.IsEmpty())
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // Nothing to do.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::ImageData image = PaintImage(size_);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!image.is_null()) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_context_.ReplaceContents(&image);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_for_flush_completion_ = true;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_context_.Flush(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          callback_factory_.NewCallback(&MyInstance::DidFlush));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::ImageData PaintImage(const pp::Size& size) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (image.is_null())
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return image;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Rect rect(size.width() / 8, size.height() / 4,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  3 * size.width() / 4, size.height() / 2);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t fill_color = pp::flash::Flash::IsRectTopmost(this, rect) ?
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0xff00ff00 : 0xffff0000;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int y = 0; y < size.height(); y++) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int x = 0; x < size.width(); x++)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *image.GetAddr32(pp::Point(x, y)) = fill_color;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int x = rect.x(); x < rect.x() + rect.width(); x++) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *image.GetAddr32(pp::Point(x, rect.y())) = 0xff202020;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *image.GetAddr32(pp::Point(x, rect.y() + rect.height() - 1)) = 0xff202020;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int y = rect.y(); y < rect.y() + rect.height(); y++) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *image.GetAddr32(pp::Point(rect.x(), y)) = 0xff202020;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *image.GetAddr32(pp::Point(rect.x() + rect.width() - 1, y)) = 0xff202020;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return image;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallbackFactory<MyInstance> callback_factory_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Painting stuff.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Size size_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Graphics2D device_context_;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pending_paint_;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool waiting_for_flush_completion_;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MyModule : public pp::Module {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual pp::Instance* CreateInstance(PP_Instance instance) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new MyInstance(instance);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Factory function for your specialization of the Module object.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Module* CreateModule() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new MyModule();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace pp
134