Home | History | Annotate | Download | only in surface
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef UI_SURFACE_ACCELERATED_SURFACE_WIN_H_
      6 #define UI_SURFACE_ACCELERATED_SURFACE_WIN_H_
      7 
      8 #include <d3d9.h>
      9 
     10 #include "base/callback_forward.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/single_thread_task_runner.h"
     13 #include "base/synchronization/lock.h"
     14 #include "base/synchronization/waitable_event.h"
     15 #include "base/time/time.h"
     16 #include "base/win/scoped_comptr.h"
     17 #include "ui/base/latency_info.h"
     18 #include "ui/gfx/native_widget_types.h"
     19 #include "ui/gfx/size.h"
     20 #include "ui/surface/surface_export.h"
     21 
     22 class PresentThread;
     23 
     24 namespace gfx {
     25 class Rect;
     26 }
     27 
     28 namespace media {
     29 class VideoFrame;
     30 }
     31 
     32 class SURFACE_EXPORT AcceleratedPresenter
     33     : public base::RefCountedThreadSafe<AcceleratedPresenter> {
     34  public:
     35   typedef base::Callback<void(bool,
     36                               base::TimeTicks,
     37                               base::TimeDelta,
     38                               const ui::LatencyInfo&)> CompletionTask;
     39 
     40   explicit AcceleratedPresenter(gfx::PluginWindowHandle window);
     41 
     42   static void SetAdapterLUID(uint64 adapter_luid);
     43 
     44   // Returns a thread safe reference to the presenter for the given window or
     45   // null is no such presenter exists. The thread safe refptr ensures the
     46   // presenter will not be destroyed. This can be called on any thread.
     47   static scoped_refptr<AcceleratedPresenter> GetForWindow(
     48       gfx::PluginWindowHandle window);
     49 
     50   // Schedule a frame to be presented. The completion callback will be invoked
     51   // when it is safe to write to the surface on another thread. The lock for
     52   // this surface will be held while the completion callback runs. This can be
     53   // called on any thread.
     54   void AsyncPresentAndAcknowledge(
     55       const gfx::Size& size,
     56       int64 surface_handle,
     57       const ui::LatencyInfo& latency_info,
     58       const CompletionTask& completion_task);
     59 
     60   // Returns true if the swap chain has been created and initialized.  This can
     61   // be called on any thread.
     62   bool IsSwapChainInitialized() const;
     63 
     64   // Schedule the presenter to free all its resources. This can be called on any
     65   // thread.
     66   void Suspend();
     67 
     68   // Indicates that the presenter has become invisible.
     69   void WasHidden();
     70 
     71   // Called when the Windows session is locked or unlocked.
     72   void SetIsSessionLocked(bool locked);
     73 
     74   // Schedule the presenter to release its reference to the shared surface.
     75   void ReleaseSurface();
     76 
     77   // The public member functions are called on the main thread.
     78   void Present(HDC dc);
     79   void AsyncCopyTo(const gfx::Rect& src_subrect,
     80                    const gfx::Size& dst_size,
     81                    const base::Callback<void(bool, const SkBitmap&)>& callback);
     82   void AsyncCopyToVideoFrame(
     83       const gfx::Rect& src_subrect,
     84       const scoped_refptr<media::VideoFrame>& target,
     85       const base::Callback<void(bool)>& callback);
     86   void Invalidate();
     87 
     88   // Destroy any D3D resources owned by the given present thread. Called on
     89   // the given present thread.
     90   void ResetPresentThread(PresentThread* present_thread);
     91 
     92 #if defined(USE_AURA)
     93   // TODO(scottmg): This is a temporary hack until we have a two-worlds ash/aura
     94   // separation.
     95   void SetNewTargetWindow(gfx::PluginWindowHandle window);
     96 #endif
     97 
     98  private:
     99   friend class base::RefCountedThreadSafe<AcceleratedPresenter>;
    100 
    101   ~AcceleratedPresenter();
    102 
    103   // These member functions are called on the PresentThread with which the
    104   // presenter has affinity.
    105   void DoPresentAndAcknowledge(
    106       const gfx::Size& size,
    107       int64 surface_handle,
    108       const ui::LatencyInfo& latency_info,
    109       const CompletionTask& completion_task);
    110   void DoSuspend();
    111   void DoPresent(const base::Closure& composite_task);
    112   void DoReleaseSurface();
    113   void DoCopyToAndAcknowledge(
    114       const gfx::Rect& src_subrect,
    115       const gfx::Size& dst_size,
    116       scoped_refptr<base::SingleThreadTaskRunner> callback_runner,
    117       const base::Callback<void(bool, const SkBitmap&)>& callback);
    118   void DoCopyToVideoFrameAndAcknowledge(
    119       const gfx::Rect& src_subrect,
    120       const scoped_refptr<media::VideoFrame>& target,
    121       const scoped_refptr<base::SingleThreadTaskRunner>& callback_runner,
    122       const base::Callback<void(bool)>& callback);
    123   bool DoCopyToYUV(const gfx::Rect& src_subrect,
    124                    const scoped_refptr<media::VideoFrame>& frame);
    125   bool DoCopyToARGB(const gfx::Rect& src_subrect,
    126                     const gfx::Size& dst_size,
    127                     SkBitmap* bitmap);
    128 
    129   void PresentWithGDI(HDC dc);
    130   gfx::Size GetWindowSize();
    131 
    132   // This function tries to guess whether Direct3D will be able to reliably
    133   // present to the window. When the window is resizing, presenting with
    134   // Direct3D causes other regions of the window rendered with GDI to
    135   // flicker transparent / non-transparent.
    136   bool CheckDirect3DWillWork();
    137 
    138   // The thread with which this presenter has affinity.
    139   PresentThread* const present_thread_;
    140 
    141   // The window that is presented to.
    142   gfx::PluginWindowHandle window_;
    143 
    144   // UI thread can wait on this event to ensure a present is finished.
    145   base::WaitableEvent event_;
    146 
    147   // The current size of the swap chain. This is only accessed on the thread
    148   // with which the surface has affinity. The swap chain size is rounded up and
    149   // is not necessarily the same as the window size.
    150   gfx::Size quantized_size_;
    151 
    152   // The size of the window on the last present. This is used to trigger the
    153   // compositor instead of presenting the last frame in the case where the
    154   // window has been resized.
    155   gfx::Size present_size_;
    156 
    157   // This is a shared texture that is being presented from.
    158   base::win::ScopedComPtr<IDirect3DTexture9> source_texture_;
    159 
    160   // The swap chain is presented to the child window. Copy semantics
    161   // are used so it is possible to represent it to quickly validate the window.
    162   base::win::ScopedComPtr<IDirect3DSwapChain9> swap_chain_;
    163 
    164   // Whether the window is hidden or has not been presented to since it was
    165   // last hidden.
    166   bool hidden_;
    167 
    168   // Set to true if the first present after the tab is unhidden needs to be done
    169   // with GDI.
    170   bool do_present_with_GDI_;
    171 
    172   // Set to true when the Windows session is locked.
    173   bool is_session_locked_;
    174 
    175   // These are used to detect when the window is resizing. For some reason,
    176   // presenting with D3D while the window resizes causes those parts not
    177   // drawn with D3D (e.g. with GDI) to flicker visible / invisible.
    178   // http://crbug.com/120904
    179   gfx::Size last_window_size_;
    180   base::Time last_window_resize_time_;
    181 
    182   ui::LatencyInfo latency_info_;
    183 
    184   DISALLOW_COPY_AND_ASSIGN(AcceleratedPresenter);
    185 };
    186 
    187 class SURFACE_EXPORT AcceleratedSurface {
    188  public:
    189   AcceleratedSurface(gfx::PluginWindowHandle window);
    190   ~AcceleratedSurface();
    191 
    192   // Synchronously present a frame with no acknowledgement.
    193   void Present(HDC dc);
    194 
    195   // Returns true if the surface is fully initialized and has been presented to
    196   // at least once.
    197   bool IsReadyForCopy() const;
    198 
    199   // Transfer the contents of the surface to an SkBitmap, and invoke a callback
    200   // with the result.
    201   void AsyncCopyTo(const gfx::Rect& src_subrect,
    202                    const gfx::Size& dst_size,
    203                    const base::Callback<void(bool, const SkBitmap&)>& callback);
    204 
    205   // Transfer the contents of the surface to an already-allocated YV12
    206   // VideoFrame, and invoke a callback to indicate success or failure.
    207   void AsyncCopyToVideoFrame(
    208       const gfx::Rect& src_subrect,
    209       const scoped_refptr<media::VideoFrame>& target,
    210       const base::Callback<void(bool)>& callback);
    211 
    212   // Temporarily release resources until a new surface is asynchronously
    213   // presented. Present will not be able to represent the last surface after
    214   // calling this and will return false.
    215   void Suspend();
    216 
    217   // Indicates that the surface has become invisible.
    218   void WasHidden();
    219 
    220   // Called when the Windows session in locked or unlocked.
    221   void SetIsSessionLocked(bool locked);
    222 
    223  private:
    224   const scoped_refptr<AcceleratedPresenter> presenter_;
    225   DISALLOW_COPY_AND_ASSIGN(AcceleratedSurface);
    226 };
    227 
    228 #endif  // UI_SURFACE_ACCELERATED_SURFACE_WIN_H_
    229