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

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

Powered by Google App Engine
This is Rietveld 408576698