// Copyright (c) 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 UI_SURFACE_ACCELERATED_SURFACE_WIN_H_ #define UI_SURFACE_ACCELERATED_SURFACE_WIN_H_ #include <d3d9.h> #include "base/callback_forward.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "base/time/time.h" #include "base/win/scoped_comptr.h" #include "ui/events/latency_info.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/size.h" #include "ui/surface/surface_export.h" class PresentThread; namespace gfx { class Rect; } namespace media { class VideoFrame; } class SURFACE_EXPORT AcceleratedPresenter : public base::RefCountedThreadSafe<AcceleratedPresenter> { public: typedef base::Callback<void(bool, base::TimeTicks, base::TimeDelta, const ui::LatencyInfo&)> CompletionTask; explicit AcceleratedPresenter(gfx::PluginWindowHandle window); static void SetAdapterLUID(uint64 adapter_luid); // Returns a thread safe reference to the presenter for the given window or // null is no such presenter exists. The thread safe refptr ensures the // presenter will not be destroyed. This can be called on any thread. static scoped_refptr<AcceleratedPresenter> GetForWindow( gfx::PluginWindowHandle window); // Schedule a frame to be presented. The completion callback will be invoked // when it is safe to write to the surface on another thread. The lock for // this surface will be held while the completion callback runs. This can be // called on any thread. void AsyncPresentAndAcknowledge( const gfx::Size& size, int64 surface_handle, const ui::LatencyInfo& latency_info, const CompletionTask& completion_task); // Returns true if the swap chain has been created and initialized. This can // be called on any thread. bool IsSwapChainInitialized() const; // Schedule the presenter to free all its resources. This can be called on any // thread. void Suspend(); // Indicates that the presenter has become invisible. void WasHidden(); // Called when the Windows session is locked or unlocked. void SetIsSessionLocked(bool locked); // Schedule the presenter to release its reference to the shared surface. void ReleaseSurface(); // The public member functions are called on the main thread. void Present(HDC dc); void AsyncCopyTo(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const base::Callback<void(bool, const SkBitmap&)>& callback); void AsyncCopyToVideoFrame( const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(bool)>& callback); void Invalidate(); // Destroy any D3D resources owned by the given present thread. Called on // the given present thread. void ResetPresentThread(PresentThread* present_thread); private: friend class base::RefCountedThreadSafe<AcceleratedPresenter>; ~AcceleratedPresenter(); // These member functions are called on the PresentThread with which the // presenter has affinity. void DoPresentAndAcknowledge( const gfx::Size& size, int64 surface_handle, const ui::LatencyInfo& latency_info, const CompletionTask& completion_task); void DoSuspend(); void DoPresent(const base::Closure& composite_task); void DoReleaseSurface(); void DoCopyToAndAcknowledge( const gfx::Rect& src_subrect, const gfx::Size& dst_size, scoped_refptr<base::SingleThreadTaskRunner> callback_runner, const base::Callback<void(bool, const SkBitmap&)>& callback); void DoCopyToVideoFrameAndAcknowledge( const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const scoped_refptr<base::SingleThreadTaskRunner>& callback_runner, const base::Callback<void(bool)>& callback); bool DoCopyToYUV(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& frame); bool DoCopyToARGB(const gfx::Rect& src_subrect, const gfx::Size& dst_size, SkBitmap* bitmap); void PresentWithGDI(HDC dc); gfx::Size GetWindowSize(); // This function tries to guess whether Direct3D will be able to reliably // present to the window. When the window is resizing, presenting with // Direct3D causes other regions of the window rendered with GDI to // flicker transparent / non-transparent. bool CheckDirect3DWillWork(); // The thread with which this presenter has affinity. PresentThread* const present_thread_; // The window that is presented to. gfx::PluginWindowHandle window_; // UI thread can wait on this event to ensure a present is finished. base::WaitableEvent event_; // The current size of the swap chain. This is only accessed on the thread // with which the surface has affinity. The swap chain size is rounded up and // is not necessarily the same as the window size. gfx::Size quantized_size_; // The size of the window on the last present. This is used to trigger the // compositor instead of presenting the last frame in the case where the // window has been resized. gfx::Size present_size_; // This is a shared texture that is being presented from. base::win::ScopedComPtr<IDirect3DTexture9> source_texture_; // The swap chain is presented to the child window. Copy semantics // are used so it is possible to represent it to quickly validate the window. base::win::ScopedComPtr<IDirect3DSwapChain9> swap_chain_; // Whether the window is hidden or has not been presented to since it was // last hidden. bool hidden_; // Set to true if the first present after the tab is unhidden needs to be done // with GDI. bool do_present_with_GDI_; // Set to true when the Windows session is locked. bool is_session_locked_; // These are used to detect when the window is resizing. For some reason, // presenting with D3D while the window resizes causes those parts not // drawn with D3D (e.g. with GDI) to flicker visible / invisible. // http://crbug.com/120904 gfx::Size last_window_size_; base::Time last_window_resize_time_; ui::LatencyInfo latency_info_; DISALLOW_COPY_AND_ASSIGN(AcceleratedPresenter); }; class SURFACE_EXPORT AcceleratedSurface { public: AcceleratedSurface(gfx::PluginWindowHandle window); ~AcceleratedSurface(); // Synchronously present a frame with no acknowledgement. void Present(HDC dc); // Returns true if the surface is fully initialized and has been presented to // at least once. bool IsReadyForCopy() const; // Transfer the contents of the surface to an SkBitmap, and invoke a callback // with the result. void AsyncCopyTo(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const base::Callback<void(bool, const SkBitmap&)>& callback); // Transfer the contents of the surface to an already-allocated YV12 // VideoFrame, and invoke a callback to indicate success or failure. void AsyncCopyToVideoFrame( const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(bool)>& callback); // Temporarily release resources until a new surface is asynchronously // presented. Present will not be able to represent the last surface after // calling this and will return false. void Suspend(); // Indicates that the surface has become invisible. void WasHidden(); // Called when the Windows session in locked or unlocked. void SetIsSessionLocked(bool locked); private: const scoped_refptr<AcceleratedPresenter> presenter_; DISALLOW_COPY_AND_ASSIGN(AcceleratedSurface); }; #endif // UI_SURFACE_ACCELERATED_SURFACE_WIN_H_