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

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 issues 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 static_cast<base::SharedMemoryHandle>(_dup(handle));
piman 2014/06/10 22:37:06 I don't think you can use _dup to duplicate win32
Peng 2014/06/10 23:03:32 Done.
100 #else
101 base::SharedMemoryHandle shm_handle(dup(handle), false);
102 #endif
103 image_shm->reset(new base::SharedMemory(shm_handle, true));
104 if (!(*image_shm)->Map(desc.stride * desc.size.height)) {
105 image_shm->reset();
106 return PP_ERROR_NOMEMORY;
107 }
108 return PP_OK;
109 }
110
111 return PP_ERROR_BADARGUMENT;
112 }
113
114 } // namespace
115
116 PepperCompositorHost::PepperCompositorHost(
117 RendererPpapiHost* host,
118 PP_Instance instance,
119 PP_Resource resource)
120 : ResourceHost(host->GetPpapiHost(), instance, resource),
121 bound_instance_(NULL),
122 weak_factory_(this) {
123 layer_ = cc::Layer::Create();
124 // TODO(penghuang): SetMasksToBounds() can be expensive if the layer is
125 // transformed. Possibly better could be to explicitly clip the child layers
126 // (by modifying their bounds).
127 layer_->SetMasksToBounds(true);
128 layer_->SetIsDrawable(true);
129 }
130
131 PepperCompositorHost::~PepperCompositorHost() {
132 // Unbind from the instance when destroyed if we're still bound.
133 if (bound_instance_)
134 bound_instance_->BindGraphics(bound_instance_->pp_instance(), 0);
135 }
136
137 bool PepperCompositorHost::BindToInstance(
138 PepperPluginInstanceImpl* new_instance) {
139 if (new_instance && new_instance->pp_instance() != pp_instance())
140 return false; // Can't bind other instance's contexts.
141 if (bound_instance_ == new_instance)
142 return true; // Rebinding the same device, nothing to do.
143 if (bound_instance_ && new_instance)
144 return false; // Can't change a bound device.
145 bound_instance_ = new_instance;
146 return true;
147 }
148
149 void PepperCompositorHost::ViewInitiatedPaint() {
150 if (!commit_layers_reply_context_.is_valid())
151 return;
152 host()->SendReply(commit_layers_reply_context_,
153 PpapiPluginMsg_Compositor_CommitLayersReply());
154 commit_layers_reply_context_ = ppapi::host::ReplyMessageContext();
155 }
156
157 void PepperCompositorHost::ViewFlushedPaint() {}
158
159 void PepperCompositorHost::UpdateLayer(
160 const scoped_refptr<cc::Layer>& layer,
161 const ppapi::CompositorLayerData* old_layer,
162 const ppapi::CompositorLayerData* new_layer,
163 scoped_ptr<base::SharedMemory> image_shm) {
164 // Always update properties on cc::Layer, because cc::Layer
165 // will ignore any setting with unchanged value.
166 layer->SetIsDrawable(true);
167 layer->SetBlendMode(SkXfermode::kSrcOver_Mode);
168 layer->SetOpacity(new_layer->common.opacity);
169 layer->SetBounds(PP_ToGfxSize(new_layer->common.size));
170 layer->SetTransformOrigin(gfx::Point3F(new_layer->common.size.width / 2,
171 new_layer->common.size.height / 2,
172 0.0f));
173
174 gfx::Transform transform(gfx::Transform::kSkipInitialization);
175 transform.matrix().setColMajorf(new_layer->common.transform.matrix);
176 layer->SetTransform(transform);
177
178 // Consider a (0,0,0,0) rect as no clip rect.
179 if (new_layer->common.clip_rect.point.x != 0 ||
180 new_layer->common.clip_rect.point.y != 0 ||
181 new_layer->common.clip_rect.size.width != 0 ||
182 new_layer->common.clip_rect.size.height != 0) {
183 scoped_refptr<cc::Layer> clip_parent = layer->parent();
184 if (clip_parent == layer_) {
185 // Create a clip parent layer, if it does not exist.
186 clip_parent = cc::Layer::Create();
187 clip_parent->SetMasksToBounds(true);
188 clip_parent->SetIsDrawable(true);
189 layer_->ReplaceChild(layer, clip_parent);
190 clip_parent->AddChild(layer);
191 }
192 gfx::Point position = PP_ToGfxPoint(new_layer->common.clip_rect.point);
193 clip_parent->SetPosition(position);
194 clip_parent->SetBounds(PP_ToGfxSize(new_layer->common.clip_rect.size));
195 layer->SetPosition(gfx::Point(-position.x(), -position.y()));
196 } else if (layer->parent() != layer_) {
197 // Remove the clip parent layer.
198 layer_->ReplaceChild(layer->parent(), layer);
199 layer->SetPosition(gfx::Point());
200 }
201
202 if (new_layer->color) {
203 layer->SetBackgroundColor(SkColorSetARGBMacro(
204 new_layer->color->alpha * 255,
205 new_layer->color->red * 255,
206 new_layer->color->green * 255,
207 new_layer->color->blue * 255));
208 return;
209 }
210
211 if (new_layer->texture) {
212 scoped_refptr<cc::TextureLayer> texture_layer(
213 static_cast<cc::TextureLayer*>(layer.get()));
214 if (!old_layer ||
215 new_layer->common.resource_id != old_layer->common.resource_id) {
216 cc::TextureMailbox mailbox(new_layer->texture->mailbox,
217 GL_TEXTURE_2D,
218 new_layer->texture->sync_point);
219 texture_layer->SetTextureMailbox(mailbox,
220 cc::SingleReleaseCallback::Create(
221 base::Bind(&PepperCompositorHost::ResourceReleased,
222 weak_factory_.GetWeakPtr(),
223 new_layer->common.resource_id)));;
224 }
225 texture_layer->SetPremultipliedAlpha(new_layer->texture->premult_alpha);
226 gfx::RectF rect = PP_ToGfxRectF(new_layer->texture->source_rect);
227 texture_layer->SetUV(rect.origin(), rect.bottom_right());
228 return;
229 }
230
231 if (new_layer->image) {
232 if (!old_layer ||
233 new_layer->common.resource_id != old_layer->common.resource_id) {
234 scoped_refptr<cc::TextureLayer> image_layer(
235 static_cast<cc::TextureLayer*>(layer.get()));
236 EnterResourceNoLock<PPB_ImageData_API> enter(new_layer->image->resource,
237 true);
238 DCHECK(enter.succeeded());
239
240 // TODO(penghuang): support all kinds of image.
241 PP_ImageDataDesc desc;
242 PP_Bool rv = enter.object()->Describe(&desc);
243 DCHECK_EQ(rv, PP_TRUE);
244 DCHECK_EQ(desc.stride, desc.size.width * 4);
245 DCHECK_EQ(desc.format, PP_IMAGEDATAFORMAT_RGBA_PREMUL);
246
247 cc::TextureMailbox mailbox(image_shm.get(),
248 PP_ToGfxSize(desc.size));
249 image_layer->SetTextureMailbox(mailbox,
250 cc::SingleReleaseCallback::Create(
251 base::Bind(&PepperCompositorHost::ImageReleased,
252 weak_factory_.GetWeakPtr(),
253 new_layer->common.resource_id,
254 base::Passed(&image_shm))));
255
256 // ImageData is always premultiplied alpha.
257 image_layer->SetPremultipliedAlpha(true);
258 }
259 return;
260 }
261 // Should not be reached.
262 DCHECK(false);
piman 2014/06/10 22:37:06 NOTREACHED() is ok here.
Peng 2014/06/10 23:03:32 Done.
263 }
264
265 void PepperCompositorHost::ResourceReleased(int32_t id,
266 uint32_t sync_point,
267 bool is_lost) {
268 host()->SendUnsolicitedReply(
269 pp_resource(),
270 PpapiPluginMsg_Compositor_ReleaseResource(id, sync_point, is_lost));
271 }
272
273 void PepperCompositorHost::ImageReleased(
274 int32_t id,
275 const scoped_ptr<base::SharedMemory>& shared_memory,
276 uint32_t sync_point,
277 bool is_lost) {
278 ResourceReleased(id, sync_point, is_lost);
279 }
280
281 int32_t PepperCompositorHost::OnResourceMessageReceived(
282 const IPC::Message& msg,
283 HostMessageContext* context) {
284 PPAPI_BEGIN_MESSAGE_MAP(PepperCompositorHost, msg)
285 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
286 PpapiHostMsg_Compositor_CommitLayers, OnHostMsgCommitLayers)
287 PPAPI_END_MESSAGE_MAP()
288 return ppapi::host::ResourceHost::OnResourceMessageReceived(msg, context);
289 }
290
291 bool PepperCompositorHost::IsCompositorHost() {
292 return true;
293 }
294
295 int32_t PepperCompositorHost::OnHostMsgCommitLayers(
296 HostMessageContext* context,
297 const std::vector<ppapi::CompositorLayerData>& layers,
298 bool reset) {
299 // Do not support CommitLayers() on an unbounded compositor.
300 if (!bound_instance_)
301 return PP_ERROR_FAILED;
302
303 if (commit_layers_reply_context_.is_valid())
304 return PP_ERROR_INPROGRESS;
305
306 commit_layers_reply_context_ = context->MakeReplyMessageContext();
307
308 scoped_ptr<base::SharedMemory> image_shms[layers.size()];
309 // Verfiy the layers first, if an error happens, we will return the error to
310 // plugin and keep current layers set by the previous CommitLayers()
311 // unchanged.
312 for (size_t i = 0; i < layers.size(); ++i) {
313 const ppapi::CompositorLayerData* old_layer = NULL;
314 if (!reset && i < layers_.size())
315 old_layer = &layers_[i].pp_layer;
316 int32_t rv = VerifyCommittedLayer(old_layer, &layers[i], &image_shms[i]);
317 if (rv != PP_OK)
318 return rv;
319 }
320
321 // ResetLayers() has been called, we need rebuild layer stack.
322 if (reset) {
323 layer_->RemoveAllChildren();
324 layers_.clear();
325 }
326
327 for (size_t i = 0; i < layers.size(); ++i) {
328 const ppapi::CompositorLayerData* pp_layer = &layers[i];
329 LayerData* data = i >= layers_.size() ? NULL : &layers_[i];
330 DCHECK(!data || data->cc_layer);
331 scoped_refptr<cc::Layer> cc_layer = data ? data->cc_layer : NULL;
332 ppapi::CompositorLayerData* old_layer = data ? &data->pp_layer : NULL;
333
334 if (!cc_layer) {
335 if (pp_layer->color)
336 cc_layer = cc::SolidColorLayer::Create();
337 else if (pp_layer->texture || pp_layer->image)
338 cc_layer = cc::TextureLayer::CreateForMailbox(NULL);
339 layer_->AddChild(cc_layer);
340 }
341
342 UpdateLayer(cc_layer, old_layer, pp_layer, image_shms[i].Pass());
343
344 if (old_layer)
345 *old_layer = *pp_layer;
346 else
347 layers_.push_back(LayerData(cc_layer, *pp_layer));
348 }
349
350 return PP_OK_COMPLETIONPENDING;
351 }
352
353 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/pepper/pepper_compositor_host.h ('k') | content/renderer/pepper/pepper_plugin_instance_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698