<commit_before>// 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 "content/browser/android/in_process/synchronous_compositor_impl.h"

#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/lock.h"
#include "cc/input/input_handler.h"
#include "cc/input/layer_scroll_offset_delegate.h"
#include "content/browser/android/in_process/synchronous_input_event_filter.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/public/browser/android/synchronous_compositor_client.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/renderer/android/synchronous_compositor_factory.h"
#include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h"
#include "gpu/command_buffer/client/gl_in_process_context.h"
#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h"
#include "ui/gl/android/surface_texture.h"
#include "ui/gl/gl_surface.h"
#include "webkit/common/gpu/context_provider_in_process.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"

namespace content {

namespace {

using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;

int GetInProcessRendererId() {
  content::RenderProcessHost::iterator it =
      content::RenderProcessHost::AllHostsIterator();
  if (it.IsAtEnd()) {
    // There should always be one RPH in single process mode.
    NOTREACHED();
    return 0;
  }

  int id = it.GetCurrentValue()->GetID();
  it.Advance();
  DCHECK(it.IsAtEnd());  // Not multiprocess compatible.
  return id;
}

class VideoContextProvider
    : public StreamTextureFactorySynchronousImpl::ContextProvider {
 public:
  VideoContextProvider(
      const scoped_refptr<cc::ContextProvider>& context_provider,
      gpu::GLInProcessContext* gl_in_process_context)
      : context_provider_(context_provider),
        gl_in_process_context_(gl_in_process_context) {}

  virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
      uint32 stream_id) OVERRIDE {
    return gl_in_process_context_->GetSurfaceTexture(stream_id);
  }

  virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
    return context_provider_->Context3d();
  }

 private:
  friend class base::RefCountedThreadSafe<VideoContextProvider>;
  virtual ~VideoContextProvider() {}

  scoped_refptr<cc::ContextProvider> context_provider_;
  gpu::GLInProcessContext* gl_in_process_context_;

  DISALLOW_COPY_AND_ASSIGN(VideoContextProvider);
};

class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
 public:
  SynchronousCompositorFactoryImpl()
      : wrapped_gl_context_for_main_thread_(NULL),
        num_hardware_compositors_(0) {
    SynchronousCompositorFactory::SetInstance(this);
  }

  // SynchronousCompositorFactory
  virtual scoped_refptr<base::MessageLoopProxy>
      GetCompositorMessageLoop() OVERRIDE {
    return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
  }

  virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
      int routing_id) OVERRIDE {
    scoped_ptr<SynchronousCompositorOutputSurface> output_surface(
        new SynchronousCompositorOutputSurface(routing_id));
    return output_surface.PassAs<cc::OutputSurface>();
  }

  virtual InputHandlerManagerClient* GetInputHandlerManagerClient() OVERRIDE {
    return synchronous_input_event_filter();
  }

  SynchronousInputEventFilter* synchronous_input_event_filter() {
    return &synchronous_input_event_filter_;
  }

  scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
  CreateOffscreenContext() {
    if (!gfx::GLSurface::InitializeOneOff())
      return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();

    const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;

    WebKit::WebGraphicsContext3D::Attributes attributes;
    attributes.antialias = false;
    attributes.shareResources = true;
    attributes.noAutomaticFlushes = true;

    gpu::GLInProcessContextAttribs in_process_attribs;
    WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
        attributes, &in_process_attribs);
    scoped_ptr<gpu::GLInProcessContext> context(
        gpu::GLInProcessContext::CreateContext(true,
                                               NULL,
                                               gfx::Size(1, 1),
                                               attributes.shareResources,
                                               in_process_attribs,
                                               gpu_preference));

    wrapped_gl_context_for_main_thread_ = context.get();
    if (!context.get())
      return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();

    return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(
        WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
            context.Pass(), attributes));
  }

  virtual scoped_refptr<cc::ContextProvider>
  GetOffscreenContextProviderForMainThread() OVERRIDE {
    // This check only guarantees the main thread context is created after
    // a compositor did successfully initialize hardware draw in the past.
    // In particular this does not guarantee that the main thread context
    // will fail creation when all compositors release hardware draw.
    bool failed = !CanCreateMainThreadContext();
    if (!failed &&
        (!offscreen_context_for_main_thread_.get() ||
         offscreen_context_for_main_thread_->DestroyedOnMainThread())) {
      offscreen_context_for_main_thread_ =
          webkit::gpu::ContextProviderInProcess::Create(
              CreateOffscreenContext(),
              "Compositor-Offscreen");
      failed = !offscreen_context_for_main_thread_.get() ||
               !offscreen_context_for_main_thread_->BindToCurrentThread();
    }

    if (failed) {
      offscreen_context_for_main_thread_ = NULL;
      wrapped_gl_context_for_main_thread_ = NULL;
    }
    return offscreen_context_for_main_thread_;
  }

  // This is called on both renderer main thread (offscreen context creation
  // path shared between cross-process and in-process platforms) and renderer
  // compositor impl thread (InitializeHwDraw) in order to support Android
  // WebView synchronously enable and disable hardware mode multiple times in
  // the same task. This is ok because in-process WGC3D creation may happen on
  // any thread and is lightweight.
  virtual scoped_refptr<cc::ContextProvider>
      GetOffscreenContextProviderForCompositorThread() OVERRIDE {
    base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
    if (!offscreen_context_for_compositor_thread_.get() ||
        offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) {
      offscreen_context_for_compositor_thread_ =
          webkit::gpu::ContextProviderInProcess::CreateOffscreen();
    }
    return offscreen_context_for_compositor_thread_;
  }

  virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory(
      int view_id) OVERRIDE {
    scoped_refptr<VideoContextProvider> context_provider;
    if (CanCreateMainThreadContext()) {
      context_provider =
          new VideoContextProvider(offscreen_context_for_main_thread_,
                                   wrapped_gl_context_for_main_thread_);
    }
    return make_scoped_ptr(new StreamTextureFactorySynchronousImpl(
                               context_provider.get(), view_id))
        .PassAs<StreamTextureFactory>();
  }

  void CompositorInitializedHardwareDraw(SynchronousCompositorImpl* compositor);
  void CompositorReleasedHardwareDraw(SynchronousCompositorImpl* compositor);

 private:
  void ReleaseGlobalHardwareResources();
  bool CanCreateMainThreadContext();
<commit_msg>[Android WebView] Fix NPE in video when context creation fails<commit_after>// 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 "content/browser/android/in_process/synchronous_compositor_impl.h"

#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/lock.h"
#include "cc/input/input_handler.h"
#include "cc/input/layer_scroll_offset_delegate.h"
#include "content/browser/android/in_process/synchronous_input_event_filter.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/public/browser/android/synchronous_compositor_client.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/renderer/android/synchronous_compositor_factory.h"
#include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h"
#include "gpu/command_buffer/client/gl_in_process_context.h"
#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h"
#include "ui/gl/android/surface_texture.h"
#include "ui/gl/gl_surface.h"
#include "webkit/common/gpu/context_provider_in_process.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"

namespace content {

namespace {

using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;

int GetInProcessRendererId() {
  content::RenderProcessHost::iterator it =
      content::RenderProcessHost::AllHostsIterator();
  if (it.IsAtEnd()) {
    // There should always be one RPH in single process mode.
    NOTREACHED();
    return 0;
  }

  int id = it.GetCurrentValue()->GetID();
  it.Advance();
  DCHECK(it.IsAtEnd());  // Not multiprocess compatible.
  return id;
}

class VideoContextProvider
    : public StreamTextureFactorySynchronousImpl::ContextProvider {
 public:
  VideoContextProvider(
      const scoped_refptr<cc::ContextProvider>& context_provider,
      gpu::GLInProcessContext* gl_in_process_context)
      : context_provider_(context_provider),
        gl_in_process_context_(gl_in_process_context) {}

  virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
      uint32 stream_id) OVERRIDE {
    return gl_in_process_context_->GetSurfaceTexture(stream_id);
  }

  virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
    return context_provider_->Context3d();
  }

 private:
  friend class base::RefCountedThreadSafe<VideoContextProvider>;
  virtual ~VideoContextProvider() {}

  scoped_refptr<cc::ContextProvider> context_provider_;
  gpu::GLInProcessContext* gl_in_process_context_;

  DISALLOW_COPY_AND_ASSIGN(VideoContextProvider);
};

class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
 public:
  SynchronousCompositorFactoryImpl()
      : wrapped_gl_context_for_main_thread_(NULL),
        num_hardware_compositors_(0) {
    SynchronousCompositorFactory::SetInstance(this);
  }

  // SynchronousCompositorFactory
  virtual scoped_refptr<base::MessageLoopProxy>
      GetCompositorMessageLoop() OVERRIDE {
    return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
  }

  virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
      int routing_id) OVERRIDE {
    scoped_ptr<SynchronousCompositorOutputSurface> output_surface(
        new SynchronousCompositorOutputSurface(routing_id));
    return output_surface.PassAs<cc::OutputSurface>();
  }

  virtual InputHandlerManagerClient* GetInputHandlerManagerClient() OVERRIDE {
    return synchronous_input_event_filter();
  }

  SynchronousInputEventFilter* synchronous_input_event_filter() {
    return &synchronous_input_event_filter_;
  }

  scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
  CreateOffscreenContext() {
    if (!gfx::GLSurface::InitializeOneOff())
      return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();

    const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;

    WebKit::WebGraphicsContext3D::Attributes attributes;
    attributes.antialias = false;
    attributes.shareResources = true;
    attributes.noAutomaticFlushes = true;

    gpu::GLInProcessContextAttribs in_process_attribs;
    WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
        attributes, &in_process_attribs);
    scoped_ptr<gpu::GLInProcessContext> context(
        gpu::GLInProcessContext::CreateContext(true,
                                               NULL,
                                               gfx::Size(1, 1),
                                               attributes.shareResources,
                                               in_process_attribs,
                                               gpu_preference));

    wrapped_gl_context_for_main_thread_ = context.get();
    if (!context.get())
      return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>();

    return scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>(
        WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
            context.Pass(), attributes));
  }

  virtual scoped_refptr<cc::ContextProvider>
  GetOffscreenContextProviderForMainThread() OVERRIDE {
    // This check only guarantees the main thread context is created after
    // a compositor did successfully initialize hardware draw in the past.
    // In particular this does not guarantee that the main thread context
    // will fail creation when all compositors release hardware draw.
    bool failed = !CanCreateMainThreadContext();
    if (!failed &&
        (!offscreen_context_for_main_thread_.get() ||
         offscreen_context_for_main_thread_->DestroyedOnMainThread())) {
      offscreen_context_for_main_thread_ =
          webkit::gpu::ContextProviderInProcess::Create(
              CreateOffscreenContext(),
              "Compositor-Offscreen");
      failed = !offscreen_context_for_main_thread_.get() ||
               !offscreen_context_for_main_thread_->BindToCurrentThread();
    }

    if (failed) {
      offscreen_context_for_main_thread_ = NULL;
      wrapped_gl_context_for_main_thread_ = NULL;
    }
    return offscreen_context_for_main_thread_;
  }

  // This is called on both renderer main thread (offscreen context creation
  // path shared between cross-process and in-process platforms) and renderer
  // compositor impl thread (InitializeHwDraw) in order to support Android
  // WebView synchronously enable and disable hardware mode multiple times in
  // the same task. This is ok because in-process WGC3D creation may happen on
  // any thread and is lightweight.
  virtual scoped_refptr<cc::ContextProvider>
      GetOffscreenContextProviderForCompositorThread() OVERRIDE {
    base::AutoLock lock(offscreen_context_for_compositor_thread_lock_);
    if (!offscreen_context_for_compositor_thread_.get() ||
        offscreen_context_for_compositor_thread_->DestroyedOnMainThread()) {
      offscreen_context_for_compositor_thread_ =
          webkit::gpu::ContextProviderInProcess::CreateOffscreen();
    }
    return offscreen_context_for_compositor_thread_;
  }

  virtual scoped_ptr<StreamTextureFactory> CreateStreamTextureFactory(
      int view_id) OVERRIDE {
    scoped_refptr<VideoContextProvider> context_provider;
    if (CanCreateMainThreadContext() && offscreen_context_for_main_thread_) {
      DCHECK(wrapped_gl_context_for_main_thread_);
      context_provider =
          new VideoContextProvider(offscreen_context_for_main_thread_,
                                   wrapped_gl_context_for_main_thread_);
    }
    return make_scoped_ptr(new StreamTextureFactorySynchronousImpl(
                               context_provider.get(), view_id))
        .PassAs<StreamTextureFactory>();
  }

  void CompositorInitializedHardwareDraw(SynchronousCompositorImpl* compositor);
  void CompositorReleasedHardwareDraw(SynchronousCompositorImpl* compositor);

 private:
  void ReleaseGlobalHardwareResources();
  bool CanCreateMainThreadContext();

{'fraction_non_alphanumeric': 0.08097191150882425, 'fraction_numerical': 0.002858563261247825, 'mean_word_length': 4.3732888146911515, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7659931', 'n_tokens_mistral': 4611, 'n_tokens_neox': 4530, 'n_words': 791}