| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2012 The Native Client 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 "gamepad.h" |
| 6 |
| 7 #include <stdio.h> |
| 8 #include <stdlib.h> |
| 9 #include <cassert> |
| 10 #include <cmath> |
| 11 #include <cstring> |
| 12 #include <string> |
| 13 #include "ppapi/cpp/completion_callback.h" |
| 14 #include "ppapi/cpp/var.h" |
| 15 |
| 16 namespace { |
| 17 |
| 18 // This is called by the browser when the 2D context has been flushed to the |
| 19 // browser window. |
| 20 void FlushCallback(void* data, int32_t result) { |
| 21 static_cast<gamepad::Gamepad*>(data)->set_flush_pending(false); |
| 22 static_cast<gamepad::Gamepad*>(data)->Paint(); |
| 23 } |
| 24 |
| 25 } // namespace |
| 26 |
| 27 namespace gamepad { |
| 28 |
| 29 Gamepad::Gamepad(PP_Instance instance) |
| 30 : pp::Instance(instance), |
| 31 graphics_2d_context_(NULL), |
| 32 pixel_buffer_(NULL), |
| 33 flush_pending_(false), |
| 34 quit_(false) { |
| 35 pp::Module* module = pp::Module::Get(); |
| 36 assert(module); |
| 37 gamepad_ = static_cast<const PPB_Gamepad_Dev*>( |
| 38 module->GetBrowserInterface(PPB_GAMEPAD_DEV_INTERFACE)); |
| 39 assert(gamepad_); |
| 40 } |
| 41 |
| 42 Gamepad::~Gamepad() { |
| 43 quit_ = true; |
| 44 DestroyContext(); |
| 45 delete pixel_buffer_; |
| 46 } |
| 47 |
| 48 void Gamepad::DidChangeView(const pp::Rect& position, |
| 49 const pp::Rect& clip) { |
| 50 if (position.size().width() == width() && |
| 51 position.size().height() == height()) |
| 52 return; // Size didn't change, no need to update anything. |
| 53 |
| 54 // Create a new device context with the new size. |
| 55 DestroyContext(); |
| 56 CreateContext(position.size()); |
| 57 // Delete the old pixel buffer and create a new one. |
| 58 delete pixel_buffer_; |
| 59 pixel_buffer_ = NULL; |
| 60 if (graphics_2d_context_ != NULL) { |
| 61 pixel_buffer_ = new pp::ImageData(this, |
| 62 PP_IMAGEDATAFORMAT_BGRA_PREMUL, |
| 63 graphics_2d_context_->size(), |
| 64 false); |
| 65 } |
| 66 Paint(); |
| 67 } |
| 68 |
| 69 void FillRect(pp::ImageData* image, int left, int top, int width, int height, |
| 70 uint32_t color) { |
| 71 for (int y = std::max(0, top); |
| 72 y < std::min(image->size().height() - 1, top + height); |
| 73 y++) { |
| 74 for (int x = std::max(0, left); |
| 75 x < std::min(image->size().width() - 1, left + width); |
| 76 x++) |
| 77 *image->GetAddr32(pp::Point(x, y)) = color; |
| 78 } |
| 79 } |
| 80 |
| 81 void Gamepad::Paint() { |
| 82 // Clear the background. |
| 83 FillRect(pixel_buffer_, 0, 0, width(), height(), 0xfff0f0f0); |
| 84 |
| 85 // Get current gamepad data. |
| 86 PP_GamepadsData_Dev gamepad_data; |
| 87 gamepad_->SampleGamepads(pp_instance(), &gamepad_data); |
| 88 |
| 89 // Draw the current state for each connected gamepad. |
| 90 for (size_t p = 0; p < gamepad_data.length; ++p) { |
| 91 int width2 = width() / gamepad_data.length / 2; |
| 92 int height2 = height() / 2; |
| 93 int offset = width2 * 2 * p; |
| 94 PP_GamepadData_Dev& pad = gamepad_data.items[p]; |
| 95 |
| 96 if (!pad.connected) |
| 97 continue; |
| 98 |
| 99 // Draw axes. |
| 100 for (size_t i = 0; i < pad.axes_length; i += 2) { |
| 101 int x = static_cast<int>(pad.axes[i + 0] * width2 + width2) + offset; |
| 102 int y = static_cast<int>(pad.axes[i + 1] * height2 + height2); |
| 103 uint32_t box_bgra = 0x80000000; // Alpha 50%. |
| 104 FillRect(pixel_buffer_, x - 3, y - 3, 7, 7, box_bgra); |
| 105 } |
| 106 |
| 107 // Draw buttons. |
| 108 for (size_t i = 0; i < pad.buttons_length; ++i) { |
| 109 float button_val = pad.buttons[i]; |
| 110 uint32_t colour = static_cast<uint32_t>((button_val * 192) + 63) << 24; |
| 111 int x = i * 8 + 10 + offset; |
| 112 int y = 10; |
| 113 FillRect(pixel_buffer_, x - 3, y - 3, 7, 7, colour); |
| 114 } |
| 115 } |
| 116 |
| 117 // Output to the screen. |
| 118 FlushPixelBuffer(); |
| 119 } |
| 120 |
| 121 void Gamepad::CreateContext(const pp::Size& size) { |
| 122 if (IsContextValid()) |
| 123 return; |
| 124 graphics_2d_context_ = new pp::Graphics2D(this, size, false); |
| 125 if (!BindGraphics(*graphics_2d_context_)) { |
| 126 printf("Couldn't bind the device context\n"); |
| 127 } |
| 128 } |
| 129 |
| 130 void Gamepad::DestroyContext() { |
| 131 if (!IsContextValid()) |
| 132 return; |
| 133 delete graphics_2d_context_; |
| 134 graphics_2d_context_ = NULL; |
| 135 } |
| 136 |
| 137 void Gamepad::FlushPixelBuffer() { |
| 138 if (!IsContextValid()) |
| 139 return; |
| 140 // Note that the pixel lock is held while the buffer is copied into the |
| 141 // device context and then flushed. |
| 142 graphics_2d_context_->PaintImageData(*pixel_buffer_, pp::Point()); |
| 143 if (flush_pending()) |
| 144 return; |
| 145 set_flush_pending(true); |
| 146 graphics_2d_context_->Flush(pp::CompletionCallback(&FlushCallback, this)); |
| 147 } |
| 148 |
| 149 } // namespace gamepad |
| OLD | NEW |