Add missing OWNERS for chrome_android.gypi
[chromium-blink-merge.git] / cc / layers / video_layer_impl.cc
blob4328067325c82ed744f33760822dd8841533b2b7
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/quad_sink.h"
10 #include "cc/layers/video_frame_provider_client_impl.h"
11 #include "cc/quads/io_surface_draw_quad.h"
12 #include "cc/quads/stream_video_draw_quad.h"
13 #include "cc/quads/texture_draw_quad.h"
14 #include "cc/quads/yuv_video_draw_quad.h"
15 #include "cc/resources/resource_provider.h"
16 #include "cc/trees/layer_tree_impl.h"
17 #include "cc/trees/proxy.h"
18 #include "media/base/video_frame.h"
20 #if defined(GOOGLE_TV)
21 #include "cc/quads/solid_color_draw_quad.h"
22 #endif
24 namespace cc {
26 // static
27 scoped_ptr<VideoLayerImpl> VideoLayerImpl::Create(
28 LayerTreeImpl* tree_impl,
29 int id,
30 VideoFrameProvider* provider) {
31 scoped_ptr<VideoLayerImpl> layer(new VideoLayerImpl(tree_impl, id));
32 layer->SetProviderClientImpl(VideoFrameProviderClientImpl::Create(provider));
33 DCHECK(tree_impl->proxy()->IsImplThread());
34 DCHECK(tree_impl->proxy()->IsMainThreadBlocked());
35 return layer.Pass();
38 VideoLayerImpl::VideoLayerImpl(LayerTreeImpl* tree_impl, int id)
39 : LayerImpl(tree_impl, id),
40 frame_(NULL) {}
42 VideoLayerImpl::~VideoLayerImpl() {
43 if (!provider_client_impl_->Stopped()) {
44 // In impl side painting, we may have a pending and active layer
45 // associated with the video provider at the same time. Both have a ref
46 // on the VideoFrameProviderClientImpl, but we stop when the first
47 // LayerImpl (the one on the pending tree) is destroyed since we know
48 // the main thread is blocked for this commit.
49 DCHECK(layer_tree_impl()->proxy()->IsImplThread());
50 DCHECK(layer_tree_impl()->proxy()->IsMainThreadBlocked());
51 provider_client_impl_->Stop();
55 scoped_ptr<LayerImpl> VideoLayerImpl::CreateLayerImpl(
56 LayerTreeImpl* tree_impl) {
57 return scoped_ptr<LayerImpl>(new VideoLayerImpl(tree_impl, id()));
60 void VideoLayerImpl::PushPropertiesTo(LayerImpl* layer) {
61 LayerImpl::PushPropertiesTo(layer);
63 VideoLayerImpl* other = static_cast<VideoLayerImpl*>(layer);
64 other->SetProviderClientImpl(provider_client_impl_);
67 void VideoLayerImpl::DidBecomeActive() {
68 provider_client_impl_->set_active_video_layer(this);
71 bool VideoLayerImpl::WillDraw(DrawMode draw_mode,
72 ResourceProvider* resource_provider) {
73 if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
74 return false;
76 // Explicitly acquire and release the provider mutex so it can be held from
77 // WillDraw to DidDraw. Since the compositor thread is in the middle of
78 // drawing, the layer will not be destroyed before DidDraw is called.
79 // Therefore, the only thing that will prevent this lock from being released
80 // is the GPU process locking it. As the GPU process can't cause the
81 // destruction of the provider (calling StopUsingProvider), holding this
82 // lock should not cause a deadlock.
83 frame_ = provider_client_impl_->AcquireLockAndCurrentFrame();
85 if (!frame_.get()) {
86 // Drop any resources used by the updater if there is no frame to display.
87 updater_.reset();
89 provider_client_impl_->ReleaseLock();
90 return false;
93 if (!LayerImpl::WillDraw(draw_mode, resource_provider))
94 return false;
96 if (!updater_) {
97 updater_.reset(
98 new VideoResourceUpdater(layer_tree_impl()->context_provider(),
99 layer_tree_impl()->resource_provider()));
102 VideoFrameExternalResources external_resources =
103 updater_->CreateExternalResourcesFromVideoFrame(frame_);
104 frame_resource_type_ = external_resources.type;
106 if (external_resources.type ==
107 VideoFrameExternalResources::SOFTWARE_RESOURCE) {
108 software_resources_ = external_resources.software_resources;
109 software_release_callback_ =
110 external_resources.software_release_callback;
111 return true;
114 for (size_t i = 0; i < external_resources.mailboxes.size(); ++i) {
115 frame_resources_.push_back(
116 resource_provider->CreateResourceFromTextureMailbox(
117 external_resources.mailboxes[i]));
120 return true;
123 void VideoLayerImpl::AppendQuads(QuadSink* quad_sink,
124 AppendQuadsData* append_quads_data) {
125 DCHECK(frame_.get());
127 SharedQuadState* shared_quad_state =
128 quad_sink->UseSharedQuadState(CreateSharedQuadState());
129 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
131 gfx::Rect quad_rect(content_bounds());
132 gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
133 gfx::Rect visible_rect = frame_->visible_rect();
134 gfx::Size coded_size = frame_->coded_size();
136 // Pixels for macroblocked formats.
137 float tex_width_scale =
138 static_cast<float>(visible_rect.width()) / coded_size.width();
139 float tex_height_scale =
140 static_cast<float>(visible_rect.height()) / coded_size.height();
142 switch (frame_resource_type_) {
143 // TODO(danakj): Remove this, hide it in the hardware path.
144 case VideoFrameExternalResources::SOFTWARE_RESOURCE: {
145 DCHECK_EQ(frame_resources_.size(), 0u);
146 DCHECK_EQ(software_resources_.size(), 1u);
147 if (software_resources_.size() < 1u)
148 break;
149 bool premultiplied_alpha = true;
150 gfx::PointF uv_top_left(0.f, 0.f);
151 gfx::PointF uv_bottom_right(tex_width_scale, tex_height_scale);
152 float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
153 bool flipped = false;
154 scoped_ptr<TextureDrawQuad> texture_quad = TextureDrawQuad::Create();
155 texture_quad->SetNew(shared_quad_state,
156 quad_rect,
157 opaque_rect,
158 software_resources_[0],
159 premultiplied_alpha,
160 uv_top_left,
161 uv_bottom_right,
162 SK_ColorTRANSPARENT,
163 opacity,
164 flipped);
165 quad_sink->Append(texture_quad.PassAs<DrawQuad>(), append_quads_data);
166 break;
168 case VideoFrameExternalResources::YUV_RESOURCE: {
169 DCHECK_GE(frame_resources_.size(), 3u);
170 if (frame_resources_.size() < 3u)
171 break;
172 gfx::SizeF tex_scale(tex_width_scale, tex_height_scale);
173 scoped_ptr<YUVVideoDrawQuad> yuv_video_quad = YUVVideoDrawQuad::Create();
174 yuv_video_quad->SetNew(shared_quad_state,
175 quad_rect,
176 opaque_rect,
177 tex_scale,
178 frame_resources_[0],
179 frame_resources_[1],
180 frame_resources_[2],
181 frame_resources_.size() > 3 ?
182 frame_resources_[3] : 0);
183 quad_sink->Append(yuv_video_quad.PassAs<DrawQuad>(), append_quads_data);
184 break;
186 case VideoFrameExternalResources::RGB_RESOURCE: {
187 DCHECK_EQ(frame_resources_.size(), 1u);
188 if (frame_resources_.size() < 1u)
189 break;
190 bool premultiplied_alpha = true;
191 gfx::PointF uv_top_left(0.f, 0.f);
192 gfx::PointF uv_bottom_right(tex_width_scale, tex_height_scale);
193 float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
194 bool flipped = false;
195 scoped_ptr<TextureDrawQuad> texture_quad = TextureDrawQuad::Create();
196 texture_quad->SetNew(shared_quad_state,
197 quad_rect,
198 opaque_rect,
199 frame_resources_[0],
200 premultiplied_alpha,
201 uv_top_left,
202 uv_bottom_right,
203 SK_ColorTRANSPARENT,
204 opacity,
205 flipped);
206 quad_sink->Append(texture_quad.PassAs<DrawQuad>(), append_quads_data);
207 break;
209 case VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE: {
210 DCHECK_EQ(frame_resources_.size(), 1u);
211 if (frame_resources_.size() < 1u)
212 break;
213 gfx::Transform transform(
214 provider_client_impl_->stream_texture_matrix());
215 transform.Scale(tex_width_scale, tex_height_scale);
216 scoped_ptr<StreamVideoDrawQuad> stream_video_quad =
217 StreamVideoDrawQuad::Create();
218 stream_video_quad->SetNew(shared_quad_state,
219 quad_rect,
220 opaque_rect,
221 frame_resources_[0],
222 transform);
223 quad_sink->Append(stream_video_quad.PassAs<DrawQuad>(),
224 append_quads_data);
225 break;
227 case VideoFrameExternalResources::IO_SURFACE: {
228 DCHECK_EQ(frame_resources_.size(), 1u);
229 if (frame_resources_.size() < 1u)
230 break;
231 gfx::Size visible_size(visible_rect.width(), visible_rect.height());
232 scoped_ptr<IOSurfaceDrawQuad> io_surface_quad =
233 IOSurfaceDrawQuad::Create();
234 io_surface_quad->SetNew(shared_quad_state,
235 quad_rect,
236 opaque_rect,
237 visible_size,
238 frame_resources_[0],
239 IOSurfaceDrawQuad::UNFLIPPED);
240 quad_sink->Append(io_surface_quad.PassAs<DrawQuad>(),
241 append_quads_data);
242 break;
244 #if defined(GOOGLE_TV)
245 // This block and other blocks wrapped around #if defined(GOOGLE_TV) is not
246 // maintained by the general compositor team. Please contact the following
247 // people instead:
249 // wonsik@chromium.org
250 // ycheo@chromium.org
251 case VideoFrameExternalResources::HOLE: {
252 DCHECK_EQ(frame_resources_.size(), 0u);
253 scoped_ptr<SolidColorDrawQuad> solid_color_draw_quad =
254 SolidColorDrawQuad::Create();
256 // Create a solid color quad with transparent black and force no
257 // blending / no anti-aliasing.
258 solid_color_draw_quad->SetAll(
259 shared_quad_state, quad_rect, quad_rect, quad_rect, false,
260 SK_ColorTRANSPARENT, true);
261 quad_sink->Append(solid_color_draw_quad.PassAs<DrawQuad>(),
262 append_quads_data);
263 break;
265 #endif
266 case VideoFrameExternalResources::NONE:
267 NOTIMPLEMENTED();
268 break;
272 void VideoLayerImpl::DidDraw(ResourceProvider* resource_provider) {
273 LayerImpl::DidDraw(resource_provider);
275 DCHECK(frame_.get());
277 if (frame_resource_type_ ==
278 VideoFrameExternalResources::SOFTWARE_RESOURCE) {
279 for (size_t i = 0; i < software_resources_.size(); ++i)
280 software_release_callback_.Run(0, false);
282 software_resources_.clear();
283 software_release_callback_.Reset();
284 } else {
285 for (size_t i = 0; i < frame_resources_.size(); ++i)
286 resource_provider->DeleteResource(frame_resources_[i]);
287 frame_resources_.clear();
290 provider_client_impl_->PutCurrentFrame(frame_);
291 frame_ = NULL;
293 provider_client_impl_->ReleaseLock();
296 void VideoLayerImpl::DidLoseOutputSurface() {
297 updater_.reset();
300 void VideoLayerImpl::SetNeedsRedraw() {
301 set_update_rect(gfx::UnionRects(update_rect(), gfx::RectF(bounds())));
302 layer_tree_impl()->SetNeedsRedraw();
305 void VideoLayerImpl::SetProviderClientImpl(
306 scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl) {
307 provider_client_impl_ = provider_client_impl;
310 const char* VideoLayerImpl::LayerTypeAsString() const {
311 return "cc::VideoLayerImpl";
314 } // namespace cc