| Index: wm/gpu/foreign_window_texture_factory.cc
|
| diff --git a/wm/gpu/foreign_window_texture_factory.cc b/wm/gpu/foreign_window_texture_factory.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8e552a9af122ad529a042d3f679362fedba65d24
|
| --- /dev/null
|
| +++ b/wm/gpu/foreign_window_texture_factory.cc
|
| @@ -0,0 +1,240 @@
|
| +// Copyright (c) 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 "wm/gpu/foreign_window_texture_factory.h"
|
| +
|
| +#include "base/lazy_instance.h"
|
| +#include "base/observer_list.h"
|
| +#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
|
| +#include "content/common/gpu/client/gl_helper.h"
|
| +#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
|
| +#include "third_party/khronos/GLES2/gl2.h"
|
| +#include "ui/compositor/compositor_setup.h"
|
| +
|
| +namespace {
|
| +
|
| +class DefaultGpuChannelHostFactory : public content::GpuChannelHostFactory {
|
| + public:
|
| + DefaultGpuChannelHostFactory() {}
|
| +
|
| + virtual bool IsMainThread() OVERRIDE {
|
| + return false;
|
| + }
|
| + virtual bool IsIOThread() OVERRIDE {
|
| + return false;
|
| + }
|
| + virtual MessageLoop* GetMainLoop() OVERRIDE {
|
| + return NULL;
|
| + }
|
| + virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() OVERRIDE {
|
| + return NULL;
|
| + }
|
| + virtual base::WaitableEvent* GetShutDownEvent() OVERRIDE { return NULL; }
|
| + virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(
|
| + size_t size) OVERRIDE {
|
| + return scoped_ptr<base::SharedMemory>();
|
| + }
|
| + virtual int32 CreateViewCommandBuffer(
|
| + int32 surface_id,
|
| + const GPUCreateCommandBufferConfig& init_params) OVERRIDE {
|
| + return 0;
|
| + }
|
| + virtual content::GpuChannelHost* EstablishGpuChannelSync(
|
| + content::CauseForGpuLaunch) OVERRIDE {
|
| + return NULL;
|
| + }
|
| + virtual void CreateImage(
|
| + gfx::PluginWindowHandle window_handle,
|
| + int32 image_id,
|
| + const CreateImageCallback& callback) OVERRIDE {
|
| + callback.Run(gfx::Size());
|
| + }
|
| + virtual void DeleteImage(int32 image_id, int32 sync_point) OVERRIDE {}
|
| +};
|
| +
|
| +base::LazyInstance<DefaultGpuChannelHostFactory> g_default_factory =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +} // namespace
|
| +
|
| +namespace wm {
|
| +
|
| +// static
|
| +ForeignWindowTextureFactory* ForeignWindowTextureFactory::instance_ = NULL;
|
| +
|
| +ForeignWindowTexture::ForeignWindowTexture(
|
| + content::GpuChannelHostFactory* factory,
|
| + WebKit::WebGraphicsContext3D* host_context,
|
| + bool flipped,
|
| + const gfx::Size& size,
|
| + float device_scale_factor,
|
| + int32 image_id)
|
| + : ui::Texture(flipped, size, device_scale_factor),
|
| + factory_(factory),
|
| + host_context_(host_context),
|
| + image_id_(image_id),
|
| + texture_id_(0),
|
| + contents_changed_(true) {
|
| + ForeignWindowTextureFactory::GetInstance()->AddObserver(this);
|
| +}
|
| +
|
| +ForeignWindowTexture::~ForeignWindowTexture() {
|
| + ForeignWindowTextureFactory::GetInstance()->RemoveObserver(this);
|
| + if (texture_id_)
|
| + host_context_->deleteTexture(texture_id_);
|
| + if (image_id_ && !host_context_->isContextLost()) {
|
| + factory_->DeleteImage(image_id_,
|
| + texture_id_ ? host_context_->insertSyncPoint() : 0);
|
| + }
|
| +}
|
| +
|
| +unsigned int ForeignWindowTexture::PrepareTexture() {
|
| + if (contents_changed_) {
|
| + unsigned texture_id = texture_id_;
|
| +
|
| + if (!texture_id)
|
| + texture_id = host_context_->createTexture();
|
| +
|
| + host_context_->bindTexture(GL_TEXTURE_2D, texture_id);
|
| + if (texture_id_)
|
| + host_context_->releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id_);
|
| + host_context_->bindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id_);
|
| + host_context_->bindTexture(GL_TEXTURE_2D, 0);
|
| + host_context_->flush();
|
| +
|
| + texture_id_ = texture_id;
|
| + contents_changed_ = false;
|
| + }
|
| +
|
| + return texture_id_;
|
| +}
|
| +
|
| +WebKit::WebGraphicsContext3D* ForeignWindowTexture::HostContext3D() {
|
| + DCHECK(host_context_); // This should never be called after lost context.
|
| + return host_context_;
|
| +}
|
| +
|
| +void ForeignWindowTexture::OnLostResources() {
|
| + if (texture_id_) {
|
| + host_context_->deleteTexture(texture_id_);
|
| + texture_id_ = 0;
|
| + }
|
| + contents_changed_ = false;
|
| + image_id_ = 0;
|
| + host_context_ = NULL;
|
| +}
|
| +
|
| +void ForeignWindowTexture::OnContentsChanged() {
|
| + if (image_id_)
|
| + contents_changed_ = true;
|
| +}
|
| +
|
| +ForeignWindowTextureFactory::ForeignWindowTextureFactory(
|
| + content::GpuChannelHostFactory* factory) : factory_(factory) {
|
| + DCHECK(factory);
|
| + DCHECK(content::ImageTransportFactory::GetInstance());
|
| + content::ImageTransportFactory::GetInstance()->AddObserver(this);
|
| +}
|
| +
|
| +ForeignWindowTextureFactory::~ForeignWindowTextureFactory() {
|
| + content::ImageTransportFactory::GetInstance()->RemoveObserver(this);
|
| +}
|
| +
|
| +void ForeignWindowTextureFactory::OnLostResources() {
|
| + content::ImageTransportFactory* transport_factory =
|
| + content::ImageTransportFactory::GetInstance();
|
| + // Make sure a new gpu channel is established before any calls to
|
| + // CreateTextureForForeignWindow() are made.
|
| + WebKit::WebGraphicsContext3D* context =
|
| + transport_factory->GetGLHelper()->context();
|
| + CHECK(context);
|
| +
|
| + FOR_EACH_OBSERVER(ForeignWindowTextureFactoryObserver,
|
| + observer_list_,
|
| + OnLostResources());
|
| +}
|
| +
|
| +void ForeignWindowTextureFactory::CreateTextureForForeignWindow(
|
| + gfx::PluginWindowHandle window_handle,
|
| + bool flipped,
|
| + float device_scale_factor,
|
| + const CreateTextureCallback& callback) {
|
| + DCHECK(window_handle);
|
| +
|
| + int32 image_id = GenerateImageID();
|
| + factory_->CreateImage(
|
| + window_handle,
|
| + image_id,
|
| + base::Bind(&ForeignWindowTextureFactory::OnImageCreated,
|
| + base::Unretained(this),
|
| + callback,
|
| + flipped,
|
| + device_scale_factor,
|
| + image_id));
|
| +}
|
| +
|
| +void ForeignWindowTextureFactory::AddObserver(
|
| + ForeignWindowTextureFactoryObserver* observer) {
|
| + observer_list_.AddObserver(observer);
|
| +}
|
| +
|
| +void ForeignWindowTextureFactory::RemoveObserver(
|
| + ForeignWindowTextureFactoryObserver* observer) {
|
| + observer_list_.RemoveObserver(observer);
|
| +}
|
| +
|
| +int ForeignWindowTextureFactory::GenerateImageID() {
|
| + static unsigned int image_id = 0;
|
| + return ++image_id;
|
| +}
|
| +
|
| +void ForeignWindowTextureFactory::OnImageCreated(
|
| + const CreateTextureCallback& callback,
|
| + bool flipped,
|
| + float device_scale_factor,
|
| + int32 image_id,
|
| + const gfx::Size size) {
|
| + if (size.IsEmpty()) {
|
| + callback.Run(NULL);
|
| + return;
|
| + }
|
| +
|
| + content::ImageTransportFactory* transport_factory =
|
| + content::ImageTransportFactory::GetInstance();
|
| + scoped_refptr<ForeignWindowTexture> texture(
|
| + new ForeignWindowTexture(factory_,
|
| + transport_factory->GetGLHelper()->context(),
|
| + flipped,
|
| + size,
|
| + device_scale_factor,
|
| + image_id));
|
| +
|
| + callback.Run(texture);
|
| +}
|
| +
|
| +// static
|
| +void ForeignWindowTextureFactory::Initialize() {
|
| + CHECK(!instance_);
|
| + if (ui::IsTestCompositorEnabled()) {
|
| + instance_ = new ForeignWindowTextureFactory(&g_default_factory.Get());
|
| + } else {
|
| + instance_ = new ForeignWindowTextureFactory(
|
| + content::BrowserGpuChannelHostFactory::instance());
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void ForeignWindowTextureFactory::Terminate() {
|
| + CHECK(instance_);
|
| + delete instance_;
|
| + instance_ = NULL;
|
| +}
|
| +
|
| +// static
|
| +ForeignWindowTextureFactory* ForeignWindowTextureFactory::GetInstance() {
|
| + DCHECK(instance_);
|
| + return instance_;
|
| +}
|
| +
|
| +} // namespace wm
|
|
|