summaryrefslogtreecommitdiffstats
path: root/ui/surface/accelerated_surface_win.h
blob: 6a19e81ca749e1a76ea68d219e75aa53b05cfc4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// 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/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/win/scoped_comptr.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;
}

class SURFACE_EXPORT AcceleratedPresenter
    : public base::RefCountedThreadSafe<AcceleratedPresenter> {
 public:
  typedef base::Callback<void(bool,
                              base::TimeTicks,
                              base::TimeDelta)> CompletionTask;

  explicit AcceleratedPresenter(gfx::NativeWindow window);

  // 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::NativeWindow 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 CompletionTask& completion_task);

  // 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();

  // Schedule the presenter to release its reference to the shared surface.
  void ReleaseSurface();

  // The public member functions are called on the main thread.
  bool Present(HDC dc);
  bool CopyTo(const gfx::Rect& src_subrect,
              const gfx::Size& dst_size,
              void* buf);
  void Invalidate();

 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 CompletionTask& completion_task);
  void DoSuspend();
  void DoPresent(HDC dc, bool* presented);
  bool DoRealPresent(HDC dc);
  void DoReleaseSurface();

  // This gets the timestamp and period of the display's last vsync.
  // The period is represented as a ratio which, when divided, will give you
  // the interval in seconds. i.e.:
  // inteval_in_seconds = interval_numerator / interval_denominator;
  // For example, some machines will return an interval_numerator of 1001
  // and an interval_denominator of 60000, resulting in an interval of
  // 1001/60000 ~= .016683 seconds
  // Note: This function assumes lock_ is acquired.
  // Returns true on success.
  bool GetPresentationStats(base::TimeTicks* timebase,
                            uint32* interval_numerator,
                            uint32* interval_denominator);

  // The thread with which this presenter has affinity.
  PresentThread* const present_thread_;

  // The window that is presented to.
  gfx::NativeWindow window_;

  // The lock is taken while any thread is calling the object, except those that
  // simply post from the main thread to the present thread via the immutable
  // present_thread_ member.
  base::Lock lock_;

  // 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_;

  bool hidden_;

  DISALLOW_COPY_AND_ASSIGN(AcceleratedPresenter);
};

class SURFACE_EXPORT AcceleratedSurface {
 public:
  AcceleratedSurface(gfx::NativeWindow window);
  ~AcceleratedSurface();

  // Synchronously present a frame with no acknowledgement.
  bool Present(HDC dc);

  // Copies the surface data to |buf|. The copied region is specified with
  // |src_subrect| and the image data is transformed so that it fits in
  // |dst_size|.
  // Caller must ensure that |buf| is allocated with the size no less than
  // |4 * dst_size.width() * dst_size.height()| bytes.
  bool CopyTo(const gfx::Rect& src_subrect,
              const gfx::Size& dst_size,
              void* buf);

  // 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();

 private:
  const scoped_refptr<AcceleratedPresenter> presenter_;
  DISALLOW_COPY_AND_ASSIGN(AcceleratedSurface);
};

#endif  // UI_SURFACE_ACCELERATED_SURFACE_WIN_H_