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/events/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  private:
     93   friend class base::RefCountedThreadSafe<AcceleratedPresenter>;
     94 
     95   ~AcceleratedPresenter();
     96 
     97   // These member functions are called on the PresentThread with which the
     98   // presenter has affinity.
     99   void DoPresentAndAcknowledge(
    100       const gfx::Size& size,
    101       int64 surface_handle,
    102       const ui::LatencyInfo& latency_info,
    103       const CompletionTask& completion_task);
    104   void DoSuspend();
    105   void DoPresent(const base::Closure& composite_task);
    106   void DoReleaseSurface();
    107   void DoCopyToAndAcknowledge(
    108       const gfx::Rect& src_subrect,
    109       const gfx::Size& dst_size,
    110       scoped_refptr<base::SingleThreadTaskRunner> callback_runner,
    111       const base::Callback<void(bool, const SkBitmap&)>& callback);
    112   void DoCopyToVideoFrameAndAcknowledge(
    113       const gfx::Rect& src_subrect,
    114       const scoped_refptr<media::VideoFrame>& target,
    115       const scoped_refptr<base::SingleThreadTaskRunner>& callback_runner,
    116       const base::Callback<void(bool)>& callback);
    117   bool DoCopyToYUV(const gfx::Rect& src_subrect,
    118                    const scoped_refptr<media::VideoFrame>& frame);
    119   bool DoCopyToARGB(const gfx::Rect& src_subrect,
    120                     const gfx::Size& dst_size,
    121                     SkBitmap* bitmap);
    122 
    123   void PresentWithGDI(HDC dc);
    124   gfx::Size GetWindowSize();
    125 
    126   // This function tries to guess whether Direct3D will be able to reliably
    127   // present to the window. When the window is resizing, presenting with
    128   // Direct3D causes other regions of the window rendered with GDI to
    129   // flicker transparent / non-transparent.
    130   bool CheckDirect3DWillWork();
    131 
    132   // The thread with which this presenter has affinity.
    133   PresentThread* const present_thread_;
    134 
    135   // The window that is presented to.
    136   gfx::PluginWindowHandle window_;
    137 
    138   // UI thread can wait on this event to ensure a present is finished.
    139   base::WaitableEvent event_;
    140 
    141   // The current size of the swap chain. This is only accessed on the thread
    142   // with which the surface has affinity. The swap chain size is rounded up and
    143   // is not necessarily the same as the window size.
    144   gfx::Size quantized_size_;
    145 
    146   // The size of the window on the last present. This is used to trigger the
    147   // compositor instead of presenting the last frame in the case where the
    148   // window has been resized.
    149   gfx::Size present_size_;
    150 
    151   // This is a shared texture that is being presented from.
    152   base::win::ScopedComPtr<IDirect3DTexture9> source_texture_;
    153 
    154   // The swap chain is presented to the child window. Copy semantics
    155   // are used so it is possible to represent it to quickly validate the window.
    156   base::win::ScopedComPtr<IDirect3DSwapChain9> swap_chain_;
    157 
    158   // Whether the window is hidden or has not been presented to since it was
    159   // last hidden.
    160   bool hidden_;
    161 
    162   // Set to true if the first present after the tab is unhidden needs to be done
    163   // with GDI.
    164   bool do_present_with_GDI_;
    165 
    166   // Set to true when the Windows session is locked.
    167   bool is_session_locked_;
    168 
    169   // These are used to detect when the window is resizing. For some reason,
    170   // presenting with D3D while the window resizes causes those parts not
    171   // drawn with D3D (e.g. with GDI) to flicker visible / invisible.
    172   // http://crbug.com/120904
    173   gfx::Size last_window_size_;
    174   base::Time last_window_resize_time_;
    175 
    176   ui::LatencyInfo latency_info_;
    177 
    178   DISALLOW_COPY_AND_ASSIGN(AcceleratedPresenter);
    179 };
    180 
    181 class SURFACE_EXPORT AcceleratedSurface {
    182  public:
    183   AcceleratedSurface(gfx::PluginWindowHandle window);
    184   ~AcceleratedSurface();
    185 
    186   // Synchronously present a frame with no acknowledgement.
    187   void Present(HDC dc);
    188 
    189   // Returns true if the surface is fully initialized and has been presented to
    190   // at least once.
    191   bool IsReadyForCopy() const;
    192 
    193   // Transfer the contents of the surface to an SkBitmap, and invoke a callback
    194   // with the result.
    195   void AsyncCopyTo(const gfx::Rect& src_subrect,
    196                    const gfx::Size& dst_size,
    197                    const base::Callback<void(bool, const SkBitmap&)>& callback);
    198 
    199   // Transfer the contents of the surface to an already-allocated YV12
    200   // VideoFrame, and invoke a callback to indicate success or failure.
    201   void AsyncCopyToVideoFrame(
    202       const gfx::Rect& src_subrect,
    203       const scoped_refptr<media::VideoFrame>& target,
    204       const base::Callback<void(bool)>& callback);
    205 
    206   // Temporarily release resources until a new surface is asynchronously
    207   // presented. Present will not be able to represent the last surface after
    208   // calling this and will return false.
    209   void Suspend();
    210 
    211   // Indicates that the surface has become invisible.
    212   void WasHidden();
    213 
    214   // Called when the Windows session in locked or unlocked.
    215   void SetIsSessionLocked(bool locked);
    216 
    217  private:
    218   const scoped_refptr<AcceleratedPresenter> presenter_;
    219   DISALLOW_COPY_AND_ASSIGN(AcceleratedSurface);
    220 };
    221 
    222 #endif  // UI_SURFACE_ACCELERATED_SURFACE_WIN_H_
    223