Index: ppapi/examples/compositor/compositor.cc |
diff --git a/ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.cc b/ppapi/examples/compositor/compositor.cc |
similarity index 31% |
copy from ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.cc |
copy to ppapi/examples/compositor/compositor.cc |
index de1ccbaa0b34147be7eabbbd631717b82ad1ce4c..61da585d30b16f58fd2a93c89544f4a11eefd508 100644 |
--- a/ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.cc |
+++ b/ppapi/examples/compositor/compositor.cc |
@@ -2,16 +2,23 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <math.h> |
+ |
+#include <vector> |
+ |
#include "ppapi/c/pp_errors.h" |
-#include "ppapi/cpp/core.h" |
+#include "ppapi/cpp/compositor.h" |
+#include "ppapi/cpp/compositor_layer.h" |
#include "ppapi/cpp/graphics_3d.h" |
#include "ppapi/cpp/graphics_3d_client.h" |
-#include "ppapi/cpp/input_event.h" |
+#include "ppapi/cpp/image_data.h" |
#include "ppapi/cpp/instance.h" |
#include "ppapi/cpp/module.h" |
#include "ppapi/cpp/rect.h" |
-#include "ppapi/examples/gles2_spinning_cube/spinning_cube.h" |
+#include "ppapi/examples/compositor/spinning_cube.h" |
#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h" |
+#include "ppapi/lib/gl/include/GLES2/gl2.h" |
+#include "ppapi/lib/gl/include/GLES2/gl2ext.h" |
#include "ppapi/utility/completion_callback_factory.h" |
// Use assert as a poor-man's CHECK, even in non-debug mode. |
@@ -22,6 +29,11 @@ |
namespace { |
+const int32_t kTextureWidth = 800; |
+const int32_t kTextureHeight = 800; |
+const int32_t kImageWidth = 256; |
+const int32_t kImageHeight = 256; |
+ |
class DemoInstance : public pp::Instance, public pp::Graphics3DClient { |
public: |
DemoInstance(PP_Instance instance); |
@@ -31,10 +43,6 @@ class DemoInstance : public pp::Instance, public pp::Graphics3DClient { |
virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); |
virtual void DidChangeView(const pp::Rect& position, |
const pp::Rect& clip); |
- virtual bool HandleInputEvent(const pp::InputEvent& event) { |
- // TODO(yzshen): Handle input events. |
- return true; |
- } |
// pp::Graphics3DClient implementation. |
virtual void Graphics3DContextLost(); |
@@ -42,24 +50,44 @@ class DemoInstance : public pp::Instance, public pp::Graphics3DClient { |
private: |
// GL-related functions. |
void InitGL(int32_t result); |
- void Paint(int32_t result); |
+ GLuint PrepareFramebuffer(); |
+ pp::ImageData PrepareImage(); |
+ void Paint(int32_t result, int32_t frame); |
+ void OnTextureReleased(int32_t result, GLuint texture); |
+ void OnImageReleased(int32_t result, const pp::ImageData& image); |
- pp::Size plugin_size_; |
pp::CompletionCallbackFactory<DemoInstance> callback_factory_; |
// Owned data. |
pp::Graphics3D* context_; |
- SpinningCube cube_; |
+ GLuint fbo_; |
+ GLuint rbo_; |
+ |
+ std::vector<GLuint> textures_; |
+ std::vector<pp::ImageData> images_; |
+ |
+ pp::Compositor compositor_; |
+ pp::CompositorLayer color_layer_; |
+ pp::CompositorLayer stable_texture_layer_; |
+ pp::CompositorLayer texture_layer_; |
+ pp::CompositorLayer image_layer_; |
+ |
+ SpinningCube* cube_; |
}; |
DemoInstance::DemoInstance(PP_Instance instance) |
: pp::Instance(instance), |
pp::Graphics3DClient(this), |
callback_factory_(this), |
- context_(NULL) {} |
+ context_(NULL), |
+ fbo_(0), |
+ rbo_(0), |
+ compositor_(this), |
+ cube_(new SpinningCube()) {} |
DemoInstance::~DemoInstance() { |
+ delete cube_; |
assert(glTerminatePPAPI()); |
delete context_; |
} |
@@ -67,7 +95,6 @@ DemoInstance::~DemoInstance() { |
bool DemoInstance::Init(uint32_t /*argc*/, |
const char* /*argn*/[], |
const char* /*argv*/[]) { |
- RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); |
return !!glInitializePPAPI(pp::Module::Get()->get_browser_interface()); |
} |
@@ -75,27 +102,30 @@ void DemoInstance::DidChangeView( |
const pp::Rect& position, const pp::Rect& /*clip*/) { |
if (position.width() == 0 || position.height() == 0) |
return; |
- plugin_size_ = position.size(); |
- |
// Initialize graphics. |
InitGL(0); |
} |
void DemoInstance::Graphics3DContextLost() { |
+ fbo_ = 0; |
+ rbo_ = 0; |
+ compositor_.ResetLayers(); |
+ color_layer_ = pp::CompositorLayer(); |
+ stable_texture_layer_ = pp::CompositorLayer(); |
+ texture_layer_ = pp::CompositorLayer(); |
+ image_layer_ = pp::CompositorLayer(); |
+ textures_.clear(); |
delete context_; |
context_ = NULL; |
+ cube_->OnGLContextLost(); |
pp::CompletionCallback cb = callback_factory_.NewCallback( |
&DemoInstance::InitGL); |
pp::Module::Get()->core()->CallOnMainThread(0, cb, 0); |
} |
void DemoInstance::InitGL(int32_t /*result*/) { |
- assert(plugin_size_.width() && plugin_size_.height()); |
- |
- if (context_) { |
- context_->ResizeBuffers(plugin_size_.width(), plugin_size_.height()); |
+ if (context_) |
return; |
- } |
int32_t context_attributes[] = { |
PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, |
PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8, |
@@ -105,27 +135,202 @@ void DemoInstance::InitGL(int32_t /*result*/) { |
PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0, |
PP_GRAPHICS3DATTRIB_SAMPLES, 0, |
PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, |
- PP_GRAPHICS3DATTRIB_WIDTH, plugin_size_.width(), |
- PP_GRAPHICS3DATTRIB_HEIGHT, plugin_size_.height(), |
+ PP_GRAPHICS3DATTRIB_WIDTH, 0, |
+ PP_GRAPHICS3DATTRIB_HEIGHT, 0, |
PP_GRAPHICS3DATTRIB_NONE, |
}; |
context_ = new pp::Graphics3D(this, context_attributes); |
assert(!context_->is_null()); |
- assert(BindGraphics(*context_)); |
+ assert(BindGraphics(compositor_)); |
glSetCurrentContextPPAPI(context_->pp_resource()); |
- cube_.Init(plugin_size_.width(), plugin_size_.height()); |
- Paint(PP_OK); |
+ |
+ cube_->Init(kTextureWidth, kTextureHeight); |
+ |
+ Paint(PP_OK, 0); |
} |
-void DemoInstance::Paint(int32_t result) { |
+GLuint DemoInstance::PrepareFramebuffer() { |
+ GLuint texture = 0; |
+ if (textures_.empty()) { |
+ // Create a texture object |
+ glGenTextures(1, &texture); |
+ glBindTexture(GL_TEXTURE_2D, texture); |
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureWidth, kTextureHeight, 0, |
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
+ // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
+ // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
+ glBindTexture(GL_TEXTURE_2D, 0); |
+ } else { |
+ texture = textures_.back(); |
+ textures_.pop_back(); |
+ } |
+ |
+ if (!rbo_) { |
+ // create a renderbuffer object to store depth info |
+ glGenRenderbuffers(1, &rbo_); |
+ glBindRenderbuffer(GL_RENDERBUFFER, rbo_); |
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, |
+ kTextureWidth, kTextureHeight); |
+ glBindRenderbuffer(GL_RENDERBUFFER, 0); |
+ } |
+ |
+ if (!fbo_) { |
+ // create a framebuffer object |
+ glGenFramebuffers(1, &fbo_); |
+ } |
+ |
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_); |
+ |
+ // attach the texture to FBO color attachment point |
+ glFramebufferTexture2D(GL_FRAMEBUFFER, |
+ GL_COLOR_ATTACHMENT0, |
+ GL_TEXTURE_2D, |
+ texture, |
+ 0); |
+ |
+ // attach the renderbuffer to depth attachment point |
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, |
+ GL_DEPTH_ATTACHMENT, |
+ GL_RENDERBUFFER, |
+ rbo_); |
+ |
+ // check FBO status |
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
+ assert(status == GL_FRAMEBUFFER_COMPLETE); |
+ |
+ return texture; |
+} |
+ |
+pp::ImageData DemoInstance::PrepareImage() { |
+ if (images_.empty()) { |
+ return pp::ImageData(this, |
+ PP_IMAGEDATAFORMAT_RGBA_PREMUL, |
+ pp::Size(kImageWidth, kImageHeight), |
+ false); |
+ } |
+ pp::ImageData image = images_.back(); |
+ images_.pop_back(); |
+ return image; |
+} |
+ |
+void DemoInstance::Paint(int32_t result, int32_t frame) { |
if (result != PP_OK || !context_) |
return; |
- cube_.UpdateForTimeDelta(0.02f); |
- cube_.Draw(); |
+ float factor_sin = sin(M_PI / 180 * frame); |
+ float factor_cos = cos(M_PI / 180 * frame); |
+ { |
+ // Set the background color layer. |
+ if (color_layer_.is_null()) { |
+ color_layer_ = compositor_.AddLayer(); |
+ assert(!color_layer_.is_null()); |
+ static const float transform[16] = { |
+ 1.0f, 0.0f, 0.0f, 0.0f, |
+ 0.0f, 1.0f, 0.0f, 0.0f, |
+ 0.0f, 0.0f, 1.0f, 0.0f, |
+ 0.0f, 0.0f, 0.0f, 1.0f, |
+ }; |
+ color_layer_.SetTransform(transform); |
+ } |
+ color_layer_.SetColor(fabs(factor_sin), |
+ fabs(factor_cos), |
+ fabs(factor_sin * factor_cos), |
+ 1.0f, |
+ pp::Size(800, 600)); |
+ } |
+ |
+ { |
+ // Set the image layer |
+ if (image_layer_.is_null()) { |
+ image_layer_ = compositor_.AddLayer(); |
+ assert(!image_layer_.is_null()); |
+ } |
+ float x = frame % 800; |
+ float y = 200 - 200 * factor_sin; |
+ const float transform[16] = { |
+ fabs(factor_sin) + 0.2f, 0.0f, 0.0f, 0.0f, |
+ 0.0f, fabs(factor_sin) + 0.2f, 0.0f, 0.0f, |
+ 0.0f, 0.0f, 1.0f, 0.0f, |
+ x, y, 0.0f, 1.0f, |
+ }; |
+ image_layer_.SetTransform(transform); |
+ pp::ImageData image = PrepareImage(); |
+ uint8_t *p = static_cast<uint8_t*>(image.data()); |
+ for (int x = 0; x < kImageWidth; ++x) { |
+ for (int y = 0; y < kImageHeight; ++y) { |
+ *(p++) = frame; |
+ *(p++) = frame * x; |
+ *(p++) = frame * y; |
+ *(p++) = 255; |
+ } |
+ } |
+ image_layer_.SetImage(image, pp::Size(kImageWidth, kImageHeight), |
+ callback_factory_.NewCallback(&DemoInstance::OnImageReleased, image)); |
+ } |
+ |
+ { |
+ // Set the stable texture layer |
+ if (stable_texture_layer_.is_null()) { |
+ stable_texture_layer_ = compositor_.AddLayer(); |
+ assert(!stable_texture_layer_.is_null()); |
+ stable_texture_layer_.SetPremultipliedAlpha(PP_FALSE); |
+ // stable_texture_layer_.SetClipRect(pp::Rect(50, 50, 400, 400)); |
+ GLuint texture = PrepareFramebuffer(); |
+ cube_->UpdateForTimeDelta(0.02f); |
+ cube_->Draw(); |
+ stable_texture_layer_.SetTexture(*context_, texture, pp::Size(600, 600), |
+ callback_factory_.NewCallback(&DemoInstance::OnTextureReleased, |
+ texture)); |
+ } |
+ float x = 10 - 100 * factor_sin; |
+ float y = 10 - 100 * factor_cos; |
+ const float transform[16] = { |
+ 1.0f, 0.0f, 0.0f, 0.0f, |
+ 0.0f, 1.0f, 0.0f, 0.0f, |
+ 0.0f, 0.0f, 1.0f, 0.0f, |
+ x, y, 0.0f, 1.0f, |
+ }; |
+ stable_texture_layer_.SetTransform(transform); |
+ } |
+ |
+ { |
+ // Set the dynamic texture layer. |
+ if (texture_layer_.is_null()) { |
+ texture_layer_ = compositor_.AddLayer(); |
+ assert(!texture_layer_.is_null()); |
+ static const float transform[16] = { |
+ 1.0f, 0.0f, 0.0f, 0.0f, |
+ 0.0f, 1.0f, 0.0f, 0.0f, |
+ 0.0f, 0.0f, 1.0f, 0.0f, |
+ 200.0f, 0.0f, 0.0f, 1.0f, |
+ }; |
+ texture_layer_.SetTransform(transform); |
+ texture_layer_.SetPremultipliedAlpha(PP_FALSE); |
+ } |
+ |
+ GLuint texture = PrepareFramebuffer(); |
+ cube_->UpdateForTimeDelta(0.02f); |
+ cube_->Draw(); |
+ texture_layer_.SetTexture(*context_, texture, pp::Size(400, 400), |
+ callback_factory_.NewCallback(&DemoInstance::OnTextureReleased, |
+ texture)); |
+ } |
+ |
+ compositor_.CommitLayers( |
+ callback_factory_.NewCallback(&DemoInstance::Paint, ++frame)); |
+} |
+ |
+void DemoInstance::OnTextureReleased(int32_t result, GLuint texture) { |
+ if (result == PP_OK) |
+ textures_.push_back(texture); |
+} |
- context_->SwapBuffers(callback_factory_.NewCallback(&DemoInstance::Paint)); |
+void DemoInstance::OnImageReleased(int32_t result, const pp::ImageData& image) { |
+ if (result == PP_OK); |
+ images_.push_back(image); |
} |
// This object is the global object representing this plugin library as long |