summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-10 04:44:49 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-10 04:44:49 +0000
commitb7cfc63c8df1f29996806b1c9395c2a5471b2c99 (patch)
tree0298586956136e4c47d43cdbebbaef92b01663c3
parentd1ba019278fb7ff108a2ceb5312599f909ac5c6d (diff)
downloadchromium_src-b7cfc63c8df1f29996806b1c9395c2a5471b2c99.zip
chromium_src-b7cfc63c8df1f29996806b1c9395c2a5471b2c99.tar.gz
chromium_src-b7cfc63c8df1f29996806b1c9395c2a5471b2c99.tar.bz2
cc: Move video upload to VideoResourceUpdater.
The VideoLayerImpl currently does upload of video frames from media::VideoFrame to hardware/software resources, and displays these resources through quads. This code is unfriendly to ubercomp as it requires holding onto the hardware resources when using hardware decode, and because it reuses the same textures every frame even though they need to be sent to the parent compositor. This CL introduces the VideoResourceUpdater class, and moves all logic around media::VideoFrame to that class. The VideoResourceUpdater class takes as input a VideoFrame, and produces a set of TextureMailboxes for the video layer to consume. In the software case, the VideoResourceUpdater sets itself up as the release callback so it can delete the backing texture when the browser compositor is done with it (it could recycle it in the future). In the hardware case, the VideoResourceUpdater takes a callback as input, so it can have the WebMediaPlayer notified when the texture is given back from the browser, and the hardware decoder can use it again for writing. This CL also prepares us better for software uber-compositing video. The video layer deals now only with abstract "resources", except for the mailboxes for ubercompositor. The TextureMailbox construct needs to be abstracted in order to hold a hardware or software backing for ubercompositor. Then the video layer's special-case code for software can be entirely removed and it will be fully software-uber-compositor-ready. Currently, the VideoLayerImpl just makes use of the VideoResourceUpdater class, making this a refactor without any functional change. This will make video playback in ubercompositor work correctly for software-decoded video. In order to address hardware-decoded video, a followup CL will have the WebMediaPlayer hook up a callback through the VideoResourceUpdater to ensure it doesn't reuse a texture for decode until it is returned from the parent compositor. R=enne,jamesr BUG=179729 Review URL: https://chromiumcodereview.appspot.com/13445009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@193323 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/layers/io_surface_layer_impl.cc34
-rw-r--r--cc/layers/io_surface_layer_impl.h3
-rw-r--r--cc/layers/video_frame_provider_client_impl.cc1
-rw-r--r--cc/layers/video_layer_impl.cc445
-rw-r--r--cc/layers/video_layer_impl.h42
-rw-r--r--cc/output/delegating_renderer_unittest.cc10
-rw-r--r--cc/output/gl_renderer.cc18
-rw-r--r--cc/quads/draw_quad_unittest.cc126
-rw-r--r--cc/quads/io_surface_draw_quad.cc13
-rw-r--r--cc/quads/io_surface_draw_quad.h6
-rw-r--r--cc/quads/stream_video_draw_quad.cc13
-rw-r--r--cc/quads/stream_video_draw_quad.h6
-rw-r--r--cc/quads/yuv_video_draw_quad.cc35
-rw-r--r--cc/quads/yuv_video_draw_quad.h18
-rw-r--r--cc/resources/video_resource_updater.cc326
-rw-r--r--cc/resources/video_resource_updater.h87
-rw-r--r--cc/test/render_pass_test_common.cc38
-rw-r--r--cc/test/test_web_graphics_context_3d.cc13
-rw-r--r--cc/test/test_web_graphics_context_3d.h6
-rw-r--r--cc/trees/layer_tree_host_unittest_delegated.cc11
-rw-r--r--content/common/cc_messages.h17
-rw-r--r--content/common/cc_messages_unittest.cc51
23 files changed, 777 insertions, 544 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 1ad272c..474ca6e 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -336,6 +336,8 @@
'layers/video_layer.h',
'layers/video_layer_impl.cc',
'layers/video_layer_impl.h',
+ 'resources/video_resource_updater.cc',
+ 'resources/video_resource_updater.h',
'scheduler/vsync_time_source.cc',
'scheduler/vsync_time_source.h',
'base/worker_pool.cc',
diff --git a/cc/layers/io_surface_layer_impl.cc b/cc/layers/io_surface_layer_impl.cc
index 2c95c00..2d4f9b7 100644
--- a/cc/layers/io_surface_layer_impl.cc
+++ b/cc/layers/io_surface_layer_impl.cc
@@ -27,11 +27,25 @@ IOSurfaceLayerImpl::~IOSurfaceLayerImpl() {
if (!io_surface_texture_id_)
return;
- OutputSurface* output_surface = layer_tree_impl()->output_surface();
- // FIXME: Implement this path for software compositing.
- WebKit::WebGraphicsContext3D* context3d = output_surface->context3d();
- if (context3d)
- context3d->deleteTexture(io_surface_texture_id_);
+ DestroyTexture();
+}
+
+void IOSurfaceLayerImpl::DestroyTexture() {
+ if (io_surface_resource_id_) {
+ ResourceProvider* resource_provider =
+ layer_tree_impl()->resource_provider();
+ resource_provider->DeleteResource(io_surface_resource_id_);
+ io_surface_resource_id_ = 0;
+ }
+
+ if (io_surface_texture_id_) {
+ OutputSurface* output_surface = layer_tree_impl()->output_surface();
+ // FIXME: Implement this path for software compositing.
+ WebKit::WebGraphicsContext3D* context3d = output_surface->context3d();
+ if (context3d)
+ context3d->deleteTexture(io_surface_texture_id_);
+ io_surface_texture_id_ = 0;
+ }
}
scoped_ptr<LayerImpl> IOSurfaceLayerImpl::CreateLayerImpl(
@@ -59,8 +73,12 @@ void IOSurfaceLayerImpl::WillDraw(ResourceProvider* resource_provider) {
}
// FIXME: Do this in a way that we can track memory usage.
- if (!io_surface_texture_id_)
+ if (!io_surface_texture_id_) {
io_surface_texture_id_ = context3d->createTexture();
+ io_surface_resource_id_ =
+ resource_provider->CreateResourceFromExternalTexture(
+ io_surface_texture_id_);
+ }
GLC(context3d, context3d->activeTexture(GL_TEXTURE0));
GLC(context3d,
@@ -107,7 +125,7 @@ void IOSurfaceLayerImpl::AppendQuads(QuadSink* quad_sink,
quad_rect,
opaque_rect,
io_surface_size_,
- io_surface_texture_id_,
+ io_surface_resource_id_,
IOSurfaceDrawQuad::FLIPPED);
quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
}
@@ -125,7 +143,7 @@ void IOSurfaceLayerImpl::DumpLayerProperties(std::string* str,
void IOSurfaceLayerImpl::DidLoseOutputSurface() {
// We don't have a valid texture ID in the new context; however,
// the IOSurface is still valid.
- io_surface_texture_id_ = 0;
+ DestroyTexture();
io_surface_changed_ = true;
}
diff --git a/cc/layers/io_surface_layer_impl.h b/cc/layers/io_surface_layer_impl.h
index 1f40215..8c8f450 100644
--- a/cc/layers/io_surface_layer_impl.h
+++ b/cc/layers/io_surface_layer_impl.h
@@ -38,12 +38,15 @@ class CC_EXPORT IOSurfaceLayerImpl : public LayerImpl {
private:
IOSurfaceLayerImpl(LayerTreeImpl* tree_impl, int id);
+ void DestroyTexture();
+
virtual const char* LayerTypeAsString() const OVERRIDE;
unsigned io_surface_id_;
gfx::Size io_surface_size_;
bool io_surface_changed_;
unsigned io_surface_texture_id_;
+ unsigned io_surface_resource_id_;
DISALLOW_COPY_AND_ASSIGN(IOSurfaceLayerImpl);
};
diff --git a/cc/layers/video_frame_provider_client_impl.cc b/cc/layers/video_frame_provider_client_impl.cc
index 6028683..732bbbb 100644
--- a/cc/layers/video_frame_provider_client_impl.cc
+++ b/cc/layers/video_frame_provider_client_impl.cc
@@ -6,6 +6,7 @@
#include "cc/base/math_util.h"
#include "cc/layers/video_layer_impl.h"
+#include "media/base/video_frame.h"
namespace cc {
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index f87cacc..233abce 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -4,21 +4,18 @@
#include "cc/layers/video_layer_impl.h"
+#include "base/bind.h"
#include "base/logging.h"
-#include "cc/base/math_util.h"
#include "cc/layers/quad_sink.h"
#include "cc/layers/video_frame_provider_client_impl.h"
-#include "cc/output/renderer.h"
#include "cc/quads/io_surface_draw_quad.h"
#include "cc/quads/stream_video_draw_quad.h"
#include "cc/quads/texture_draw_quad.h"
#include "cc/quads/yuv_video_draw_quad.h"
#include "cc/resources/resource_provider.h"
#include "cc/trees/layer_tree_impl.h"
-#include "gpu/GLES2/gl2extchromium.h"
-#include "media/filters/skcanvas_video_renderer.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/khronos/GLES2/gl2ext.h"
+#include "cc/trees/proxy.h"
+#include "media/base/video_frame.h"
#if defined(GOOGLE_TV)
#include "cc/quads/solid_color_draw_quad.h"
@@ -40,10 +37,7 @@ scoped_ptr<VideoLayerImpl> VideoLayerImpl::Create(
VideoLayerImpl::VideoLayerImpl(LayerTreeImpl* tree_impl, int id)
: LayerImpl(tree_impl, id),
- frame_(NULL),
- format_(media::VideoFrame::INVALID),
- convert_yuv_(false),
- external_texture_resource_(0) {}
+ frame_(NULL) {}
VideoLayerImpl::~VideoLayerImpl() {
if (!provider_client_impl_->Stopped()) {
@@ -56,13 +50,6 @@ VideoLayerImpl::~VideoLayerImpl() {
DCHECK(layer_tree_impl()->proxy()->IsMainThreadBlocked());
provider_client_impl_->Stop();
}
- FreeFramePlanes(layer_tree_impl()->resource_provider());
-
-#ifndef NDEBUG
- for (size_t i = 0; i < media::VideoFrame::kMaxPlanes; ++i)
- DCHECK(!frame_planes_[i].resource_id);
- DCHECK(!external_texture_resource_);
-#endif
}
scoped_ptr<LayerImpl> VideoLayerImpl::CreateLayerImpl(
@@ -81,10 +68,11 @@ void VideoLayerImpl::DidBecomeActive() {
provider_client_impl_->set_active_video_layer(this);
}
+static void EmptyCallback(unsigned sync_point) {}
+
void VideoLayerImpl::WillDraw(ResourceProvider* resource_provider) {
LayerImpl::WillDraw(resource_provider);
-
// Explicitly acquire and release the provider mutex so it can be held from
// WillDraw to DidDraw. Since the compositor thread is in the middle of
// drawing, the layer will not be destroyed before DidDraw is called.
@@ -94,61 +82,40 @@ void VideoLayerImpl::WillDraw(ResourceProvider* resource_provider) {
// lock should not cause a deadlock.
frame_ = provider_client_impl_->AcquireLockAndCurrentFrame();
- WillDrawInternal(resource_provider);
- FreeUnusedFramePlanes(resource_provider);
-
- if (!frame_)
+ if (!frame_) {
provider_client_impl_->ReleaseLock();
-}
-
-void VideoLayerImpl::WillDrawInternal(ResourceProvider* resource_provider) {
- DCHECK(!external_texture_resource_);
-
- if (!frame_)
return;
+ }
- format_ = frame_->format();
-
-#if defined(GOOGLE_TV)
- if (format_ == media::VideoFrame::HOLE)
- return;
-#endif
-
- // If these fail, we'll have to add draw logic that handles offset bitmap/
- // texture UVs. For now, just expect (0, 0) offset, since all our decoders
- // so far don't offset.
- DCHECK_EQ(frame_->visible_rect().x(), 0);
- DCHECK_EQ(frame_->visible_rect().y(), 0);
-
- if (format_ == media::VideoFrame::INVALID) {
- provider_client_impl_->PutCurrentFrame(frame_);
- frame_ = NULL;
- return;
+ if (!updater_)
+ updater_.reset(new VideoResourceUpdater(resource_provider));
+
+ VideoFrameExternalResources external_resources;
+ if (frame_->format() == media::VideoFrame::NATIVE_TEXTURE) {
+ // TODO(danakj): To make this work for ubercomp, push this code out to
+ // WebMediaPlayer and have it set a callback so it knows it can reuse the
+ // texture.
+ TextureMailbox::ReleaseCallback empty_callback = base::Bind(&EmptyCallback);
+ external_resources = updater_->CreateForHardwarePlanes(
+ frame_, empty_callback);
+ } else {
+ external_resources = updater_->CreateForSoftwarePlanes(frame_);
}
- // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB
- // conversion here. That involves an extra copy of each frame to a bitmap.
- // Obviously, this is suboptimal and should be addressed once ubercompositor
- // starts shaping up.
- convert_yuv_ =
- resource_provider->default_resource_type() == ResourceProvider::Bitmap &&
- (format_ == media::VideoFrame::YV12 ||
- format_ == media::VideoFrame::YV16);
-
- if (convert_yuv_)
- format_ = media::VideoFrame::RGB32;
-
- if (!SetupFramePlanes(resource_provider)) {
- provider_client_impl_->PutCurrentFrame(frame_);
- frame_ = NULL;
+ frame_resource_type_ = external_resources.type;
+
+ if (external_resources.type ==
+ VideoFrameExternalResources::SOFTWARE_RESOURCE) {
+ software_resources_ = external_resources.software_resources;
+ software_release_callback_ =
+ external_resources.software_release_callback;
return;
}
- if (format_ == media::VideoFrame::NATIVE_TEXTURE &&
- frame_->texture_target() == GL_TEXTURE_2D) {
- external_texture_resource_ =
- resource_provider->CreateResourceFromExternalTexture(
- frame_->texture_id());
+ for (size_t i = 0; i < external_resources.mailboxes.size(); ++i) {
+ frame_resources_.push_back(
+ resource_provider->CreateResourceFromTextureMailbox(
+ external_resources.mailboxes[i]));
}
}
@@ -161,64 +128,62 @@ void VideoLayerImpl::AppendQuads(QuadSink* quad_sink,
quad_sink->UseSharedQuadState(CreateSharedQuadState());
AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
- // TODO(danakj): When we pass quads out of process, we need to double-buffer,
- // or otherwise synchonize use of all textures in the quad.
-
gfx::Rect quad_rect(content_bounds());
gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
gfx::Rect visible_rect = frame_->visible_rect();
gfx::Size coded_size = frame_->coded_size();
- // pixels for macroblocked formats.
+ // Pixels for macroblocked formats.
float tex_width_scale =
static_cast<float>(visible_rect.width()) / coded_size.width();
float tex_height_scale =
static_cast<float>(visible_rect.height()) / coded_size.height();
-#if defined(GOOGLE_TV)
- // This block and other blocks wrapped around #if defined(GOOGLE_TV) is not
- // maintained by the general compositor team. Please contact the following
- // people instead:
- //
- // wonsik@chromium.org
- // ycheo@chromium.org
-
- if (frame_->format() == media::VideoFrame::HOLE) {
- scoped_ptr<SolidColorDrawQuad> solid_color_draw_quad =
- SolidColorDrawQuad::Create();
- // Create a solid color quad with transparent black and force no
- // blending.
- solid_color_draw_quad->SetAll(
- shared_quad_state, quad_rect, quad_rect, quad_rect, false,
- SK_ColorTRANSPARENT);
- quad_sink->Append(solid_color_draw_quad.PassAs<DrawQuad>(),
- append_quads_data);
- return;
- }
-#endif
-
- switch (format_) {
- case media::VideoFrame::YV12:
- case media::VideoFrame::YV16: {
- // YUV software decoder.
- const FramePlane& y_plane = frame_planes_[media::VideoFrame::kYPlane];
- const FramePlane& u_plane = frame_planes_[media::VideoFrame::kUPlane];
- const FramePlane& v_plane = frame_planes_[media::VideoFrame::kVPlane];
+ switch (frame_resource_type_) {
+ // TODO(danakj): Remove this, hide it in the hardware path.
+ case VideoFrameExternalResources::SOFTWARE_RESOURCE: {
+ DCHECK_EQ(frame_resources_.size(), 0u);
+ DCHECK_EQ(software_resources_.size(), 1u);
+ if (software_resources_.size() < 1u)
+ break;
+ bool premultiplied_alpha = true;
+ gfx::PointF uv_top_left(0.f, 0.f);
+ gfx::PointF uv_bottom_right(tex_width_scale, tex_height_scale);
+ float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
+ bool flipped = false;
+ scoped_ptr<TextureDrawQuad> texture_quad = TextureDrawQuad::Create();
+ texture_quad->SetNew(shared_quad_state,
+ quad_rect,
+ opaque_rect,
+ software_resources_[0],
+ premultiplied_alpha,
+ uv_top_left,
+ uv_bottom_right,
+ opacity,
+ flipped);
+ quad_sink->Append(texture_quad.PassAs<DrawQuad>(), append_quads_data);
+ break;
+ }
+ case VideoFrameExternalResources::YUV_RESOURCE: {
+ DCHECK_EQ(frame_resources_.size(), 3u);
+ if (frame_resources_.size() < 3u)
+ break;
gfx::SizeF tex_scale(tex_width_scale, tex_height_scale);
scoped_ptr<YUVVideoDrawQuad> yuv_video_quad = YUVVideoDrawQuad::Create();
yuv_video_quad->SetNew(shared_quad_state,
quad_rect,
opaque_rect,
tex_scale,
- y_plane,
- u_plane,
- v_plane);
+ frame_resources_[0],
+ frame_resources_[1],
+ frame_resources_[2]);
quad_sink->Append(yuv_video_quad.PassAs<DrawQuad>(), append_quads_data);
break;
}
- case media::VideoFrame::RGB32: {
- // RGBA software decoder: a converted YUV frame (see: convert_yuv_).
- const FramePlane& plane = frame_planes_[media::VideoFrame::kRGBPlane];
+ case VideoFrameExternalResources::RGB_RESOURCE: {
+ DCHECK_EQ(frame_resources_.size(), 1u);
+ if (frame_resources_.size() < 1u)
+ break;
bool premultiplied_alpha = true;
gfx::PointF uv_top_left(0.f, 0.f);
gfx::PointF uv_bottom_right(tex_width_scale, tex_height_scale);
@@ -228,7 +193,7 @@ void VideoLayerImpl::AppendQuads(QuadSink* quad_sink,
texture_quad->SetNew(shared_quad_state,
quad_rect,
opaque_rect,
- plane.resource_id,
+ frame_resources_[0],
premultiplied_alpha,
uv_top_left,
uv_bottom_right,
@@ -237,70 +202,64 @@ void VideoLayerImpl::AppendQuads(QuadSink* quad_sink,
quad_sink->Append(texture_quad.PassAs<DrawQuad>(), append_quads_data);
break;
}
- case media::VideoFrame::NATIVE_TEXTURE:
- switch (frame_->texture_target()) {
- case GL_TEXTURE_2D: {
- // NativeTexture hardware decoder.
- bool premultiplied_alpha = true;
- gfx::PointF uv_top_left(0.f, 0.f);
- gfx::PointF uv_bottom_right(tex_width_scale, tex_height_scale);
- float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
- bool flipped = false;
- scoped_ptr<TextureDrawQuad> texture_quad = TextureDrawQuad::Create();
- texture_quad->SetNew(shared_quad_state,
- quad_rect,
- opaque_rect,
- external_texture_resource_,
- premultiplied_alpha,
- uv_top_left,
- uv_bottom_right,
- opacity,
- flipped);
- quad_sink->Append(texture_quad.PassAs<DrawQuad>(), append_quads_data);
- break;
- }
- case GL_TEXTURE_RECTANGLE_ARB: {
- gfx::Size visible_size(visible_rect.width(), visible_rect.height());
- scoped_ptr<IOSurfaceDrawQuad> io_surface_quad =
- IOSurfaceDrawQuad::Create();
- io_surface_quad->SetNew(shared_quad_state,
- quad_rect,
- opaque_rect,
- visible_size,
- frame_->texture_id(),
- IOSurfaceDrawQuad::UNFLIPPED);
- quad_sink->Append(io_surface_quad.PassAs<DrawQuad>(),
- append_quads_data);
- break;
- }
- case GL_TEXTURE_EXTERNAL_OES: {
- // StreamTexture hardware decoder.
- gfx::Transform transform(
- provider_client_impl_->stream_texture_matrix());
- transform.Scale(tex_width_scale, tex_height_scale);
- scoped_ptr<StreamVideoDrawQuad> stream_video_quad =
- StreamVideoDrawQuad::Create();
- stream_video_quad->SetNew(shared_quad_state,
- quad_rect,
- opaque_rect,
- frame_->texture_id(),
- transform);
- quad_sink->Append(stream_video_quad.PassAs<DrawQuad>(),
- append_quads_data);
- break;
- }
- default:
- NOTREACHED();
- break;
- }
+ case VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE: {
+ DCHECK_EQ(frame_resources_.size(), 1u);
+ if (frame_resources_.size() < 1u)
+ break;
+ gfx::Transform transform(
+ provider_client_impl_->stream_texture_matrix());
+ transform.Scale(tex_width_scale, tex_height_scale);
+ scoped_ptr<StreamVideoDrawQuad> stream_video_quad =
+ StreamVideoDrawQuad::Create();
+ stream_video_quad->SetNew(shared_quad_state,
+ quad_rect,
+ opaque_rect,
+ frame_resources_[0],
+ transform);
+ quad_sink->Append(stream_video_quad.PassAs<DrawQuad>(),
+ append_quads_data);
break;
- case media::VideoFrame::INVALID:
- case media::VideoFrame::EMPTY:
- case media::VideoFrame::I420:
+ }
+ case VideoFrameExternalResources::IO_SURFACE: {
+ DCHECK_EQ(frame_resources_.size(), 1u);
+ if (frame_resources_.size() < 1u)
+ break;
+ gfx::Size visible_size(visible_rect.width(), visible_rect.height());
+ scoped_ptr<IOSurfaceDrawQuad> io_surface_quad =
+ IOSurfaceDrawQuad::Create();
+ io_surface_quad->SetNew(shared_quad_state,
+ quad_rect,
+ opaque_rect,
+ visible_size,
+ frame_resources_[0],
+ IOSurfaceDrawQuad::UNFLIPPED);
+ quad_sink->Append(io_surface_quad.PassAs<DrawQuad>(),
+ append_quads_data);
+ break;
+ }
#if defined(GOOGLE_TV)
- case media::VideoFrame::HOLE:
+ // This block and other blocks wrapped around #if defined(GOOGLE_TV) is not
+ // maintained by the general compositor team. Please contact the following
+ // people instead:
+ //
+ // wonsik@chromium.org
+ // ycheo@chromium.org
+ case VideoFrameExternalResources::HOLE: {
+ DCHECK_EQ(frame_resources_.size(), 0u);
+ scoped_ptr<SolidColorDrawQuad> solid_color_draw_quad =
+ SolidColorDrawQuad::Create();
+ // Create a solid color quad with transparent black and force no
+ // blending.
+ solid_color_draw_quad->SetAll(
+ shared_quad_state, quad_rect, quad_rect, quad_rect, false,
+ SK_ColorTRANSPARENT);
+ quad_sink->Append(solid_color_draw_quad.PassAs<DrawQuad>(),
+ append_quads_data);
+ break;
+ }
#endif
- NOTREACHED();
+ case VideoFrameExternalResources::NONE:
+ NOTIMPLEMENTED();
break;
}
}
@@ -311,15 +270,17 @@ void VideoLayerImpl::DidDraw(ResourceProvider* resource_provider) {
if (!frame_)
return;
- if (format_ == media::VideoFrame::NATIVE_TEXTURE &&
- frame_->texture_target() == GL_TEXTURE_2D) {
- DCHECK(external_texture_resource_);
- // TODO(danakj): the following assert will not be true when sending
- // resources to a parent compositor. We will probably need to hold on to
- // frame_ for longer, and have several "current frames" in the pipeline.
- DCHECK(!resource_provider->InUseByConsumer(external_texture_resource_));
- resource_provider->DeleteResource(external_texture_resource_);
- external_texture_resource_ = 0;
+ if (frame_resource_type_ ==
+ VideoFrameExternalResources::SOFTWARE_RESOURCE) {
+ for (size_t i = 0; i < software_resources_.size(); ++i)
+ software_release_callback_.Run(0);
+
+ software_resources_.clear();
+ software_release_callback_.Reset();
+ } else {
+ for (size_t i = 0; i < frame_resources_.size(); ++i)
+ resource_provider->DeleteResource(frame_resources_[i]);
+ frame_resources_.clear();
}
provider_client_impl_->PutCurrentFrame(frame_);
@@ -328,140 +289,8 @@ void VideoLayerImpl::DidDraw(ResourceProvider* resource_provider) {
provider_client_impl_->ReleaseLock();
}
-static gfx::Size VideoFrameDimension(media::VideoFrame* frame, int plane) {
- gfx::Size dimensions = frame->coded_size();
- switch (frame->format()) {
- case media::VideoFrame::YV12:
- if (plane != media::VideoFrame::kYPlane) {
- dimensions.set_width(dimensions.width() / 2);
- dimensions.set_height(dimensions.height() / 2);
- }
- break;
- case media::VideoFrame::YV16:
- if (plane != media::VideoFrame::kYPlane)
- dimensions.set_width(dimensions.width() / 2);
- break;
- default:
- break;
- }
- return dimensions;
-}
-
-bool VideoLayerImpl::FramePlane::AllocateData(
- ResourceProvider* resource_provider) {
- if (resource_id)
- return true;
-
- resource_id = resource_provider->CreateResource(
- size, format, ResourceProvider::TextureUsageAny);
- return resource_id != 0;
-}
-
-void VideoLayerImpl::FramePlane::FreeData(ResourceProvider* resource_provider) {
- if (!resource_id)
- return;
-
- resource_provider->DeleteResource(resource_id);
- resource_id = 0;
-}
-
-// Convert media::VideoFrame::Format to OpenGL enum values.
-static GLenum ConvertVFCFormatToGLenum(const media::VideoFrame::Format format) {
- switch (format) {
- case media::VideoFrame::YV12:
- case media::VideoFrame::YV16:
- return GL_LUMINANCE;
- case media::VideoFrame::RGB32:
- return GL_RGBA;
- case media::VideoFrame::NATIVE_TEXTURE:
-#if defined(GOOGLE_TV)
- case media::VideoFrame::HOLE:
-#endif
- case media::VideoFrame::INVALID:
- case media::VideoFrame::EMPTY:
- case media::VideoFrame::I420:
- NOTREACHED();
- break;
- }
- return GL_INVALID_VALUE;
-}
-
-bool VideoLayerImpl::SetupFramePlanes(ResourceProvider* resource_provider) {
- const size_t plane_count = media::VideoFrame::NumPlanes(format_);
- if (!plane_count)
- return true;
-
- const int max_texture_size = resource_provider->max_texture_size();
- const GLenum pixel_format = ConvertVFCFormatToGLenum(format_);
- for (size_t plane_index = 0; plane_index < plane_count; ++plane_index) {
- VideoLayerImpl::FramePlane* plane = &frame_planes_[plane_index];
-
- gfx::Size required_texture_size = VideoFrameDimension(frame_, plane_index);
- // TODO(danakj): Remove the test against max_texture_size when tiled layers
- // are implemented.
- if (required_texture_size.IsEmpty() ||
- required_texture_size.width() > max_texture_size ||
- required_texture_size.height() > max_texture_size)
- return false;
-
- if (plane->size != required_texture_size || plane->format != pixel_format) {
- plane->FreeData(resource_provider);
- plane->size = required_texture_size;
- plane->format = pixel_format;
- }
-
- if (!plane->AllocateData(resource_provider))
- return false;
- }
-
- if (convert_yuv_) {
- if (!video_renderer_)
- video_renderer_.reset(new media::SkCanvasVideoRenderer);
- const VideoLayerImpl::FramePlane& plane =
- frame_planes_[media::VideoFrame::kRGBPlane];
- ResourceProvider::ScopedWriteLockSoftware lock(resource_provider,
- plane.resource_id);
- video_renderer_->Paint(frame_,
- lock.sk_canvas(),
- frame_->visible_rect(),
- 0xff);
- return true;
- }
-
- for (size_t plane_index = 0; plane_index < plane_count; ++plane_index) {
- const VideoLayerImpl::FramePlane& plane = frame_planes_[plane_index];
- // Only planar formats planes should need upload.
- DCHECK_EQ(plane.format, static_cast<unsigned>(GL_LUMINANCE));
- const uint8_t* software_plane_pixels = frame_->data(plane_index);
- gfx::Rect image_rect(0,
- 0,
- frame_->stride(plane_index),
- plane.size.height());
- gfx::Rect source_rect(plane.size);
- resource_provider->SetPixels(plane.resource_id,
- software_plane_pixels,
- image_rect,
- source_rect,
- gfx::Vector2d());
- }
- return true;
-}
-
-void VideoLayerImpl::FreeFramePlanes(ResourceProvider* resource_provider) {
- for (size_t i = 0; i < media::VideoFrame::kMaxPlanes; ++i)
- frame_planes_[i].FreeData(resource_provider);
-}
-
-void VideoLayerImpl::FreeUnusedFramePlanes(
- ResourceProvider* resource_provider) {
- size_t first_unused_plane = (frame_ ? media::VideoFrame::NumPlanes(format_)
- : 0);
- for (size_t i = first_unused_plane; i < media::VideoFrame::kMaxPlanes; ++i)
- frame_planes_[i].FreeData(resource_provider);
-}
-
void VideoLayerImpl::DidLoseOutputSurface() {
- FreeFramePlanes(layer_tree_impl()->resource_provider());
+ updater_.reset();
}
void VideoLayerImpl::SetNeedsRedraw() {
diff --git a/cc/layers/video_layer_impl.h b/cc/layers/video_layer_impl.h
index da1c53f..b272f8f 100644
--- a/cc/layers/video_layer_impl.h
+++ b/cc/layers/video_layer_impl.h
@@ -5,22 +5,16 @@
#ifndef CC_LAYERS_VIDEO_LAYER_IMPL_H_
#define CC_LAYERS_VIDEO_LAYER_IMPL_H_
-#include "base/callback.h"
-#include "base/synchronization/lock.h"
#include "cc/base/cc_export.h"
#include "cc/layers/layer_impl.h"
-#include "cc/layers/video_frame_provider.h"
-#include "media/base/video_frame.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "ui/gfx/size.h"
-#include "ui/gfx/transform.h"
+#include "cc/resources/video_resource_updater.h"
namespace media {
-class SkCanvasVideoRenderer;
+class VideoFrame;
}
namespace cc {
-class LayerTreeHostImpl;
+class VideoFrameProvider;
class VideoFrameProviderClientImpl;
class CC_EXPORT VideoLayerImpl : public LayerImpl {
@@ -46,37 +40,23 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
void SetProviderClientImpl(
scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl);
- struct FramePlane {
- ResourceProvider::ResourceId resource_id;
- gfx::Size size;
- GLenum format;
-
- FramePlane() : resource_id(0), format(GL_LUMINANCE) {}
-
- bool AllocateData(ResourceProvider* resource_provider);
- void FreeData(ResourceProvider* resource_provider);
- };
-
private:
VideoLayerImpl(LayerTreeImpl* tree_impl, int id);
virtual const char* LayerTypeAsString() const OVERRIDE;
- void WillDrawInternal(ResourceProvider* resource_provider);
- bool SetupFramePlanes(ResourceProvider* resource_provider);
- void FreeFramePlanes(ResourceProvider* resource_provider);
- void FreeUnusedFramePlanes(ResourceProvider* resource_provider);
-
scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl_;
scoped_refptr<media::VideoFrame> frame_;
- media::VideoFrame::Format format_;
- bool convert_yuv_;
- ResourceProvider::ResourceId external_texture_resource_;
- scoped_ptr<media::SkCanvasVideoRenderer> video_renderer_;
- // Each index in this array corresponds to a plane in media::VideoFrame.
- FramePlane frame_planes_[media::VideoFrame::kMaxPlanes];
+ scoped_ptr<VideoResourceUpdater> updater_;
+ VideoFrameExternalResources::ResourceType frame_resource_type_;
+ std::vector<ResourceProvider::ResourceId> frame_resources_;
+
+ // TODO(danakj): Remove these, hide software path inside ResourceProvider and
+ // ExternalResource (aka TextureMailbox) classes.
+ std::vector<unsigned> software_resources_;
+ TextureMailbox::ReleaseCallback software_release_callback_;
DISALLOW_COPY_AND_ASSIGN(VideoLayerImpl);
};
diff --git a/cc/output/delegating_renderer_unittest.cc b/cc/output/delegating_renderer_unittest.cc
index e270860..cf85cb9 100644
--- a/cc/output/delegating_renderer_unittest.cc
+++ b/cc/output/delegating_renderer_unittest.cc
@@ -120,12 +120,12 @@ class DelegatingRendererTestResources : public DelegatingRendererTest {
ASSERT_TRUE(last_frame.delegated_frame_data);
EXPECT_EQ(2u, last_frame.delegated_frame_data->render_pass_list.size());
- // Each render pass has 7 resources in it. And the root render pass has a
- // mask resource used when drawing the child render pass. The number 7 may
- // change if AppendOneOfEveryQuadType is updated, and the value here should
- // be updated accordingly.
+ // Each render pass has 9 resources in it. And the root render pass has a
+ // mask resource used when drawing the child render pass. The number 9 may
+ // change if AppendOneOfEveryQuadType() is updated, and the value here
+ // should be updated accordingly.
EXPECT_EQ(
- 15u, last_frame.delegated_frame_data->resource_list.size());
+ 19u, last_frame.delegated_frame_data->resource_list.size());
EndTest();
}
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index d449ee7..14b5365 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -1342,19 +1342,15 @@ void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
const VideoYUVProgram* program = GetVideoYUVProgram(texCoordPrecision);
DCHECK(program && (program->initialized() || IsContextLost()));
- const VideoLayerImpl::FramePlane& y_plane = quad->y_plane;
- const VideoLayerImpl::FramePlane& u_plane = quad->u_plane;
- const VideoLayerImpl::FramePlane& v_plane = quad->v_plane;
-
GLC(Context(), Context()->activeTexture(GL_TEXTURE1));
ResourceProvider::ScopedSamplerGL y_plane_lock(
- resource_provider_, y_plane.resource_id, GL_TEXTURE_2D, GL_LINEAR);
+ resource_provider_, quad->y_plane_resource_id, GL_TEXTURE_2D, GL_LINEAR);
GLC(Context(), Context()->activeTexture(GL_TEXTURE2));
ResourceProvider::ScopedSamplerGL u_plane_lock(
- resource_provider_, u_plane.resource_id, GL_TEXTURE_2D, GL_LINEAR);
+ resource_provider_, quad->u_plane_resource_id, GL_TEXTURE_2D, GL_LINEAR);
GLC(Context(), Context()->activeTexture(GL_TEXTURE3));
ResourceProvider::ScopedSamplerGL v_plane_lock(
- resource_provider_, v_plane.resource_id, GL_TEXTURE_2D, GL_LINEAR);
+ resource_provider_, quad->v_plane_resource_id, GL_TEXTURE_2D, GL_LINEAR);
SetUseProgram(program->program());
@@ -1424,8 +1420,10 @@ void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame,
Context()->uniformMatrix4fv(
program->vertex_shader().tex_matrix_location(), 1, false, gl_matrix));
+ ResourceProvider::ScopedReadLockGL lock(resource_provider_,
+ quad->resource_id);
GLC(Context(),
- Context()->bindTexture(GL_TEXTURE_EXTERNAL_OES, quad->texture_id));
+ Context()->bindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id()));
GLC(Context(),
Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
@@ -1722,9 +1720,11 @@ void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame,
Context()->uniform1fv(
binding.vertex_opacity_location, 4, vertex_opacity));
+ ResourceProvider::ScopedReadLockGL lock(resource_provider_,
+ quad->io_surface_resource_id);
GLC(Context(),
Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB,
- quad->io_surface_texture_id));
+ lock.texture_id()));
DrawQuadGeometry(
frame, quad->quadTransform(), quad->rect, binding.matrix_location);
diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc
index 7177e6b..ae5a7f1 100644
--- a/cc/quads/draw_quad_unittest.cc
+++ b/cc/quads/draw_quad_unittest.cc
@@ -336,22 +336,22 @@ TEST(DrawQuadTest, CopyDebugBorderDrawQuad) {
TEST(DrawQuadTest, CopyIOSurfaceDrawQuad) {
gfx::Rect opaque_rect(3, 7, 10, 12);
gfx::Size size(58, 95);
- unsigned texture_id = 72;
+ ResourceProvider::ResourceId resource_id = 72;
IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED;
CREATE_SHARED_STATE();
CREATE_QUAD_4_NEW(
- IOSurfaceDrawQuad, opaque_rect, size, texture_id, orientation);
+ IOSurfaceDrawQuad, opaque_rect, size, resource_id, orientation);
EXPECT_EQ(DrawQuad::IO_SURFACE_CONTENT, copy_quad->material);
EXPECT_RECT_EQ(opaque_rect, copy_quad->opaque_rect);
EXPECT_EQ(size, copy_quad->io_surface_size);
- EXPECT_EQ(texture_id, copy_quad->io_surface_texture_id);
+ EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id);
EXPECT_EQ(orientation, copy_quad->orientation);
- CREATE_QUAD_3_ALL(IOSurfaceDrawQuad, size, texture_id, orientation);
+ CREATE_QUAD_3_ALL(IOSurfaceDrawQuad, size, resource_id, orientation);
EXPECT_EQ(DrawQuad::IO_SURFACE_CONTENT, copy_quad->material);
EXPECT_EQ(size, copy_quad->io_surface_size);
- EXPECT_EQ(texture_id, copy_quad->io_surface_texture_id);
+ EXPECT_EQ(resource_id, copy_quad->io_surface_resource_id);
EXPECT_EQ(orientation, copy_quad->orientation);
}
@@ -430,19 +430,19 @@ TEST(DrawQuadTest, CopySolidColorDrawQuad) {
TEST(DrawQuadTest, CopyStreamVideoDrawQuad) {
gfx::Rect opaque_rect(3, 7, 10, 12);
- unsigned texture_id = 64;
+ ResourceProvider::ResourceId resource_id = 64;
gfx::Transform matrix = gfx::Transform(0.5, 0.25, 1, 0.75, 0, 1);
CREATE_SHARED_STATE();
- CREATE_QUAD_3_NEW(StreamVideoDrawQuad, opaque_rect, texture_id, matrix);
+ CREATE_QUAD_3_NEW(StreamVideoDrawQuad, opaque_rect, resource_id, matrix);
EXPECT_EQ(DrawQuad::STREAM_VIDEO_CONTENT, copy_quad->material);
EXPECT_RECT_EQ(opaque_rect, copy_quad->opaque_rect);
- EXPECT_EQ(texture_id, copy_quad->texture_id);
+ EXPECT_EQ(resource_id, copy_quad->resource_id);
EXPECT_EQ(matrix, copy_quad->matrix);
- CREATE_QUAD_2_ALL(StreamVideoDrawQuad, texture_id, matrix);
+ CREATE_QUAD_2_ALL(StreamVideoDrawQuad, resource_id, matrix);
EXPECT_EQ(DrawQuad::STREAM_VIDEO_CONTENT, copy_quad->material);
- EXPECT_EQ(texture_id, copy_quad->texture_id);
+ EXPECT_EQ(resource_id, copy_quad->resource_id);
EXPECT_EQ(matrix, copy_quad->matrix);
}
@@ -617,47 +617,34 @@ TEST(DrawQuadTest, CopyTileDrawQuad) {
TEST(DrawQuadTest, CopyYUVVideoDrawQuad) {
gfx::Rect opaque_rect(3, 7, 10, 12);
gfx::SizeF tex_scale(0.75f, 0.5f);
- VideoLayerImpl::FramePlane y_plane;
- y_plane.resource_id = 45;
- y_plane.size = gfx::Size(34, 23);
- y_plane.format = 8;
- VideoLayerImpl::FramePlane u_plane;
- u_plane.resource_id = 532;
- u_plane.size = gfx::Size(134, 16);
- u_plane.format = 2;
- VideoLayerImpl::FramePlane v_plane;
- v_plane.resource_id = 4;
- v_plane.size = gfx::Size(456, 486);
- v_plane.format = 46;
+ ResourceProvider::ResourceId y_plane_resource_id = 45;
+ ResourceProvider::ResourceId u_plane_resource_id = 532;
+ ResourceProvider::ResourceId v_plane_resource_id = 4;
CREATE_SHARED_STATE();
- CREATE_QUAD_5_NEW(
- YUVVideoDrawQuad, opaque_rect, tex_scale, y_plane, u_plane, v_plane);
+ CREATE_QUAD_5_NEW(YUVVideoDrawQuad,
+ opaque_rect,
+ tex_scale,
+ y_plane_resource_id,
+ u_plane_resource_id,
+ v_plane_resource_id);
EXPECT_EQ(DrawQuad::YUV_VIDEO_CONTENT, copy_quad->material);
EXPECT_RECT_EQ(opaque_rect, copy_quad->opaque_rect);
EXPECT_EQ(tex_scale, copy_quad->tex_scale);
- EXPECT_EQ(y_plane.resource_id, copy_quad->y_plane.resource_id);
- EXPECT_EQ(y_plane.size, copy_quad->y_plane.size);
- EXPECT_EQ(y_plane.format, copy_quad->y_plane.format);
- EXPECT_EQ(u_plane.resource_id, copy_quad->u_plane.resource_id);
- EXPECT_EQ(u_plane.size, copy_quad->u_plane.size);
- EXPECT_EQ(u_plane.format, copy_quad->u_plane.format);
- EXPECT_EQ(v_plane.resource_id, copy_quad->v_plane.resource_id);
- EXPECT_EQ(v_plane.size, copy_quad->v_plane.size);
- EXPECT_EQ(v_plane.format, copy_quad->v_plane.format);
-
- CREATE_QUAD_4_ALL(YUVVideoDrawQuad, tex_scale, y_plane, u_plane, v_plane);
+ EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id);
+ EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id);
+ EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id);
+
+ CREATE_QUAD_4_ALL(YUVVideoDrawQuad,
+ tex_scale,
+ y_plane_resource_id,
+ u_plane_resource_id,
+ v_plane_resource_id);
EXPECT_EQ(DrawQuad::YUV_VIDEO_CONTENT, copy_quad->material);
EXPECT_EQ(tex_scale, copy_quad->tex_scale);
- EXPECT_EQ(y_plane.resource_id, copy_quad->y_plane.resource_id);
- EXPECT_EQ(y_plane.size, copy_quad->y_plane.size);
- EXPECT_EQ(y_plane.format, copy_quad->y_plane.format);
- EXPECT_EQ(u_plane.resource_id, copy_quad->u_plane.resource_id);
- EXPECT_EQ(u_plane.size, copy_quad->u_plane.size);
- EXPECT_EQ(u_plane.format, copy_quad->u_plane.format);
- EXPECT_EQ(v_plane.resource_id, copy_quad->v_plane.resource_id);
- EXPECT_EQ(v_plane.size, copy_quad->v_plane.size);
- EXPECT_EQ(v_plane.format, copy_quad->v_plane.format);
+ EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id);
+ EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id);
+ EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id);
}
TEST(DrawQuadTest, CopyPictureDrawQuad) {
@@ -742,13 +729,15 @@ TEST_F(DrawQuadIteratorTest, DebugBorderDrawQuad) {
TEST_F(DrawQuadIteratorTest, IOSurfaceDrawQuad) {
gfx::Rect opaque_rect(3, 7, 10, 12);
gfx::Size size(58, 95);
- unsigned texture_id = 72;
+ ResourceProvider::ResourceId resource_id = 72;
IOSurfaceDrawQuad::Orientation orientation = IOSurfaceDrawQuad::UNFLIPPED;
CREATE_SHARED_STATE();
CREATE_QUAD_4_NEW(
- IOSurfaceDrawQuad, opaque_rect, size, texture_id, orientation);
- EXPECT_EQ(0, IterateAndCount(quad_new.get()));
+ IOSurfaceDrawQuad, opaque_rect, size, resource_id, orientation);
+ EXPECT_EQ(resource_id, quad_new->io_surface_resource_id);
+ EXPECT_EQ(1, IterateAndCount(quad_new.get()));
+ EXPECT_EQ(resource_id + 1, quad_new->io_surface_resource_id);
}
TEST_F(DrawQuadIteratorTest, RenderPassDrawQuad) {
@@ -793,12 +782,14 @@ TEST_F(DrawQuadIteratorTest, SolidColorDrawQuad) {
TEST_F(DrawQuadIteratorTest, StreamVideoDrawQuad) {
gfx::Rect opaque_rect(3, 7, 10, 12);
- unsigned texture_id = 64;
+ ResourceProvider::ResourceId resource_id = 64;
gfx::Transform matrix = gfx::Transform(0.5, 0.25, 1, 0.75, 0, 1);
CREATE_SHARED_STATE();
- CREATE_QUAD_3_NEW(StreamVideoDrawQuad, opaque_rect, texture_id, matrix);
- EXPECT_EQ(0, IterateAndCount(quad_new.get()));
+ CREATE_QUAD_3_NEW(StreamVideoDrawQuad, opaque_rect, resource_id, matrix);
+ EXPECT_EQ(resource_id, quad_new->resource_id);
+ EXPECT_EQ(1, IterateAndCount(quad_new.get()));
+ EXPECT_EQ(resource_id + 1, quad_new->resource_id);
}
TEST_F(DrawQuadIteratorTest, TextureDrawQuad) {
@@ -846,30 +837,25 @@ TEST_F(DrawQuadIteratorTest, TileDrawQuad) {
TEST_F(DrawQuadIteratorTest, YUVVideoDrawQuad) {
gfx::Rect opaque_rect(3, 7, 10, 12);
gfx::SizeF tex_scale(0.75f, 0.5f);
- VideoLayerImpl::FramePlane y_plane;
- y_plane.resource_id = 45;
- y_plane.size = gfx::Size(34, 23);
- y_plane.format = 8;
- VideoLayerImpl::FramePlane u_plane;
- u_plane.resource_id = 532;
- u_plane.size = gfx::Size(134, 16);
- u_plane.format = 2;
- VideoLayerImpl::FramePlane v_plane;
- v_plane.resource_id = 4;
- v_plane.size = gfx::Size(456, 486);
- v_plane.format = 46;
+ ResourceProvider::ResourceId y_plane_resource_id = 45;
+ ResourceProvider::ResourceId u_plane_resource_id = 532;
+ ResourceProvider::ResourceId v_plane_resource_id = 4;
CREATE_SHARED_STATE();
- CREATE_QUAD_5_NEW(
- YUVVideoDrawQuad, opaque_rect, tex_scale, y_plane, u_plane, v_plane);
+ CREATE_QUAD_5_NEW(YUVVideoDrawQuad,
+ opaque_rect,
+ tex_scale,
+ y_plane_resource_id,
+ u_plane_resource_id,
+ v_plane_resource_id);
EXPECT_EQ(DrawQuad::YUV_VIDEO_CONTENT, copy_quad->material);
- EXPECT_EQ(y_plane.resource_id, quad_new->y_plane.resource_id);
- EXPECT_EQ(u_plane.resource_id, quad_new->u_plane.resource_id);
- EXPECT_EQ(v_plane.resource_id, quad_new->v_plane.resource_id);
+ EXPECT_EQ(y_plane_resource_id, quad_new->y_plane_resource_id);
+ EXPECT_EQ(u_plane_resource_id, quad_new->u_plane_resource_id);
+ EXPECT_EQ(v_plane_resource_id, quad_new->v_plane_resource_id);
EXPECT_EQ(3, IterateAndCount(quad_new.get()));
- EXPECT_EQ(y_plane.resource_id + 1, quad_new->y_plane.resource_id);
- EXPECT_EQ(u_plane.resource_id + 1, quad_new->u_plane.resource_id);
- EXPECT_EQ(v_plane.resource_id + 1, quad_new->v_plane.resource_id);
+ EXPECT_EQ(y_plane_resource_id + 1, quad_new->y_plane_resource_id);
+ EXPECT_EQ(u_plane_resource_id + 1, quad_new->u_plane_resource_id);
+ EXPECT_EQ(v_plane_resource_id + 1, quad_new->v_plane_resource_id);
}
TEST_F(DrawQuadIteratorTest, PictureDrawQuad) {
diff --git a/cc/quads/io_surface_draw_quad.cc b/cc/quads/io_surface_draw_quad.cc
index eb4aa20..1bbf8a4 100644
--- a/cc/quads/io_surface_draw_quad.cc
+++ b/cc/quads/io_surface_draw_quad.cc
@@ -9,7 +9,7 @@
namespace cc {
IOSurfaceDrawQuad::IOSurfaceDrawQuad()
- : io_surface_texture_id(0),
+ : io_surface_resource_id(0),
orientation(FLIPPED) {
}
@@ -21,14 +21,14 @@ void IOSurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
gfx::Rect rect,
gfx::Rect opaque_rect,
gfx::Size io_surface_size,
- unsigned io_surface_texture_id,
+ unsigned io_surface_resource_id,
Orientation orientation) {
gfx::Rect visible_rect = rect;
bool needs_blending = false;
DrawQuad::SetAll(shared_quad_state, DrawQuad::IO_SURFACE_CONTENT, rect,
opaque_rect, visible_rect, needs_blending);
this->io_surface_size = io_surface_size;
- this->io_surface_texture_id = io_surface_texture_id;
+ this->io_surface_resource_id = io_surface_resource_id;
this->orientation = orientation;
}
@@ -38,19 +38,18 @@ void IOSurfaceDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
gfx::Rect visible_rect,
bool needs_blending,
gfx::Size io_surface_size,
- unsigned io_surface_texture_id,
+ unsigned io_surface_resource_id,
Orientation orientation) {
DrawQuad::SetAll(shared_quad_state, DrawQuad::IO_SURFACE_CONTENT, rect,
opaque_rect, visible_rect, needs_blending);
this->io_surface_size = io_surface_size;
- this->io_surface_texture_id = io_surface_texture_id;
+ this->io_surface_resource_id = io_surface_resource_id;
this->orientation = orientation;
}
void IOSurfaceDrawQuad::IterateResources(
const ResourceIteratorCallback& callback) {
- // TODO(danakj): Convert to TextureDrawQuad?
- NOTIMPLEMENTED();
+ io_surface_resource_id = callback.Run(io_surface_resource_id);
}
const IOSurfaceDrawQuad* IOSurfaceDrawQuad::MaterialCast(
diff --git a/cc/quads/io_surface_draw_quad.h b/cc/quads/io_surface_draw_quad.h
index 38dabf8..1a30c90 100644
--- a/cc/quads/io_surface_draw_quad.h
+++ b/cc/quads/io_surface_draw_quad.h
@@ -25,7 +25,7 @@ class CC_EXPORT IOSurfaceDrawQuad : public DrawQuad {
gfx::Rect rect,
gfx::Rect opaque_rect,
gfx::Size io_surface_size,
- unsigned io_surface_texture_id,
+ unsigned io_surface_resource_id,
Orientation orientation);
void SetAll(const SharedQuadState* shared_quad_state,
@@ -34,11 +34,11 @@ class CC_EXPORT IOSurfaceDrawQuad : public DrawQuad {
gfx::Rect visible_rect,
bool needs_blending,
gfx::Size io_surface_size,
- unsigned io_surface_texture_id,
+ unsigned io_surface_resource_id,
Orientation orientation);
gfx::Size io_surface_size;
- unsigned io_surface_texture_id;
+ unsigned io_surface_resource_id;
Orientation orientation;
virtual void IterateResources(const ResourceIteratorCallback& callback)
diff --git a/cc/quads/stream_video_draw_quad.cc b/cc/quads/stream_video_draw_quad.cc
index 89e4003..831304f 100644
--- a/cc/quads/stream_video_draw_quad.cc
+++ b/cc/quads/stream_video_draw_quad.cc
@@ -8,7 +8,7 @@
namespace cc {
-StreamVideoDrawQuad::StreamVideoDrawQuad() : texture_id(0) {}
+StreamVideoDrawQuad::StreamVideoDrawQuad() : resource_id(0) {}
scoped_ptr<StreamVideoDrawQuad> StreamVideoDrawQuad::Create() {
return make_scoped_ptr(new StreamVideoDrawQuad);
@@ -17,13 +17,13 @@ scoped_ptr<StreamVideoDrawQuad> StreamVideoDrawQuad::Create() {
void StreamVideoDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
gfx::Rect rect,
gfx::Rect opaque_rect,
- unsigned texture_id,
+ unsigned resource_id,
const gfx::Transform& matrix) {
gfx::Rect visible_rect = rect;
bool needs_blending = false;
DrawQuad::SetAll(shared_quad_state, DrawQuad::STREAM_VIDEO_CONTENT, rect,
opaque_rect, visible_rect, needs_blending);
- this->texture_id = texture_id;
+ this->resource_id = resource_id;
this->matrix = matrix;
}
@@ -32,18 +32,17 @@ void StreamVideoDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
gfx::Rect opaque_rect,
gfx::Rect visible_rect,
bool needs_blending,
- unsigned texture_id,
+ unsigned resource_id,
const gfx::Transform& matrix) {
DrawQuad::SetAll(shared_quad_state, DrawQuad::STREAM_VIDEO_CONTENT, rect,
opaque_rect, visible_rect, needs_blending);
- this->texture_id = texture_id;
+ this->resource_id = resource_id;
this->matrix = matrix;
}
void StreamVideoDrawQuad::IterateResources(
const ResourceIteratorCallback& callback) {
- // TODO(danakj): Convert to TextureDrawQuad?
- NOTIMPLEMENTED();
+ resource_id = callback.Run(resource_id);
}
const StreamVideoDrawQuad* StreamVideoDrawQuad::MaterialCast(
diff --git a/cc/quads/stream_video_draw_quad.h b/cc/quads/stream_video_draw_quad.h
index e6a46b4..0ce31af 100644
--- a/cc/quads/stream_video_draw_quad.h
+++ b/cc/quads/stream_video_draw_quad.h
@@ -19,7 +19,7 @@ class CC_EXPORT StreamVideoDrawQuad : public DrawQuad {
void SetNew(const SharedQuadState* shared_quad_state,
gfx::Rect rect,
gfx::Rect opaque_rect,
- unsigned texture_id,
+ unsigned resource_id,
const gfx::Transform& matrix);
void SetAll(const SharedQuadState* shared_quad_state,
@@ -27,10 +27,10 @@ class CC_EXPORT StreamVideoDrawQuad : public DrawQuad {
gfx::Rect opaque_rect,
gfx::Rect visible_rect,
bool needs_blending,
- unsigned texture_id,
+ unsigned resource_id,
const gfx::Transform& matrix);
- unsigned texture_id;
+ unsigned resource_id;
gfx::Transform matrix;
virtual void IterateResources(const ResourceIteratorCallback& callback)
diff --git a/cc/quads/yuv_video_draw_quad.cc b/cc/quads/yuv_video_draw_quad.cc
index 7876861..f63c612 100644
--- a/cc/quads/yuv_video_draw_quad.cc
+++ b/cc/quads/yuv_video_draw_quad.cc
@@ -8,7 +8,10 @@
namespace cc {
-YUVVideoDrawQuad::YUVVideoDrawQuad() {}
+YUVVideoDrawQuad::YUVVideoDrawQuad()
+ : y_plane_resource_id(0),
+ u_plane_resource_id(0),
+ v_plane_resource_id(0) {}
YUVVideoDrawQuad::~YUVVideoDrawQuad() {}
scoped_ptr<YUVVideoDrawQuad> YUVVideoDrawQuad::Create() {
@@ -19,17 +22,17 @@ void YUVVideoDrawQuad::SetNew(const SharedQuadState* shared_quad_state,
gfx::Rect rect,
gfx::Rect opaque_rect,
gfx::SizeF tex_scale,
- const VideoLayerImpl::FramePlane& y_plane,
- const VideoLayerImpl::FramePlane& u_plane,
- const VideoLayerImpl::FramePlane& v_plane) {
+ unsigned y_plane_resource_id,
+ unsigned u_plane_resource_id,
+ unsigned v_plane_resource_id) {
gfx::Rect visible_rect = rect;
bool needs_blending = false;
DrawQuad::SetAll(shared_quad_state, DrawQuad::YUV_VIDEO_CONTENT, rect,
opaque_rect, visible_rect, needs_blending);
this->tex_scale = tex_scale;
- this->y_plane = y_plane;
- this->u_plane = u_plane;
- this->v_plane = v_plane;
+ this->y_plane_resource_id = y_plane_resource_id;
+ this->u_plane_resource_id = u_plane_resource_id;
+ this->v_plane_resource_id = v_plane_resource_id;
}
void YUVVideoDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
@@ -38,22 +41,22 @@ void YUVVideoDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
gfx::Rect visible_rect,
bool needs_blending,
gfx::SizeF tex_scale,
- const VideoLayerImpl::FramePlane& y_plane,
- const VideoLayerImpl::FramePlane& u_plane,
- const VideoLayerImpl::FramePlane& v_plane) {
+ unsigned y_plane_resource_id,
+ unsigned u_plane_resource_id,
+ unsigned v_plane_resource_id) {
DrawQuad::SetAll(shared_quad_state, DrawQuad::YUV_VIDEO_CONTENT, rect,
opaque_rect, visible_rect, needs_blending);
this->tex_scale = tex_scale;
- this->y_plane = y_plane;
- this->u_plane = u_plane;
- this->v_plane = v_plane;
+ this->y_plane_resource_id = y_plane_resource_id;
+ this->u_plane_resource_id = u_plane_resource_id;
+ this->v_plane_resource_id = v_plane_resource_id;
}
void YUVVideoDrawQuad::IterateResources(
const ResourceIteratorCallback& callback) {
- y_plane.resource_id = callback.Run(y_plane.resource_id);
- u_plane.resource_id = callback.Run(u_plane.resource_id);
- v_plane.resource_id = callback.Run(v_plane.resource_id);
+ y_plane_resource_id = callback.Run(y_plane_resource_id);
+ u_plane_resource_id = callback.Run(u_plane_resource_id);
+ v_plane_resource_id = callback.Run(v_plane_resource_id);
}
const YUVVideoDrawQuad* YUVVideoDrawQuad::MaterialCast(
diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h
index 8885a5a..9d54227 100644
--- a/cc/quads/yuv_video_draw_quad.h
+++ b/cc/quads/yuv_video_draw_quad.h
@@ -23,9 +23,9 @@ class CC_EXPORT YUVVideoDrawQuad : public DrawQuad {
gfx::Rect rect,
gfx::Rect opaque_rect,
gfx::SizeF tex_scale,
- const VideoLayerImpl::FramePlane& y_plane,
- const VideoLayerImpl::FramePlane& u_plane,
- const VideoLayerImpl::FramePlane& v_plane);
+ unsigned y_plane_resource_id,
+ unsigned u_plane_resource_id,
+ unsigned v_plane_resource_id);
void SetAll(const SharedQuadState* shared_quad_state,
gfx::Rect rect,
@@ -33,14 +33,14 @@ class CC_EXPORT YUVVideoDrawQuad : public DrawQuad {
gfx::Rect visible_rect,
bool needs_blending,
gfx::SizeF tex_scale,
- const VideoLayerImpl::FramePlane& y_plane,
- const VideoLayerImpl::FramePlane& u_plane,
- const VideoLayerImpl::FramePlane& v_plane);
+ unsigned y_plane_resource_id,
+ unsigned u_plane_resource_id,
+ unsigned v_plane_resource_id);
gfx::SizeF tex_scale;
- VideoLayerImpl::FramePlane y_plane;
- VideoLayerImpl::FramePlane u_plane;
- VideoLayerImpl::FramePlane v_plane;
+ unsigned y_plane_resource_id;
+ unsigned u_plane_resource_id;
+ unsigned v_plane_resource_id;
virtual void IterateResources(const ResourceIteratorCallback& callback)
OVERRIDE;
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
new file mode 100644
index 0000000..ca2d3bb
--- /dev/null
+++ b/cc/resources/video_resource_updater.cc
@@ -0,0 +1,326 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/resources/video_resource_updater.h"
+
+#include "base/bind.h"
+#include "cc/output/gl_renderer.h"
+#include "cc/resources/resource_provider.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "media/base/video_frame.h"
+#include "media/filters/skcanvas_video_renderer.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "ui/gfx/size_conversions.h"
+
+const unsigned kYUVResourceFormat = GL_LUMINANCE;
+const unsigned kRGBResourceFormat = GL_RGBA;
+
+namespace cc {
+
+VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {}
+
+VideoFrameExternalResources::~VideoFrameExternalResources() {}
+
+VideoResourceUpdater::VideoResourceUpdater(ResourceProvider* resource_provider)
+ : resource_provider_(resource_provider) {
+}
+
+VideoResourceUpdater::~VideoResourceUpdater() {}
+
+bool VideoResourceUpdater::VerifyFrame(
+ const scoped_refptr<media::VideoFrame>& video_frame) {
+ // If these fail, we'll have to add logic that handles offset bitmap/texture
+ // UVs. For now, just expect (0, 0) offset, since all our decoders so far
+ // don't offset.
+ DCHECK_EQ(video_frame->visible_rect().x(), 0);
+ DCHECK_EQ(video_frame->visible_rect().y(), 0);
+
+ switch (video_frame->format()) {
+ // Acceptable inputs.
+ case media::VideoFrame::YV12:
+ case media::VideoFrame::YV16:
+ case media::VideoFrame::NATIVE_TEXTURE:
+#if defined(GOOGLE_TV)
+ case media::VideoFrame::HOLE:
+#endif
+ return true;
+
+ // Unacceptable inputs. ¯\(°_o)/¯
+ case media::VideoFrame::INVALID:
+ case media::VideoFrame::RGB32:
+ case media::VideoFrame::EMPTY:
+ case media::VideoFrame::I420:
+ break;
+ }
+ return false;
+}
+
+// For frames that we receive in software format, determine the dimensions of
+// each plane in the frame.
+static gfx::Size SoftwarePlaneDimension(
+ media::VideoFrame::Format input_frame_format,
+ gfx::Size coded_size,
+ GLenum output_resource_format,
+ int plane_index) {
+ if (output_resource_format == kYUVResourceFormat) {
+ if (plane_index == media::VideoFrame::kYPlane)
+ return coded_size;
+
+ switch (input_frame_format) {
+ case media::VideoFrame::YV12:
+ return gfx::ToFlooredSize(gfx::ScaleSize(coded_size, 0.5f, 0.5f));
+ case media::VideoFrame::YV16:
+ return gfx::ToFlooredSize(gfx::ScaleSize(coded_size, 0.5f, 1.f));
+
+ case media::VideoFrame::INVALID:
+ case media::VideoFrame::RGB32:
+ case media::VideoFrame::EMPTY:
+ case media::VideoFrame::I420:
+ case media::VideoFrame::NATIVE_TEXTURE:
+#if defined(GOOGLE_TV)
+ case media::VideoFrame::HOLE:
+#endif
+ NOTREACHED();
+ }
+ }
+
+ DCHECK_EQ(output_resource_format, static_cast<unsigned>(kRGBResourceFormat));
+ return coded_size;
+}
+
+static void ReleaseResource(ResourceProvider* resource_provider,
+ ResourceProvider::ResourceId resource_id,
+ unsigned sync_point) {
+ resource_provider->DeleteResource(resource_id);
+}
+
+VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
+ const scoped_refptr<media::VideoFrame>& video_frame) {
+ if (!VerifyFrame(video_frame))
+ return VideoFrameExternalResources();
+
+ media::VideoFrame::Format input_frame_format = video_frame->format();
+
+#if defined(GOOGLE_TV)
+ if (input_frame_format == media::VideoFrame::HOLE) {
+ VideoFrameExternalResources external_resources;
+ external_resources.type = VideoFrameExternalResources::HOLE;
+ return external_resources;
+ }
+#endif
+
+ // Only YUV software video frames are supported.
+ DCHECK(input_frame_format == media::VideoFrame::YV12 ||
+ input_frame_format == media::VideoFrame::YV16);
+ if (input_frame_format != media::VideoFrame::YV12 &&
+ input_frame_format != media::VideoFrame::YV16)
+ return VideoFrameExternalResources();
+
+ bool software_compositor = !resource_provider_->GraphicsContext3D();
+
+ GLenum output_resource_format = kYUVResourceFormat;
+ size_t output_plane_count = 3;
+
+ // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB
+ // conversion here. That involves an extra copy of each frame to a bitmap.
+ // Obviously, this is suboptimal and should be addressed once ubercompositor
+ // starts shaping up.
+ if (software_compositor) {
+ output_resource_format = kRGBResourceFormat;
+ output_plane_count = 1;
+ }
+
+ int max_resource_size = resource_provider_->max_texture_size();
+ gfx::Size coded_frame_size = video_frame->coded_size();
+
+ ResourceProvider::ResourceIdArray plane_resources;
+ bool allocation_success = true;
+
+ for (size_t i = 0; i < output_plane_count; ++i) {
+ gfx::Size plane_size =
+ SoftwarePlaneDimension(input_frame_format,
+ coded_frame_size,
+ output_resource_format,
+ i);
+ if (plane_size.IsEmpty() ||
+ plane_size.width() > max_resource_size ||
+ plane_size.height() > max_resource_size) {
+ allocation_success = false;
+ break;
+ }
+
+ // TODO(danakj): Could recycle resources that we previously allocated and
+ // were returned to us.
+ ResourceProvider::ResourceId resource_id =
+ resource_provider_->CreateResource(plane_size,
+ output_resource_format,
+ ResourceProvider::TextureUsageAny);
+ if (resource_id == 0) {
+ allocation_success = false;
+ break;
+ }
+
+ plane_resources.push_back(resource_id);
+ }
+
+ if (!allocation_success) {
+ for (size_t i = 0; i < plane_resources.size(); ++i)
+ resource_provider_->DeleteResource(plane_resources[i]);
+ return VideoFrameExternalResources();
+ }
+
+ VideoFrameExternalResources external_resources;
+
+ if (software_compositor) {
+ DCHECK_EQ(output_resource_format, kRGBResourceFormat);
+ DCHECK_EQ(plane_resources.size(), 1u);
+
+ if (!video_renderer_)
+ video_renderer_.reset(new media::SkCanvasVideoRenderer);
+
+ {
+ ResourceProvider::ScopedWriteLockSoftware lock(
+ resource_provider_, plane_resources[0]);
+ video_renderer_->Paint(video_frame,
+ lock.sk_canvas(),
+ video_frame->visible_rect(),
+ 0xff);
+ }
+
+ // In software mode, the resource provider won't be lost. Soon this callback
+ // will be called directly from the resource provider, same as 3d
+ // compositing mode, so this raw unretained resource_provider will always
+ // be valid when the callback is fired.
+ TextureMailbox::ReleaseCallback callback_to_free_resource =
+ base::Bind(&ReleaseResource,
+ base::Unretained(resource_provider_),
+ plane_resources[0]);
+ external_resources.software_resources.push_back(plane_resources[0]);
+ external_resources.software_release_callback = callback_to_free_resource;
+
+ external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
+ return external_resources;
+ }
+
+ DCHECK_EQ(output_resource_format,
+ static_cast<unsigned>(kYUVResourceFormat));
+
+ WebKit::WebGraphicsContext3D* context =
+ resource_provider_->GraphicsContext3D();
+ DCHECK(context);
+
+ for (size_t plane = 0; plane < plane_resources.size(); ++plane) {
+ // Update each plane's resource id with its content.
+ ResourceProvider::ResourceId output_plane_resource_id =
+ plane_resources[plane];
+ gfx::Size plane_size =
+ SoftwarePlaneDimension(input_frame_format,
+ coded_frame_size,
+ output_resource_format,
+ plane);
+ const uint8_t* input_plane_pixels = video_frame->data(plane);
+
+ gfx::Rect image_rect(
+ 0, 0, video_frame->stride(plane), plane_size.height());
+ gfx::Rect source_rect(plane_size);
+ resource_provider_->SetPixels(output_plane_resource_id,
+ input_plane_pixels,
+ image_rect,
+ source_rect,
+ gfx::Vector2d());
+
+ gpu::Mailbox mailbox;
+ {
+ ResourceProvider::ScopedWriteLockGL lock(
+ resource_provider_, output_plane_resource_id);
+
+ GLC(context, context->genMailboxCHROMIUM(mailbox.name));
+ GLC(context, context->bindTexture(GL_TEXTURE_2D, lock.texture_id()));
+ GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D,
+ mailbox.name));
+ GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
+ }
+
+ // This callback is called by the resource provider itself, so it's okay to
+ // use an unretained raw pointer here.
+ TextureMailbox::ReleaseCallback callback_to_free_resource =
+ base::Bind(&ReleaseResource,
+ base::Unretained(resource_provider_),
+ output_plane_resource_id);
+ external_resources.mailboxes.push_back(
+ TextureMailbox(mailbox, callback_to_free_resource));
+ }
+
+ external_resources.type = VideoFrameExternalResources::YUV_RESOURCE;
+ return external_resources;
+}
+
+VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
+ const scoped_refptr<media::VideoFrame>& video_frame,
+ const TextureMailbox::ReleaseCallback& release_callback) {
+ if (!VerifyFrame(video_frame))
+ return VideoFrameExternalResources();
+
+ media::VideoFrame::Format frame_format = video_frame->format();
+
+ DCHECK_EQ(frame_format, media::VideoFrame::NATIVE_TEXTURE);
+ if (frame_format != media::VideoFrame::NATIVE_TEXTURE)
+ return VideoFrameExternalResources();
+
+ WebKit::WebGraphicsContext3D* context =
+ resource_provider_->GraphicsContext3D();
+ if (!context)
+ return VideoFrameExternalResources();
+
+ VideoFrameExternalResources external_resources;
+ switch (video_frame->texture_target()) {
+ case GL_TEXTURE_2D:
+ external_resources.type = VideoFrameExternalResources::RGB_RESOURCE;
+ break;
+ case GL_TEXTURE_EXTERNAL_OES:
+ external_resources.type =
+ VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE;
+ break;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ external_resources.type = VideoFrameExternalResources::IO_SURFACE;
+ break;
+ default:
+ NOTREACHED();
+ return VideoFrameExternalResources();
+ }
+
+ gpu::Mailbox mailbox;
+ GLC(context, context->genMailboxCHROMIUM(mailbox.name));
+ GLC(context, context->bindTexture(GL_TEXTURE_2D, video_frame->texture_id()));
+ GLC(context, context->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
+ GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
+
+ TextureMailbox::ReleaseCallback callback_to_return_resource =
+ base::Bind(&ReturnTexture,
+ base::Unretained(resource_provider_),
+ release_callback,
+ video_frame->texture_id(),
+ mailbox);
+ external_resources.mailboxes.push_back(
+ TextureMailbox(mailbox, callback_to_return_resource));
+ return external_resources;
+}
+
+// static
+void VideoResourceUpdater::ReturnTexture(
+ ResourceProvider* resource_provider,
+ TextureMailbox::ReleaseCallback callback,
+ unsigned texture_id,
+ gpu::Mailbox mailbox,
+ unsigned sync_point) {
+ WebKit::WebGraphicsContext3D* context =
+ resource_provider->GraphicsContext3D();
+ GLC(context, context->bindTexture(GL_TEXTURE_2D, texture_id));
+ GLC(context, context->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
+ GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
+ callback.Run(sync_point);
+}
+
+} // namespace cc
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h
new file mode 100644
index 0000000..fba59fc
--- /dev/null
+++ b/cc/resources/video_resource_updater.h
@@ -0,0 +1,87 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RESOURCES_VIDEO_RESOURCE_UPDATER_H_
+#define CC_RESOURCES_VIDEO_RESOURCE_UPDATER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/resources/texture_mailbox.h"
+
+namespace media {
+class SkCanvasVideoRenderer;
+class VideoFrame;
+}
+
+namespace cc {
+class ResourceProvider;
+
+class VideoFrameExternalResources {
+ public:
+ // Specifies what type of data is contained in the mailboxes, as well as how
+ // many mailboxes will be present.
+ enum ResourceType {
+ NONE,
+ YUV_RESOURCE,
+ RGB_RESOURCE,
+ STREAM_TEXTURE_RESOURCE,
+ IO_SURFACE,
+
+#if defined(GOOGLE_TV)
+ // TODO(danakj): Implement this with a solid color layer instead of a video
+ // frame and video layer.
+ HOLE,
+#endif
+
+ // TODO(danakj): Remove this and abstract TextureMailbox into
+ // "ExternalResource" that can hold a hardware or software backing.
+ SOFTWARE_RESOURCE
+ };
+
+ ResourceType type;
+ std::vector<TextureMailbox> mailboxes;
+
+ // TODO(danakj): Remove these too.
+ std::vector<unsigned> software_resources;
+ TextureMailbox::ReleaseCallback software_release_callback;
+
+ VideoFrameExternalResources();
+ ~VideoFrameExternalResources();
+};
+
+// VideoResourceUpdater is by the video system to produce frame content as
+// resources consumable by the compositor.
+class VideoResourceUpdater {
+ public:
+ explicit VideoResourceUpdater(ResourceProvider* resource_provider);
+ ~VideoResourceUpdater();
+
+ VideoFrameExternalResources CreateForHardwarePlanes(
+ const scoped_refptr<media::VideoFrame>& video_frame,
+ const TextureMailbox::ReleaseCallback& release_callback);
+
+ VideoFrameExternalResources CreateForSoftwarePlanes(
+ const scoped_refptr<media::VideoFrame>& video_frame);
+
+ private:
+ bool VerifyFrame(const scoped_refptr<media::VideoFrame>& video_frame);
+
+ static void ReturnTexture(ResourceProvider* resource_provider,
+ TextureMailbox::ReleaseCallback callback,
+ unsigned texture_id,
+ gpu::Mailbox mailbox,
+ unsigned sync_point);
+
+ ResourceProvider* resource_provider_;
+ scoped_ptr<media::SkCanvasVideoRenderer> video_renderer_;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoResourceUpdater);
+};
+
+} // namespace cc
+
+#endif // CC_RESOURCES_VIDEO_RESOURCE_UPDATER_H_
diff --git a/cc/test/render_pass_test_common.cc b/cc/test/render_pass_test_common.cc
index 7ceaef9..c4f6310 100644
--- a/cc/test/render_pass_test_common.cc
+++ b/cc/test/render_pass_test_common.cc
@@ -33,14 +33,6 @@ void TestRenderPass::AppendOneOfEveryQuadType(
gfx::Rect rect(0, 0, 100, 100);
gfx::Rect opaque_rect(10, 10, 80, 80);
const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
- cc::ResourceProvider::ResourceId texture_resource =
- resource_provider->CreateResource(
- gfx::Size(20, 12),
- resource_provider->best_texture_format(),
- ResourceProvider::TextureUsageAny);
- resource_provider->AllocateForTesting(texture_resource);
- unsigned texture_id = ResourceProvider::ScopedReadLockGL(
- resource_provider, texture_resource).texture_id();
cc::ResourceProvider::ResourceId resource1 =
resource_provider->CreateResource(
gfx::Size(45, 5),
@@ -71,6 +63,18 @@ void TestRenderPass::AppendOneOfEveryQuadType(
resource_provider->best_texture_format(),
ResourceProvider::TextureUsageAny);
resource_provider->AllocateForTesting(resource5);
+ cc::ResourceProvider::ResourceId resource6 =
+ resource_provider->CreateResource(
+ gfx::Size(64, 92),
+ resource_provider->best_texture_format(),
+ ResourceProvider::TextureUsageAny);
+ resource_provider->AllocateForTesting(resource6);
+ cc::ResourceProvider::ResourceId resource7 =
+ resource_provider->CreateResource(
+ gfx::Size(9, 14),
+ resource_provider->best_texture_format(),
+ ResourceProvider::TextureUsageAny);
+ resource_provider->AllocateForTesting(resource7);
scoped_ptr<cc::SharedQuadState> shared_state = cc::SharedQuadState::Create();
shared_state->SetAll(gfx::Transform(),
@@ -101,7 +105,7 @@ void TestRenderPass::AppendOneOfEveryQuadType(
rect,
opaque_rect,
gfx::Size(50, 50),
- texture_id,
+ resource7,
cc::IOSurfaceDrawQuad::FLIPPED);
AppendQuad(io_surface_quad.PassAs<DrawQuad>());
@@ -147,7 +151,7 @@ void TestRenderPass::AppendOneOfEveryQuadType(
stream_video_quad->SetNew(shared_state.get(),
rect,
opaque_rect,
- texture_id,
+ resource6,
gfx::Transform());
AppendQuad(stream_video_quad.PassAs<DrawQuad>());
@@ -202,16 +206,14 @@ void TestRenderPass::AppendOneOfEveryQuadType(
false);
AppendQuad(tile_quad.PassAs<DrawQuad>());
- cc::VideoLayerImpl::FramePlane planes[3];
+ ResourceProvider::ResourceId plane_resources[3];
for (int i = 0; i < 3; ++i) {
- planes[i].resource_id =
+ plane_resources[i] =
resource_provider->CreateResource(
gfx::Size(20, 12),
resource_provider->best_texture_format(),
ResourceProvider::TextureUsageAny);
- resource_provider->AllocateForTesting(planes[i].resource_id);
- planes[i].size = gfx::Size(100, 100);
- planes[i].format = GL_LUMINANCE;
+ resource_provider->AllocateForTesting(plane_resources[i]);
}
scoped_ptr<cc::YUVVideoDrawQuad> yuv_quad =
cc::YUVVideoDrawQuad::Create();
@@ -219,9 +221,9 @@ void TestRenderPass::AppendOneOfEveryQuadType(
rect,
opaque_rect,
gfx::Size(100, 100),
- planes[0],
- planes[1],
- planes[2]);
+ plane_resources[0],
+ plane_resources[1],
+ plane_resources[2]);
AppendQuad(yuv_quad.PassAs<DrawQuad>());
AppendSharedQuadState(transformed_state.Pass());
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc
index 0663f77..462f603 100644
--- a/cc/test/test_web_graphics_context_3d.cc
+++ b/cc/test/test_web_graphics_context_3d.cc
@@ -295,6 +295,19 @@ void TestWebGraphicsContext3D::getQueryObjectuivEXT(
*params = 1;
}
+
+void TestWebGraphicsContext3D::genMailboxCHROMIUM(WebKit::WGC3Dbyte* mailbox) {
+ static char mailbox_name1 = '1';
+ static char mailbox_name2 = '1';
+ mailbox[0] = mailbox_name1;
+ mailbox[1] = mailbox_name2;
+ mailbox[2] = '\0';
+ if (++mailbox_name1 == 0) {
+ mailbox_name1 = '1';
+ ++mailbox_name2;
+ }
+}
+
void TestWebGraphicsContext3D::setContextLostCallback(
WebGraphicsContextLostCallback* callback) {
context_lost_callback_ = callback;
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h
index 47f2054..82dd63e 100644
--- a/cc/test/test_web_graphics_context_3d.h
+++ b/cc/test/test_web_graphics_context_3d.h
@@ -89,6 +89,12 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D {
WebKit::WGC3Denum pname,
WebKit::WGC3Duint* params);
+ virtual void genMailboxCHROMIUM(WebKit::WGC3Dbyte* mailbox);
+ virtual void produceTextureCHROMIUM(WebKit::WGC3Denum target,
+ const WebKit::WGC3Dbyte* mailbox) { }
+ virtual void consumeTextureCHROMIUM(WebKit::WGC3Denum target,
+ const WebKit::WGC3Dbyte* mailbox) { }
+
virtual void setContextLostCallback(
WebGraphicsContextLostCallback* callback);
diff --git a/cc/trees/layer_tree_host_unittest_delegated.cc b/cc/trees/layer_tree_host_unittest_delegated.cc
index f16b2ef..b0bc59e 100644
--- a/cc/trees/layer_tree_host_unittest_delegated.cc
+++ b/cc/trees/layer_tree_host_unittest_delegated.cc
@@ -1108,6 +1108,9 @@ class LayerTreeHostDelegatedTestResourceSentToParent
TransferableResourceArray transferable_resources;
host_impl->resource_provider()->PrepareSendToParent(
resources_for_parent, &transferable_resources);
+
+ resource_in_grandparent = transferable_resources[0];
+ EXPECT_EQ(map.find(999)->second, resource_in_grandparent.id);
break;
}
case 2: {
@@ -1120,10 +1123,10 @@ class LayerTreeHostDelegatedTestResourceSentToParent
EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second));
// Receive 999 back from the grandparent.
- TransferableResource resource;
- resource.id = map.find(999)->second;
+ EXPECT_EQ(map.find(999)->second, resource_in_grandparent.id);
TransferableResourceArray transferable_resources;
- transferable_resources.push_back(resource);
+ transferable_resources.push_back(resource_in_grandparent);
+
host_impl->resource_provider()->ReceiveFromParent(
transferable_resources);
break;
@@ -1139,6 +1142,8 @@ class LayerTreeHostDelegatedTestResourceSentToParent
}
virtual void AfterTest() OVERRIDE {}
+
+ TransferableResource resource_in_grandparent;
};
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestResourceSentToParent);
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h
index 3cc7b9e..e12acf1 100644
--- a/content/common/cc_messages.h
+++ b/content/common/cc_messages.h
@@ -4,7 +4,6 @@
//
// IPC Messages sent between compositor instances.
-#include "cc/layers/video_layer_impl.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
#include "cc/quads/checkerboard_draw_quad.h"
@@ -115,12 +114,6 @@ IPC_STRUCT_TRAITS_BEGIN(cc::RenderPass::Id)
IPC_STRUCT_TRAITS_MEMBER(index)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(cc::VideoLayerImpl::FramePlane)
- IPC_STRUCT_TRAITS_MEMBER(resource_id)
- IPC_STRUCT_TRAITS_MEMBER(size)
- IPC_STRUCT_TRAITS_MEMBER(format)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(cc::DrawQuad)
IPC_STRUCT_TRAITS_MEMBER(material)
IPC_STRUCT_TRAITS_MEMBER(rect)
@@ -143,7 +136,7 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::IOSurfaceDrawQuad)
IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
IPC_STRUCT_TRAITS_MEMBER(io_surface_size)
- IPC_STRUCT_TRAITS_MEMBER(io_surface_texture_id)
+ IPC_STRUCT_TRAITS_MEMBER(io_surface_resource_id)
IPC_STRUCT_TRAITS_MEMBER(orientation)
IPC_STRUCT_TRAITS_END()
@@ -166,7 +159,7 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::StreamVideoDrawQuad)
IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
- IPC_STRUCT_TRAITS_MEMBER(texture_id)
+ IPC_STRUCT_TRAITS_MEMBER(resource_id)
IPC_STRUCT_TRAITS_MEMBER(matrix)
IPC_STRUCT_TRAITS_END()
@@ -194,9 +187,9 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::YUVVideoDrawQuad)
IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
IPC_STRUCT_TRAITS_MEMBER(tex_scale)
- IPC_STRUCT_TRAITS_MEMBER(y_plane)
- IPC_STRUCT_TRAITS_MEMBER(u_plane)
- IPC_STRUCT_TRAITS_MEMBER(v_plane)
+ IPC_STRUCT_TRAITS_MEMBER(y_plane_resource_id)
+ IPC_STRUCT_TRAITS_MEMBER(u_plane_resource_id)
+ IPC_STRUCT_TRAITS_MEMBER(v_plane_resource_id)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::SharedQuadState)
diff --git a/content/common/cc_messages_unittest.cc b/content/common/cc_messages_unittest.cc
index c665467..d442b23 100644
--- a/content/common/cc_messages_unittest.cc
+++ b/content/common/cc_messages_unittest.cc
@@ -122,7 +122,7 @@ class CCMessagesTest : public testing::Test {
void Compare(const IOSurfaceDrawQuad* a, const IOSurfaceDrawQuad* b) {
EXPECT_EQ(a->io_surface_size.ToString(), b->io_surface_size.ToString());
- EXPECT_EQ(a->io_surface_texture_id, b->io_surface_texture_id);
+ EXPECT_EQ(a->io_surface_resource_id, b->io_surface_resource_id);
EXPECT_EQ(a->orientation, b->orientation);
}
@@ -142,7 +142,7 @@ class CCMessagesTest : public testing::Test {
}
void Compare(const StreamVideoDrawQuad* a, const StreamVideoDrawQuad* b) {
- EXPECT_EQ(a->texture_id, b->texture_id);
+ EXPECT_EQ(a->resource_id, b->resource_id);
EXPECT_EQ(a->matrix, b->matrix);
}
@@ -167,15 +167,9 @@ class CCMessagesTest : public testing::Test {
void Compare(const YUVVideoDrawQuad* a, const YUVVideoDrawQuad* b) {
EXPECT_EQ(a->tex_scale, b->tex_scale);
- EXPECT_EQ(a->y_plane.resource_id, b->y_plane.resource_id);
- EXPECT_EQ(a->y_plane.size.ToString(), b->y_plane.size.ToString());
- EXPECT_EQ(a->y_plane.format, b->y_plane.format);
- EXPECT_EQ(a->u_plane.resource_id, b->u_plane.resource_id);
- EXPECT_EQ(a->u_plane.size.ToString(), b->u_plane.size.ToString());
- EXPECT_EQ(a->u_plane.format, b->u_plane.format);
- EXPECT_EQ(a->v_plane.resource_id, b->v_plane.resource_id);
- EXPECT_EQ(a->v_plane.size.ToString(), b->v_plane.size.ToString());
- EXPECT_EQ(a->v_plane.format, b->v_plane.format);
+ EXPECT_EQ(a->y_plane_resource_id, b->y_plane_resource_id);
+ EXPECT_EQ(a->u_plane_resource_id, b->u_plane_resource_id);
+ EXPECT_EQ(a->v_plane_resource_id, b->v_plane_resource_id);
}
void Compare(const TransferableResource& a, const TransferableResource& b) {
@@ -218,22 +212,9 @@ TEST_F(CCMessagesTest, AllQuads) {
IOSurfaceDrawQuad::Orientation arbitrary_orientation =
IOSurfaceDrawQuad::UNFLIPPED;
RenderPass::Id arbitrary_id(10, 14);
- ResourceProvider::ResourceId arbitrary_resourceid = 55;
-
- VideoLayerImpl::FramePlane arbitrary_plane1;
- arbitrary_plane1.resource_id = arbitrary_resourceid;
- arbitrary_plane1.size = arbitrary_size1;
- arbitrary_plane1.format = arbitrary_int;
-
- VideoLayerImpl::FramePlane arbitrary_plane2;
- arbitrary_plane2.resource_id = arbitrary_resourceid;
- arbitrary_plane2.size = arbitrary_size2;
- arbitrary_plane2.format = arbitrary_int;
-
- VideoLayerImpl::FramePlane arbitrary_plane3;
- arbitrary_plane3.resource_id = arbitrary_resourceid;
- arbitrary_plane3.size = arbitrary_size3;
- arbitrary_plane3.format = arbitrary_int;
+ ResourceProvider::ResourceId arbitrary_resourceid1 = 55;
+ ResourceProvider::ResourceId arbitrary_resourceid2 = 47;
+ ResourceProvider::ResourceId arbitrary_resourceid3 = 23;
WebFilterOperations arbitrary_filters1;
arbitrary_filters1.append(WebFilterOperation::createGrayscaleFilter(
@@ -286,7 +267,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect1,
arbitrary_bool1,
arbitrary_size1,
- arbitrary_int,
+ arbitrary_resourceid3,
arbitrary_orientation);
scoped_ptr<DrawQuad> iosurface_cmp = iosurface_in->Copy(
iosurface_in->shared_quad_state);
@@ -300,7 +281,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_bool1,
arbitrary_id,
arbitrary_bool2,
- arbitrary_resourceid,
+ arbitrary_resourceid2,
arbitrary_rect1,
arbitrary_rectf1,
arbitrary_filters1,
@@ -345,7 +326,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect3,
arbitrary_rect1,
arbitrary_bool1,
- arbitrary_int,
+ arbitrary_resourceid2,
arbitrary_matrix);
scoped_ptr<DrawQuad> streamvideo_cmp = streamvideo_in->Copy(
streamvideo_in->shared_quad_state);
@@ -356,7 +337,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect3,
arbitrary_rect1,
arbitrary_bool1,
- arbitrary_resourceid,
+ arbitrary_resourceid1,
arbitrary_bool2,
arbitrary_pointf1,
arbitrary_pointf2,
@@ -371,7 +352,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect3,
arbitrary_rect1,
arbitrary_bool1,
- arbitrary_resourceid,
+ arbitrary_resourceid3,
arbitrary_rectf1,
arbitrary_size1,
arbitrary_bool2);
@@ -386,9 +367,9 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect3,
arbitrary_bool1,
arbitrary_sizef1,
- arbitrary_plane1,
- arbitrary_plane2,
- arbitrary_plane3);
+ arbitrary_resourceid1,
+ arbitrary_resourceid2,
+ arbitrary_resourceid3);
scoped_ptr<DrawQuad> yuvvideo_cmp = yuvvideo_in->Copy(
yuvvideo_in->shared_quad_state);