| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gamepad.h" | |
| 6 | |
| 7 #include <stdio.h> | 5 #include <stdio.h> |
| 8 #include <stdlib.h> | 6 #include <stdlib.h> |
| 7 |
| 9 #include <cassert> | 8 #include <cassert> |
| 10 #include <cmath> | 9 |
| 11 #include <cstring> | |
| 12 #include <string> | |
| 13 #include "ppapi/c/ppb_gamepad.h" | 10 #include "ppapi/c/ppb_gamepad.h" |
| 14 #include "ppapi/cpp/completion_callback.h" | 11 #include "ppapi/cpp/graphics_2d.h" |
| 12 #include "ppapi/cpp/image_data.h" |
| 13 #include "ppapi/cpp/instance.h" |
| 14 #include "ppapi/cpp/rect.h" |
| 15 #include "ppapi/cpp/size.h" |
| 15 #include "ppapi/cpp/var.h" | 16 #include "ppapi/cpp/var.h" |
| 17 #include "ppapi/utility/completion_callback_factory.h" |
| 16 | 18 |
| 17 namespace { | 19 class GamepadInstance : public pp::Instance { |
| 20 public: |
| 21 explicit GamepadInstance(PP_Instance instance); |
| 22 virtual ~GamepadInstance(); |
| 18 | 23 |
| 19 // This is called by the browser when the 2D context has been flushed to the | 24 // Update the graphics context to the new size, and regenerate |pixel_buffer_| |
| 20 // browser window. | 25 // to fit the new size as well. |
| 21 void FlushCallback(void* data, int32_t result) { | 26 virtual void DidChangeView(const pp::View& view); |
| 22 static_cast<gamepad::Gamepad*>(data)->set_flush_pending(false); | |
| 23 static_cast<gamepad::Gamepad*>(data)->Paint(); | |
| 24 } | |
| 25 | 27 |
| 26 } // namespace | 28 // Flushes its contents of |pixel_buffer_| to the 2D graphics context. |
| 29 void Paint(); |
| 27 | 30 |
| 28 namespace gamepad { | 31 int width() const { |
| 32 return pixel_buffer_ ? pixel_buffer_->size().width() : 0; |
| 33 } |
| 34 int height() const { |
| 35 return pixel_buffer_ ? pixel_buffer_->size().height() : 0; |
| 36 } |
| 29 | 37 |
| 30 Gamepad::Gamepad(PP_Instance instance) | 38 // Indicate whether a flush is pending. This can only be called from the |
| 39 // main thread; it is not thread safe. |
| 40 bool flush_pending() const { return flush_pending_; } |
| 41 void set_flush_pending(bool flag) { flush_pending_ = flag; } |
| 42 |
| 43 private: |
| 44 // Create and initialize the 2D context used for drawing. |
| 45 void CreateContext(const pp::Size& size); |
| 46 // Destroy the 2D drawing context. |
| 47 void DestroyContext(); |
| 48 // Push the pixels to the browser, then attempt to flush the 2D context. If |
| 49 // there is a pending flush on the 2D context, then update the pixels only |
| 50 // and do not flush. |
| 51 void FlushPixelBuffer(); |
| 52 |
| 53 void FlushCallback(int32_t result); |
| 54 |
| 55 bool IsContextValid() const { return graphics_2d_context_ != NULL; } |
| 56 |
| 57 pp::CompletionCallbackFactory<GamepadInstance> callback_factory_; |
| 58 pp::Graphics2D* graphics_2d_context_; |
| 59 pp::ImageData* pixel_buffer_; |
| 60 const PPB_Gamepad* gamepad_; |
| 61 bool flush_pending_; |
| 62 }; |
| 63 |
| 64 GamepadInstance::GamepadInstance(PP_Instance instance) |
| 31 : pp::Instance(instance), | 65 : pp::Instance(instance), |
| 66 callback_factory_(this), |
| 32 graphics_2d_context_(NULL), | 67 graphics_2d_context_(NULL), |
| 33 pixel_buffer_(NULL), | 68 pixel_buffer_(NULL), |
| 34 flush_pending_(false), | 69 flush_pending_(false) { |
| 35 quit_(false) { | |
| 36 pp::Module* module = pp::Module::Get(); | 70 pp::Module* module = pp::Module::Get(); |
| 37 assert(module); | 71 assert(module); |
| 38 gamepad_ = static_cast<const PPB_Gamepad*>( | 72 gamepad_ = static_cast<const PPB_Gamepad*>( |
| 39 module->GetBrowserInterface(PPB_GAMEPAD_INTERFACE)); | 73 module->GetBrowserInterface(PPB_GAMEPAD_INTERFACE)); |
| 40 assert(gamepad_); | 74 assert(gamepad_); |
| 41 } | 75 } |
| 42 | 76 |
| 43 Gamepad::~Gamepad() { | 77 GamepadInstance::~GamepadInstance() { |
| 44 quit_ = true; | |
| 45 DestroyContext(); | 78 DestroyContext(); |
| 46 delete pixel_buffer_; | 79 delete pixel_buffer_; |
| 47 } | 80 } |
| 48 | 81 |
| 49 void Gamepad::DidChangeView(const pp::View& view) { | 82 void GamepadInstance::DidChangeView(const pp::View& view) { |
| 50 pp::Rect position = view.GetRect(); | 83 pp::Rect position = view.GetRect(); |
| 51 if (position.size().width() == width() && | 84 if (position.size().width() == width() && |
| 52 position.size().height() == height()) | 85 position.size().height() == height()) |
| 53 return; // Size didn't change, no need to update anything. | 86 return; // Size didn't change, no need to update anything. |
| 54 | 87 |
| 55 // Create a new device context with the new size. | 88 // Create a new device context with the new size. |
| 56 DestroyContext(); | 89 DestroyContext(); |
| 57 CreateContext(position.size()); | 90 CreateContext(position.size()); |
| 58 // Delete the old pixel buffer and create a new one. | 91 // Delete the old pixel buffer and create a new one. |
| 59 delete pixel_buffer_; | 92 delete pixel_buffer_; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 76 for (int y = std::max(0, top); | 109 for (int y = std::max(0, top); |
| 77 y < std::min(image->size().height() - 1, top + height); | 110 y < std::min(image->size().height() - 1, top + height); |
| 78 y++) { | 111 y++) { |
| 79 for (int x = std::max(0, left); | 112 for (int x = std::max(0, left); |
| 80 x < std::min(image->size().width() - 1, left + width); | 113 x < std::min(image->size().width() - 1, left + width); |
| 81 x++) | 114 x++) |
| 82 *image->GetAddr32(pp::Point(x, y)) = color; | 115 *image->GetAddr32(pp::Point(x, y)) = color; |
| 83 } | 116 } |
| 84 } | 117 } |
| 85 | 118 |
| 86 void Gamepad::Paint() { | 119 void GamepadInstance::Paint() { |
| 87 // Clear the background. | 120 // Clear the background. |
| 88 FillRect(pixel_buffer_, 0, 0, width(), height(), 0xfff0f0f0); | 121 FillRect(pixel_buffer_, 0, 0, width(), height(), 0xfff0f0f0); |
| 89 | 122 |
| 90 // Get current gamepad data. | 123 // Get current gamepad data. |
| 91 PP_GamepadsSampleData gamepad_data; | 124 PP_GamepadsSampleData gamepad_data; |
| 92 gamepad_->Sample(pp_instance(), &gamepad_data); | 125 gamepad_->Sample(pp_instance(), &gamepad_data); |
| 93 | 126 |
| 94 // Draw the current state for each connected gamepad. | 127 // Draw the current state for each connected gamepad. |
| 95 for (size_t p = 0; p < gamepad_data.length; ++p) { | 128 for (size_t p = 0; p < gamepad_data.length; ++p) { |
| 96 int width2 = width() / gamepad_data.length / 2; | 129 int width2 = width() / gamepad_data.length / 2; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 116 int x = i * 8 + 10 + offset; | 149 int x = i * 8 + 10 + offset; |
| 117 int y = 10; | 150 int y = 10; |
| 118 FillRect(pixel_buffer_, x - 3, y - 3, 7, 7, colour); | 151 FillRect(pixel_buffer_, x - 3, y - 3, 7, 7, colour); |
| 119 } | 152 } |
| 120 } | 153 } |
| 121 | 154 |
| 122 // Output to the screen. | 155 // Output to the screen. |
| 123 FlushPixelBuffer(); | 156 FlushPixelBuffer(); |
| 124 } | 157 } |
| 125 | 158 |
| 126 void Gamepad::CreateContext(const pp::Size& size) { | 159 void GamepadInstance::CreateContext(const pp::Size& size) { |
| 127 if (IsContextValid()) | 160 if (IsContextValid()) |
| 128 return; | 161 return; |
| 129 graphics_2d_context_ = new pp::Graphics2D(this, size, false); | 162 graphics_2d_context_ = new pp::Graphics2D(this, size, false); |
| 130 if (!BindGraphics(*graphics_2d_context_)) { | 163 if (!BindGraphics(*graphics_2d_context_)) { |
| 131 printf("Couldn't bind the device context\n"); | 164 printf("Couldn't bind the device context\n"); |
| 132 } | 165 } |
| 133 } | 166 } |
| 134 | 167 |
| 135 void Gamepad::DestroyContext() { | 168 void GamepadInstance::DestroyContext() { |
| 136 if (!IsContextValid()) | 169 if (!IsContextValid()) |
| 137 return; | 170 return; |
| 138 delete graphics_2d_context_; | 171 delete graphics_2d_context_; |
| 139 graphics_2d_context_ = NULL; | 172 graphics_2d_context_ = NULL; |
| 140 } | 173 } |
| 141 | 174 |
| 142 void Gamepad::FlushPixelBuffer() { | 175 void GamepadInstance::FlushPixelBuffer() { |
| 143 if (!IsContextValid()) | 176 if (!IsContextValid()) |
| 144 return; | 177 return; |
| 145 // Note that the pixel lock is held while the buffer is copied into the | 178 // Note that the pixel lock is held while the buffer is copied into the |
| 146 // device context and then flushed. | 179 // device context and then flushed. |
| 147 graphics_2d_context_->PaintImageData(*pixel_buffer_, pp::Point()); | 180 graphics_2d_context_->PaintImageData(*pixel_buffer_, pp::Point()); |
| 148 if (flush_pending()) | 181 if (flush_pending()) |
| 149 return; | 182 return; |
| 150 set_flush_pending(true); | 183 set_flush_pending(true); |
| 151 graphics_2d_context_->Flush(pp::CompletionCallback(&FlushCallback, this)); | 184 graphics_2d_context_->Flush( |
| 185 callback_factory_.NewCallback(&GamepadInstance::FlushCallback)); |
| 152 } | 186 } |
| 153 | 187 |
| 154 } // namespace gamepad | 188 void GamepadInstance::FlushCallback(int32_t result) { |
| 189 set_flush_pending(false); |
| 190 Paint(); |
| 191 } |
| 192 |
| 193 class GamepadModule : public pp::Module { |
| 194 public: |
| 195 GamepadModule() : pp::Module() {} |
| 196 virtual ~GamepadModule() {} |
| 197 |
| 198 virtual pp::Instance* CreateInstance(PP_Instance instance) { |
| 199 return new GamepadInstance(instance); |
| 200 } |
| 201 }; |
| 202 |
| 203 namespace pp { |
| 204 Module* CreateModule() { return new GamepadModule(); } |
| 205 } // namespace pp |
| OLD | NEW |