| Index: ui/gfx/compositor/compositor.cc
|
| diff --git a/ui/gfx/compositor/compositor.cc b/ui/gfx/compositor/compositor.cc
|
| index 4fbd94cc4e54a5dd14e1721731a2a19334b39bad..6dd9fc3e576d8538b40903321c2f4a54bae10b5b 100644
|
| --- a/ui/gfx/compositor/compositor.cc
|
| +++ b/ui/gfx/compositor/compositor.cc
|
| @@ -4,31 +4,175 @@
|
|
|
| #include "ui/gfx/compositor/compositor.h"
|
|
|
| +#include "base/command_line.h"
|
| +#include "third_party/skia/include/images/SkImageEncoder.h"
|
| +#include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositor.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatPoint.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
|
| #include "ui/gfx/compositor/compositor_observer.h"
|
| +#include "ui/gfx/compositor/compositor_switches.h"
|
| +#include "ui/gfx/compositor/test_web_graphics_context_3d.h"
|
| #include "ui/gfx/compositor/layer.h"
|
| +#include "ui/gfx/gl/gl_context.h"
|
| +#include "ui/gfx/gl/gl_surface.h"
|
| +#include "ui/gfx/gl/gl_implementation.h"
|
| +#include "ui/gfx/gl/scoped_make_current.h"
|
| +#include "webkit/glue/webthread_impl.h"
|
| +#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
|
| +
|
| +namespace {
|
| +
|
| +const double kDefaultRefreshRate = 60.0;
|
| +const double kTestRefreshRate = 100.0;
|
| +
|
| +webkit_glue::WebThreadImpl* g_compositor_thread = NULL;
|
| +
|
| +bool test_compositor_enabled = false;
|
| +
|
| +} // anonymous namespace
|
|
|
| namespace ui {
|
|
|
| -TextureDrawParams::TextureDrawParams()
|
| - : blend(false),
|
| - has_valid_alpha_channel(false),
|
| - opacity(1.0f),
|
| - vertically_flipped(false) {
|
| +SharedResources::SharedResources() : initialized_(false) {
|
| +}
|
| +
|
| +
|
| +SharedResources::~SharedResources() {
|
| +}
|
| +
|
| +// static
|
| +SharedResources* SharedResources::GetInstance() {
|
| + // We use LeakySingletonTraits so that we don't race with
|
| + // the tear down of the gl_bindings.
|
| + SharedResources* instance = Singleton<SharedResources,
|
| + LeakySingletonTraits<SharedResources> >::get();
|
| + if (instance->Initialize()) {
|
| + return instance;
|
| + } else {
|
| + instance->Destroy();
|
| + return NULL;
|
| + }
|
| +}
|
| +
|
| +bool SharedResources::Initialize() {
|
| + if (initialized_)
|
| + return true;
|
| +
|
| + {
|
| + // The following line of code exists soley to disable IO restrictions
|
| + // on this thread long enough to perform the GL bindings.
|
| + // TODO(wjmaclean) Remove this when GL initialisation cleaned up.
|
| + base::ThreadRestrictions::ScopedAllowIO allow_io;
|
| + if (!gfx::GLSurface::InitializeOneOff() ||
|
| + gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
|
| + LOG(ERROR) << "Could not load the GL bindings";
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1));
|
| + if (!surface_.get()) {
|
| + LOG(ERROR) << "Unable to create offscreen GL surface.";
|
| + return false;
|
| + }
|
| +
|
| + context_ = gfx::GLContext::CreateGLContext(
|
| + NULL, surface_.get(), gfx::PreferIntegratedGpu);
|
| + if (!context_.get()) {
|
| + LOG(ERROR) << "Unable to create GL context.";
|
| + return false;
|
| + }
|
| +
|
| + initialized_ = true;
|
| + return true;
|
| +}
|
| +
|
| +void SharedResources::Destroy() {
|
| + context_ = NULL;
|
| + surface_ = NULL;
|
| +
|
| + initialized_ = false;
|
| +}
|
| +
|
| +gfx::ScopedMakeCurrent* SharedResources::GetScopedMakeCurrent() {
|
| + DCHECK(initialized_);
|
| + if (initialized_)
|
| + return new gfx::ScopedMakeCurrent(context_.get(), surface_.get());
|
| + else
|
| + return NULL;
|
| +}
|
| +
|
| +void* SharedResources::GetDisplay() {
|
| + return surface_->GetDisplay();
|
| +}
|
| +
|
| +gfx::GLShareGroup* SharedResources::GetShareGroup() {
|
| + DCHECK(initialized_);
|
| + return context_->share_group();
|
| +}
|
| +
|
| +Texture::Texture()
|
| + : texture_id_(0),
|
| + flipped_(false) {
|
| +}
|
| +
|
| +Texture::~Texture() {
|
| }
|
|
|
| -Compositor::Compositor(CompositorDelegate* delegate, const gfx::Size& size)
|
| +Compositor::Compositor(CompositorDelegate* delegate,
|
| + gfx::AcceleratedWidget widget,
|
| + const gfx::Size& size)
|
| : delegate_(delegate),
|
| size_(size),
|
| - root_layer_(NULL) {
|
| + root_layer_(NULL),
|
| + widget_(widget),
|
| + root_web_layer_(WebKit::WebLayer::create()) {
|
| + WebKit::WebLayerTreeView::Settings settings;
|
| + CommandLine* command_line = CommandLine::ForCurrentProcess();
|
| + settings.showFPSCounter =
|
| + command_line->HasSwitch(switches::kUIShowFPSCounter);
|
| + settings.showPlatformLayerTree =
|
| + command_line->HasSwitch(switches::kUIShowLayerTree);
|
| + settings.refreshRate = test_compositor_enabled ?
|
| + kTestRefreshRate : kDefaultRefreshRate;
|
| + settings.partialSwapEnabled =
|
| + command_line->HasSwitch(switches::kUIEnablePartialSwap);
|
| +
|
| + host_ = WebKit::WebLayerTreeView::create(this, root_web_layer_, settings);
|
| + root_web_layer_.setAnchorPoint(WebKit::WebFloatPoint(0.f, 0.f));
|
| + WidgetSizeChanged(size_);
|
| }
|
|
|
| Compositor::~Compositor() {
|
| + // There's a cycle between |root_web_layer_| and |host_|, which results in
|
| + // leaking and/or crashing. Explicitly set the root layer to NULL so the cycle
|
| + // is broken.
|
| + host_.setRootLayer(NULL);
|
| if (root_layer_)
|
| root_layer_->SetCompositor(NULL);
|
| }
|
|
|
| +void Compositor::Initialize(bool use_thread) {
|
| + if (use_thread)
|
| + g_compositor_thread = new webkit_glue::WebThreadImpl("Browser Compositor");
|
| + WebKit::WebCompositor::initialize(g_compositor_thread);
|
| +}
|
| +
|
| +void Compositor::Terminate() {
|
| + WebKit::WebCompositor::shutdown();
|
| + if (g_compositor_thread) {
|
| + delete g_compositor_thread;
|
| + g_compositor_thread = NULL;
|
| + }
|
| +}
|
| +
|
| void Compositor::ScheduleDraw() {
|
| - delegate_->ScheduleDraw();
|
| + if (g_compositor_thread)
|
| + host_.composite();
|
| + else
|
| + delegate_->ScheduleDraw();
|
| }
|
|
|
| void Compositor::SetRootLayer(Layer* root_layer) {
|
| @@ -39,18 +183,46 @@ void Compositor::SetRootLayer(Layer* root_layer) {
|
| root_layer_ = root_layer;
|
| if (root_layer_ && !root_layer_->GetCompositor())
|
| root_layer_->SetCompositor(this);
|
| - OnRootLayerChanged();
|
| + root_web_layer_.removeAllChildren();
|
| + if (root_layer_)
|
| + root_web_layer_.addChild(root_layer_->web_layer());
|
| }
|
|
|
| void Compositor::Draw(bool force_clear) {
|
| if (!root_layer_)
|
| return;
|
|
|
| - NotifyStart(force_clear);
|
| - DrawTree();
|
| - if (!CompositesAsynchronously()) {
|
| + host_.composite();
|
| + if (!g_compositor_thread)
|
| NotifyEnd();
|
| +}
|
| +
|
| +bool Compositor::ReadPixels(SkBitmap* bitmap, const gfx::Rect& bounds) {
|
| + if (bounds.right() > size().width() || bounds.bottom() > size().height())
|
| + return false;
|
| + // Convert to OpenGL coordinates.
|
| + gfx::Point new_origin(bounds.x(),
|
| + size().height() - bounds.height() - bounds.y());
|
| +
|
| + bitmap->setConfig(SkBitmap::kARGB_8888_Config,
|
| + bounds.width(), bounds.height());
|
| + bitmap->allocPixels();
|
| + SkAutoLockPixels lock_image(*bitmap);
|
| + unsigned char* pixels = static_cast<unsigned char*>(bitmap->getPixels());
|
| + if (host_.compositeAndReadback(pixels,
|
| + gfx::Rect(new_origin, bounds.size()))) {
|
| + SwizzleRGBAToBGRAAndFlip(pixels, bounds.size());
|
| + return true;
|
| }
|
| + return false;
|
| +}
|
| +
|
| +void Compositor::WidgetSizeChanged(const gfx::Size& size) {
|
| + if (size.IsEmpty())
|
| + return;
|
| + size_ = size;
|
| + host_.setViewportSize(size_);
|
| + root_web_layer_.setBounds(size_);
|
| }
|
|
|
| void Compositor::AddObserver(CompositorObserver* observer) {
|
| @@ -65,15 +237,60 @@ bool Compositor::HasObserver(CompositorObserver* observer) {
|
| return observer_list_.HasObserver(observer);
|
| }
|
|
|
| -void Compositor::OnRootLayerChanged() {
|
| - ScheduleDraw();
|
| +
|
| +void Compositor::updateAnimations(double frameBeginTime) {
|
| }
|
|
|
| -void Compositor::DrawTree() {
|
| +void Compositor::layout() {
|
| }
|
|
|
| -bool Compositor::CompositesAsynchronously() {
|
| - return false;
|
| +void Compositor::applyScrollAndScale(const WebKit::WebSize& scrollDelta,
|
| + float scaleFactor) {
|
| +}
|
| +
|
| +WebKit::WebGraphicsContext3D* Compositor::createContext3D() {
|
| + WebKit::WebGraphicsContext3D* context;
|
| + if (test_compositor_enabled) {
|
| + // Use context that results in no rendering to the screen.
|
| + context = new TestWebGraphicsContext3D();
|
| + } else {
|
| +#if defined(OS_MACOSX) && !defined(USE_AURA)
|
| + // Non-Aura builds compile this code but doesn't call it. Unfortunately
|
| + // this is where we translate gfx::AcceleratedWidget to
|
| + // gfx::PluginWindowHandle, and they are different on non-Aura Mac.
|
| + // TODO(piman): remove ifdefs when AcceleratedWidget is rationalized on Mac.
|
| + NOTIMPLEMENTED();
|
| + return NULL;
|
| +#else
|
| + gfx::GLShareGroup* share_group =
|
| + SharedResources::GetInstance()->GetShareGroup();
|
| + context = new webkit::gpu::WebGraphicsContext3DInProcessImpl(
|
| + widget_, share_group);
|
| +#endif
|
| + }
|
| + WebKit::WebGraphicsContext3D::Attributes attrs;
|
| + context->initialize(attrs, 0, true);
|
| +
|
| + CommandLine* command_line = CommandLine::ForCurrentProcess();
|
| + if (!command_line->HasSwitch(switches::kDisableUIVsync)) {
|
| + context->makeContextCurrent();
|
| + gfx::GLContext* gl_context = gfx::GLContext::GetCurrent();
|
| + gl_context->SetSwapInterval(1);
|
| + gl_context->ReleaseCurrent(NULL);
|
| + }
|
| +
|
| + return context;
|
| +}
|
| +
|
| +void Compositor::didCompleteSwapBuffers() {
|
| + NotifyEnd();
|
| +}
|
| +
|
| +void Compositor::didRebindGraphicsContext(bool success) {
|
| +}
|
| +
|
| +void Compositor::scheduleComposite() {
|
| + ScheduleDraw();
|
| }
|
|
|
| void Compositor::SwizzleRGBAToBGRAAndFlip(unsigned char* pixels,
|
| @@ -100,14 +317,20 @@ void Compositor::SwizzleRGBAToBGRAAndFlip(unsigned char* pixels,
|
| }
|
|
|
| void Compositor::NotifyEnd() {
|
| - OnNotifyEnd();
|
| FOR_EACH_OBSERVER(CompositorObserver,
|
| observer_list_,
|
| OnCompositingEnded(this));
|
| }
|
|
|
| -void Compositor::NotifyStart(bool clear) {
|
| - OnNotifyStart(clear);
|
| +COMPOSITOR_EXPORT void SetupTestCompositor() {
|
| + if (!CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kDisableTestCompositor)) {
|
| + test_compositor_enabled = true;
|
| + }
|
| +}
|
| +
|
| +COMPOSITOR_EXPORT void DisableTestCompositor() {
|
| + test_compositor_enabled = false;
|
| }
|
|
|
| } // namespace ui
|
|
|