summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/examples/compositor/compositor.cc439
-rw-r--r--ppapi/examples/compositor/compositor.html28
-rw-r--r--ppapi/examples/compositor/spinning_cube.cc459
-rw-r--r--ppapi/examples/compositor/spinning_cube.h42
-rw-r--r--ppapi/host/resource_host.cc4
-rw-r--r--ppapi/host/resource_host.h1
-rw-r--r--ppapi/ppapi_internal.gyp1
-rw-r--r--ppapi/ppapi_shared.gypi2
-rw-r--r--ppapi/ppapi_tests.gypi16
-rw-r--r--ppapi/proxy/compositor_layer_resource.cc331
-rw-r--r--ppapi/proxy/compositor_layer_resource.h48
-rw-r--r--ppapi/proxy/compositor_resource.cc107
-rw-r--r--ppapi/proxy/compositor_resource.h45
-rw-r--r--ppapi/proxy/ppapi_messages.h59
-rw-r--r--ppapi/proxy/ppapi_param_traits.cc27
-rw-r--r--ppapi/proxy/ppapi_param_traits.h9
-rw-r--r--ppapi/proxy/ppb_instance_proxy.cc5
-rw-r--r--ppapi/shared_impl/compositor_layer_data.cc36
-rw-r--r--ppapi/shared_impl/compositor_layer_data.h119
19 files changed, 1755 insertions, 23 deletions
diff --git a/ppapi/examples/compositor/compositor.cc b/ppapi/examples/compositor/compositor.cc
new file mode 100644
index 0000000..d437bc84
--- /dev/null
+++ b/ppapi/examples/compositor/compositor.cc
@@ -0,0 +1,439 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Needed on Windows to get |M_PI| from math.h.
+#ifdef _WIN32
+#define _USE_MATH_DEFINES
+#endif
+
+#include <math.h>
+
+#include <vector>
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_input_event.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/image_data.h"
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/var_dictionary.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.
+// Since <assert.h> redefines assert on every inclusion (it doesn't use
+// include-guards), make sure this is the last file #include'd in this file.
+#undef NDEBUG
+#include <assert.h>
+
+// When compiling natively on Windows, PostMessage can be #define-d to
+// something else.
+#ifdef PostMessage
+#undef PostMessage
+#endif
+
+// Assert |context_| isn't holding any GL Errors. Done as a macro instead of a
+// function to preserve line number information in the failure message.
+#define AssertNoGLError() \
+ PP_DCHECK(!glGetError());
+
+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);
+ virtual ~DemoInstance();
+
+ // pp::Instance implementation (see PPP_Instance).
+ 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);
+
+ // pp::Graphics3DClient implementation.
+ virtual void Graphics3DContextLost();
+
+ private:
+ // GL-related functions.
+ void InitGL(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::CompletionCallbackFactory<DemoInstance> callback_factory_;
+
+ // Owned data.
+ pp::Graphics3D* context_;
+
+ 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_;
+
+ bool rebuild_layers_;
+ int32_t total_resource_;
+
+ SpinningCube* cube_;
+};
+
+DemoInstance::DemoInstance(PP_Instance instance)
+ : pp::Instance(instance),
+ pp::Graphics3DClient(this),
+ callback_factory_(this),
+ context_(NULL),
+ fbo_(0),
+ rbo_(0),
+ compositor_(this),
+ rebuild_layers_(false),
+ total_resource_(0),
+ cube_(new SpinningCube()) {
+ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
+}
+
+DemoInstance::~DemoInstance() {
+ delete cube_;
+ assert(glTerminatePPAPI());
+ delete context_;
+}
+
+bool DemoInstance::Init(uint32_t /*argc*/,
+ const char* /*argn*/[],
+ const char* /*argv*/[]) {
+ return !!glInitializePPAPI(pp::Module::Get()->get_browser_interface());
+}
+
+void DemoInstance::DidChangeView(
+ const pp::Rect& position, const pp::Rect& /*clip*/) {
+ if (position.width() == 0 || position.height() == 0)
+ return;
+ // Initialize graphics.
+ InitGL(0);
+}
+
+bool DemoInstance::HandleInputEvent(const pp::InputEvent& event) {
+ switch (event.GetType()) {
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ rebuild_layers_ = true;
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+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();
+ total_resource_ -= static_cast<int32_t>(textures_.size());
+ 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*/) {
+ if (context_)
+ return;
+ int32_t context_attributes[] = {
+ PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_RED_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0,
+ PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0,
+ PP_GRAPHICS3DATTRIB_SAMPLES, 0,
+ PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
+ PP_GRAPHICS3DATTRIB_WIDTH, 32,
+ PP_GRAPHICS3DATTRIB_HEIGHT, 32,
+ PP_GRAPHICS3DATTRIB_NONE,
+ };
+ context_ = new pp::Graphics3D(this, context_attributes);
+ assert(!context_->is_null());
+ assert(BindGraphics(compositor_));
+
+ glSetCurrentContextPPAPI(context_->pp_resource());
+
+ cube_->Init(kTextureWidth, kTextureHeight);
+
+ Paint(PP_OK, 0);
+}
+
+GLuint DemoInstance::PrepareFramebuffer() {
+ GLuint texture = 0;
+ if (textures_.empty()) {
+ total_resource_++;
+ // 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);
+
+ AssertNoGLError();
+ return texture;
+}
+
+pp::ImageData DemoInstance::PrepareImage() {
+ if (images_.empty()) {
+ total_resource_++;
+ 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) {
+ assert(result == PP_OK);
+
+ if (result != PP_OK || !context_)
+ return;
+
+ int32_t rv;
+
+ if (rebuild_layers_) {
+ compositor_.ResetLayers();
+ color_layer_ = pp::CompositorLayer();
+ stable_texture_layer_ = pp::CompositorLayer();
+ texture_layer_ = pp::CompositorLayer();
+ image_layer_ = pp::CompositorLayer();
+ frame = 0;
+ rebuild_layers_ = false;
+ }
+
+ 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,
+ };
+ rv = color_layer_.SetTransform(transform);
+ assert(rv == PP_OK);
+ }
+ rv = color_layer_.SetColor(fabs(factor_sin),
+ fabs(factor_cos),
+ fabs(factor_sin * factor_cos),
+ 1.0f,
+ pp::Size(800, 600));
+ assert(rv == PP_OK);
+ }
+
+ {
+ // 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,
+ };
+ rv = image_layer_.SetTransform(transform);
+ assert(rv == PP_OK);
+
+ 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;
+ }
+ }
+ rv = image_layer_.SetImage(image, pp::Size(kImageWidth, kImageHeight),
+ callback_factory_.NewCallback(&DemoInstance::OnImageReleased, image));
+ assert(rv == PP_OK_COMPLETIONPENDING);
+ }
+
+ {
+ // Set the stable texture layer
+ if (stable_texture_layer_.is_null()) {
+ stable_texture_layer_ = compositor_.AddLayer();
+ assert(!stable_texture_layer_.is_null());
+ GLuint texture = PrepareFramebuffer();
+ cube_->UpdateForTimeDelta(0.02f);
+ cube_->Draw();
+ rv = stable_texture_layer_.SetTexture(
+ *context_,
+ texture, pp::Size(600, 600),
+ callback_factory_.NewCallback(&DemoInstance::OnTextureReleased,
+ texture));
+ assert(rv == PP_OK_COMPLETIONPENDING);
+ rv = stable_texture_layer_.SetPremultipliedAlpha(PP_FALSE);
+ assert(rv == PP_OK);
+ }
+
+ int32_t delta = 200 * fabsf(factor_sin);
+ if (delta != 0) {
+ int32_t x_y = 25 + delta;
+ int32_t w_h = 650 - delta - delta;
+ rv = stable_texture_layer_.SetClipRect(pp::Rect(x_y, x_y, w_h, w_h));
+ } else {
+ rv = stable_texture_layer_.SetClipRect(pp::Rect());
+ }
+ assert(rv == PP_OK);
+
+ const float transform[16] = {
+ factor_cos, -factor_sin, 0.0f, 0.0f,
+ factor_sin, factor_cos, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 50.0f, 50.0f, 0.0f, 1.0f,
+ };
+ rv = stable_texture_layer_.SetTransform(transform);
+ assert(rv == PP_OK);
+ }
+
+ {
+ // 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,
+ };
+ rv = texture_layer_.SetTransform(transform);
+ assert(rv == PP_OK);
+ }
+
+ GLuint texture = PrepareFramebuffer();
+ cube_->UpdateForTimeDelta(0.02f);
+ cube_->Draw();
+ rv = texture_layer_.SetTexture(*context_, texture, pp::Size(400, 400),
+ callback_factory_.NewCallback(&DemoInstance::OnTextureReleased,
+ texture));
+ assert(rv == PP_OK_COMPLETIONPENDING);
+ rv = texture_layer_.SetPremultipliedAlpha(PP_FALSE);
+ assert(rv == PP_OK);
+ }
+
+ rv = compositor_.CommitLayers(
+ callback_factory_.NewCallback(&DemoInstance::Paint, ++frame));
+ assert(rv == PP_OK_COMPLETIONPENDING);
+
+ pp::VarDictionary dict;
+ dict.Set(pp::Var("total_resource"), pp::Var(total_resource_));
+ dict.Set(pp::Var("free_resource"),
+ pp::Var((int32_t)(textures_.size() + images_.size())));
+ PostMessage(dict);
+}
+
+void DemoInstance::OnTextureReleased(int32_t result, GLuint texture) {
+ if (result == PP_OK)
+ textures_.push_back(texture);
+}
+
+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
+// as it is loaded.
+class DemoModule : public pp::Module {
+ public:
+ DemoModule() : Module() {}
+ virtual ~DemoModule() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new DemoInstance(instance);
+ }
+};
+
+} // anonymous namespace
+
+namespace pp {
+// Factory function for your specialization of the Module object.
+Module* CreateModule() {
+ return new DemoModule();
+}
+} // namespace pp
diff --git a/ppapi/examples/compositor/compositor.html b/ppapi/examples/compositor/compositor.html
new file mode 100644
index 0000000..a0dcfbe
--- /dev/null
+++ b/ppapi/examples/compositor/compositor.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <!--
+ Copyright 2014 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+ -->
+<head>
+ <title>GLES2 Spinning Cube Example</title>
+</head>
+
+<body>
+
+<embed id="plugin" type="application/x-ppapi-example-compositor"
+ width="800" height="600"/> <br/>
+ Total resource: <input id="total" > <br/>
+ Free resource: <input id="free" > <br/>
+<script type="text/javascript">
+ var plugin = document.getElementById('plugin');
+ var total = document.getElementById('total');
+ var free = document.getElementById('free');
+ plugin.addEventListener('message', function(message) {
+ total.value = message.data.total_resource;
+ free.value = message.data.free_resource;
+ }, false);
+</script>
+</body>
+</html>
diff --git a/ppapi/examples/compositor/spinning_cube.cc b/ppapi/examples/compositor/spinning_cube.cc
new file mode 100644
index 0000000..2e76699
--- /dev/null
+++ b/ppapi/examples/compositor/spinning_cube.cc
@@ -0,0 +1,459 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This example program is based on Simple_VertexShader.c from:
+
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+#include "ppapi/examples/compositor/spinning_cube.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "ppapi/lib/gl/include/GLES2/gl2.h"
+
+namespace {
+
+const float kPi = 3.14159265359f;
+
+int GenerateCube(GLuint *vbo_vertices,
+ GLuint *vbo_indices) {
+ const int num_indices = 36;
+
+ const GLfloat cube_vertices[] = {
+ -0.5f, -0.5f, -0.5f,
+ 0.5f, -0.5f, -0.5f,
+ 0.5f, -0.5f, 0.5f,
+ -0.5f, -0.5f, 0.5f,
+ -0.5f, 0.5f, -0.5f,
+ 0.5f, 0.5f, -0.5f,
+ 0.5f, 0.5f, 0.5f,
+ -0.5f, 0.5f, 0.5f,
+ };
+
+ const GLushort cube_indices[] = {
+ 0, 2, 1,
+ 0, 3, 2,
+ 4, 5, 6,
+ 4, 6, 7,
+ 3, 6, 2,
+ 3, 7, 6,
+ 0, 1, 5,
+ 0, 5, 4,
+ 0, 7, 3,
+ 0, 4, 7,
+ 1, 2, 6,
+ 1, 6, 5,
+ };
+
+ if (vbo_vertices) {
+ glGenBuffers(1, vbo_vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, *vbo_vertices);
+ glBufferData(GL_ARRAY_BUFFER,
+ sizeof(cube_vertices),
+ cube_vertices,
+ GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
+ if (vbo_indices) {
+ glGenBuffers(1, vbo_indices);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *vbo_indices);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+ sizeof(cube_indices),
+ cube_indices,
+ GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ return num_indices;
+}
+
+GLuint LoadShader(GLenum type,
+ const char* shader_source) {
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, &shader_source, NULL);
+ glCompileShader(shader);
+
+ GLint compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+
+ if (!compiled) {
+ glDeleteShader(shader);
+ return 0;
+ }
+
+ return shader;
+}
+
+GLuint LoadProgram(const char* vertext_shader_source,
+ const char* fragment_shader_source) {
+ GLuint vertex_shader = LoadShader(GL_VERTEX_SHADER,
+ vertext_shader_source);
+ if (!vertex_shader)
+ return 0;
+
+ GLuint fragment_shader = LoadShader(GL_FRAGMENT_SHADER,
+ fragment_shader_source);
+ if (!fragment_shader) {
+ glDeleteShader(vertex_shader);
+ return 0;
+ }
+
+ GLuint program_object = glCreateProgram();
+ glAttachShader(program_object, vertex_shader);
+ glAttachShader(program_object, fragment_shader);
+
+ glLinkProgram(program_object);
+
+ glDeleteShader(vertex_shader);
+ glDeleteShader(fragment_shader);
+
+ GLint linked = 0;
+ glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
+
+ if (!linked) {
+ glDeleteProgram(program_object);
+ return 0;
+ }
+
+ return program_object;
+}
+
+class ESMatrix {
+ public:
+ GLfloat m[4][4];
+
+ ESMatrix() {
+ LoadZero();
+ }
+
+ void LoadZero() {
+ memset(this, 0x0, sizeof(ESMatrix));
+ }
+
+ void LoadIdentity() {
+ LoadZero();
+ m[0][0] = 1.0f;
+ m[1][1] = 1.0f;
+ m[2][2] = 1.0f;
+ m[3][3] = 1.0f;
+ }
+
+ void Multiply(ESMatrix* a, ESMatrix* b) {
+ ESMatrix result;
+ for (int i = 0; i < 4; ++i) {
+ result.m[i][0] = (a->m[i][0] * b->m[0][0]) +
+ (a->m[i][1] * b->m[1][0]) +
+ (a->m[i][2] * b->m[2][0]) +
+ (a->m[i][3] * b->m[3][0]);
+
+ result.m[i][1] = (a->m[i][0] * b->m[0][1]) +
+ (a->m[i][1] * b->m[1][1]) +
+ (a->m[i][2] * b->m[2][1]) +
+ (a->m[i][3] * b->m[3][1]);
+
+ result.m[i][2] = (a->m[i][0] * b->m[0][2]) +
+ (a->m[i][1] * b->m[1][2]) +
+ (a->m[i][2] * b->m[2][2]) +
+ (a->m[i][3] * b->m[3][2]);
+
+ result.m[i][3] = (a->m[i][0] * b->m[0][3]) +
+ (a->m[i][1] * b->m[1][3]) +
+ (a->m[i][2] * b->m[2][3]) +
+ (a->m[i][3] * b->m[3][3]);
+ }
+ *this = result;
+ }
+
+ void Frustum(float left,
+ float right,
+ float bottom,
+ float top,
+ float near_z,
+ float far_z) {
+ float delta_x = right - left;
+ float delta_y = top - bottom;
+ float delta_z = far_z - near_z;
+
+ if ((near_z <= 0.0f) ||
+ (far_z <= 0.0f) ||
+ (delta_z <= 0.0f) ||
+ (delta_y <= 0.0f) ||
+ (delta_y <= 0.0f))
+ return;
+
+ ESMatrix frust;
+ frust.m[0][0] = 2.0f * near_z / delta_x;
+ frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
+
+ frust.m[1][1] = 2.0f * near_z / delta_y;
+ frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
+
+ frust.m[2][0] = (right + left) / delta_x;
+ frust.m[2][1] = (top + bottom) / delta_y;
+ frust.m[2][2] = -(near_z + far_z) / delta_z;
+ frust.m[2][3] = -1.0f;
+
+ frust.m[3][2] = -2.0f * near_z * far_z / delta_z;
+ frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
+
+ Multiply(&frust, this);
+ }
+
+ void Perspective(float fov_y, float aspect, float near_z, float far_z) {
+ GLfloat frustum_h = tanf(fov_y / 360.0f * kPi) * near_z;
+ GLfloat frustum_w = frustum_h * aspect;
+ Frustum(-frustum_w, frustum_w, -frustum_h, frustum_h, near_z, far_z);
+ }
+
+ void Translate(GLfloat tx, GLfloat ty, GLfloat tz) {
+ m[3][0] += m[0][0] * tx + m[1][0] * ty + m[2][0] * tz;
+ m[3][1] += m[0][1] * tx + m[1][1] * ty + m[2][1] * tz;
+ m[3][2] += m[0][2] * tx + m[1][2] * ty + m[2][2] * tz;
+ m[3][3] += m[0][3] * tx + m[1][3] * ty + m[2][3] * tz;
+ }
+
+ void Rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
+ GLfloat mag = sqrtf(x * x + y * y + z * z);
+
+ GLfloat sin_angle = sinf(angle * kPi / 180.0f);
+ GLfloat cos_angle = cosf(angle * kPi / 180.0f);
+ if (mag > 0.0f) {
+ GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
+ GLfloat one_minus_cos;
+ ESMatrix rotation;
+
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+ xx = x * x;
+ yy = y * y;
+ zz = z * z;
+ xy = x * y;
+ yz = y * z;
+ zx = z * x;
+ xs = x * sin_angle;
+ ys = y * sin_angle;
+ zs = z * sin_angle;
+ one_minus_cos = 1.0f - cos_angle;
+
+ rotation.m[0][0] = (one_minus_cos * xx) + cos_angle;
+ rotation.m[0][1] = (one_minus_cos * xy) - zs;
+ rotation.m[0][2] = (one_minus_cos * zx) + ys;
+ rotation.m[0][3] = 0.0F;
+
+ rotation.m[1][0] = (one_minus_cos * xy) + zs;
+ rotation.m[1][1] = (one_minus_cos * yy) + cos_angle;
+ rotation.m[1][2] = (one_minus_cos * yz) - xs;
+ rotation.m[1][3] = 0.0F;
+
+ rotation.m[2][0] = (one_minus_cos * zx) - ys;
+ rotation.m[2][1] = (one_minus_cos * yz) + xs;
+ rotation.m[2][2] = (one_minus_cos * zz) + cos_angle;
+ rotation.m[2][3] = 0.0F;
+
+ rotation.m[3][0] = 0.0F;
+ rotation.m[3][1] = 0.0F;
+ rotation.m[3][2] = 0.0F;
+ rotation.m[3][3] = 1.0F;
+
+ Multiply(&rotation, this);
+ }
+ }
+};
+
+float RotationForTimeDelta(float delta_time) {
+ return delta_time * 40.0f;
+}
+
+float RotationForDragDistance(float drag_distance) {
+ return drag_distance / 5; // Arbitrary damping.
+}
+
+} // namespace
+
+class SpinningCube::GLState {
+ public:
+ GLState();
+
+ void OnGLContextLost();
+
+ GLfloat angle_; // Survives losing the GL context.
+
+ GLuint program_object_;
+ GLint position_location_;
+ GLint mvp_location_;
+ GLuint vbo_vertices_;
+ GLuint vbo_indices_;
+ int num_indices_;
+ ESMatrix mvp_matrix_;
+};
+
+SpinningCube::GLState::GLState()
+ : angle_(0) {
+ OnGLContextLost();
+}
+
+void SpinningCube::GLState::OnGLContextLost() {
+ program_object_ = 0;
+ position_location_ = 0;
+ mvp_location_ = 0;
+ vbo_vertices_ = 0;
+ vbo_indices_ = 0;
+ num_indices_ = 0;
+}
+
+SpinningCube::SpinningCube()
+ : initialized_(false),
+ width_(0),
+ height_(0),
+ state_(new GLState()),
+ fling_multiplier_(1.0f),
+ direction_(1) {
+ state_->angle_ = 45.0f;
+}
+
+SpinningCube::~SpinningCube() {
+ if (!initialized_)
+ return;
+ if (state_->vbo_vertices_)
+ glDeleteBuffers(1, &state_->vbo_vertices_);
+ if (state_->vbo_indices_)
+ glDeleteBuffers(1, &state_->vbo_indices_);
+ if (state_->program_object_)
+ glDeleteProgram(state_->program_object_);
+
+ delete state_;
+}
+
+void SpinningCube::Init(uint32_t width, uint32_t height) {
+ width_ = width;
+ height_ = height;
+
+ if (!initialized_) {
+ initialized_ = true;
+ const char vertext_shader_source[] =
+ "uniform mat4 u_mvpMatrix; \n"
+ "attribute vec4 a_position; \n"
+ "varying vec4 v_color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_mvpMatrix * a_position; \n"
+ " v_color = vec4(a_position.x + 0.5, \n"
+ " a_position.y + 0.5, \n"
+ " a_position.z + 0.5, \n"
+ " 0.8); \n"
+ "} \n";
+
+ const char fragment_shader_source[] =
+ "precision mediump float; \n"
+ "varying vec4 v_color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = v_color; \n"
+ "} \n";
+
+ state_->program_object_ = LoadProgram(
+ vertext_shader_source, fragment_shader_source);
+ state_->position_location_ = glGetAttribLocation(
+ state_->program_object_, "a_position");
+ state_->mvp_location_ = glGetUniformLocation(
+ state_->program_object_, "u_mvpMatrix");
+ state_->num_indices_ = GenerateCube(&state_->vbo_vertices_,
+ &state_->vbo_indices_);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.2f);
+ }
+}
+
+void SpinningCube::OnGLContextLost() {
+ // TODO(yzshen): Is it correct that in this case we don't need to do cleanup
+ // for program and buffers?
+ initialized_ = false;
+ height_ = 0;
+ width_ = 0;
+ state_->OnGLContextLost();
+}
+
+void SpinningCube::SetFlingMultiplier(float drag_distance,
+ float drag_time) {
+ fling_multiplier_ = RotationForDragDistance(drag_distance) /
+ RotationForTimeDelta(drag_time);
+
+}
+
+void SpinningCube::UpdateForTimeDelta(float delta_time) {
+ state_->angle_ += RotationForTimeDelta(delta_time) * fling_multiplier_;
+ if (state_->angle_ >= 360.0f)
+ state_->angle_ -= 360.0f;
+
+ // Arbitrary 50-step linear reduction in spin speed.
+ if (fling_multiplier_ > 1.0f) {
+ fling_multiplier_ =
+ std::max(1.0f, fling_multiplier_ - (fling_multiplier_ - 1.0f) / 50);
+ }
+
+ Update();
+}
+
+void SpinningCube::UpdateForDragDistance(float distance) {
+ state_->angle_ += RotationForDragDistance(distance);
+ if (state_->angle_ >= 360.0f )
+ state_->angle_ -= 360.0f;
+
+ Update();
+}
+
+void SpinningCube::Draw() {
+ glViewport(0, 0, width_, height_);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ glUseProgram(state_->program_object_);
+
+ glBindBuffer(GL_ARRAY_BUFFER, state_->vbo_vertices_);
+ glVertexAttribPointer(state_->position_location_,
+ 3,
+ GL_FLOAT,
+ GL_FALSE, 3 * sizeof(GLfloat),
+ 0);
+ glEnableVertexAttribArray(state_->position_location_);
+
+ glUniformMatrix4fv(state_->mvp_location_,
+ 1,
+ GL_FALSE,
+ (GLfloat*) &state_->mvp_matrix_.m[0][0]);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state_->vbo_indices_);
+ glDrawElements(GL_TRIANGLES,
+ state_->num_indices_,
+ GL_UNSIGNED_SHORT,
+ 0);
+}
+
+void SpinningCube::Update() {
+ float aspect = static_cast<GLfloat>(width_) / static_cast<GLfloat>(height_);
+
+ ESMatrix perspective;
+ perspective.LoadIdentity();
+ perspective.Perspective(60.0f, aspect, 1.0f, 20.0f );
+
+ ESMatrix modelview;
+ modelview.LoadIdentity();
+ modelview.Translate(0.0, 0.0, -2.0);
+ modelview.Rotate(state_->angle_ * direction_, 1.0, 0.0, 1.0);
+
+ state_->mvp_matrix_.Multiply(&modelview, &perspective);
+}
diff --git a/ppapi/examples/compositor/spinning_cube.h b/ppapi/examples/compositor/spinning_cube.h
new file mode 100644
index 0000000..84a302c2
--- /dev/null
+++ b/ppapi/examples/compositor/spinning_cube.h
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_EXAMPLES_GLES2_SPINNING_CUBE_SPINNING_CUBE_H_
+#define PPAPI_EXAMPLES_GLES2_SPINNING_CUBE_SPINNING_CUBE_H_
+
+#include "ppapi/c/pp_stdint.h"
+
+class SpinningCube {
+ public:
+ SpinningCube();
+ ~SpinningCube();
+
+ void Init(uint32_t width, uint32_t height);
+ void set_direction(int direction) { direction_ = direction; }
+ void SetFlingMultiplier(float drag_distance, float drag_time);
+ void UpdateForTimeDelta(float delta_time);
+ void UpdateForDragDistance(float distance);
+ void Draw();
+
+ void OnGLContextLost();
+
+ private:
+ class GLState;
+
+ // Disallow copy and assign.
+ SpinningCube(const SpinningCube& other);
+ SpinningCube& operator=(const SpinningCube& other);
+
+ void Update();
+
+ bool initialized_;
+ uint32_t width_;
+ uint32_t height_;
+ // Owned ptr.
+ GLState* state_;
+ float fling_multiplier_;
+ int direction_;
+};
+
+#endif // PPAPI_EXAMPLES_GLES2_SPINNING_CUBE_SPINNING_CUBE_H_
diff --git a/ppapi/host/resource_host.cc b/ppapi/host/resource_host.cc
index b453398..2d5af58 100644
--- a/ppapi/host/resource_host.cc
+++ b/ppapi/host/resource_host.cc
@@ -48,6 +48,10 @@ void ResourceHost::SendReply(const ReplyMessageContext& context,
host_->SendReply(context, msg);
}
+bool ResourceHost::IsCompositorHost() {
+ return false;
+}
+
bool ResourceHost::IsFileRefHost() {
return false;
}
diff --git a/ppapi/host/resource_host.h b/ppapi/host/resource_host.h
index a9518ee..a2d3885 100644
--- a/ppapi/host/resource_host.h
+++ b/ppapi/host/resource_host.h
@@ -56,6 +56,7 @@ class PPAPI_HOST_EXPORT ResourceHost : public ResourceMessageHandler {
// Simple RTTI. A subclass that is a host for one of these APIs will override
// the appropriate function and return true.
+ virtual bool IsCompositorHost();
virtual bool IsFileRefHost();
virtual bool IsFileSystemHost();
virtual bool IsGraphics2DHost();
diff --git a/ppapi/ppapi_internal.gyp b/ppapi/ppapi_internal.gyp
index 3a07317..4c1614f 100644
--- a/ppapi/ppapi_internal.gyp
+++ b/ppapi/ppapi_internal.gyp
@@ -231,6 +231,7 @@
'ppapi.gyp:ppapi_c',
'../base/base.gyp:base_win64',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
+ '../gpu/gpu.gyp:command_buffer_common_win64',
'../ipc/ipc.gyp:ipc_win64',
'../ui/events/latency_info_nacl.gyp:latency_info_nacl_win64',
],
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index d62758f..23b00de 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -17,6 +17,8 @@
'shared_impl/array_writer.h',
'shared_impl/callback_tracker.cc',
'shared_impl/callback_tracker.h',
+ 'shared_impl/compositor_layer_data.cc',
+ 'shared_impl/compositor_layer_data.h',
'shared_impl/dictionary_var.cc',
'shared_impl/dictionary_var.h',
'shared_impl/file_io_state_manager.cc',
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index 35b0ff1..bc02aa1 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -571,5 +571,21 @@
'examples/gles2_spinning_cube/spinning_cube.h',
],
},
+ {
+ 'target_name': 'ppapi_example_compositor',
+ 'dependencies': [
+ 'ppapi_example_skeleton',
+ 'ppapi.gyp:ppapi_cpp',
+ 'ppapi.gyp:ppapi_gles2',
+ ],
+ 'include_dirs': [
+ 'lib/gl/include',
+ ],
+ 'sources': [
+ 'examples/compositor/compositor.cc',
+ 'examples/compositor/spinning_cube.cc',
+ 'examples/compositor/spinning_cube.h',
+ ],
+ },
],
}
diff --git a/ppapi/proxy/compositor_layer_resource.cc b/ppapi/proxy/compositor_layer_resource.cc
index 829ff18..fb1bbe5 100644
--- a/ppapi/proxy/compositor_layer_resource.cc
+++ b/ppapi/proxy/compositor_layer_resource.cc
@@ -4,15 +4,99 @@
#include "ppapi/proxy/compositor_layer_resource.h"
+#include "base/logging.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "ppapi/proxy/compositor_resource.h"
+#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_graphics_3d_api.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
+
+using gpu::gles2::GLES2Implementation;
+using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_ImageData_API;
+using ppapi::thunk::PPB_Graphics3D_API;
+
namespace ppapi {
namespace proxy {
-CompositorLayerResource::CompositorLayerResource(Connection connection,
- PP_Instance instance)
- : PluginResource(connection, instance) {
+namespace {
+
+class Scoped2DTextureBinder {
+ public:
+ Scoped2DTextureBinder(GLES2Implementation* gl, uint32_t id)
+ : gl_(gl), old_id_(-1) {
+ gl_->GetIntegerv(GL_TEXTURE_BINDING_2D, &old_id_);
+ gl_->BindTexture(GL_TEXTURE_2D, id);
+ }
+
+ ~Scoped2DTextureBinder() {
+ gl_->BindTexture(GL_TEXTURE_2D, old_id_);
+ }
+
+ private:
+ GLES2Implementation* gl_;
+ int32_t old_id_;
+};
+
+float clamp(float value) {
+ return std::min(std::max(value, 0.0f), 1.0f);
+}
+
+void OnTextureReleased(
+ const ScopedPPResource& layer,
+ const ScopedPPResource& context,
+ uint32_t texture,
+ const scoped_refptr<TrackedCallback>& release_callback,
+ uint32_t sync_point,
+ bool is_lost) {
+ if (!TrackedCallback::IsPending(release_callback))
+ return;
+
+ do {
+ if (!sync_point)
+ break;
+
+ EnterResourceNoLock<PPB_Graphics3D_API> enter(context.get(), true);
+ if (enter.failed())
+ break;
+
+ PPB_Graphics3D_Shared* graphics =
+ static_cast<PPB_Graphics3D_Shared*>(enter.object());
+
+ GLES2Implementation* gl = graphics->gles2_impl();
+ gl->WaitSyncPointCHROMIUM(sync_point);
+ } while (false);
+
+ release_callback->Run(is_lost ? PP_ERROR_FAILED : PP_OK);
+}
+
+void OnImageReleased(
+ const ScopedPPResource& layer,
+ const ScopedPPResource& image,
+ const scoped_refptr<TrackedCallback>& release_callback,
+ uint32_t sync_point,
+ bool is_lost) {
+ if (!TrackedCallback::IsPending(release_callback))
+ return;
+ release_callback->Run(PP_OK);
+}
+
+} // namespace
+
+CompositorLayerResource::CompositorLayerResource(
+ Connection connection,
+ PP_Instance instance,
+ const CompositorResource* compositor)
+ : PluginResource(connection, instance),
+ compositor_(compositor),
+ source_size_(PP_MakeFloatSize(0.0f, 0.0f)) {
}
CompositorLayerResource::~CompositorLayerResource() {
+ DCHECK(!compositor_);
+ DCHECK(release_callback_.is_null());
}
thunk::PPB_CompositorLayer_API*
@@ -25,47 +109,266 @@ int32_t CompositorLayerResource::SetColor(float red,
float blue,
float alpha,
const PP_Size* size) {
- return PP_ERROR_NOTSUPPORTED;
+ if (!compositor_)
+ return PP_ERROR_BADRESOURCE;
+
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ if (!SetType(TYPE_COLOR))
+ return PP_ERROR_BADARGUMENT;
+ DCHECK(data_.color);
+
+ if (!size)
+ return PP_ERROR_BADARGUMENT;
+
+
+ data_.color->red = clamp(red);
+ data_.color->green = clamp(green);
+ data_.color->blue = clamp(blue);
+ data_.color->alpha = clamp(alpha);
+ data_.common.size = *size;
+
+ return PP_OK;
}
int32_t CompositorLayerResource::SetTexture(
PP_Resource context,
uint32_t texture,
const PP_Size* size,
- const scoped_refptr<ppapi::TrackedCallback>& callback) {
- return PP_ERROR_NOTSUPPORTED;
+ const scoped_refptr<TrackedCallback>& release_callback) {
+ int32_t rv = CheckForSetTextureAndImage(TYPE_TEXTURE, release_callback);
+ if (rv != PP_OK)
+ return rv;
+ DCHECK(data_.texture);
+
+ EnterResourceNoLock<PPB_Graphics3D_API> enter(context, true);
+ if (enter.failed())
+ return PP_ERROR_BADRESOURCE;
+
+ if (!size || size->width <= 0 || size->height <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ PPB_Graphics3D_Shared* graphics =
+ static_cast<PPB_Graphics3D_Shared*>(enter.object());
+
+ GLES2Implementation* gl = graphics->gles2_impl();
+ Scoped2DTextureBinder scoped_2d_texture_binder(gl, texture);
+
+ // Generate a Mailbox for the texture.
+ gl->GenMailboxCHROMIUM(
+ reinterpret_cast<GLbyte*>(data_.texture->mailbox.name));
+ gl->ProduceTextureCHROMIUM(
+ GL_TEXTURE_2D,
+ reinterpret_cast<const GLbyte*>(data_.texture->mailbox.name));
+
+ // Set the source size to (1, 1). It will be used to verify the source_rect
+ // passed to SetSourceRect().
+ source_size_ = PP_MakeFloatSize(1.0f, 1.0f);
+
+ data_.common.size = *size;
+ data_.common.resource_id = compositor_->GenerateResourceId();
+ data_.texture->sync_point = gl->InsertSyncPointCHROMIUM();
+ data_.texture->source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f);
+ data_.texture->source_rect.size = source_size_;
+
+ // If the PP_Resource of this layer is released by the plugin, the
+ // release_callback will be aborted immediately, but the texture or image
+ // in this layer may still being used by chromium compositor. So we have to
+ // use ScopedPPResource to keep this resource alive until the texture or image
+ // is released by the chromium compositor.
+ release_callback_ = base::Bind(
+ &OnTextureReleased,
+ ScopedPPResource(pp_resource()), // Keep layer alive.
+ ScopedPPResource(context), // Keep context alive
+ texture,
+ release_callback);
+
+ return PP_OK_COMPLETIONPENDING;
}
int32_t CompositorLayerResource::SetImage(
PP_Resource image_data,
const PP_Size* size,
- const scoped_refptr<ppapi::TrackedCallback>& callback) {
- return PP_ERROR_NOTSUPPORTED;
+ const scoped_refptr<TrackedCallback>& release_callback) {
+ int32_t rv = CheckForSetTextureAndImage(TYPE_IMAGE, release_callback);
+ if (rv != PP_OK)
+ return rv;
+ DCHECK(data_.image);
+
+ EnterResourceNoLock<PPB_ImageData_API> enter(image_data, true);
+ if (enter.failed())
+ return PP_ERROR_BADRESOURCE;
+
+ PP_ImageDataDesc desc;
+ if (!enter.object()->Describe(&desc))
+ return PP_ERROR_BADARGUMENT;
+
+ // TODO(penghuang): Support image which width * 4 != stride.
+ if (desc.size.width * 4 != desc.stride)
+ return PP_ERROR_BADARGUMENT;
+
+ // TODO(penghuang): Support all formats.
+ if (desc.format != PP_IMAGEDATAFORMAT_RGBA_PREMUL)
+ return PP_ERROR_BADARGUMENT;
+
+ if (!size || size->width <= 0 || size->height <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ // Set the source size to image's size. It will be used to verify
+ // the source_rect passed to SetSourceRect().
+ source_size_ = PP_MakeFloatSize(desc.size.width, desc.size.height);
+
+ data_.common.size = size ? *size : desc.size;
+ data_.common.resource_id = compositor_->GenerateResourceId();
+ data_.image->resource = enter.resource()->host_resource().host_resource();
+ data_.image->source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f);
+ data_.image->source_rect.size = source_size_;
+
+ release_callback_ = base::Bind(
+ &OnImageReleased,
+ ScopedPPResource(pp_resource()), // Keep layer alive.
+ ScopedPPResource(image_data), // Keep image_data alive.
+ release_callback);
+
+ return PP_OK_COMPLETIONPENDING;
}
int32_t CompositorLayerResource::SetClipRect(const PP_Rect* rect) {
- return PP_ERROR_NOTSUPPORTED;
+ if (!compositor_)
+ return PP_ERROR_BADRESOURCE;
+
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ data_.common.clip_rect = rect ? *rect : PP_MakeRectFromXYWH(0, 0, 0, 0);
+ return PP_OK;
}
int32_t CompositorLayerResource::SetTransform(const float matrix[16]) {
- return PP_ERROR_NOTSUPPORTED;
+ if (!compositor_)
+ return PP_ERROR_BADRESOURCE;
+
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ std::copy(matrix, matrix + 16, data_.common.transform.matrix);
+ return PP_OK;
}
int32_t CompositorLayerResource::SetOpacity(float opacity) {
- return PP_ERROR_NOTSUPPORTED;
+ if (!compositor_)
+ return PP_ERROR_BADRESOURCE;
+
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ data_.common.opacity = clamp(opacity);
+ return PP_OK;
}
int32_t CompositorLayerResource::SetBlendMode(PP_BlendMode mode) {
- return PP_ERROR_NOTSUPPORTED;
+ if (!compositor_)
+ return PP_ERROR_BADRESOURCE;
+
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ switch (mode) {
+ case PP_BLENDMODE_NONE:
+ case PP_BLENDMODE_SRC_OVER:
+ data_.common.blend_mode = mode;
+ return PP_OK;
+ }
+ return PP_ERROR_BADARGUMENT;
}
int32_t CompositorLayerResource::SetSourceRect(
const PP_FloatRect* rect) {
- return PP_ERROR_NOTSUPPORTED;
+ if (!compositor_)
+ return PP_ERROR_BADRESOURCE;
+
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ if (!rect ||
+ rect->point.x < 0.0f ||
+ rect->point.y < 0.0f ||
+ rect->point.x + rect->size.width > source_size_.width ||
+ rect->point.y + rect->size.height > source_size_.height) {
+ return PP_ERROR_BADARGUMENT;
+ }
+
+ if (data_.texture) {
+ data_.texture->source_rect = *rect;
+ return PP_OK;
+ }
+ if (data_.image) {
+ data_.image->source_rect = *rect;
+ return PP_OK;
+ }
+ return PP_ERROR_BADARGUMENT;
}
int32_t CompositorLayerResource::SetPremultipliedAlpha(PP_Bool premult) {
- return PP_ERROR_NOTSUPPORTED;
+ if (!compositor_)
+ return PP_ERROR_BADRESOURCE;
+
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ if (data_.texture) {
+ data_.texture->premult_alpha = PP_ToBool(premult);
+ return PP_OK;
+ }
+ return PP_ERROR_BADARGUMENT;
+}
+
+bool CompositorLayerResource::SetType(LayerType type) {
+ if (type == TYPE_COLOR) {
+ if (data_.is_null())
+ data_.color.reset(new CompositorLayerData::ColorLayer());
+ return data_.color;
+ }
+
+ if (type == TYPE_TEXTURE) {
+ if (data_.is_null())
+ data_.texture.reset(new CompositorLayerData::TextureLayer());
+ return data_.texture;
+ }
+
+ if (type == TYPE_IMAGE) {
+ if (data_.is_null())
+ data_.image.reset(new CompositorLayerData::ImageLayer());
+ return data_.image;
+ }
+
+ // Should not be reached.
+ DCHECK(false);
+ return false;
+}
+
+int32_t CompositorLayerResource::CheckForSetTextureAndImage(
+ LayerType type,
+ const scoped_refptr<TrackedCallback>& release_callback) {
+ if (!compositor_)
+ return PP_ERROR_BADRESOURCE;
+
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ if (!SetType(type))
+ return PP_ERROR_BADARGUMENT;
+
+ // The layer's image has been set and it is not committed.
+ if (!release_callback_.is_null())
+ return PP_ERROR_INPROGRESS;
+
+ // Do not allow using a block callback as a release callback.
+ if (release_callback->is_blocking())
+ return PP_ERROR_BADARGUMENT;
+
+ return PP_OK;
}
} // namespace proxy
diff --git a/ppapi/proxy/compositor_layer_resource.h b/ppapi/proxy/compositor_layer_resource.h
index b620510..fafaa98 100644
--- a/ppapi/proxy/compositor_layer_resource.h
+++ b/ppapi/proxy/compositor_layer_resource.h
@@ -8,19 +8,40 @@
#include "ppapi/c/ppb_compositor_layer.h"
#include "ppapi/proxy/plugin_resource.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/compositor_layer_data.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
#include "ppapi/thunk/ppb_compositor_layer_api.h"
namespace ppapi {
namespace proxy {
+class CompositorResource;
+
class PPAPI_PROXY_EXPORT CompositorLayerResource
: public PluginResource,
public thunk::PPB_CompositorLayer_API {
public:
+ // Release callback for texture or image layer.
+ typedef base::Callback<void(uint32_t, bool)> ReleaseCallback;
+
CompositorLayerResource(Connection connection,
- PP_Instance instance);
+ PP_Instance instance,
+ const CompositorResource* compositor);
+
+ const CompositorLayerData& data() const { return data_; }
+ const ReleaseCallback& release_callback() const {
+ return release_callback_;
+ }
+ void ResetReleaseCallback() { release_callback_.Reset(); }
+ void Invalidate() { compositor_ = NULL; }
private:
+ enum LayerType {
+ TYPE_COLOR,
+ TYPE_TEXTURE,
+ TYPE_IMAGE,
+ };
+
virtual ~CompositorLayerResource();
// Resource overrides:
@@ -36,11 +57,11 @@ class PPAPI_PROXY_EXPORT CompositorLayerResource
PP_Resource context,
uint32_t texture,
const PP_Size* size,
- const scoped_refptr<ppapi::TrackedCallback>& callback) OVERRIDE;
+ const scoped_refptr<TrackedCallback>& callback) OVERRIDE;
virtual int32_t SetImage(
PP_Resource image_data,
const PP_Size* size,
- const scoped_refptr<ppapi::TrackedCallback>& callback) OVERRIDE;
+ const scoped_refptr<TrackedCallback>& callback) OVERRIDE;
virtual int32_t SetClipRect(const PP_Rect* rect) OVERRIDE;
virtual int32_t SetTransform(const float matrix[16]) OVERRIDE;
virtual int32_t SetOpacity(float opacity) OVERRIDE;
@@ -48,6 +69,27 @@ class PPAPI_PROXY_EXPORT CompositorLayerResource
virtual int32_t SetSourceRect(const PP_FloatRect* rect) OVERRIDE;
virtual int32_t SetPremultipliedAlpha(PP_Bool premult) OVERRIDE;
+ bool SetType(LayerType type);
+ int32_t CheckForSetTextureAndImage(
+ LayerType type,
+ const scoped_refptr<TrackedCallback>& release_callback);
+
+ // The CompositorResource which own the layer. The layer is invalidated if
+ // compositor_ is NULL.
+ const CompositorResource* compositor_;
+
+ // Release callback for uncommitted texture or image. When CommitLayers() on
+ // the compositor_ is called, the callback will be copied into a map in the
+ // compositor_, and it will be reset to NULL.
+ ReleaseCallback release_callback_;
+
+ // Size of texture or image. It is used to verify the rect arg of
+ // SetSourceRect().
+ PP_FloatSize source_size_;
+
+ // Layer data.
+ CompositorLayerData data_;
+
DISALLOW_COPY_AND_ASSIGN(CompositorLayerResource);
};
diff --git a/ppapi/proxy/compositor_resource.cc b/ppapi/proxy/compositor_resource.cc
index 497e58a..3ada734 100644
--- a/ppapi/proxy/compositor_resource.cc
+++ b/ppapi/proxy/compositor_resource.cc
@@ -4,32 +4,131 @@
#include "ppapi/proxy/compositor_resource.h"
+#include "base/logging.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
namespace ppapi {
namespace proxy {
CompositorResource::CompositorResource(Connection connection,
PP_Instance instance)
- : PluginResource(connection, instance) {
+ : PluginResource(connection, instance),
+ layer_reset_(true),
+ last_resource_id_(0) {
+ SendCreate(RENDERER, PpapiHostMsg_Compositor_Create());
}
CompositorResource::~CompositorResource() {
+ ResetLayersInternal();
}
thunk::PPB_Compositor_API* CompositorResource::AsPPB_Compositor_API() {
return this;
}
+void CompositorResource::OnReplyReceived(
+ const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) {
+ PPAPI_BEGIN_MESSAGE_MAP(CompositorResource, msg)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
+ PpapiPluginMsg_Compositor_ReleaseResource,
+ OnPluginMsgReleaseResource)
+ PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
+ PluginResource::OnReplyReceived(params, msg))
+ PPAPI_END_MESSAGE_MAP()
+}
+
PP_Resource CompositorResource::AddLayer() {
- return 0;
+ scoped_refptr<CompositorLayerResource> resource(new CompositorLayerResource(
+ connection(), pp_instance(), this));
+ layers_.push_back(resource);
+ return resource->GetReference();
}
int32_t CompositorResource::CommitLayers(
const scoped_refptr<ppapi::TrackedCallback>& callback) {
- return PP_ERROR_NOTSUPPORTED;
+ if (IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ std::vector<CompositorLayerData> layers;
+ layers.reserve(layers_.size());
+
+ for (LayerList::const_iterator it = layers_.begin();
+ it != layers_.end(); ++it) {
+ if ((*it)->data().is_null())
+ return PP_ERROR_FAILED;
+ layers.push_back((*it)->data());
+ }
+
+ commit_callback_ = callback;
+ Call<PpapiPluginMsg_Compositor_CommitLayersReply>(
+ RENDERER,
+ PpapiHostMsg_Compositor_CommitLayers(layers, layer_reset_),
+ base::Bind(&CompositorResource::OnPluginMsgCommitLayersReply,
+ base::Unretained(this)),
+ callback);
+
+ return PP_OK_COMPLETIONPENDING;
}
int32_t CompositorResource::ResetLayers() {
- return PP_ERROR_NOTSUPPORTED;
+ if (IsInProgress())
+ return PP_ERROR_INPROGRESS;
+ ResetLayersInternal();
+ return PP_OK;
+}
+
+void CompositorResource::OnPluginMsgCommitLayersReply(
+ const ResourceMessageReplyParams& params) {
+ if (!TrackedCallback::IsPending(commit_callback_))
+ return;
+
+ // On success, we put layers' release_callbacks into a map,
+ // otherwise we will do nothing. So plugin may change layers and
+ // call CommitLayers() again.
+ if (params.result() == PP_OK) {
+ layer_reset_ = false;
+ for (LayerList::iterator it = layers_.begin();
+ it != layers_.end(); ++it) {
+ ReleaseCallback release_callback = (*it)->release_callback();
+ if (!release_callback.is_null()) {
+ release_callback_map_.insert(ReleaseCallbackMap::value_type(
+ (*it)->data().common.resource_id, release_callback));
+ (*it)->ResetReleaseCallback();
+ }
+ }
+ }
+
+ scoped_refptr<TrackedCallback> callback;
+ callback.swap(commit_callback_);
+ callback->Run(params.result());
+}
+
+void CompositorResource::OnPluginMsgReleaseResource(
+ const ResourceMessageReplyParams& params,
+ int32_t id,
+ uint32_t sync_point,
+ bool is_lost) {
+ ReleaseCallbackMap::iterator it = release_callback_map_.find(id);
+ DCHECK(it != release_callback_map_.end()) <<
+ "Can not found release_callback_ by id(" << id << ")!";
+ it->second.Run(sync_point, is_lost);
+ release_callback_map_.erase(it);
+}
+
+void CompositorResource::ResetLayersInternal() {
+ for (LayerList::iterator it = layers_.begin();
+ it != layers_.end(); ++it) {
+ ReleaseCallback release_callback = (*it)->release_callback();
+ if (!release_callback.is_null()) {
+ release_callback.Run(0, false);
+ (*it)->ResetReleaseCallback();
+ }
+ (*it)->Invalidate();
+ }
+
+ layers_.clear();
+ layer_reset_ = true;
}
} // namespace proxy
diff --git a/ppapi/proxy/compositor_resource.h b/ppapi/proxy/compositor_resource.h
index 1ad74b9..f3d13d4 100644
--- a/ppapi/proxy/compositor_resource.h
+++ b/ppapi/proxy/compositor_resource.h
@@ -5,6 +5,9 @@
#ifndef PPAPI_PROXY_COMPOSITOR_RESOURCE_H_
#define PPAPI_PROXY_COMPOSITOR_RESOURCE_H_
+#include <map>
+
+#include "ppapi/proxy/compositor_layer_resource.h"
#include "ppapi/proxy/plugin_resource.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
#include "ppapi/thunk/ppb_compositor_api.h"
@@ -19,18 +22,58 @@ class PPAPI_PROXY_EXPORT CompositorResource
CompositorResource(Connection connection,
PP_Instance instance);
+ bool IsInProgress() const {
+ return TrackedCallback::IsPending(commit_callback_);
+ }
+
+ int32_t GenerateResourceId() const {
+ return ++last_resource_id_;
+ }
+
private:
virtual ~CompositorResource();
// Resource overrides:
virtual thunk::PPB_Compositor_API* AsPPB_Compositor_API() OVERRIDE;
+ // PluginResource overrides:
+ virtual void OnReplyReceived(const ResourceMessageReplyParams& params,
+ const IPC::Message& msg) OVERRIDE;
+
// thunk::PPB_Compositor_API overrides:
virtual PP_Resource AddLayer() OVERRIDE;
virtual int32_t CommitLayers(
- const scoped_refptr<ppapi::TrackedCallback>& callback) OVERRIDE;
+ const scoped_refptr<TrackedCallback>& callback) OVERRIDE;
virtual int32_t ResetLayers() OVERRIDE;
+ // IPC msg handlers:
+ void OnPluginMsgCommitLayersReply(const ResourceMessageReplyParams& params);
+ void OnPluginMsgReleaseResource(
+ const ResourceMessageReplyParams& params,
+ int32_t id,
+ uint32_t sync_point,
+ bool is_lost);
+
+ void ResetLayersInternal();
+
+ // Callback for CommitLayers().
+ scoped_refptr<TrackedCallback> commit_callback_;
+
+ // True if layers_ has been reset by ResetLayers().
+ bool layer_reset_;
+
+ // Layer stack.
+ typedef std::vector<scoped_refptr<CompositorLayerResource> > LayerList;
+ LayerList layers_;
+
+ // Release callback map for texture and image.
+ typedef CompositorLayerResource::ReleaseCallback ReleaseCallback;
+ typedef std::map<int32_t, ReleaseCallback> ReleaseCallbackMap;
+ ReleaseCallbackMap release_callback_map_;
+
+ // The last resource id for texture or image.
+ mutable int32_t last_resource_id_;
+
DISALLOW_COPY_AND_ASSIGN(CompositorResource);
};
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 41b40ce..a1ef6d6 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -37,6 +37,7 @@
#include "ppapi/c/pp_size.h"
#include "ppapi/c/pp_time.h"
#include "ppapi/c/ppb_audio_config.h"
+#include "ppapi/c/ppb_compositor_layer.h"
#include "ppapi/c/ppb_image_data.h"
#include "ppapi/c/ppb_tcp_socket.h"
#include "ppapi/c/ppb_text_input_controller.h"
@@ -59,6 +60,7 @@
#include "ppapi/proxy/serialized_handle.h"
#include "ppapi/proxy/serialized_structs.h"
#include "ppapi/proxy/serialized_var.h"
+#include "ppapi/shared_impl/compositor_layer_data.h"
#include "ppapi/shared_impl/dir_contents.h"
#include "ppapi/shared_impl/file_growth.h"
#include "ppapi/shared_impl/file_path.h"
@@ -86,6 +88,7 @@
IPC_ENUM_TRAITS_MAX_VALUE(ppapi::TCPSocketVersion,
ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE)
IPC_ENUM_TRAITS(PP_AudioSampleRate)
+IPC_ENUM_TRAITS_MAX_VALUE(PP_BlendMode, PP_BLENDMODE_LAST)
IPC_ENUM_TRAITS(PP_DeviceType_Dev)
IPC_ENUM_TRAITS(PP_DecryptorStreamType)
IPC_ENUM_TRAITS(PP_SessionType)
@@ -143,11 +146,21 @@ IPC_STRUCT_TRAITS_BEGIN(PP_Size)
IPC_STRUCT_TRAITS_MEMBER(width)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(PP_FloatSize)
+ IPC_STRUCT_TRAITS_MEMBER(height)
+ IPC_STRUCT_TRAITS_MEMBER(width)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(PP_Rect)
IPC_STRUCT_TRAITS_MEMBER(point)
IPC_STRUCT_TRAITS_MEMBER(size)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(PP_FloatRect)
+ IPC_STRUCT_TRAITS_MEMBER(point)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(PP_ImageDataDesc)
IPC_STRUCT_TRAITS_MEMBER(format)
IPC_STRUCT_TRAITS_MEMBER(size)
@@ -222,6 +235,41 @@ IPC_STRUCT_TRAITS_BEGIN(ppapi::FileGrowth)
IPC_STRUCT_TRAITS_MEMBER(append_mode_write_amount)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData)
+ IPC_STRUCT_TRAITS_MEMBER(common)
+ IPC_STRUCT_TRAITS_MEMBER(color)
+ IPC_STRUCT_TRAITS_MEMBER(texture)
+ IPC_STRUCT_TRAITS_MEMBER(image)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::LayerCommon)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+ IPC_STRUCT_TRAITS_MEMBER(clip_rect)
+ IPC_STRUCT_TRAITS_MEMBER(transform)
+ IPC_STRUCT_TRAITS_MEMBER(blend_mode)
+ IPC_STRUCT_TRAITS_MEMBER(opacity)
+ IPC_STRUCT_TRAITS_MEMBER(resource_id)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::ColorLayer)
+ IPC_STRUCT_TRAITS_MEMBER(red)
+ IPC_STRUCT_TRAITS_MEMBER(green)
+ IPC_STRUCT_TRAITS_MEMBER(blue)
+ IPC_STRUCT_TRAITS_MEMBER(alpha)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::ImageLayer)
+ IPC_STRUCT_TRAITS_MEMBER(resource)
+ IPC_STRUCT_TRAITS_MEMBER(source_rect)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(ppapi::CompositorLayerData::TextureLayer)
+ IPC_STRUCT_TRAITS_MEMBER(mailbox)
+ IPC_STRUCT_TRAITS_MEMBER(sync_point)
+ IPC_STRUCT_TRAITS_MEMBER(source_rect)
+ IPC_STRUCT_TRAITS_MEMBER(premult_alpha)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(ppapi::DeviceRefData)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(name)
@@ -1299,6 +1347,17 @@ IPC_MESSAGE_CONTROL3(PpapiHostMsg_UMA_HistogramEnumeration,
IPC_MESSAGE_CONTROL0(PpapiHostMsg_UMA_IsCrashReportingEnabled);
IPC_MESSAGE_CONTROL0(PpapiPluginMsg_UMA_IsCrashReportingEnabledReply);
+// Compositor
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_Compositor_Create)
+IPC_MESSAGE_CONTROL2(PpapiHostMsg_Compositor_CommitLayers,
+ std::vector<ppapi::CompositorLayerData> /* layers */,
+ bool /* reset */)
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_Compositor_CommitLayersReply)
+IPC_MESSAGE_CONTROL3(PpapiPluginMsg_Compositor_ReleaseResource,
+ int32_t /* id */,
+ uint32_t /* sync_point */,
+ bool /* is_lost */)
+
// File chooser.
IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileChooser_Create)
IPC_MESSAGE_CONTROL4(PpapiHostMsg_FileChooser_Show,
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
index 1e91f5c..1623395 100644
--- a/ppapi/proxy/ppapi_param_traits.cc
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -633,4 +633,31 @@ void ParamTraits<ppapi::SocketOptionData>::Log(const param_type& p,
std::string* l) {
}
+// ppapi::CompositorLayerData --------------------------------------------------
+
+// static
+void ParamTraits<ppapi::CompositorLayerData::Transform>::Write(
+ Message* m,
+ const param_type& p) {
+ for (size_t i = 0; i < arraysize(p.matrix); i++)
+ ParamTraits<float>::Write(m, p.matrix[i]);
+}
+
+// static
+bool ParamTraits<ppapi::CompositorLayerData::Transform>::Read(
+ const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
+ for (size_t i = 0; i < arraysize(r->matrix);i++) {
+ if (!ParamTraits<float>::Read(m, iter, &r->matrix[i]))
+ return false;
+ }
+ return true;
+}
+
+void ParamTraits<ppapi::CompositorLayerData::Transform>::Log(
+ const param_type& p,
+ std::string* l) {
+}
+
} // namespace IPC
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
index 96ff11c..76dd10d 100644
--- a/ppapi/proxy/ppapi_param_traits.h
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -14,6 +14,7 @@
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
+#include "ppapi/shared_impl/compositor_layer_data.h"
#include "ppapi/shared_impl/file_path.h"
#include "ppapi/shared_impl/file_ref_create_info.h"
#include "ppapi/shared_impl/media_stream_video_track_shared.h"
@@ -177,6 +178,14 @@ struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::SocketOptionData> {
static void Log(const param_type& p, std::string* l);
};
+template<>
+struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::CompositorLayerData::Transform> {
+ typedef ppapi::CompositorLayerData::Transform param_type;
+ static void Write(Message* m, const param_type& p);
+ static bool Read(const Message* m, PickleIterator* iter, param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
} // namespace IPC
#endif // PPAPI_PROXY_PPAPI_PARAM_TRAITS_H_
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
index 79664f6..48f4378 100644
--- a/ppapi/proxy/ppb_instance_proxy.cc
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -39,6 +39,7 @@
#include "ppapi/shared_impl/ppb_view_shared.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_compositor_api.h"
#include "ppapi/thunk/ppb_graphics_2d_api.h"
#include "ppapi/thunk/ppb_graphics_3d_api.h"
#include "ppapi/thunk/thunk.h"
@@ -50,6 +51,7 @@
using ppapi::thunk::EnterInstanceNoLock;
using ppapi::thunk::EnterResourceNoLock;
+using ppapi::thunk::PPB_Compositor_API;
using ppapi::thunk::PPB_Graphics2D_API;
using ppapi::thunk::PPB_Graphics3D_API;
using ppapi::thunk::PPB_Instance_API;
@@ -232,9 +234,10 @@ PP_Bool PPB_Instance_Proxy::BindGraphics(PP_Instance instance,
// We need to pass different resource to Graphics 2D and 3D right now. Once
// 3D is migrated to the new design, we should be able to unify this.
+ EnterResourceNoLock<PPB_Compositor_API> enter_compositor(device, false);
EnterResourceNoLock<PPB_Graphics2D_API> enter_2d(device, false);
EnterResourceNoLock<PPB_Graphics3D_API> enter_3d(device, false);
- if (enter_2d.succeeded()) {
+ if (enter_compositor.succeeded() || enter_2d.succeeded()) {
dispatcher()->Send(new PpapiHostMsg_PPBInstance_BindGraphics(
API_ID_PPB_INSTANCE, instance, pp_resource));
return PP_TRUE;
diff --git a/ppapi/shared_impl/compositor_layer_data.cc b/ppapi/shared_impl/compositor_layer_data.cc
new file mode 100644
index 0000000..a4b51d37
--- /dev/null
+++ b/ppapi/shared_impl/compositor_layer_data.cc
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/shared_impl/compositor_layer_data.h"
+
+namespace ppapi {
+
+namespace {
+
+template<typename T>
+void Copy(scoped_ptr<T>* a, const scoped_ptr<T>& b) {
+ if (b) {
+ if (!(*a))
+ a->reset(new T());
+ **a = *b;
+ } else {
+ a->reset();
+ }
+}
+
+} // namespace
+
+const CompositorLayerData& CompositorLayerData::operator=(
+ const CompositorLayerData& other) {
+ DCHECK(other.is_null() || other.is_valid());
+
+ common = other.common;
+ Copy(&color, other.color);
+ Copy(&texture, other.texture);
+ Copy(&image, other.image);
+
+ return *this;
+}
+
+} // namespace ppapi
diff --git a/ppapi/shared_impl/compositor_layer_data.h b/ppapi/shared_impl/compositor_layer_data.h
new file mode 100644
index 0000000..b51fcd7
--- /dev/null
+++ b/ppapi/shared_impl/compositor_layer_data.h
@@ -0,0 +1,119 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_SHARED_IMPL_COMPOSITOR_LAYER_DATA_H_
+#define PPAPI_SHARED_IMPL_COMPOSITOR_LAYER_DATA_H_
+
+#include <string.h>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "ppapi/c/ppb_compositor_layer.h"
+#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/ppapi_shared_export.h"
+
+namespace ppapi {
+
+struct PPAPI_SHARED_EXPORT CompositorLayerData {
+
+ struct Transform {
+ Transform() {
+ matrix[0] = 1.0f;
+ matrix[1] = 0.0f;
+ matrix[2] = 0.0f;
+ matrix[3] = 0.0f;
+ matrix[4] = 0.0f;
+ matrix[5] = 1.0f;
+ matrix[6] = 0.0f;
+ matrix[7] = 0.0f;
+ matrix[8] = 0.0f;
+ matrix[9] = 0.0f;
+ matrix[10] = 1.0f;
+ matrix[11] = 0.0f;
+ matrix[12] = 0.0f;
+ matrix[13] = 0.0f;
+ matrix[14] = 0.0f;
+ matrix[15] = 1.0f;
+ }
+
+ float matrix[16];
+ };
+
+ struct LayerCommon {
+ LayerCommon()
+ : size(PP_MakeSize(0, 0)),
+ clip_rect(PP_MakeRectFromXYWH(0, 0, 0, 0)),
+ blend_mode(PP_BLENDMODE_SRC_OVER),
+ opacity(1.0f),
+ resource_id(0) {
+ }
+
+ PP_Size size;
+ PP_Rect clip_rect;
+ Transform transform;
+ PP_BlendMode blend_mode;
+ float opacity;
+ uint32_t resource_id;
+ };
+
+ struct ColorLayer {
+ ColorLayer() : red(0.0f), green(0.0f), blue(0.0f), alpha(0.0f) {}
+
+ float red;
+ float green;
+ float blue;
+ float alpha;
+ };
+
+ struct ImageLayer {
+ ImageLayer()
+ : resource(0),
+ source_rect(PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 0.0f, 0.0f)) {}
+
+ PP_Resource resource;
+ PP_FloatRect source_rect;
+ };
+
+ struct TextureLayer {
+ TextureLayer()
+ : sync_point(0),
+ source_rect(PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 1.0f, 1.0f)),
+ premult_alpha(true) {}
+
+ gpu::Mailbox mailbox;
+ uint32_t sync_point;
+ PP_FloatRect source_rect;
+ bool premult_alpha;
+ };
+
+ CompositorLayerData() {}
+
+ CompositorLayerData(const CompositorLayerData& other) {
+ *this = other;
+ }
+
+ bool is_null() const {
+ return !(color || texture || image);
+ }
+
+ bool is_valid() const {
+ int i = 0;
+ if (color) ++i;
+ if (texture) ++i;
+ if (image) ++i;
+ return i == 1;
+ }
+
+ const CompositorLayerData& operator=(const CompositorLayerData& other);
+
+ LayerCommon common;
+ scoped_ptr<ColorLayer> color;
+ scoped_ptr<TextureLayer> texture;
+ scoped_ptr<ImageLayer> image;
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_COMPOSITOR_LAYER_DATA_H_