OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <math.h> |
| 6 |
| 7 #include <vector> |
| 8 |
5 #include "ppapi/c/pp_errors.h" | 9 #include "ppapi/c/pp_errors.h" |
6 #include "ppapi/cpp/core.h" | 10 #include "ppapi/cpp/compositor.h" |
| 11 #include "ppapi/cpp/compositor_layer.h" |
7 #include "ppapi/cpp/graphics_3d.h" | 12 #include "ppapi/cpp/graphics_3d.h" |
8 #include "ppapi/cpp/graphics_3d_client.h" | 13 #include "ppapi/cpp/graphics_3d_client.h" |
9 #include "ppapi/cpp/input_event.h" | 14 #include "ppapi/cpp/image_data.h" |
10 #include "ppapi/cpp/instance.h" | 15 #include "ppapi/cpp/instance.h" |
11 #include "ppapi/cpp/module.h" | 16 #include "ppapi/cpp/module.h" |
12 #include "ppapi/cpp/rect.h" | 17 #include "ppapi/cpp/rect.h" |
13 #include "ppapi/examples/gles2_spinning_cube/spinning_cube.h" | 18 #include "ppapi/examples/compositor/spinning_cube.h" |
14 #include "ppapi/lib/gl/gles2/gl2ext_ppapi.h" | 19 #include "ppapi/lib/gl/gles2/gl2ext_ppapi.h" |
| 20 #include "ppapi/lib/gl/include/GLES2/gl2.h" |
| 21 #include "ppapi/lib/gl/include/GLES2/gl2ext.h" |
15 #include "ppapi/utility/completion_callback_factory.h" | 22 #include "ppapi/utility/completion_callback_factory.h" |
16 | 23 |
17 // Use assert as a poor-man's CHECK, even in non-debug mode. | 24 // Use assert as a poor-man's CHECK, even in non-debug mode. |
18 // Since <assert.h> redefines assert on every inclusion (it doesn't use | 25 // Since <assert.h> redefines assert on every inclusion (it doesn't use |
19 // include-guards), make sure this is the last file #include'd in this file. | 26 // include-guards), make sure this is the last file #include'd in this file. |
20 #undef NDEBUG | 27 #undef NDEBUG |
21 #include <assert.h> | 28 #include <assert.h> |
22 | 29 |
23 namespace { | 30 namespace { |
24 | 31 |
| 32 const int32_t kTextureWidth = 800; |
| 33 const int32_t kTextureHeight = 800; |
| 34 const int32_t kImageWidth = 256; |
| 35 const int32_t kImageHeight = 256; |
| 36 |
25 class DemoInstance : public pp::Instance, public pp::Graphics3DClient { | 37 class DemoInstance : public pp::Instance, public pp::Graphics3DClient { |
26 public: | 38 public: |
27 DemoInstance(PP_Instance instance); | 39 DemoInstance(PP_Instance instance); |
28 virtual ~DemoInstance(); | 40 virtual ~DemoInstance(); |
29 | 41 |
30 // pp::Instance implementation (see PPP_Instance). | 42 // pp::Instance implementation (see PPP_Instance). |
31 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); | 43 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); |
32 virtual void DidChangeView(const pp::Rect& position, | 44 virtual void DidChangeView(const pp::Rect& position, |
33 const pp::Rect& clip); | 45 const pp::Rect& clip); |
34 virtual bool HandleInputEvent(const pp::InputEvent& event) { | |
35 // TODO(yzshen): Handle input events. | |
36 return true; | |
37 } | |
38 | 46 |
39 // pp::Graphics3DClient implementation. | 47 // pp::Graphics3DClient implementation. |
40 virtual void Graphics3DContextLost(); | 48 virtual void Graphics3DContextLost(); |
41 | 49 |
42 private: | 50 private: |
43 // GL-related functions. | 51 // GL-related functions. |
44 void InitGL(int32_t result); | 52 void InitGL(int32_t result); |
45 void Paint(int32_t result); | 53 GLuint PrepareFramebuffer(); |
| 54 pp::ImageData PrepareImage(); |
| 55 void Paint(int32_t result, int32_t frame); |
| 56 void OnTextureReleased(int32_t result, GLuint texture); |
| 57 void OnImageReleased(int32_t result, const pp::ImageData& image); |
46 | 58 |
47 pp::Size plugin_size_; | |
48 pp::CompletionCallbackFactory<DemoInstance> callback_factory_; | 59 pp::CompletionCallbackFactory<DemoInstance> callback_factory_; |
49 | 60 |
50 // Owned data. | 61 // Owned data. |
51 pp::Graphics3D* context_; | 62 pp::Graphics3D* context_; |
52 | 63 |
53 SpinningCube cube_; | 64 GLuint fbo_; |
| 65 GLuint rbo_; |
| 66 |
| 67 std::vector<GLuint> textures_; |
| 68 std::vector<pp::ImageData> images_; |
| 69 |
| 70 pp::Compositor compositor_; |
| 71 pp::CompositorLayer color_layer_; |
| 72 pp::CompositorLayer stable_texture_layer_; |
| 73 pp::CompositorLayer texture_layer_; |
| 74 pp::CompositorLayer image_layer_; |
| 75 |
| 76 SpinningCube* cube_; |
54 }; | 77 }; |
55 | 78 |
56 DemoInstance::DemoInstance(PP_Instance instance) | 79 DemoInstance::DemoInstance(PP_Instance instance) |
57 : pp::Instance(instance), | 80 : pp::Instance(instance), |
58 pp::Graphics3DClient(this), | 81 pp::Graphics3DClient(this), |
59 callback_factory_(this), | 82 callback_factory_(this), |
60 context_(NULL) {} | 83 context_(NULL), |
| 84 fbo_(0), |
| 85 rbo_(0), |
| 86 compositor_(this), |
| 87 cube_(new SpinningCube()) {} |
61 | 88 |
62 DemoInstance::~DemoInstance() { | 89 DemoInstance::~DemoInstance() { |
| 90 delete cube_; |
63 assert(glTerminatePPAPI()); | 91 assert(glTerminatePPAPI()); |
64 delete context_; | 92 delete context_; |
65 } | 93 } |
66 | 94 |
67 bool DemoInstance::Init(uint32_t /*argc*/, | 95 bool DemoInstance::Init(uint32_t /*argc*/, |
68 const char* /*argn*/[], | 96 const char* /*argn*/[], |
69 const char* /*argv*/[]) { | 97 const char* /*argv*/[]) { |
70 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); | |
71 return !!glInitializePPAPI(pp::Module::Get()->get_browser_interface()); | 98 return !!glInitializePPAPI(pp::Module::Get()->get_browser_interface()); |
72 } | 99 } |
73 | 100 |
74 void DemoInstance::DidChangeView( | 101 void DemoInstance::DidChangeView( |
75 const pp::Rect& position, const pp::Rect& /*clip*/) { | 102 const pp::Rect& position, const pp::Rect& /*clip*/) { |
76 if (position.width() == 0 || position.height() == 0) | 103 if (position.width() == 0 || position.height() == 0) |
77 return; | 104 return; |
78 plugin_size_ = position.size(); | |
79 | |
80 // Initialize graphics. | 105 // Initialize graphics. |
81 InitGL(0); | 106 InitGL(0); |
82 } | 107 } |
83 | 108 |
84 void DemoInstance::Graphics3DContextLost() { | 109 void DemoInstance::Graphics3DContextLost() { |
| 110 fbo_ = 0; |
| 111 rbo_ = 0; |
| 112 compositor_.ResetLayers(); |
| 113 color_layer_ = pp::CompositorLayer(); |
| 114 stable_texture_layer_ = pp::CompositorLayer(); |
| 115 texture_layer_ = pp::CompositorLayer(); |
| 116 image_layer_ = pp::CompositorLayer(); |
| 117 textures_.clear(); |
85 delete context_; | 118 delete context_; |
86 context_ = NULL; | 119 context_ = NULL; |
| 120 cube_->OnGLContextLost(); |
87 pp::CompletionCallback cb = callback_factory_.NewCallback( | 121 pp::CompletionCallback cb = callback_factory_.NewCallback( |
88 &DemoInstance::InitGL); | 122 &DemoInstance::InitGL); |
89 pp::Module::Get()->core()->CallOnMainThread(0, cb, 0); | 123 pp::Module::Get()->core()->CallOnMainThread(0, cb, 0); |
90 } | 124 } |
91 | 125 |
92 void DemoInstance::InitGL(int32_t /*result*/) { | 126 void DemoInstance::InitGL(int32_t /*result*/) { |
93 assert(plugin_size_.width() && plugin_size_.height()); | 127 if (context_) |
94 | |
95 if (context_) { | |
96 context_->ResizeBuffers(plugin_size_.width(), plugin_size_.height()); | |
97 return; | 128 return; |
98 } | |
99 int32_t context_attributes[] = { | 129 int32_t context_attributes[] = { |
100 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, | 130 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, |
101 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, | 131 PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, |
102 PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8, | 132 PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8, |
103 PP_GRAPHICS3DATTRIB_RED_SIZE, 8, | 133 PP_GRAPHICS3DATTRIB_RED_SIZE, 8, |
104 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0, | 134 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0, |
105 PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0, | 135 PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0, |
106 PP_GRAPHICS3DATTRIB_SAMPLES, 0, | 136 PP_GRAPHICS3DATTRIB_SAMPLES, 0, |
107 PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, | 137 PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, |
108 PP_GRAPHICS3DATTRIB_WIDTH, plugin_size_.width(), | 138 PP_GRAPHICS3DATTRIB_WIDTH, 0, |
109 PP_GRAPHICS3DATTRIB_HEIGHT, plugin_size_.height(), | 139 PP_GRAPHICS3DATTRIB_HEIGHT, 0, |
110 PP_GRAPHICS3DATTRIB_NONE, | 140 PP_GRAPHICS3DATTRIB_NONE, |
111 }; | 141 }; |
112 context_ = new pp::Graphics3D(this, context_attributes); | 142 context_ = new pp::Graphics3D(this, context_attributes); |
113 assert(!context_->is_null()); | 143 assert(!context_->is_null()); |
114 assert(BindGraphics(*context_)); | 144 assert(BindGraphics(compositor_)); |
115 | 145 |
116 glSetCurrentContextPPAPI(context_->pp_resource()); | 146 glSetCurrentContextPPAPI(context_->pp_resource()); |
117 cube_.Init(plugin_size_.width(), plugin_size_.height()); | 147 |
118 Paint(PP_OK); | 148 cube_->Init(kTextureWidth, kTextureHeight); |
119 } | 149 |
120 | 150 Paint(PP_OK, 0); |
121 void DemoInstance::Paint(int32_t result) { | 151 } |
| 152 |
| 153 GLuint DemoInstance::PrepareFramebuffer() { |
| 154 GLuint texture = 0; |
| 155 if (textures_.empty()) { |
| 156 // Create a texture object |
| 157 glGenTextures(1, &texture); |
| 158 glBindTexture(GL_TEXTURE_2D, texture); |
| 159 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, |
| 160 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| 161 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 162 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 163 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 164 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 165 glBindTexture(GL_TEXTURE_2D, 0); |
| 166 } else { |
| 167 texture = textures_.back(); |
| 168 textures_.pop_back(); |
| 169 } |
| 170 |
| 171 if (!rbo_) { |
| 172 // create a renderbuffer object to store depth info |
| 173 glGenRenderbuffers(1, &rbo_); |
| 174 glBindRenderbuffer(GL_RENDERBUFFER, rbo_); |
| 175 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, |
| 176 kTextureWidth, kTextureHeight); |
| 177 glBindRenderbuffer(GL_RENDERBUFFER, 0); |
| 178 } |
| 179 |
| 180 if (!fbo_) { |
| 181 // create a framebuffer object |
| 182 glGenFramebuffers(1, &fbo_); |
| 183 } |
| 184 |
| 185 glBindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| 186 |
| 187 // attach the texture to FBO color attachment point |
| 188 glFramebufferTexture2D(GL_FRAMEBUFFER, |
| 189 GL_COLOR_ATTACHMENT0, |
| 190 GL_TEXTURE_2D, |
| 191 texture, |
| 192 0); |
| 193 |
| 194 // attach the renderbuffer to depth attachment point |
| 195 glFramebufferRenderbuffer(GL_FRAMEBUFFER, |
| 196 GL_DEPTH_ATTACHMENT, |
| 197 GL_RENDERBUFFER, |
| 198 rbo_); |
| 199 |
| 200 // check FBO status |
| 201 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
| 202 assert(status == GL_FRAMEBUFFER_COMPLETE); |
| 203 |
| 204 return texture; |
| 205 } |
| 206 |
| 207 pp::ImageData DemoInstance::PrepareImage() { |
| 208 if (images_.empty()) { |
| 209 return pp::ImageData(this, |
| 210 PP_IMAGEDATAFORMAT_RGBA_PREMUL, |
| 211 pp::Size(kImageWidth, kImageHeight), |
| 212 false); |
| 213 } |
| 214 pp::ImageData image = images_.back(); |
| 215 images_.pop_back(); |
| 216 return image; |
| 217 } |
| 218 |
| 219 void DemoInstance::Paint(int32_t result, int32_t frame) { |
122 if (result != PP_OK || !context_) | 220 if (result != PP_OK || !context_) |
123 return; | 221 return; |
124 | 222 |
125 cube_.UpdateForTimeDelta(0.02f); | 223 float factor_sin = sin(M_PI / 180 * frame); |
126 cube_.Draw(); | 224 float factor_cos = cos(M_PI / 180 * frame); |
127 | 225 { |
128 context_->SwapBuffers(callback_factory_.NewCallback(&DemoInstance::Paint)); | 226 // Set the background color layer. |
| 227 if (color_layer_.is_null()) { |
| 228 color_layer_ = compositor_.AddLayer(); |
| 229 assert(!color_layer_.is_null()); |
| 230 static const float transform[16] = { |
| 231 1.0f, 0.0f, 0.0f, 0.0f, |
| 232 0.0f, 1.0f, 0.0f, 0.0f, |
| 233 0.0f, 0.0f, 1.0f, 0.0f, |
| 234 0.0f, 0.0f, 0.0f, 1.0f, |
| 235 }; |
| 236 color_layer_.SetTransform(transform); |
| 237 } |
| 238 color_layer_.SetColor(fabs(factor_sin), |
| 239 fabs(factor_cos), |
| 240 fabs(factor_sin * factor_cos), |
| 241 1.0f, |
| 242 pp::Size(800, 600)); |
| 243 } |
| 244 |
| 245 { |
| 246 // Set the image layer |
| 247 if (image_layer_.is_null()) { |
| 248 image_layer_ = compositor_.AddLayer(); |
| 249 assert(!image_layer_.is_null()); |
| 250 } |
| 251 float x = frame % 800; |
| 252 float y = 200 - 200 * factor_sin; |
| 253 const float transform[16] = { |
| 254 fabs(factor_sin) + 0.2f, 0.0f, 0.0f, 0.0f, |
| 255 0.0f, fabs(factor_sin) + 0.2f, 0.0f, 0.0f, |
| 256 0.0f, 0.0f, 1.0f, 0.0f, |
| 257 x, y, 0.0f, 1.0f, |
| 258 }; |
| 259 image_layer_.SetTransform(transform); |
| 260 pp::ImageData image = PrepareImage(); |
| 261 uint8_t *p = static_cast<uint8_t*>(image.data()); |
| 262 for (int x = 0; x < kImageWidth; ++x) { |
| 263 for (int y = 0; y < kImageHeight; ++y) { |
| 264 *(p++) = frame; |
| 265 *(p++) = frame * x; |
| 266 *(p++) = frame * y; |
| 267 *(p++) = 255; |
| 268 } |
| 269 } |
| 270 image_layer_.SetImage(image, pp::Size(kImageWidth, kImageHeight), |
| 271 callback_factory_.NewCallback(&DemoInstance::OnImageReleased, image)); |
| 272 } |
| 273 |
| 274 { |
| 275 // Set the stable texture layer |
| 276 if (stable_texture_layer_.is_null()) { |
| 277 stable_texture_layer_ = compositor_.AddLayer(); |
| 278 assert(!stable_texture_layer_.is_null()); |
| 279 stable_texture_layer_.SetPremultipliedAlpha(PP_FALSE); |
| 280 // stable_texture_layer_.SetClipRect(pp::Rect(50, 50, 400, 400)); |
| 281 GLuint texture = PrepareFramebuffer(); |
| 282 cube_->UpdateForTimeDelta(0.02f); |
| 283 cube_->Draw(); |
| 284 stable_texture_layer_.SetTexture(*context_, texture, pp::Size(600, 600), |
| 285 callback_factory_.NewCallback(&DemoInstance::OnTextureReleased, |
| 286 texture)); |
| 287 } |
| 288 float x = 10 - 100 * factor_sin; |
| 289 float y = 10 - 100 * factor_cos; |
| 290 const float transform[16] = { |
| 291 1.0f, 0.0f, 0.0f, 0.0f, |
| 292 0.0f, 1.0f, 0.0f, 0.0f, |
| 293 0.0f, 0.0f, 1.0f, 0.0f, |
| 294 x, y, 0.0f, 1.0f, |
| 295 }; |
| 296 stable_texture_layer_.SetTransform(transform); |
| 297 } |
| 298 |
| 299 { |
| 300 // Set the dynamic texture layer. |
| 301 if (texture_layer_.is_null()) { |
| 302 texture_layer_ = compositor_.AddLayer(); |
| 303 assert(!texture_layer_.is_null()); |
| 304 static const float transform[16] = { |
| 305 1.0f, 0.0f, 0.0f, 0.0f, |
| 306 0.0f, 1.0f, 0.0f, 0.0f, |
| 307 0.0f, 0.0f, 1.0f, 0.0f, |
| 308 200.0f, 0.0f, 0.0f, 1.0f, |
| 309 }; |
| 310 texture_layer_.SetTransform(transform); |
| 311 texture_layer_.SetPremultipliedAlpha(PP_FALSE); |
| 312 } |
| 313 |
| 314 GLuint texture = PrepareFramebuffer(); |
| 315 cube_->UpdateForTimeDelta(0.02f); |
| 316 cube_->Draw(); |
| 317 texture_layer_.SetTexture(*context_, texture, pp::Size(400, 400), |
| 318 callback_factory_.NewCallback(&DemoInstance::OnTextureReleased, |
| 319 texture)); |
| 320 } |
| 321 |
| 322 compositor_.CommitLayers( |
| 323 callback_factory_.NewCallback(&DemoInstance::Paint, ++frame)); |
| 324 } |
| 325 |
| 326 void DemoInstance::OnTextureReleased(int32_t result, GLuint texture) { |
| 327 if (result == PP_OK) |
| 328 textures_.push_back(texture); |
| 329 } |
| 330 |
| 331 void DemoInstance::OnImageReleased(int32_t result, const pp::ImageData& image) { |
| 332 if (result == PP_OK); |
| 333 images_.push_back(image); |
129 } | 334 } |
130 | 335 |
131 // This object is the global object representing this plugin library as long | 336 // This object is the global object representing this plugin library as long |
132 // as it is loaded. | 337 // as it is loaded. |
133 class DemoModule : public pp::Module { | 338 class DemoModule : public pp::Module { |
134 public: | 339 public: |
135 DemoModule() : Module() {} | 340 DemoModule() : Module() {} |
136 virtual ~DemoModule() {} | 341 virtual ~DemoModule() {} |
137 | 342 |
138 virtual pp::Instance* CreateInstance(PP_Instance instance) { | 343 virtual pp::Instance* CreateInstance(PP_Instance instance) { |
139 return new DemoInstance(instance); | 344 return new DemoInstance(instance); |
140 } | 345 } |
141 }; | 346 }; |
142 | 347 |
143 } // anonymous namespace | 348 } // anonymous namespace |
144 | 349 |
145 namespace pp { | 350 namespace pp { |
146 // Factory function for your specialization of the Module object. | 351 // Factory function for your specialization of the Module object. |
147 Module* CreateModule() { | 352 Module* CreateModule() { |
148 return new DemoModule(); | 353 return new DemoModule(); |
149 } | 354 } |
150 } // namespace pp | 355 } // namespace pp |
OLD | NEW |