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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
|
// 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 CONTENT_BROWSER_RENDERER_HOST_ACCELERATED_COMPOSITING_VIEW_MAC_H
#define CONTENT_BROWSER_RENDERER_HOST_ACCELERATED_COMPOSITING_VIEW_MAC_H
#import <Cocoa/Cocoa.h>
#import <QuartzCore/CVDisplayLink.h>
#include <QuartzCore/QuartzCore.h>
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_nsobject.h"
#include "base/synchronization/lock.h"
#include "base/time.h"
#include "base/timer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
class IOSurfaceSupport;
namespace gfx {
class Rect;
}
namespace content {
// This class manages an OpenGL context and IOSurface for the accelerated
// compositing code path. The GL context is attached to
// RenderWidgetHostViewCocoa for blitting the IOSurface.
class CompositingIOSurfaceMac {
public:
// Returns NULL if IOSurface support is missing or GL APIs fail.
static CompositingIOSurfaceMac* Create();
~CompositingIOSurfaceMac();
// Set IOSurface that will be drawn on the next NSView drawRect.
void SetIOSurface(uint64 io_surface_handle);
// Blit the IOSurface at the upper-left corner of the |view|. If |view| window
// size is larger than the IOSurface, the remaining right and bottom edges
// will be white. |scaleFactor| is 1 in normal views, 2 in HiDPI views.
void DrawIOSurface(NSView* view, float scale_factor);
// Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef
// into |out|. The copied region is specified with |src_pixel_subrect| and
// the data is transformed so that it fits in |dst_pixel_size|.
// |src_pixel_subrect| and |dst_pixel_size| are not in DIP but in pixel.
// Caller must ensure that |out| is allocated with the size no less than
// |4 * dst_pixel_size.width() * dst_pixel_size.height()| bytes.
bool CopyTo(const gfx::Rect& src_pixel_subrect,
const gfx::Size& dst_pixel_size,
void* out);
// Unref the IOSurface and delete the associated GL texture. If the GPU
// process is no longer referencing it, this will delete the IOSurface.
void UnrefIOSurface();
// Call when globalFrameDidChange is received on the NSView.
void GlobalFrameDidChange();
// Disassociate the GL context with the NSView and unref the IOSurface. Do
// this to switch to software drawing mode.
void ClearDrawable();
bool HasIOSurface() { return !!io_surface_.get(); }
const gfx::Size& pixel_io_surface_size() const {
return pixel_io_surface_size_;
}
// In cocoa view units / DIPs.
const gfx::Size& io_surface_size() const { return io_surface_size_; }
bool is_vsync_disabled() const { return is_vsync_disabled_; }
// Get vsync scheduling parameters.
// |interval_numerator/interval_denominator| equates to fractional number of
// seconds between vsyncs.
void GetVSyncParameters(base::TimeTicks* timebase,
uint32* interval_numerator,
uint32* interval_denominator);
private:
friend CVReturn DisplayLinkCallback(CVDisplayLinkRef,
const CVTimeStamp*,
const CVTimeStamp*,
CVOptionFlags,
CVOptionFlags*,
void*);
// Vertex structure for use in glDraw calls.
struct SurfaceVertex {
SurfaceVertex() : x_(0.0f), y_(0.0f), tx_(0.0f), ty_(0.0f) { }
void set(float x, float y, float tx, float ty) {
x_ = x;
y_ = y;
tx_ = tx;
ty_ = ty;
}
void set_position(float x, float y) {
x_ = x;
y_ = y;
}
void set_texcoord(float tx, float ty) {
tx_ = tx;
ty_ = ty;
}
float x_;
float y_;
float tx_;
float ty_;
};
// Counter-clockwise verts starting from upper-left corner (0, 0).
struct SurfaceQuad {
void set_size(gfx::Size vertex_size, gfx::Size texcoord_size) {
// Texture coordinates are flipped vertically so they can be drawn on
// a projection with a flipped y-axis (origin is top left).
float vw = static_cast<float>(vertex_size.width());
float vh = static_cast<float>(vertex_size.height());
float tw = static_cast<float>(texcoord_size.width());
float th = static_cast<float>(texcoord_size.height());
verts_[0].set(0.0f, 0.0f, 0.0f, th);
verts_[1].set(0.0f, vh, 0.0f, 0.0f);
verts_[2].set(vw, vh, tw, 0.0f);
verts_[3].set(vw, 0.0f, tw, th);
}
void set_rect(float x1, float y1, float x2, float y2) {
verts_[0].set_position(x1, y1);
verts_[1].set_position(x1, y2);
verts_[2].set_position(x2, y2);
verts_[3].set_position(x2, y1);
}
void set_texcoord_rect(float tx1, float ty1, float tx2, float ty2) {
// Texture coordinates are flipped vertically so they can be drawn on
// a projection with a flipped y-axis (origin is top left).
verts_[0].set_texcoord(tx1, ty2);
verts_[1].set_texcoord(tx1, ty1);
verts_[2].set_texcoord(tx2, ty1);
verts_[3].set_texcoord(tx2, ty2);
}
SurfaceVertex verts_[4];
};
CompositingIOSurfaceMac(IOSurfaceSupport* io_surface_support,
NSOpenGLContext* glContext,
CGLContextObj cglContext,
GLuint shader_program_blit_rgb,
GLint blit_rgb_sampler_location,
GLuint shader_program_white,
bool is_vsync_disabled,
CVDisplayLinkRef display_link);
// Returns true if IOSurface is ready to render. False otherwise.
bool MapIOSurfaceToTexture(uint64 io_surface_handle);
void UnrefIOSurfaceWithContextCurrent();
void DrawQuad(const SurfaceQuad& quad);
// Called on display-link thread.
void DisplayLinkTick(CVDisplayLinkRef display_link,
const CVTimeStamp* time);
void CalculateVsyncParametersLockHeld(const CVTimeStamp* time);
// Prevent from spinning on CGLFlushDrawable when it fails to throttle to
// VSync frequency.
void RateLimitDraws();
void StartOrContinueDisplayLink();
void StopDisplayLink();
// Cached pointer to IOSurfaceSupport Singleton.
IOSurfaceSupport* io_surface_support_;
// GL context
scoped_nsobject<NSOpenGLContext> glContext_;
CGLContextObj cglContext_; // weak, backed by |glContext_|.
// IOSurface data.
uint64 io_surface_handle_;
base::mac::ScopedCFTypeRef<CFTypeRef> io_surface_;
// The width and height of the io surface.
gfx::Size pixel_io_surface_size_; // In pixels.
gfx::Size io_surface_size_; // In view units.
// The "live" OpenGL texture referring to this IOSurfaceRef. Note
// that per the CGLTexImageIOSurface2D API we do not need to
// explicitly update this texture's contents once created. All we
// need to do is ensure it is re-bound before attempting to draw
// with it.
GLuint texture_;
// Shader parameters.
GLuint shader_program_blit_rgb_;
GLint blit_rgb_sampler_location_;
GLuint shader_program_white_;
SurfaceQuad quad_;
bool is_vsync_disabled_;
// CVDisplayLink for querying Vsync timing info and throttling swaps.
CVDisplayLinkRef display_link_;
// Timer for stopping display link after a timeout with no swaps.
base::DelayTimer<CompositingIOSurfaceMac> display_link_stop_timer_;
// Lock for sharing data between UI thread and display-link thread.
base::Lock lock_;
// Counts for throttling swaps.
int64 vsync_count_;
int64 swap_count_;
// Vsync timing data.
base::TimeTicks vsync_timebase_;
uint32 vsync_interval_numerator_;
uint32 vsync_interval_denominator_;
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_ACCELERATED_COMPOSITING_VIEW_MAC_H
|