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)
58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <algorithm>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_gamepad.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_input_event.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/completion_callback.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/graphics_2d.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/image_data.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/input_event.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/logging.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/rect.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/view.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FillRect(pp::ImageData* image, int left, int top, int width, int height,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              uint32_t color) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int y = std::max(0, top);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       y < std::min(image->size().height() - 1, top + height);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       y++) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int x = std::max(0, left);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         x < std::min(image->size().width() - 1, left + width);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         x++)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *image->GetAddr32(pp::Point(x, y)) = color;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MyInstance : public pp::Instance {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MyInstance(PP_Instance instance)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : pp::Instance(instance),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        width_(0),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        height_(0),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_factory_(this),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gamepad_(NULL) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MyInstance() {}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gamepad_ = reinterpret_cast<const PPB_Gamepad*>(
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pp::Module::Get()->GetBrowserInterface(PPB_GAMEPAD_INTERFACE));
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!gamepad_)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidChangeView(const pp::View& view) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Rect rect = view.GetRect();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rect.size().width() == width_ &&
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rect.size().height() == height_)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // We don't care about the position, only the size.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width_ = rect.size().width();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height_ = rect.size().height();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device_context_ = pp::Graphics2D(this, pp::Size(width_, height_), false);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!BindGraphics(device_context_))
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Paint();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnFlush(int32_t) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Paint();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Paint() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::ImageData image = PaintImage(device_context_.size());
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!image.is_null()) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_context_.ReplaceContents(&image);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_context_.Flush(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          callback_factory_.NewCallback(&MyInstance::OnFlush));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printf("NullImage\n");
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::ImageData PaintImage(const pp::Size& size) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, true);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (image.is_null())
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return image;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_GamepadsSampleData gamepad_data;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gamepad_->Sample(pp_instance(), &gamepad_data);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (gamepad_data.length > 1 && gamepad_data.items[0].connected) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int width2 = size.width() / 2;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int height2 = size.height() / 2;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Draw 2 axes
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < gamepad_data.items[0].axes_length; i += 2) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int x = static_cast<int>(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            gamepad_data.items[0].axes[i + 0] * width2 + width2);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int y = static_cast<int>(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            gamepad_data.items[0].axes[i + 1] * height2 + height2);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t box_bgra = 0x80000000;  // Alpha 50%.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FillRect(&image, x - 3, y - 3, 7, 7, box_bgra);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < gamepad_data.items[0].buttons_length; ++i) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        float button_val = gamepad_data.items[0].buttons[i];
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t colour = static_cast<uint32_t>((button_val * 192) + 63) << 24;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int x = i * 8 + 10;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int y = 10;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FillRect(&image, x - 3, y - 3, 7, 7, colour);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return image;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallbackFactory<MyInstance> callback_factory_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_Gamepad* gamepad_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Graphics2D device_context_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This object is the global object representing this plugin library as long
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as it is loaded.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MyModule : public pp::Module {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MyModule() : pp::Module() {}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MyModule() {}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Override CreateInstance to create your customized Instance object.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual pp::Instance* CreateInstance(PP_Instance instance) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new MyInstance(instance);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Factory function for your specialization of the Module object.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Module* CreateModule() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new MyModule();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace pp
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
151