Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(849)

Unified Diff: ppapi/proxy/compositor_resource.cc

Issue 298023004: [PPAPI] Compositor API implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@compositor_api_def_new
Patch Set: Update Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ppapi/proxy/compositor_resource.cc
diff --git a/ppapi/proxy/compositor_resource.cc b/ppapi/proxy/compositor_resource.cc
index 925087b46241a0989b21002a3cd01e110fd30dbc..51d62eb59446e2c59ecd46547cca2e6d2becb04f 100644
--- a/ppapi/proxy/compositor_resource.cc
+++ b/ppapi/proxy/compositor_resource.cc
@@ -9,11 +9,13 @@
#include "base/logging.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/common/mailbox.h"
+#include "ppapi/proxy/compositor_layer_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_graphics_3d_api.h"
+#include "ppapi/thunk/ppb_image_data_api.h"
using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Graphics3D_API;
@@ -21,9 +23,294 @@ using ppapi::thunk::PPB_Graphics3D_API;
namespace ppapi {
namespace proxy {
+namespace {
+
+class Scoped2DTextureBinder {
+ public:
+ Scoped2DTextureBinder(gpu::gles2::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:
+ gpu::gles2::GLES2Implementation* gl_;
+ int32_t old_id_;
+};
+
+} // namespace
+
+CompositorResource::Layer::Layer(CompositorResource* compositor)
+ : compositor_(compositor),
+ source_size_(PP_MakeFloatSize(0.0f, 0.0f)) {
+}
+
+CompositorResource::Layer::~Layer() {}
+
+int32_t CompositorResource::Layer::SetColor(
+ uint8_t red,
+ uint8_t green,
+ uint8_t blue,
+ uint8_t alpha,
+ const struct PP_Size* size) {
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ if (!SetType(CompositorLayer::TYPE_COLOR))
+ return PP_ERROR_BADARGUMENT;
+
+ if (!size)
+ return PP_ERROR_BADARGUMENT;
+
+ data_.color.red = red;
+ data_.color.green = green;
+ data_.color.blue = blue;
+ data_.color.alpha = alpha;
+ data_.size = *size;
+
+ return PP_OK;
+}
+
+int32_t CompositorResource::Layer::SetTexture(
+ PP_Resource context,
+ uint32_t texture,
+ const struct PP_Size* size,
+ const scoped_refptr<ppapi::TrackedCallback>& release_callback) {
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ if (!SetType(CompositorLayer::TYPE_TEXTURE))
+ return PP_ERROR_BADARGUMENT;
+
+ // The layer's texture has been set and it is not committed.
+ if (!release_callback_.is_null())
+ return PP_ERROR_INPROGRESS;
+
+ EnterResourceNoLock<PPB_Graphics3D_API> enter(context, true);
+ if (enter.failed())
+ return PP_ERROR_BADARGUMENT;
+
+ if (!size || size->width <= 0 || size->height <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ // Do not allow using a block callback as a release callback.
+ if (release_callback->is_blocking())
+ return PP_ERROR_BADARGUMENT;
+
+ PPB_Graphics3D_Shared* graphics =
+ static_cast<PPB_Graphics3D_Shared*>(enter.object());
+
+ gpu::gles2::GLES2Implementation* gl = graphics->gles2_impl();
+ Scoped2DTextureBinder scoped_2d_texture_binder(gl, texture);
+
+ // Generate a Mailbox for the texture.
+ gl->GenMailboxCHROMIUM(data_.texture.mailbox);
+ gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, data_.texture.mailbox);
+
+ // 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_.texture.id = compositor_->GenerateResourceId();
+ data_.texture.sync_point = gl->InsertSyncPointCHROMIUM();
+ data_.size = *size;
+ data_.texture.source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f);
+ data_.texture.source_rect.size = source_size_;
+
+ release_callback_ = base::Bind(
+ &CompositorResource::Layer::OnTextureReleased,
+ AsWeakPtr(),
+ ScopedPPResource(context), // Keep context alive
+ texture,
+ release_callback);
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t CompositorResource::Layer::SetImage(
+ PP_Resource image_data,
+ const struct PP_Size* size,
+ const scoped_refptr<ppapi::TrackedCallback>& release_callback) {
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ if (!SetType(CompositorLayer::TYPE_IMAGE))
+ return PP_ERROR_BADARGUMENT;
+
+ EnterResourceNoLock<thunk::PPB_ImageData_API> enter(image_data, true);
+ if (enter.failed())
+ 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;
+
+ 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;
+
+ // Do not allow using a block callback as a release callback.
+ if (release_callback->is_blocking())
+ return PP_ERROR_BADARGUMENT;
+
+ // Set the source size to image'size. It will be used to verify
raymes 2014/06/02 03:51:08 to the image's size
Peng 2014/06/02 19:01:55 Done.
+ // the source_rect passed to SetSourceRect().
+ source_size_ = PP_MakeFloatSize(desc.size.width, desc.size.height);
+
+ data_.size = size ? *size : desc.size;
+ data_.image.id = compositor_->GenerateResourceId();
+ data_.image.instance = enter.resource()->host_resource().instance();
+ data_.image.host_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(
+ &CompositorResource::Layer::OnImageReleased,
+ AsWeakPtr(),
+ ScopedPPResource(image_data), // Keep image_data alive.
+ release_callback);
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t CompositorResource::Layer::SetClipRect(const struct PP_Rect* rect) {
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ data_.clip_rect = rect ? *rect : PP_MakeRectFromXYWH(0, 0, 0, 0);
+ return PP_OK;
+}
+
+int32_t CompositorResource::Layer::SetTransform(const float matrix[16]) {
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ std::copy(matrix, matrix + 16, data_.transform);
raymes 2014/06/02 03:51:08 matrix + arraysize(matrix)?
Peng 2014/06/02 19:01:55 arraysize() does not work here. Probably it is bec
+ return PP_OK;
+}
+
+int32_t CompositorResource::Layer::SetOpacity(uint8_t opacity) {
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ data_.opacity = opacity;
+ return PP_OK;
+}
+
+int32_t CompositorResource::Layer::SetBlendMode(PP_BlendMode mode) {
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ switch (mode) {
+ case PP_BLENDMODE_NONE:
+ case PP_BLENDMODE_SRC_OVER:
+ data_.blend_mode = mode;
+ return PP_OK;
+ default:
+ return PP_ERROR_BADARGUMENT;
raymes 2014/06/02 03:51:08 Maybe remove the default because we won't get comp
Peng 2014/06/02 19:01:55 Done.
+ }
+}
+
+int32_t CompositorResource::Layer::SetSourceRect(
+ const struct PP_FloatRect* rect) {
+ 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;
+
+ switch (data_.type) {
+ case CompositorLayer::TYPE_TEXTURE:
+ data_.texture.source_rect = *rect;
+ return PP_OK;
+ case CompositorLayer::TYPE_IMAGE:
+ data_.image.source_rect = *rect;
+ return PP_OK;
+ default:
+ return PP_ERROR_BADARGUMENT;
+ }
+}
+
+int32_t CompositorResource::Layer::SetPremultipliedAlpha(PP_Bool premult) {
+ if (compositor_->IsInProgress())
+ return PP_ERROR_INPROGRESS;
+
+ if (data_.type != CompositorLayer::TYPE_TEXTURE)
+ return PP_ERROR_BADARGUMENT;
+
+ data_.texture.premult_alpha = PP_FromBool(premult);
+ return PP_OK;
+}
+
+bool CompositorResource::Layer::SetType(CompositorLayer::Type type) {
+ DCHECK(type == CompositorLayer::TYPE_COLOR ||
+ type == CompositorLayer::TYPE_TEXTURE ||
+ type == CompositorLayer::TYPE_IMAGE);
raymes 2014/06/02 03:51:08 If this is not the case, should we return false he
Peng 2014/06/02 19:01:55 Because this function is for internal using only (
+ if (type != data_.type) {
+ if (data_.type != CompositorLayer::TYPE_UNKNOWN)
+ return false;
+ data_.type = type;
+ }
+ return true;
+}
+
+void CompositorResource::Layer::OnTextureReleased(
+ const ScopedPPResource& context,
+ uint32_t texture,
+ const scoped_refptr<TrackedCallback>& release_callback,
+ uint32_t sync_point,
+ bool is_lost) {
+ do {
+ if (!sync_point)
+ break;
+
+ EnterResourceNoLock<PPB_Graphics3D_API> enter(context.get(), true);
+ if (enter.failed())
+ break;;
raymes 2014/06/02 03:51:08 extra ;
Peng 2014/06/02 19:01:55 Done.
+
+ PPB_Graphics3D_Shared* graphics =
+ static_cast<PPB_Graphics3D_Shared*>(enter.object());
+
+ gpu::gles2::GLES2Implementation* gl = graphics->gles2_impl();
+ gl->WaitSyncPointCHROMIUM(sync_point);
+ } while (false);
+
+ release_callback->Run(PP_OK);
+}
+
+void CompositorResource::Layer::OnImageReleased(
+ const ScopedPPResource& image,
+ const scoped_refptr<TrackedCallback>& release_callback,
+ uint32_t sync_point,
+ bool is_lost) {
+ release_callback->Run(PP_OK);
+}
+
CompositorResource::CompositorResource(Connection connection,
PP_Instance instance)
- : PluginResource(connection, instance) {
+ : PluginResource(connection, instance),
+ layer_changed_(true),
+ last_resource_id_(0) {
+ SendCreate(RENDERER, PpapiHostMsg_Compositor_Create());
}
CompositorResource::~CompositorResource() {
@@ -33,17 +320,129 @@ 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;
+ Layer* layer = new Layer(this);
+ layers_.push_back(layer);
+ CompositorLayerResource *resource = new CompositorLayerResource(
+ connection(), pp_instance(), layer->AsWeakPtr());
+ 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<CompositorLayer> layers;
+ layers.reserve(layers_.size());
+
+ for (ScopedVector<Layer>::const_iterator it = layers_.begin();
+ it != layers_.end(); ++it) {
+ switch ((*it)->data().type) {
+ case CompositorLayer::TYPE_UNKNOWN:
+ return PP_ERROR_FAILED;
+ case CompositorLayer::TYPE_COLOR:
+ case CompositorLayer::TYPE_TEXTURE:
+ case CompositorLayer::TYPE_IMAGE:
+ layers.push_back((*it)->data());
+ continue;
+ default:
+ NOTREACHED();
+ }
+ }
+
+ commit_callback_ = callback;
+ Call<PpapiPluginMsg_Compositor_CommitLayersReply>(
+ RENDERER,
+ PpapiHostMsg_Compositor_CommitLayers(layers, layer_changed_),
+ 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;
+
+ // Call release_callback for every layer.
+ for (ScopedVector<Layer>::iterator it = layers_.begin();
+ it != layers_.end(); ++it) {
+ ReleaseCallback release_callback = (*it)->release_callback();
+ if (!release_callback.is_null())
+ release_callback.Run(0, false);
+ }
+
+ layers_.clear();
+ layer_changed_ = true;
raymes 2014/06/02 03:51:08 Does this mean that CommitLayers has to be called
Peng 2014/06/02 19:01:55 No. This function can be called with or without ca
raymes 2014/06/03 00:43:22 But the layers won't really be destroyed until Com
Peng 2014/06/03 18:32:23 I understand your point. This API only reset layer
+ 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_changed_ = false;
+ for (ScopedVector<Layer>::iterator it = layers_.begin();
+ it != layers_.end(); ++it) {
+ switch ((*it)->data().type) {
+ case CompositorLayer::TYPE_TEXTURE: {
+ ReleaseCallback release_callback = (*it)->release_callback();
+ (*it)->ResetReleaseCallback();
+ if (!release_callback.is_null()) {
+ release_callback_map_.insert(ReleaseCallbackMap::value_type(
+ (*it)->data().texture.id, release_callback));
raymes 2014/06/02 03:51:08 I think the indentation is off
Peng 2014/06/02 19:01:55 Sorry, what do you mean?
raymes 2014/06/03 00:43:22 I think there should just be 4 space indent from t
Peng 2014/06/03 18:32:23 Done.
+ }
+ break;
+ }
+ case CompositorLayer::TYPE_IMAGE: {
+ ReleaseCallback release_callback = (*it)->release_callback();
+ (*it)->ResetReleaseCallback();
+ if (!release_callback.is_null()) {
+ release_callback_map_.insert(ReleaseCallbackMap::value_type(
+ (*it)->data().image.id, release_callback));
raymes 2014/06/02 03:51:08 Why not just have a id for every ppapi::Compositor
Peng 2014/06/02 19:01:55 Actually this id is for the texture or image resou
raymes 2014/06/03 00:43:22 But we could just make it a layer ID instead right
Peng 2014/06/03 18:32:23 Moved it to toplevel structure, and renamed it to
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ 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);
}
} // namespace proxy

Powered by Google App Engine
This is Rietveld 408576698