C++程序  |  221行  |  7.84 KB

// Copyright 2012 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_OUTPUT_OUTPUT_SURFACE_H_
#define CC_OUTPUT_OUTPUT_SURFACE_H_

#include <deque>

#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/output/context_provider.h"
#include "cc/output/software_output_device.h"
#include "cc/scheduler/frame_rate_controller.h"
#include "cc/scheduler/rolling_time_delta_history.h"

namespace base { class SingleThreadTaskRunner; }

namespace ui { struct LatencyInfo; }

namespace gfx {
class Rect;
class Size;
class Transform;
}

namespace cc {

class CompositorFrame;
class CompositorFrameAck;
struct ManagedMemoryPolicy;
class OutputSurfaceClient;

// Represents the output surface for a compositor. The compositor owns
// and manages its destruction. Its lifetime is:
//   1. Created on the main thread by the LayerTreeHost through its client.
//   2. Passed to the compositor thread and bound to a client via BindToClient.
//      From here on, it will only be used on the compositor thread.
//   3. If the 3D context is lost, then the compositor will delete the output
//      surface (on the compositor thread) and go back to step 1.
class CC_EXPORT OutputSurface : public FrameRateControllerClient {
 public:
  enum {
    DEFAULT_MAX_FRAMES_PENDING = 2
  };

  explicit OutputSurface(scoped_refptr<ContextProvider> context_provider);

  explicit OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device);

  OutputSurface(scoped_refptr<ContextProvider> context_provider,
                scoped_ptr<SoftwareOutputDevice> software_device);

  virtual ~OutputSurface();

  struct Capabilities {
    Capabilities()
        : delegated_rendering(false),
          max_frames_pending(0),
          deferred_gl_initialization(false),
          draw_and_swap_full_viewport_every_frame(false),
          adjust_deadline_for_parent(true),
          uses_default_gl_framebuffer(true) {}
    bool delegated_rendering;
    int max_frames_pending;
    bool deferred_gl_initialization;
    bool draw_and_swap_full_viewport_every_frame;
    // This doesn't handle the <webview> case, but once BeginImplFrame is
    // supported natively, we shouldn't need adjust_deadline_for_parent.
    bool adjust_deadline_for_parent;
    // Whether this output surface renders to the default OpenGL zero
    // framebuffer or to an offscreen framebuffer.
    bool uses_default_gl_framebuffer;
  };

  const Capabilities& capabilities() const {
    return capabilities_;
  }

  virtual bool HasExternalStencilTest() const;

  // Obtain the 3d context or the software device associated with this output
  // surface. Either of these may return a null pointer, but not both.
  // In the event of a lost context, the entire output surface should be
  // recreated.
  scoped_refptr<ContextProvider> context_provider() const {
    return context_provider_.get();
  }
  SoftwareOutputDevice* software_device() const {
    return software_device_.get();
  }

  // In the case where both the context3d and software_device are present
  // (namely Android WebView), this is called to determine whether the software
  // device should be used on the current frame.
  virtual bool ForcedDrawToSoftwareDevice() const;

  // Called by the compositor on the compositor thread. This is a place where
  // thread-specific data for the output surface can be initialized, since from
  // this point on the output surface will only be used on the compositor
  // thread.
  virtual bool BindToClient(OutputSurfaceClient* client);

  void InitializeBeginImplFrameEmulation(
      base::SingleThreadTaskRunner* task_runner,
      bool throttle_frame_production,
      base::TimeDelta interval);

  void SetMaxFramesPending(int max_frames_pending);

  virtual void EnsureBackbuffer();
  virtual void DiscardBackbuffer();

  virtual void Reshape(gfx::Size size, float scale_factor);
  virtual gfx::Size SurfaceSize() const;

  virtual void BindFramebuffer();

  // The implementation may destroy or steal the contents of the CompositorFrame
  // passed in (though it will not take ownership of the CompositorFrame
  // itself).
  virtual void SwapBuffers(CompositorFrame* frame);

  // Notifies frame-rate smoothness preference. If true, all non-critical
  // processing should be stopped, or lowered in priority.
  virtual void UpdateSmoothnessTakesPriority(bool prefer_smoothness) {}

  // Requests a BeginImplFrame notification from the output surface. The
  // notification will be delivered by calling
  // OutputSurfaceClient::BeginImplFrame until the callback is disabled.
  virtual void SetNeedsBeginImplFrame(bool enable);

  bool HasClient() { return !!client_; }

  // Returns an estimate of the current GPU latency. When only a software
  // device is present, returns 0.
  base::TimeDelta GpuLatencyEstimate();

 protected:
  // Synchronously initialize context3d and enter hardware mode.
  // This can only supported in threaded compositing mode.
  // |offscreen_context_provider| should match what is returned by
  // LayerTreeClient::OffscreenContextProvider().
  bool InitializeAndSetContext3d(
      scoped_refptr<ContextProvider> context_provider,
      scoped_refptr<ContextProvider> offscreen_context_provider);
  void ReleaseGL();

  void PostSwapBuffersComplete();

  struct OutputSurface::Capabilities capabilities_;
  scoped_refptr<ContextProvider> context_provider_;
  scoped_ptr<SoftwareOutputDevice> software_device_;
  gfx::Size surface_size_;
  float device_scale_factor_;

  // The FrameRateController is deprecated.
  // Platforms should move to native BeginImplFrames instead.
  void OnVSyncParametersChanged(base::TimeTicks timebase,
                                base::TimeDelta interval);
  virtual void FrameRateControllerTick(bool throttled,
                                       const BeginFrameArgs& args) OVERRIDE;
  scoped_ptr<FrameRateController> frame_rate_controller_;
  int max_frames_pending_;
  int pending_swap_buffers_;
  bool needs_begin_impl_frame_;
  bool client_ready_for_begin_impl_frame_;

  // This stores a BeginImplFrame that we couldn't process immediately,
  // but might process retroactively in the near future.
  BeginFrameArgs skipped_begin_impl_frame_args_;

  // Forwarded to OutputSurfaceClient but threaded through OutputSurface
  // first so OutputSurface has a chance to update the FrameRateController
  void SetNeedsRedrawRect(gfx::Rect damage_rect);
  void BeginImplFrame(const BeginFrameArgs& args);
  void DidSwapBuffers();
  void OnSwapBuffersComplete();
  void ReclaimResources(const CompositorFrameAck* ack);
  void DidLoseOutputSurface();
  void SetExternalStencilTest(bool enabled);
  void SetExternalDrawConstraints(const gfx::Transform& transform,
                                  gfx::Rect viewport,
                                  gfx::Rect clip,
                                  bool valid_for_tile_management);

  // virtual for testing.
  virtual base::TimeTicks RetroactiveBeginImplFrameDeadline();
  virtual void PostCheckForRetroactiveBeginImplFrame();
  void CheckForRetroactiveBeginImplFrame();

 private:
  OutputSurfaceClient* client_;

  void SetUpContext3d();
  void ResetContext3d();
  void SetMemoryPolicy(const ManagedMemoryPolicy& policy);
  void UpdateAndMeasureGpuLatency();

  // check_for_retroactive_begin_impl_frame_pending_ is used to avoid posting
  // redundant checks for a retroactive BeginImplFrame.
  bool check_for_retroactive_begin_impl_frame_pending_;

  bool external_stencil_test_enabled_;

  base::WeakPtrFactory<OutputSurface> weak_ptr_factory_;

  std::deque<unsigned> available_gpu_latency_query_ids_;
  std::deque<unsigned> pending_gpu_latency_query_ids_;
  RollingTimeDeltaHistory gpu_latency_history_;

  DISALLOW_COPY_AND_ASSIGN(OutputSurface);
};

}  // namespace cc

#endif  // CC_OUTPUT_OUTPUT_SURFACE_H_