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

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 build issue on windowswq 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/layer.h"
10 #include "cc/layers/solid_color_layer.h"
11 #include "cc/layers/texture_layer.h"
12 #include "cc/resources/texture_mailbox.h"
13 #include "content/public/renderer/renderer_ppapi_host.h"
14 #include "content/renderer/pepper/gfx_conversion.h"
15 #include "content/renderer/pepper/host_globals.h"
16 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
17 #include "content/renderer/pepper/ppb_image_data_impl.h"
18 #include "ppapi/c/pp_errors.h"
19 #include "ppapi/host/dispatch_host_message.h"
20 #include "ppapi/host/ppapi_host.h"
21 #include "ppapi/proxy/ppapi_messages.h"
22 #include "ppapi/thunk/enter.h"
23 #include "ppapi/thunk/ppb_image_data_api.h"
24 #include "third_party/khronos/GLES2/gl2.h"
25 #include "ui/gfx/transform.h"
26
27 using ppapi::host::HostMessageContext;
28 using ppapi::thunk::EnterResourceNoLock;
29 using ppapi::thunk::PPB_ImageData_API;
30
31 namespace content {
32
33 namespace {
34
35 int32_t VerifyCommittedLayer(
36 const ppapi::CompositorLayerData* old_layer,
37 const ppapi::CompositorLayerData* new_layer,
38 scoped_ptr<base::SharedMemory>* image_shm) {
39 if (!new_layer->is_valid())
40 return PP_ERROR_BADARGUMENT;
41
42 if (new_layer->color) {
43 // Make sure the old layer is a color layer too.
44 if (old_layer && !old_layer->color)
45 return PP_ERROR_BADARGUMENT;
46 return PP_OK;
47 }
48
49 if (new_layer->texture) {
50 if (old_layer) {
51 // Make sure the old layer is a texture layer too.
52 if (!new_layer->texture)
53 return PP_ERROR_BADARGUMENT;
54 // The mailbox should be same, if the resource_id is not changed.
55 if (new_layer->common.resource_id == old_layer->common.resource_id) {
56 if (new_layer->texture->mailbox != old_layer->texture->mailbox)
57 return PP_ERROR_BADARGUMENT;
58 return PP_OK;
59 }
60 }
61 if (!new_layer->texture->mailbox.Verify())
62 return PP_ERROR_BADARGUMENT;
63 return PP_OK;
64 }
65
66 if (new_layer->image) {
67 if (old_layer) {
68 // Make sure the old layer is an image layer too.
69 if (!new_layer->image)
70 return PP_ERROR_BADARGUMENT;
71 // The image data resource should be same, if the resource_id is not
72 // changed.
73 if (new_layer->common.resource_id == old_layer->common.resource_id) {
74 if (new_layer->image->resource != old_layer->image->resource)
75 return PP_ERROR_BADARGUMENT;
76 return PP_OK;
77 }
78 }
79 EnterResourceNoLock<PPB_ImageData_API> enter(new_layer->image->resource,
80 true);
81 if (enter.failed())
82 return PP_ERROR_BADRESOURCE;
83
84 // TODO(penghuang): support all kinds of image.
85 PP_ImageDataDesc desc;
86 if (enter.object()->Describe(&desc) != PP_TRUE ||
87 desc.stride != desc.size.width * 4 ||
88 desc.format != PP_IMAGEDATAFORMAT_RGBA_PREMUL) {
89 return PP_ERROR_BADARGUMENT;
90 }
91
92 int handle;
93 uint32_t byte_count;
94 if (enter.object()->GetSharedMemory(&handle, &byte_count) != PP_OK)
95 return PP_ERROR_FAILED;
96
97 #if defined(OS_WIN)
98 base::SharedMemoryHandle shm_handle;
99 if (!::DuplicateHandle(::GetCurrentProcess(),
100 reinterpret_cast<base::SharedMemoryHandle>(handle),
101 ::GetCurrentProcess(),
102 &shm_handle,
103 0,
104 FALSE,
105 DUPLICATE_SAME_ACCESS)) {
106 return PP_ERROR_FAILED;
107 }
108 #else
109 base::SharedMemoryHandle shm_handle(dup(handle), false);
110 #endif
111 image_shm->reset(new base::SharedMemory(shm_handle, true));
112 if (!(*image_shm)->Map(desc.stride * desc.size.height)) {
113 image_shm->reset();
114 return PP_ERROR_NOMEMORY;
115 }
116 return PP_OK;
117 }
118
119 return PP_ERROR_BADARGUMENT;
120 }
121
122 } // namespace
123
124 PepperCompositorHost::LayerData::LayerData(
125 const scoped_refptr<cc::Layer>& cc,
126 const ppapi::CompositorLayerData& pp) : cc_layer(cc), pp_layer(pp) {}
127
128 PepperCompositorHost::LayerData::~LayerData() {}
129
130 PepperCompositorHost::PepperCompositorHost(
131 RendererPpapiHost* host,
132 PP_Instance instance,
133 PP_Resource resource)
134 : ResourceHost(host->GetPpapiHost(), instance, resource),
135 bound_instance_(NULL),
136 weak_factory_(this) {
137 layer_ = cc::Layer::Create();
138 // TODO(penghuang): SetMasksToBounds() can be expensive if the layer is
139 // transformed. Possibly better could be to explicitly clip the child layers
140 // (by modifying their bounds).
141 layer_->SetMasksToBounds(true);
142 layer_->SetIsDrawable(true);
143 }
144
145 PepperCompositorHost::~PepperCompositorHost() {
146 // Unbind from the instance when destroyed if we're still bound.
147 if (bound_instance_)
148 bound_instance_->BindGraphics(bound_instance_->pp_instance(), 0);
149 }
150
151 bool PepperCompositorHost::BindToInstance(
152 PepperPluginInstanceImpl* new_instance) {
153 if (new_instance && new_instance->pp_instance() != pp_instance())
154 return false; // Can't bind other instance's contexts.
155 if (bound_instance_ == new_instance)
156 return true; // Rebinding the same device, nothing to do.
157 if (bound_instance_ && new_instance)
158 return false; // Can't change a bound device.
159 bound_instance_ = new_instance;
160 return true;
161 }
162
163 void PepperCompositorHost::ViewInitiatedPaint() {
164 if (!commit_layers_reply_context_.is_valid())
165 return;
166 host()->SendReply(commit_layers_reply_context_,
167 PpapiPluginMsg_Compositor_CommitLayersReply());
168 commit_layers_reply_context_ = ppapi::host::ReplyMessageContext();
169 }
170
171 void PepperCompositorHost::ViewFlushedPaint() {}
172
173 void PepperCompositorHost::UpdateLayer(
174 const scoped_refptr<cc::Layer>& layer,
175 const ppapi::CompositorLayerData* old_layer,
176 const ppapi::CompositorLayerData* new_layer,
177 scoped_ptr<base::SharedMemory> image_shm) {
178 // Always update properties on cc::Layer, because cc::Layer
179 // will ignore any setting with unchanged value.
180 layer->SetIsDrawable(true);
181 layer->SetBlendMode(SkXfermode::kSrcOver_Mode);
182 layer->SetOpacity(new_layer->common.opacity);
183 layer->SetBounds(PP_ToGfxSize(new_layer->common.size));
184 layer->SetTransformOrigin(gfx::Point3F(new_layer->common.size.width / 2,
185 new_layer->common.size.height / 2,
186 0.0f));
187
188 gfx::Transform transform(gfx::Transform::kSkipInitialization);
189 transform.matrix().setColMajorf(new_layer->common.transform.matrix);
190 layer->SetTransform(transform);
191
192 // Consider a (0,0,0,0) rect as no clip rect.
193 if (new_layer->common.clip_rect.point.x != 0 ||
194 new_layer->common.clip_rect.point.y != 0 ||
195 new_layer->common.clip_rect.size.width != 0 ||
196 new_layer->common.clip_rect.size.height != 0) {
197 scoped_refptr<cc::Layer> clip_parent = layer->parent();
198 if (clip_parent == layer_) {
199 // Create a clip parent layer, if it does not exist.
200 clip_parent = cc::Layer::Create();
201 clip_parent->SetMasksToBounds(true);
202 clip_parent->SetIsDrawable(true);
203 layer_->ReplaceChild(layer, clip_parent);
204 clip_parent->AddChild(layer);
205 }
206 gfx::Point position = PP_ToGfxPoint(new_layer->common.clip_rect.point);
207 clip_parent->SetPosition(position);
208 clip_parent->SetBounds(PP_ToGfxSize(new_layer->common.clip_rect.size));
209 layer->SetPosition(gfx::Point(-position.x(), -position.y()));
210 } else if (layer->parent() != layer_) {
211 // Remove the clip parent layer.
212 layer_->ReplaceChild(layer->parent(), layer);
213 layer->SetPosition(gfx::Point());
214 }
215
216 if (new_layer->color) {
217 layer->SetBackgroundColor(SkColorSetARGBMacro(
218 new_layer->color->alpha * 255,
219 new_layer->color->red * 255,
220 new_layer->color->green * 255,
221 new_layer->color->blue * 255));
222 return;
223 }
224
225 if (new_layer->texture) {
226 scoped_refptr<cc::TextureLayer> texture_layer(
227 static_cast<cc::TextureLayer*>(layer.get()));
228 if (!old_layer ||
229 new_layer->common.resource_id != old_layer->common.resource_id) {
230 cc::TextureMailbox mailbox(new_layer->texture->mailbox,
231 GL_TEXTURE_2D,
232 new_layer->texture->sync_point);
233 texture_layer->SetTextureMailbox(mailbox,
234 cc::SingleReleaseCallback::Create(
235 base::Bind(&PepperCompositorHost::ResourceReleased,
236 weak_factory_.GetWeakPtr(),
237 new_layer->common.resource_id)));;
238 }
239 texture_layer->SetPremultipliedAlpha(new_layer->texture->premult_alpha);
240 gfx::RectF rect = PP_ToGfxRectF(new_layer->texture->source_rect);
241 texture_layer->SetUV(rect.origin(), rect.bottom_right());
242 return;
243 }
244
245 if (new_layer->image) {
246 if (!old_layer ||
247 new_layer->common.resource_id != old_layer->common.resource_id) {
248 scoped_refptr<cc::TextureLayer> image_layer(
249 static_cast<cc::TextureLayer*>(layer.get()));
250 EnterResourceNoLock<PPB_ImageData_API> enter(new_layer->image->resource,
251 true);
252 DCHECK(enter.succeeded());
253
254 // TODO(penghuang): support all kinds of image.
255 PP_ImageDataDesc desc;
256 PP_Bool rv = enter.object()->Describe(&desc);
257 DCHECK_EQ(rv, PP_TRUE);
258 DCHECK_EQ(desc.stride, desc.size.width * 4);
259 DCHECK_EQ(desc.format, PP_IMAGEDATAFORMAT_RGBA_PREMUL);
260
261 cc::TextureMailbox mailbox(image_shm.get(),
262 PP_ToGfxSize(desc.size));
263 image_layer->SetTextureMailbox(mailbox,
264 cc::SingleReleaseCallback::Create(
265 base::Bind(&PepperCompositorHost::ImageReleased,
266 weak_factory_.GetWeakPtr(),
267 new_layer->common.resource_id,
268 base::Passed(&image_shm))));
269
270 // ImageData is always premultiplied alpha.
271 image_layer->SetPremultipliedAlpha(true);
272 }
273 return;
274 }
275 // Should not be reached.
276 NOTREACHED();
277 }
278
279 void PepperCompositorHost::ResourceReleased(int32_t id,
280 uint32_t sync_point,
281 bool is_lost) {
282 host()->SendUnsolicitedReply(
283 pp_resource(),
284 PpapiPluginMsg_Compositor_ReleaseResource(id, sync_point, is_lost));
285 }
286
287 void PepperCompositorHost::ImageReleased(
288 int32_t id,
289 const scoped_ptr<base::SharedMemory>& shared_memory,
290 uint32_t sync_point,
291 bool is_lost) {
292 ResourceReleased(id, sync_point, is_lost);
293 }
294
295 int32_t PepperCompositorHost::OnResourceMessageReceived(
296 const IPC::Message& msg,
297 HostMessageContext* context) {
298 PPAPI_BEGIN_MESSAGE_MAP(PepperCompositorHost, msg)
299 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
300 PpapiHostMsg_Compositor_CommitLayers, OnHostMsgCommitLayers)
301 PPAPI_END_MESSAGE_MAP()
302 return ppapi::host::ResourceHost::OnResourceMessageReceived(msg, context);
303 }
304
305 bool PepperCompositorHost::IsCompositorHost() {
306 return true;
307 }
308
309 int32_t PepperCompositorHost::OnHostMsgCommitLayers(
310 HostMessageContext* context,
311 const std::vector<ppapi::CompositorLayerData>& layers,
312 bool reset) {
313 // Do not support CommitLayers() on an unbounded compositor.
314 if (!bound_instance_)
315 return PP_ERROR_FAILED;
316
317 if (commit_layers_reply_context_.is_valid())
318 return PP_ERROR_INPROGRESS;
319
320 commit_layers_reply_context_ = context->MakeReplyMessageContext();
321
322 scoped_ptr<scoped_ptr<base::SharedMemory>[]> image_shms(
323 new scoped_ptr<base::SharedMemory>[layers.size()]);
nasko 2014/06/13 17:23:01 nit: You should verify the layers sizing.
Peng 2014/06/13 18:04:05 Done.
324 // Verfiy the layers first, if an error happens, we will return the error to
325 // plugin and keep current layers set by the previous CommitLayers()
326 // unchanged.
327 for (size_t i = 0; i < layers.size(); ++i) {
328 const ppapi::CompositorLayerData* old_layer = NULL;
329 if (!reset && i < layers_.size())
330 old_layer = &layers_[i].pp_layer;
331 int32_t rv = VerifyCommittedLayer(old_layer, &layers[i], &image_shms[i]);
332 if (rv != PP_OK)
333 return rv;
334 }
335
336 // ResetLayers() has been called, we need rebuild layer stack.
337 if (reset) {
338 layer_->RemoveAllChildren();
339 layers_.clear();
340 }
341
342 for (size_t i = 0; i < layers.size(); ++i) {
343 const ppapi::CompositorLayerData* pp_layer = &layers[i];
344 LayerData* data = i >= layers_.size() ? NULL : &layers_[i];
345 DCHECK(!data || data->cc_layer);
346 scoped_refptr<cc::Layer> cc_layer = data ? data->cc_layer : NULL;
347 ppapi::CompositorLayerData* old_layer = data ? &data->pp_layer : NULL;
348
349 if (!cc_layer) {
350 if (pp_layer->color)
351 cc_layer = cc::SolidColorLayer::Create();
352 else if (pp_layer->texture || pp_layer->image)
353 cc_layer = cc::TextureLayer::CreateForMailbox(NULL);
354 layer_->AddChild(cc_layer);
355 }
356
357 UpdateLayer(cc_layer, old_layer, pp_layer, image_shms[i].Pass());
358
359 if (old_layer)
360 *old_layer = *pp_layer;
361 else
362 layers_.push_back(LayerData(cc_layer, *pp_layer));
363 }
364
365 return PP_OK_COMPLETIONPENDING;
366 }
367
368 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698