Chromium Code Reviews| OLD | NEW |
|---|---|
| (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() {} | |
| 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 const ppapi::CompositorLayerData* old_layer, | |
| 104 const ppapi::CompositorLayerData* 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) { | |
| 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::CompositorLayerData::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::CompositorLayerData::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::CompositorLayerData::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 CHECK(enter.succeeded()) << "Image is invalid!"; | |
| 161 PP_ImageDataDesc desc; | |
| 162 CHECK(enter.object()->Describe(&desc)) << "Can not describe the image!"; | |
| 163 | |
| 164 // TODO(penghuang): support all kinds of image. | |
| 165 CHECK_EQ(desc.stride, desc.size.width * 4); | |
| 166 CHECK_EQ(desc.format, PP_IMAGEDATAFORMAT_RGBA_PREMUL); | |
| 167 | |
| 168 int handle; | |
| 169 uint32_t byte_count; | |
| 170 CHECK_EQ(enter.object()->GetSharedMemory(&handle, &byte_count), PP_OK) | |
| 171 <<"Can not access the image's shared memory!"; | |
|
raymes
2014/06/04 01:11:38
You might as well keep all of these checks in now,
Peng
2014/06/05 00:50:38
Done.
| |
| 172 #if defined(OS_WIN) | |
| 173 base::SharedMemoryHandle shm_handle = | |
| 174 static_cast<base::SharedMemoryHandle>(_dup(handle)); | |
| 175 #else | |
| 176 base::SharedMemoryHandle shm_handle(dup(handle), false); | |
| 177 #endif | |
| 178 // Use a scoped_ptr to keep shared_memory alive until | |
| 179 // PepperCompositorHost::ImageReleased is called. | |
| 180 scoped_ptr<base::SharedMemory> shared_memory( | |
| 181 new base::SharedMemory(shm_handle, true)); | |
| 182 CHECK(shared_memory->Map(desc.stride * desc.size.height)); | |
| 183 cc::TextureMailbox mailbox(shared_memory.get(), | |
| 184 PP_ToGfxSize(desc.size)); | |
| 185 image_layer->SetTextureMailbox(mailbox, | |
| 186 cc::SingleReleaseCallback::Create( | |
| 187 base::Bind(&PepperCompositorHost::ImageReleased, | |
| 188 weak_factory_.GetWeakPtr(), | |
| 189 new_layer->image.id, | |
| 190 base::Passed(&shared_memory)))); | |
| 191 | |
| 192 // ImageData is always premultiplied alpha. | |
| 193 image_layer->SetPremultipliedAlpha(true); | |
| 194 } | |
| 195 } else { | |
| 196 NOTREACHED(); | |
| 197 } | |
| 198 } | |
| 199 | |
| 200 int32_t PepperCompositorHost::OnHostMsgCommitLayers( | |
| 201 HostMessageContext* context, | |
| 202 const std::vector<ppapi::CompositorLayerData>& layers, | |
| 203 bool reset) { | |
| 204 // Do not support CommitLayers on an unbounded compositor. | |
| 205 if (!bound_instance_) | |
| 206 return PP_ERROR_FAILED; | |
| 207 | |
| 208 CHECK(!commit_layers_reply_context_.is_valid()); | |
| 209 commit_layers_reply_context_ = context->MakeReplyMessageContext(); | |
| 210 | |
| 211 // ResetLayers() has been called, we need rebuild layer stack. | |
| 212 if (reset) { | |
| 213 layer_->RemoveAllChildren(); | |
| 214 cc_layers_.clear(); | |
| 215 pp_layers_.clear(); | |
| 216 } | |
| 217 | |
| 218 for (size_t i = 0; i < layers.size(); ++i) { | |
| 219 const ppapi::CompositorLayerData& pp_layer = layers[i]; | |
| 220 ppapi::CompositorLayerData* old_layer = | |
| 221 i >= pp_layers_.size() ? NULL : &pp_layers_[i]; | |
| 222 scoped_refptr<cc::Layer> cc_layer = | |
| 223 i >= cc_layers_.size() ? NULL : cc_layers_[i]; | |
| 224 | |
| 225 CHECK((old_layer && cc_layer) || (!old_layer && !cc_layer)); | |
| 226 | |
| 227 if (!cc_layer) { | |
| 228 if (pp_layer.type == ppapi::CompositorLayerData::TYPE_COLOR) { | |
| 229 cc_layer = cc::SolidColorLayer::Create(); | |
| 230 } else if (pp_layer.type == ppapi::CompositorLayerData::TYPE_TEXTURE || | |
| 231 pp_layer.type == ppapi::CompositorLayerData::TYPE_IMAGE) { | |
| 232 cc_layer = cc::TextureLayer::CreateForMailbox(NULL); | |
| 233 } else { | |
| 234 NOTREACHED(); | |
| 235 } | |
| 236 cc_layer->SetIsDrawable(true); | |
| 237 cc_layer->SetAnchorPoint(gfx::PointF()); | |
| 238 } | |
| 239 | |
| 240 UpdateLayer(cc_layer, old_layer, &pp_layer); | |
| 241 | |
| 242 if (old_layer) { | |
| 243 *old_layer = pp_layer; | |
| 244 } else { | |
| 245 layer_->AddChild(cc_layer); | |
| 246 cc_layers_.push_back(cc_layer); | |
| 247 pp_layers_.push_back(pp_layer); | |
| 248 } | |
| 249 } | |
| 250 return PP_OK_COMPLETIONPENDING; | |
| 251 } | |
| 252 | |
| 253 } // namespace content | |
| OLD | NEW |