Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / cc / layers / video_layer_impl.cc
bloba7e1bdec3beb2aaefd7e5b0fce7907b48efd6490
1 // Copyright 2011 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.
5 #include "cc/layers/video_layer_impl.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "cc/layers/video_frame_provider_client_impl.h"
10 #include "cc/quads/io_surface_draw_quad.h"
11 #include "cc/quads/stream_video_draw_quad.h"
12 #include "cc/quads/texture_draw_quad.h"
13 #include "cc/quads/yuv_video_draw_quad.h"
14 #include "cc/resources/resource_provider.h"
15 #include "cc/resources/single_release_callback_impl.h"
16 #include "cc/trees/layer_tree_impl.h"
17 #include "cc/trees/occlusion.h"
18 #include "cc/trees/proxy.h"
19 #include "media/base/video_frame.h"
21 #if defined(VIDEO_HOLE)
22 #include "cc/quads/solid_color_draw_quad.h"
23 #endif // defined(VIDEO_HOLE)
25 namespace cc {
27 // static
28 scoped_ptr<VideoLayerImpl> VideoLayerImpl::Create(
29 LayerTreeImpl* tree_impl,
30 int id,
31 VideoFrameProvider* provider,
32 media::VideoRotation video_rotation) {
33 scoped_ptr<VideoLayerImpl> layer(
34 new VideoLayerImpl(tree_impl, id, video_rotation));
35 layer->SetProviderClientImpl(VideoFrameProviderClientImpl::Create(provider));
36 DCHECK(tree_impl->proxy()->IsImplThread());
37 DCHECK(tree_impl->proxy()->IsMainThreadBlocked());
38 return layer.Pass();
41 VideoLayerImpl::VideoLayerImpl(LayerTreeImpl* tree_impl,
42 int id,
43 media::VideoRotation video_rotation)
44 : LayerImpl(tree_impl, id),
45 frame_(nullptr),
46 video_rotation_(video_rotation) {
49 VideoLayerImpl::~VideoLayerImpl() {
50 if (!provider_client_impl_->Stopped()) {
51 // In impl side painting, we may have a pending and active layer
52 // associated with the video provider at the same time. Both have a ref
53 // on the VideoFrameProviderClientImpl, but we stop when the first
54 // LayerImpl (the one on the pending tree) is destroyed since we know
55 // the main thread is blocked for this commit.
56 DCHECK(layer_tree_impl()->proxy()->IsImplThread());
57 DCHECK(layer_tree_impl()->proxy()->IsMainThreadBlocked());
58 provider_client_impl_->Stop();
62 scoped_ptr<LayerImpl> VideoLayerImpl::CreateLayerImpl(
63 LayerTreeImpl* tree_impl) {
64 return make_scoped_ptr(new VideoLayerImpl(tree_impl, id(), video_rotation_));
67 void VideoLayerImpl::PushPropertiesTo(LayerImpl* layer) {
68 LayerImpl::PushPropertiesTo(layer);
70 VideoLayerImpl* other = static_cast<VideoLayerImpl*>(layer);
71 other->SetProviderClientImpl(provider_client_impl_);
74 void VideoLayerImpl::DidBecomeActive() {
75 provider_client_impl_->set_active_video_layer(this);
78 bool VideoLayerImpl::WillDraw(DrawMode draw_mode,
79 ResourceProvider* resource_provider) {
80 if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
81 return false;
83 // Explicitly acquire and release the provider mutex so it can be held from
84 // WillDraw to DidDraw. Since the compositor thread is in the middle of
85 // drawing, the layer will not be destroyed before DidDraw is called.
86 // Therefore, the only thing that will prevent this lock from being released
87 // is the GPU process locking it. As the GPU process can't cause the
88 // destruction of the provider (calling StopUsingProvider), holding this
89 // lock should not cause a deadlock.
90 frame_ = provider_client_impl_->AcquireLockAndCurrentFrame();
92 if (!frame_.get()) {
93 // Drop any resources used by the updater if there is no frame to display.
94 updater_ = nullptr;
96 provider_client_impl_->ReleaseLock();
97 return false;
100 if (!LayerImpl::WillDraw(draw_mode, resource_provider))
101 return false;
103 if (!updater_) {
104 updater_.reset(
105 new VideoResourceUpdater(layer_tree_impl()->context_provider(),
106 layer_tree_impl()->resource_provider()));
109 VideoFrameExternalResources external_resources =
110 updater_->CreateExternalResourcesFromVideoFrame(frame_);
111 frame_resource_type_ = external_resources.type;
113 if (external_resources.type ==
114 VideoFrameExternalResources::SOFTWARE_RESOURCE) {
115 software_resources_ = external_resources.software_resources;
116 software_release_callback_ =
117 external_resources.software_release_callback;
118 return true;
121 DCHECK_EQ(external_resources.mailboxes.size(),
122 external_resources.release_callbacks.size());
123 for (size_t i = 0; i < external_resources.mailboxes.size(); ++i) {
124 unsigned resource_id = resource_provider->CreateResourceFromTextureMailbox(
125 external_resources.mailboxes[i],
126 SingleReleaseCallbackImpl::Create(
127 external_resources.release_callbacks[i]));
128 frame_resources_.push_back(resource_id);
131 return true;
134 void VideoLayerImpl::AppendQuads(RenderPass* render_pass,
135 const Occlusion& occlusion_in_content_space,
136 AppendQuadsData* append_quads_data) {
137 DCHECK(frame_.get());
139 gfx::Transform transform = draw_transform();
140 gfx::Size rotated_size = content_bounds();
142 switch (video_rotation_) {
143 case media::VIDEO_ROTATION_90:
144 rotated_size = gfx::Size(rotated_size.height(), rotated_size.width());
145 transform.Rotate(90.0);
146 transform.Translate(0.0, -rotated_size.height());
147 break;
148 case media::VIDEO_ROTATION_180:
149 transform.Rotate(180.0);
150 transform.Translate(-rotated_size.width(), -rotated_size.height());
151 break;
152 case media::VIDEO_ROTATION_270:
153 rotated_size = gfx::Size(rotated_size.height(), rotated_size.width());
154 transform.Rotate(270.0);
155 transform.Translate(-rotated_size.width(), 0);
156 case media::VIDEO_ROTATION_0:
157 break;
160 SharedQuadState* shared_quad_state =
161 render_pass->CreateAndAppendSharedQuadState();
162 shared_quad_state->SetAll(transform, rotated_size, visible_content_rect(),
163 clip_rect(), is_clipped(), draw_opacity(),
164 draw_blend_mode(), sorting_context_id());
166 AppendDebugBorderQuad(
167 render_pass, rotated_size, shared_quad_state, append_quads_data);
169 gfx::Rect quad_rect(rotated_size);
170 gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
171 gfx::Rect visible_rect = frame_->visible_rect();
172 gfx::Size coded_size = frame_->coded_size();
174 Occlusion occlusion_in_video_space =
175 occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(transform);
176 gfx::Rect visible_quad_rect =
177 occlusion_in_video_space.GetUnoccludedContentRect(quad_rect);
178 if (visible_quad_rect.IsEmpty())
179 return;
181 // Pixels for macroblocked formats.
182 const float tex_width_scale =
183 static_cast<float>(visible_rect.width()) / coded_size.width();
184 const float tex_height_scale =
185 static_cast<float>(visible_rect.height()) / coded_size.height();
186 const float tex_x_offset =
187 static_cast<float>(visible_rect.x()) / coded_size.width();
188 const float tex_y_offset =
189 static_cast<float>(visible_rect.y()) / coded_size.height();
191 switch (frame_resource_type_) {
192 // TODO(danakj): Remove this, hide it in the hardware path.
193 case VideoFrameExternalResources::SOFTWARE_RESOURCE: {
194 DCHECK_EQ(frame_resources_.size(), 0u);
195 DCHECK_EQ(software_resources_.size(), 1u);
196 if (software_resources_.size() < 1u)
197 break;
198 bool premultiplied_alpha = true;
199 gfx::PointF uv_top_left(0.f, 0.f);
200 gfx::PointF uv_bottom_right(tex_width_scale, tex_height_scale);
201 float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
202 bool flipped = false;
203 TextureDrawQuad* texture_quad =
204 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
205 texture_quad->SetNew(shared_quad_state,
206 quad_rect,
207 opaque_rect,
208 visible_quad_rect,
209 software_resources_[0],
210 premultiplied_alpha,
211 uv_top_left,
212 uv_bottom_right,
213 SK_ColorTRANSPARENT,
214 opacity,
215 flipped);
216 break;
218 case VideoFrameExternalResources::YUV_RESOURCE: {
219 DCHECK_GE(frame_resources_.size(), 3u);
220 if (frame_resources_.size() < 3u)
221 break;
222 YUVVideoDrawQuad::ColorSpace color_space =
223 frame_->format() == media::VideoFrame::YV12J
224 ? YUVVideoDrawQuad::REC_601_JPEG
225 : YUVVideoDrawQuad::REC_601;
226 gfx::RectF tex_coord_rect(
227 tex_x_offset, tex_y_offset, tex_width_scale, tex_height_scale);
228 YUVVideoDrawQuad* yuv_video_quad =
229 render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
230 yuv_video_quad->SetNew(
231 shared_quad_state,
232 quad_rect,
233 opaque_rect,
234 visible_quad_rect,
235 tex_coord_rect,
236 frame_resources_[0],
237 frame_resources_[1],
238 frame_resources_[2],
239 frame_resources_.size() > 3 ? frame_resources_[3] : 0,
240 color_space);
241 break;
243 case VideoFrameExternalResources::RGB_RESOURCE: {
244 DCHECK_EQ(frame_resources_.size(), 1u);
245 if (frame_resources_.size() < 1u)
246 break;
247 bool premultiplied_alpha = true;
248 gfx::PointF uv_top_left(0.f, 0.f);
249 gfx::PointF uv_bottom_right(tex_width_scale, tex_height_scale);
250 float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
251 bool flipped = false;
252 TextureDrawQuad* texture_quad =
253 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
254 texture_quad->SetNew(shared_quad_state,
255 quad_rect,
256 opaque_rect,
257 visible_quad_rect,
258 frame_resources_[0],
259 premultiplied_alpha,
260 uv_top_left,
261 uv_bottom_right,
262 SK_ColorTRANSPARENT,
263 opacity,
264 flipped);
265 break;
267 case VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE: {
268 DCHECK_EQ(frame_resources_.size(), 1u);
269 if (frame_resources_.size() < 1u)
270 break;
271 gfx::Transform scale;
272 scale.Scale(tex_width_scale, tex_height_scale);
273 StreamVideoDrawQuad* stream_video_quad =
274 render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>();
275 stream_video_quad->SetNew(
276 shared_quad_state,
277 quad_rect,
278 opaque_rect,
279 visible_quad_rect,
280 frame_resources_[0],
281 scale * provider_client_impl_->stream_texture_matrix());
282 break;
284 case VideoFrameExternalResources::IO_SURFACE: {
285 DCHECK_EQ(frame_resources_.size(), 1u);
286 if (frame_resources_.size() < 1u)
287 break;
288 IOSurfaceDrawQuad* io_surface_quad =
289 render_pass->CreateAndAppendDrawQuad<IOSurfaceDrawQuad>();
290 io_surface_quad->SetNew(shared_quad_state,
291 quad_rect,
292 opaque_rect,
293 visible_quad_rect,
294 visible_rect.size(),
295 frame_resources_[0],
296 IOSurfaceDrawQuad::UNFLIPPED);
297 break;
299 #if defined(VIDEO_HOLE)
300 // This block and other blocks wrapped around #if defined(GOOGLE_TV) is not
301 // maintained by the general compositor team. Please contact the following
302 // people instead:
304 // wonsik@chromium.org
305 // ycheo@chromium.org
306 case VideoFrameExternalResources::HOLE: {
307 DCHECK_EQ(frame_resources_.size(), 0u);
308 SolidColorDrawQuad* solid_color_draw_quad =
309 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
311 // Create a solid color quad with transparent black and force no
312 // blending / no anti-aliasing.
313 gfx::Rect opaque_rect = quad_rect;
314 solid_color_draw_quad->SetAll(shared_quad_state,
315 quad_rect,
316 opaque_rect,
317 visible_quad_rect,
318 false,
319 SK_ColorTRANSPARENT,
320 true);
321 break;
323 #endif // defined(VIDEO_HOLE)
324 case VideoFrameExternalResources::NONE:
325 NOTIMPLEMENTED();
326 break;
330 void VideoLayerImpl::DidDraw(ResourceProvider* resource_provider) {
331 LayerImpl::DidDraw(resource_provider);
333 DCHECK(frame_.get());
335 if (frame_resource_type_ ==
336 VideoFrameExternalResources::SOFTWARE_RESOURCE) {
337 for (size_t i = 0; i < software_resources_.size(); ++i) {
338 software_release_callback_.Run(
339 0, false, layer_tree_impl()->BlockingMainThreadTaskRunner());
342 software_resources_.clear();
343 software_release_callback_.Reset();
344 } else {
345 for (size_t i = 0; i < frame_resources_.size(); ++i)
346 resource_provider->DeleteResource(frame_resources_[i]);
347 frame_resources_.clear();
350 provider_client_impl_->PutCurrentFrame(frame_);
351 frame_ = nullptr;
353 provider_client_impl_->ReleaseLock();
356 void VideoLayerImpl::ReleaseResources() {
357 updater_ = nullptr;
360 void VideoLayerImpl::SetNeedsRedraw() {
361 SetUpdateRect(gfx::UnionRects(update_rect(), gfx::Rect(bounds())));
362 layer_tree_impl()->SetNeedsRedraw();
365 void VideoLayerImpl::SetProviderClientImpl(
366 scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl) {
367 provider_client_impl_ = provider_client_impl;
370 const char* VideoLayerImpl::LayerTypeAsString() const {
371 return "cc::VideoLayerImpl";
374 } // namespace cc