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

Side by Side Diff: content/renderer/pepper/pepper_compositor_host.cc

Issue 298023004: [PPAPI] Compositor API implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@compositor_api_def_new
Patch Set: Fix review issue Created 6 years, 6 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/renderer/pepper/pepper_compositor_host.h"
6
7 #include "base/logging.h"
8 #include "base/memory/shared_memory.h"
9 #include "cc/layers/solid_color_layer.h"
10 #include "cc/layers/texture_layer.h"
11 #include "cc/resources/texture_mailbox.h"
12 #include "content/public/renderer/renderer_ppapi_host.h"
13 #include "content/renderer/pepper/gfx_conversion.h"
14 #include "content/renderer/pepper/host_globals.h"
15 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
16 #include "content/renderer/pepper/ppb_image_data_impl.h"
17 #include "ppapi/c/pp_errors.h"
18 #include "ppapi/host/dispatch_host_message.h"
19 #include "ppapi/host/ppapi_host.h"
20 #include "ppapi/proxy/ppapi_messages.h"
21 #include "ppapi/thunk/enter.h"
22 #include "ppapi/thunk/ppb_image_data_api.h"
23 #include "third_party/khronos/GLES2/gl2.h"
24 #include "ui/gfx/transform.h"
25
26 using ppapi::host::HostMessageContext;
27 using ppapi::thunk::EnterResourceNoLock;
28 using ppapi::thunk::PPB_ImageData_API;
29
30 namespace content {
31
32 PepperCompositorHost::PepperCompositorHost(
33 RendererPpapiHost* host,
34 PP_Instance instance,
35 PP_Resource resource)
36 : ResourceHost(host->GetPpapiHost(), instance, resource),
37 bound_instance_(NULL),
38 weak_factory_(this) {
39 layer_ = cc::SolidColorLayer::Create();
piman 2014/06/04 13:19:42 You're only using this for grouping, maybe just ma
Peng 2014/06/05 00:50:38 Done.
40 layer_->SetMasksToBounds(true);
piman 2014/06/04 13:19:43 Note: this can be expensive if the layer is transf
Peng 2014/06/05 00:50:38 Done.
41 layer_->SetIsDrawable(true);
42 }
43
44 PepperCompositorHost::~PepperCompositorHost() {
45 // Unbind from the instance when destroyed if we're still bound.
46 if (bound_instance_)
47 bound_instance_->BindGraphics(bound_instance_->pp_instance(), 0);
48 }
49
50 bool PepperCompositorHost::BindToInstance(
51 PepperPluginInstanceImpl* new_instance) {
52 if (new_instance && new_instance->pp_instance() != pp_instance())
53 return false; // Can't bind other instance's contexts.
54 if (bound_instance_ == new_instance)
55 return true; // Rebinding the same device, nothing to do.
piman 2014/06/04 13:19:42 This can only happen for bound_instance_ == new_in
Peng 2014/06/05 00:50:38 Seems it is not necessary to check this case.
56 if (bound_instance_ && new_instance)
57 return false; // Can't change a bound device.
piman 2014/06/04 13:19:42 You can replace this by a DCHECK, since we call Bi
Peng 2014/06/05 00:50:38 Done.
58 bound_instance_ = new_instance;
59 return true;
60 }
61
62 void PepperCompositorHost::ViewInitiatedPaint() {
63 if (!commit_layers_reply_context_.is_valid())
64 return;
65 host()->SendReply(commit_layers_reply_context_,
66 PpapiPluginMsg_Compositor_CommitLayersReply());
67 commit_layers_reply_context_ = ppapi::host::ReplyMessageContext();
68 }
69
70 void PepperCompositorHost::ViewFlushedPaint() {}
71
72 void PepperCompositorHost::ResourceReleased(int32_t id,
73 uint32_t sync_point,
74 bool is_lost) {
75 host()->SendUnsolicitedReply(
76 pp_resource(),
77 PpapiPluginMsg_Compositor_ReleaseResource(id, sync_point, is_lost));
78 }
79
80 void PepperCompositorHost::ImageReleased(
81 int32_t id,
82 const scoped_ptr<base::SharedMemory>& shared_memory,
83 uint32_t sync_point,
84 bool is_lost) {
85 ResourceReleased(id, sync_point, is_lost);
86 }
87
88 int32_t PepperCompositorHost::OnResourceMessageReceived(
89 const IPC::Message& msg,
90 HostMessageContext* context) {
91 PPAPI_BEGIN_MESSAGE_MAP(PepperCompositorHost, msg)
92 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
93 PpapiHostMsg_Compositor_CommitLayers, OnHostMsgCommitLayers)
94 PPAPI_END_MESSAGE_MAP()
95 return ppapi::host::ResourceHost::OnResourceMessageReceived(msg, context);
96 }
97
98 bool PepperCompositorHost::IsCompositorHost() {
99 return true;
100 }
101
102 void PepperCompositorHost::UpdateLayer(
103 const scoped_refptr<cc::Layer>& layer,
104 const ppapi::CompositorLayerData* old_layer,
105 const ppapi::CompositorLayerData* new_layer) {
106 CHECK(!old_layer || new_layer->type == old_layer->type);
piman 2014/06/04 13:19:42 no CHECK. Use DCHECK.
Peng 2014/06/05 00:50:38 Done.
107
108 // Always update properties on cc::Layer, because cc::Layer
109 // will ignore any setting with unchanged value.
110 layer->SetBounds(PP_ToGfxSize((new_layer)->size));
piman 2014/06/04 13:19:42 no need for extra () around new_layer
Peng 2014/06/05 00:50:38 Done.
111 layer->SetBlendMode(SkXfermode::kSrcOver_Mode);
112 layer->SetOpacity(new_layer->opacity / 255.0f);
113
114 gfx::Transform transform(gfx::Transform::kSkipInitialization);
115 transform.matrix().setColMajorf(new_layer->transform);
116 layer->SetTransform(transform);
117
118 // Consider a (0,0,0,0) rect as no clip rect.
119 if (new_layer->clip_rect.point.x != 0 ||
120 new_layer->clip_rect.point.y != 0 ||
121 new_layer->clip_rect.size.width != 0 ||
122 new_layer->clip_rect.size.height != 0) {
123 if (!layer->mask_layer())
124 layer->SetMaskLayer(cc::Layer::Create());
piman 2014/06/04 13:19:43 Masks are *very* expensive. It's most likely not w
Peng 2014/06/05 00:50:38 Done.
125 layer->mask_layer()->SetPosition(PP_ToGfxPoint(new_layer->clip_rect.point));
126 layer->mask_layer()->SetBounds(PP_ToGfxSize(new_layer->clip_rect.size));
127 } else {
128 layer->SetMaskLayer(NULL);
129 }
130
131 if (new_layer->type == ppapi::CompositorLayerData::TYPE_COLOR) {
132 layer->SetBackgroundColor(SkColorSetARGBMacro(new_layer->color.alpha,
133 new_layer->color.red,
134 new_layer->color.green,
135 new_layer->color.blue));
136 } else if (new_layer->type == ppapi::CompositorLayerData::TYPE_TEXTURE) {
137 scoped_refptr<cc::TextureLayer> texture_layer(
138 static_cast<cc::TextureLayer*>(layer.get()));
139 if (!old_layer || new_layer->resource_id != old_layer->resource_id) {
140 gpu::Mailbox gpu_mailbox;
141 gpu_mailbox.SetName(new_layer->texture.mailbox);
142 cc::TextureMailbox mailbox(gpu_mailbox,
143 GL_TEXTURE_2D,
144 new_layer->texture.sync_point);
145 texture_layer->SetTextureMailbox(mailbox,
146 cc::SingleReleaseCallback::Create(
147 base::Bind(&PepperCompositorHost::ResourceReleased,
148 weak_factory_.GetWeakPtr(),
149 new_layer->resource_id)));;
150 }
151 texture_layer->SetPremultipliedAlpha(new_layer->texture.premult_alpha);
152 gfx::RectF rect = PP_ToGfxRectF(new_layer->texture.source_rect);
153 texture_layer->SetUV(rect.origin(), rect.bottom_right());
154 } else if (new_layer->type == ppapi::CompositorLayerData::TYPE_IMAGE) {
155 if (!old_layer || new_layer->resource_id != old_layer->resource_id) {
156 scoped_refptr<cc::TextureLayer> image_layer(
157 static_cast<cc::TextureLayer*>(layer.get()));
158 EnterResourceNoLock<PPB_ImageData_API> enter(
159 new_layer->image.host_resource, true);
160 PP_ImageDataDesc desc;
161 enter.object()->Describe(&desc);
162 int handle;
163 uint32_t byte_count;
164 enter.object()->GetSharedMemory(&handle, &byte_count);
165 #if defined(OS_WIN)
166 base::SharedMemoryHandle shm_handle =
167 static_cast<base::SharedMemoryHandle>(_dup(handle));
168 #else
169 base::SharedMemoryHandle shm_handle(dup(handle), false);
170 #endif
piman 2014/06/04 13:19:43 rather than duping the handle, can we just keep a
Peng 2014/06/05 00:50:38 I found SharedMemory will closed the handle in dto
171 // Use a scoped_ptr to keep shared_memory alive until
172 // PepperCompositorHost::ImageReleased is called.
173 scoped_ptr<base::SharedMemory> shared_memory(
174 new base::SharedMemory(shm_handle, true));
175 CHECK(shared_memory->Map(desc.stride * desc.size.height));
piman 2014/06/04 13:19:43 no CHECK.
Peng 2014/06/05 00:50:38 If the Map() failed. cc will crash anyway. So what
piman 2014/06/09 18:27:24 Return failure and not crash?
Peng 2014/06/10 16:20:28 Done
176 cc::TextureMailbox mailbox(shared_memory.get(),
177 PP_ToGfxSize(desc.size));
178 image_layer->SetTextureMailbox(mailbox,
179 cc::SingleReleaseCallback::Create(
180 base::Bind(&PepperCompositorHost::ImageReleased,
181 weak_factory_.GetWeakPtr(),
182 new_layer->resource_id,
183 base::Passed(&shared_memory))));
184
185 // ImageData is always premultiplied alpha.
186 image_layer->SetPremultipliedAlpha(true);
187 }
188 }
189 }
190
191 int32_t PepperCompositorHost::OnHostMsgCommitLayers(
192 HostMessageContext* context,
193 const std::vector<ppapi::CompositorLayerData>& layers,
194 bool reset) {
195 // Do not support CommitLayers() on an unbounded compositor.
196 if (!bound_instance_)
197 return PP_ERROR_FAILED;
198
199 if (commit_layers_reply_context_.is_valid()) {
200 NOTREACHED();
piman 2014/06/04 13:19:42 Not NOTREACHED(), it can be reached by untrusted p
Peng 2014/06/05 00:50:38 Sorry. I don't understand. In plugin process, we w
danakj 2014/06/06 14:54:31 NOTREACHED() means "it's impossible to get here".
Peng 2014/06/06 19:29:43 Remove NOTREACHED(). Done
201 return PP_ERROR_INPROGRESS;
202 }
203
204 commit_layers_reply_context_ = context->MakeReplyMessageContext();
205
206 // Verfiy layers first, if an error happens, we will return the error to
raymes 2014/06/04 01:11:38 nit: Verify the layers first
Peng 2014/06/05 00:50:38 Done.
207 // plugin and keep current layers set by previous CommitLayers() unchanged.
raymes 2014/06/04 01:11:38 nit: by the previous CommitLayers()
Peng 2014/06/05 00:50:38 Done.
208 for (size_t i = 0; i < layers.size(); ++i) {
209 const ppapi::CompositorLayerData& pp_layer = layers[i];
210 // Make sure the layer type is not changed.
211 if (!reset) {
212 ppapi::CompositorLayerData* old_layer =
213 i >= pp_layers_.size() ? NULL : &pp_layers_[i];
214 if (old_layer && old_layer->type != pp_layer.type) {
215 NOTREACHED();
piman 2014/06/04 13:19:42 Same here, not NOTREACHED
Peng 2014/06/05 00:50:38 Same. It should only crash in debug build. And jus
216 return PP_ERROR_BADARGUMENT;
217 }
218 }
219
220 if (pp_layer.type == ppapi::CompositorLayerData::TYPE_COLOR ||
221 pp_layer.type == ppapi::CompositorLayerData::TYPE_TEXTURE) {
222 continue;
223 }
224
225 // Check image layer.
226 if (pp_layer.type == ppapi::CompositorLayerData::TYPE_IMAGE) {
227 EnterResourceNoLock<PPB_ImageData_API> enter(
228 pp_layer.image.host_resource, true);
229 if (enter.failed()) {
230 NOTREACHED();
piman 2014/06/04 13:19:42 same here
Peng 2014/06/10 16:20:28 Done.
231 return PP_ERROR_BADRESOURCE;
232 }
233
234 // TODO(penghuang): support all kinds of image.
235 PP_ImageDataDesc desc;
236 if (!enter.object()->Describe(&desc) ||
237 desc.stride != desc.size.width * 4 ||
238 desc.format != PP_IMAGEDATAFORMAT_RGBA_PREMUL) {
239 NOTREACHED();
piman 2014/06/04 13:19:43 same here
Peng 2014/06/10 16:20:28 Done.
240 return PP_ERROR_BADARGUMENT;
241 }
242
243 int handle;
244 uint32_t byte_count;
245 if (enter.object()->GetSharedMemory(&handle, &byte_count) != PP_OK)
246 return PP_ERROR_FAILED;
247 continue;
248 }
249 return PP_ERROR_BADARGUMENT;
raymes 2014/06/04 01:11:38 nit: Could we pull the body of this loop out into
Peng 2014/06/05 00:50:38 Done.
250 }
251
252 // ResetLayers() has been called, we need rebuild layer stack.
253 if (reset) {
254 layer_->RemoveAllChildren();
255 cc_layers_.clear();
256 pp_layers_.clear();
257 }
258
259 for (size_t i = 0; i < layers.size(); ++i) {
260 const ppapi::CompositorLayerData& pp_layer = layers[i];
261 ppapi::CompositorLayerData* old_layer =
262 i >= pp_layers_.size() ? NULL : &pp_layers_[i];
263 scoped_refptr<cc::Layer> cc_layer =
264 i >= cc_layers_.size() ? NULL : cc_layers_[i];
265
266 CHECK((old_layer && cc_layer) || (!old_layer && !cc_layer));
piman 2014/06/04 13:19:43 no CHECK. use DCHECK. can also be written as DCHE
Peng 2014/06/05 00:50:38 After adding struct LayerData { cc_layer, pp_layer
267
268 if (!cc_layer) {
269 if (pp_layer.type == ppapi::CompositorLayerData::TYPE_COLOR) {
270 cc_layer = cc::SolidColorLayer::Create();
271 } else if (pp_layer.type == ppapi::CompositorLayerData::TYPE_TEXTURE ||
272 pp_layer.type == ppapi::CompositorLayerData::TYPE_IMAGE) {
273 cc_layer = cc::TextureLayer::CreateForMailbox(NULL);
274 }
275 cc_layer->SetIsDrawable(true);
276 cc_layer->SetAnchorPoint(gfx::PointF());
raymes 2014/06/04 01:11:38 Would it make sense to shift these into UpdateLaye
Peng 2014/06/05 00:50:38 Done.
277 }
278
279 UpdateLayer(cc_layer, old_layer, &pp_layer);
280
281 if (old_layer) {
282 *old_layer = pp_layer;
283 } else {
284 layer_->AddChild(cc_layer);
285 cc_layers_.push_back(cc_layer);
286 pp_layers_.push_back(pp_layer);
287 }
288 }
289
290 return PP_OK_COMPLETIONPENDING;
291 }
292
293 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698