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