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

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: Update 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 "cc/layers/texture_layer.h"
9 #include "cc/resources/texture_mailbox.h"
10 #include "content/public/renderer/renderer_ppapi_host.h"
11 #include "content/renderer/pepper/gfx_conversion.h"
12 #include "content/renderer/pepper/host_globals.h"
13 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
14 #include "content/renderer/pepper/ppb_image_data_impl.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/host/dispatch_host_message.h"
17 #include "ppapi/host/host_message_context.h"
18 #include "ppapi/host/ppapi_host.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/thunk/enter.h"
21 #include "ppapi/thunk/ppb_image_data_api.h"
22 #include "third_party/khronos/GLES2/gl2.h"
23 #include "ui/gfx/transform.h"
24
25 using ppapi::host::HostMessageContext;
26 using ppapi::thunk::EnterResourceNoLock;
27 using ppapi::thunk::PPB_ImageData_API;
28
29 namespace content {
30
31 PepperCompositorHost::PepperCompositorHost(
32 RendererPpapiHost* host,
33 PP_Instance instance,
34 PP_Resource resource)
35 : ResourceHost(host->GetPpapiHost(), instance, resource),
36 bound_instance_(NULL),
37 weak_factory_(this) {
38 layer_ = cc::SolidColorLayer::Create();
39 layer_->SetMasksToBounds(true);
40 layer_->SetIsDrawable(true);
41 }
42
43 PepperCompositorHost::~PepperCompositorHost() {
44 // Unbind from the instance when destroyed if we're still bound.
45 if (bound_instance_)
46 bound_instance_->BindGraphics(bound_instance_->pp_instance(), 0);
47 }
48
49 bool PepperCompositorHost::BindToInstance(
50 PepperPluginInstanceImpl* new_instance) {
51 if (new_instance && new_instance->pp_instance() != pp_instance())
52 return false; // Can't bind other instance's contexts.
53 if (bound_instance_ == new_instance)
54 return true; // Rebinding the same device, nothing to do.
55 if (bound_instance_ && new_instance)
56 return false; // Can't change a bound device.
57 bound_instance_ = new_instance;
58 return true;
59 }
60
61 void PepperCompositorHost::ViewInitiatedPaint() {
62 if (!commit_layers_reply_context_.is_valid())
63 return;
64 host()->SendReply(commit_layers_reply_context_,
65 PpapiPluginMsg_Compositor_CommitLayersReply());
66 commit_layers_reply_context_ = ppapi::host::ReplyMessageContext();
67 }
68
69 void PepperCompositorHost::ViewFlushedPaint() {}
raymes 2014/06/02 03:51:08 Why is this function implemented at all?
Peng 2014/06/02 19:01:55 Graphics3d and 2d Hosts implements both ViewFlushe
raymes 2014/06/03 00:43:22 Ah ok, that seems reasonable then. Thanks.
70
71 void PepperCompositorHost::ResourceReleased(int32_t id,
72 uint32_t sync_point,
73 bool is_lost) {
74 host()->SendUnsolicitedReply(
75 pp_resource(),
76 PpapiPluginMsg_Compositor_ReleaseResource(id, sync_point, is_lost));
77 }
78
79 void PepperCompositorHost::ImageReleased(
80 int32_t id,
81 scoped_ptr<base::SharedMemory> shared_memory,
82 uint32_t sync_point,
83 bool is_lost) {
84 ResourceReleased(id, sync_point, is_lost);
85 }
86
87 int32_t PepperCompositorHost::OnResourceMessageReceived(
88 const IPC::Message& msg,
89 HostMessageContext* context) {
90 PPAPI_BEGIN_MESSAGE_MAP(PepperCompositorHost, msg)
91 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
92 PpapiHostMsg_Compositor_CommitLayers, OnHostMsgCommitLayers)
93 PPAPI_END_MESSAGE_MAP()
94 return ppapi::host::ResourceHost::OnResourceMessageReceived(msg, context);
95 }
96
97 bool PepperCompositorHost::IsCompositorHost() {
98 return true;
99 }
100
101 void PepperCompositorHost::UpdateLayer(
102 const scoped_refptr<cc::Layer>& layer,
103 ppapi::CompositorLayer* old_layer,
raymes 2014/06/02 03:51:08 Can this be const too?
Peng 2014/06/02 19:01:55 Done.
104 const ppapi::CompositorLayer* new_layer) {
105 CHECK(!old_layer || new_layer->type == old_layer->type);
106
107 // Always update properties on cc::Layer, because cc::Layer
108 // will ignore any setting with unchanged value.
109 layer->SetBounds(PP_ToGfxSize((new_layer)->size));
110 layer->SetBlendMode(SkXfermode::kSrcOver_Mode);
111 layer->SetOpacity(new_layer->opacity / 255.0f);
112
113 gfx::Transform transform(gfx::Transform::kSkipInitialization);
114 transform.matrix().setColMajorf(new_layer->transform);
115 layer->SetTransform(transform);
116
117 // Consider a (0,0,0,0) rect as no clip rect.
118 if (new_layer->clip_rect.point.x != 0 ||
119 new_layer->clip_rect.point.y != 0 ||
120 new_layer->clip_rect.size.width != 0 ||
121 new_layer->clip_rect.size.height != 0) {
raymes 2014/06/02 03:51:08 Would it be better to consider any rect that has a
Peng 2014/06/02 19:01:55 I think using (0,0,0,0) is a better. Otherwise, if
raymes 2014/06/03 00:43:22 Ah I see.
122 if (!layer->mask_layer())
123 layer->SetMaskLayer(cc::Layer::Create());
124 layer->mask_layer()->SetPosition(PP_ToGfxPoint(new_layer->clip_rect.point));
125 layer->mask_layer()->SetBounds(PP_ToGfxSize(new_layer->clip_rect.size));
126 } else {
127 layer->SetMaskLayer(NULL);
128 }
129
130 if (new_layer->type == ppapi::CompositorLayer::TYPE_COLOR) {
131 layer->SetBackgroundColor(SkColorSetARGBMacro(new_layer->color.alpha,
132 new_layer->color.red,
133 new_layer->color.green,
134 new_layer->color.blue));
135 } else if (new_layer->type == ppapi::CompositorLayer::TYPE_TEXTURE) {
136 scoped_refptr<cc::TextureLayer> texture_layer(
137 static_cast<cc::TextureLayer*>(layer.get()));
138 if (!old_layer || new_layer->texture.id != old_layer->texture.id) {
139 gpu::Mailbox gpu_mailbox;
140 gpu_mailbox.SetName(new_layer->texture.mailbox);
141 cc::TextureMailbox mailbox(gpu_mailbox,
142 GL_TEXTURE_2D,
143 new_layer->texture.sync_point);
144 texture_layer->SetTextureMailbox(mailbox,
145 cc::SingleReleaseCallback::Create(
146 base::Bind(&PepperCompositorHost::ResourceReleased,
147 weak_factory_.GetWeakPtr(),
148 new_layer->texture.id)));;
149 }
150 texture_layer->SetPremultipliedAlpha(new_layer->texture.premult_alpha);
151 gfx::RectF rect = PP_ToGfxRectF(new_layer->texture.source_rect);
152 texture_layer->SetUV(rect.origin(), rect.bottom_right());
153 } else if (new_layer->type == ppapi::CompositorLayer::TYPE_IMAGE) {
154 if (!old_layer || new_layer->image.id != old_layer->image.id) {
155 scoped_refptr<cc::TextureLayer> image_layer(
156 static_cast<cc::TextureLayer*>(layer.get()));
157 EnterResourceNoLock<PPB_ImageData_API> enter(
158 new_layer->image.host_resource, true);
159
160 do {
raymes 2014/06/02 03:51:08 Why not get rid of this do/while and just return f
Peng 2014/06/02 19:01:55 Done
161 if(enter.failed()) {
162 LOG(WARNING) << "Image is invalid!";
163 break;
164 }
165
166 PP_ImageDataDesc desc;
167 if (!enter.object()->Describe(&desc)) {
168 LOG(WARNING) << "Can not describe the image!";
169 break;
170 }
171
172 // TODO(penghuang): support all kinds of image.
173 DCHECK_EQ(desc.stride, desc.size.width * 4);
174 DCHECK_EQ(desc.format, PP_IMAGEDATAFORMAT_RGBA_PREMUL);
raymes 2014/06/02 03:51:08 Should we early exit in these cases too?
Peng 2014/06/02 19:01:55 Maybe using CHECK() is better. Because we also che
raymes 2014/06/03 00:43:22 That's a good point. But I think we usually just r
Peng 2014/06/03 18:32:23 Done.
175
176 int handle;
177 uint32_t byte_count;
178 if (enter.object()->GetSharedMemory(&handle, &byte_count) != PP_OK) {
179 LOG(WARNING) << "Can not access the image's shared memory!";
180 break;
181 }
182
183 #if defined(OS_WIN)
184 base::SharedMemoryHandle shm_handle =
185 static_cast<base::SharedMemoryHandle>(_dup(handle));
186 #else
187 base::SharedMemoryHandle shm_handle(dup(handle), false);
188 #endif
189 // Use a scoped_ptr to keep shared_memory alive until
190 // PepperCompositorHost::ImageReleased is called.
191 scoped_ptr<base::SharedMemory> shared_memory(
192 new base::SharedMemory(shm_handle, true));
193 CHECK(shared_memory->Map(desc.stride * desc.size.height));
194 cc::TextureMailbox mailbox(shared_memory.get(),
195 PP_ToGfxSize(desc.size));
196 image_layer->SetTextureMailbox(mailbox,
197 cc::SingleReleaseCallback::Create(
198 base::Bind(&PepperCompositorHost::ImageReleased,
199 weak_factory_.GetWeakPtr(),
200 new_layer->image.id,
201 base::Passed(&shared_memory))));
202
203 // ImageData is always premultiplied alpha.
204 image_layer->SetPremultipliedAlpha(true);
205 } while (false);
206 }
207 } else {
208 NOTREACHED();
209 }
210 }
211
212 int32_t PepperCompositorHost::OnHostMsgCommitLayers(
213 HostMessageContext* context,
214 const std::vector<ppapi::CompositorLayer>& layers,
215 bool changed) {
raymes 2014/06/02 03:51:08 Would "reset" be a better parameter name here?
Peng 2014/06/02 19:01:55 Done.
216 // Do not support CommitLayers on an unbounded compositor.
217 if (!bound_instance_)
218 return PP_ERROR_FAILED;
219
220 DCHECK(!commit_layers_reply_context_.is_valid());
raymes 2014/06/02 03:51:08 I think it might be better to return an error in t
Peng 2014/06/02 19:01:55 In plugin process, the CompositorResource does not
raymes 2014/06/03 00:43:22 See the note above.
Peng 2014/06/03 18:32:23 Done.
221 commit_layers_reply_context_ = context->MakeReplyMessageContext();
222
223 // ResetLayers() has been called, we need rebuild layer stack.
224 if (changed) {
225 layer_->RemoveAllChildren();
226 cc_layers_.clear();
227 pp_layers_.clear();
228 }
229
230 size_t i = 0;
231 for (std::vector<ppapi::CompositorLayer>::const_iterator it = layers.begin();
232 it != layers.end(); ++it, ++i) {
raymes 2014/06/02 03:51:08 Rather than having two iterating variables, it mig
Peng 2014/06/02 19:01:55 Done.
233 ppapi::CompositorLayer* old_layer =
234 i >= pp_layers_.size() ? NULL : &pp_layers_[i];
235 scoped_refptr<cc::Layer> layer =
raymes 2014/06/02 03:51:08 cc_layer (may be slightly more descriptive)
Peng 2014/06/02 19:01:55 Done.
236 i >= cc_layers_.size() ? NULL : cc_layers_[i];
237
238 CHECK((old_layer && layer) || (!old_layer && !layer));
239
240 if (!layer) {
241 if (it->type == ppapi::CompositorLayer::TYPE_COLOR) {
242 layer = cc::SolidColorLayer::Create();
243 } else if (it->type == ppapi::CompositorLayer::TYPE_TEXTURE ||
244 it->type == ppapi::CompositorLayer::TYPE_IMAGE) {
245 layer = cc::TextureLayer::CreateForMailbox(NULL);
246 } else {
247 NOTREACHED();
raymes 2014/06/02 03:51:08 We should return an error value here.
Peng 2014/06/02 19:01:55 Same. CompositorLayer() already verifies all layer
raymes 2014/06/03 00:43:22 See the note above.
Peng 2014/06/03 18:32:23 Done.
248 }
249 layer->SetIsDrawable(true);
250 layer->SetAnchorPoint(gfx::PointF());
251 }
252
253 UpdateLayer(layer, old_layer, &(*it));
254
255 if (old_layer) {
256 *old_layer = *it;
257 } else {
258 layer_->AddChild(layer);
259 cc_layers_.push_back(layer);
260 pp_layers_.push_back(*it);
261 }
262 }
263 return PP_OK_COMPLETIONPENDING;
264 }
265
266 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698