blob: 28e1a11d4a2a2b698717f90dfbb653ee4bad135b [file] [log] [blame]
[email protected]77a3bbbb2012-04-05 19:39:321// 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 CONTENT_BROWSER_RENDERER_HOST_ACCELERATED_COMPOSITING_VIEW_MAC_H
6#define CONTENT_BROWSER_RENDERER_HOST_ACCELERATED_COMPOSITING_VIEW_MAC_H
7
8#import <Cocoa/Cocoa.h>
[email protected]bd1200b2012-08-05 21:58:089#import <QuartzCore/CVDisplayLink.h>
[email protected]77a3bbbb2012-04-05 19:39:3210#include <QuartzCore/QuartzCore.h>
11
[email protected]a02f64e42012-09-24 21:32:4112#include "base/callback.h"
[email protected]77a3bbbb2012-04-05 19:39:3213#include "base/mac/scoped_cftyperef.h"
14#include "base/memory/scoped_nsobject.h"
[email protected]bd1200b2012-08-05 21:58:0815#include "base/synchronization/lock.h"
16#include "base/time.h"
17#include "base/timer.h"
[email protected]da1b5fa2013-03-02 03:57:4718#include "media/base/video_frame.h"
[email protected]d748d0f2013-02-02 23:31:0719#include "third_party/skia/include/core/SkBitmap.h"
[email protected]77a3bbbb2012-04-05 19:39:3220#include "ui/gfx/native_widget_types.h"
[email protected]a02f64e42012-09-24 21:32:4121#include "ui/gfx/rect.h"
[email protected]da1b5fa2013-03-02 03:57:4722#include "ui/gfx/rect_conversions.h"
[email protected]77a3bbbb2012-04-05 19:39:3223#include "ui/gfx/size.h"
24
25class IOSurfaceSupport;
26
[email protected]474e4dc2012-07-27 01:38:3427namespace gfx {
28class Rect;
29}
30
[email protected]fc4616f2012-07-21 01:29:5831namespace content {
32
[email protected]77a3bbbb2012-04-05 19:39:3233// This class manages an OpenGL context and IOSurface for the accelerated
34// compositing code path. The GL context is attached to
35// RenderWidgetHostViewCocoa for blitting the IOSurface.
36class CompositingIOSurfaceMac {
37 public:
[email protected]9c481fa2012-11-30 19:21:1638 // Passed to Create() to specify the ordering of the surface relative to the
39 // containing window.
40 enum SurfaceOrder {
41 SURFACE_ORDER_ABOVE_WINDOW,
42 SURFACE_ORDER_BELOW_WINDOW
43 };
44
45 // Returns NULL if IOSurface support is missing or GL APIs fail. Specify in
46 // |order| the desired ordering relationship of the surface to the containing
47 // window.
48 static CompositingIOSurfaceMac* Create(SurfaceOrder order);
[email protected]77a3bbbb2012-04-05 19:39:3249 ~CompositingIOSurfaceMac();
50
51 // Set IOSurface that will be drawn on the next NSView drawRect.
[email protected]f03bcf82012-09-11 02:57:2452 void SetIOSurface(uint64 io_surface_handle,
53 const gfx::Size& size);
[email protected]77a3bbbb2012-04-05 19:39:3254
55 // Blit the IOSurface at the upper-left corner of the |view|. If |view| window
[email protected]4abb018e2012-06-11 17:38:2456 // size is larger than the IOSurface, the remaining right and bottom edges
57 // will be white. |scaleFactor| is 1 in normal views, 2 in HiDPI views.
58 void DrawIOSurface(NSView* view, float scale_factor);
[email protected]77a3bbbb2012-04-05 19:39:3259
[email protected]a2a1f482012-04-11 03:58:5960 // Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef
[email protected]474e4dc2012-07-27 01:38:3461 // into |out|. The copied region is specified with |src_pixel_subrect| and
62 // the data is transformed so that it fits in |dst_pixel_size|.
63 // |src_pixel_subrect| and |dst_pixel_size| are not in DIP but in pixel.
[email protected]d748d0f2013-02-02 23:31:0764 // Caller must ensure that |out| is allocated to dimensions that match
65 // dst_pixel_size, with no additional padding.
[email protected]a02f64e42012-09-24 21:32:4166 // |callback| is invoked when the operation is completed or failed.
67 // Do no call this method again before |callback| is invoked.
68 void CopyTo(const gfx::Rect& src_pixel_subrect,
[email protected]da1b5fa2013-03-02 03:57:4769 float src_scale_factor,
[email protected]474e4dc2012-07-27 01:38:3470 const gfx::Size& dst_pixel_size,
[email protected]d748d0f2013-02-02 23:31:0771 const SkBitmap& out,
72 const base::Callback<void(bool, const SkBitmap&)>& callback);
[email protected]a2a1f482012-04-11 03:58:5973
[email protected]da1b5fa2013-03-02 03:57:4774 // Transfer the contents of the surface to an already-allocated YV12
75 // VideoFrame, and invoke a callback to indicate success or failure.
76 void CopyToVideoFrame(
77 const gfx::Rect& src_subrect,
78 float src_scale_factor,
79 const scoped_refptr<media::VideoFrame>& target,
80 const base::Callback<void(bool)>& callback);
81
[email protected]77a3bbbb2012-04-05 19:39:3282 // Unref the IOSurface and delete the associated GL texture. If the GPU
83 // process is no longer referencing it, this will delete the IOSurface.
84 void UnrefIOSurface();
85
86 // Call when globalFrameDidChange is received on the NSView.
87 void GlobalFrameDidChange();
88
89 // Disassociate the GL context with the NSView and unref the IOSurface. Do
90 // this to switch to software drawing mode.
91 void ClearDrawable();
92
93 bool HasIOSurface() { return !!io_surface_.get(); }
94
[email protected]4abb018e2012-06-11 17:38:2495 const gfx::Size& pixel_io_surface_size() const {
96 return pixel_io_surface_size_;
97 }
[email protected]b44642b2012-06-12 17:18:2798 // In cocoa view units / DIPs.
99 const gfx::Size& io_surface_size() const { return io_surface_size_; }
[email protected]77a3bbbb2012-04-05 19:39:32100
[email protected]2c38e472012-05-24 20:53:43101 bool is_vsync_disabled() const { return is_vsync_disabled_; }
102
[email protected]bd1200b2012-08-05 21:58:08103 // Get vsync scheduling parameters.
[email protected]db2a3c02012-08-17 17:26:18104 // |interval_numerator/interval_denominator| equates to fractional number of
105 // seconds between vsyncs.
[email protected]bd1200b2012-08-05 21:58:08106 void GetVSyncParameters(base::TimeTicks* timebase,
107 uint32* interval_numerator,
108 uint32* interval_denominator);
109
[email protected]77a3bbbb2012-04-05 19:39:32110 private:
[email protected]bd1200b2012-08-05 21:58:08111 friend CVReturn DisplayLinkCallback(CVDisplayLinkRef,
112 const CVTimeStamp*,
113 const CVTimeStamp*,
114 CVOptionFlags,
115 CVOptionFlags*,
116 void*);
117
[email protected]77a3bbbb2012-04-05 19:39:32118 // Vertex structure for use in glDraw calls.
119 struct SurfaceVertex {
120 SurfaceVertex() : x_(0.0f), y_(0.0f), tx_(0.0f), ty_(0.0f) { }
[email protected]77a3bbbb2012-04-05 19:39:32121 void set(float x, float y, float tx, float ty) {
122 x_ = x;
123 y_ = y;
124 tx_ = tx;
125 ty_ = ty;
126 }
[email protected]8c498442012-05-09 01:29:39127 void set_position(float x, float y) {
128 x_ = x;
129 y_ = y;
130 }
[email protected]474e4dc2012-07-27 01:38:34131 void set_texcoord(float tx, float ty) {
132 tx_ = tx;
133 ty_ = ty;
134 }
[email protected]77a3bbbb2012-04-05 19:39:32135 float x_;
136 float y_;
137 float tx_;
138 float ty_;
139 };
140
141 // Counter-clockwise verts starting from upper-left corner (0, 0).
142 struct SurfaceQuad {
[email protected]a2a1f482012-04-11 03:58:59143 void set_size(gfx::Size vertex_size, gfx::Size texcoord_size) {
[email protected]77a3bbbb2012-04-05 19:39:32144 // Texture coordinates are flipped vertically so they can be drawn on
145 // a projection with a flipped y-axis (origin is top left).
[email protected]a2a1f482012-04-11 03:58:59146 float vw = static_cast<float>(vertex_size.width());
147 float vh = static_cast<float>(vertex_size.height());
148 float tw = static_cast<float>(texcoord_size.width());
149 float th = static_cast<float>(texcoord_size.height());
150 verts_[0].set(0.0f, 0.0f, 0.0f, th);
151 verts_[1].set(0.0f, vh, 0.0f, 0.0f);
152 verts_[2].set(vw, vh, tw, 0.0f);
153 verts_[3].set(vw, 0.0f, tw, th);
[email protected]77a3bbbb2012-04-05 19:39:32154 }
[email protected]8c498442012-05-09 01:29:39155 void set_rect(float x1, float y1, float x2, float y2) {
156 verts_[0].set_position(x1, y1);
157 verts_[1].set_position(x1, y2);
158 verts_[2].set_position(x2, y2);
159 verts_[3].set_position(x2, y1);
160 }
[email protected]474e4dc2012-07-27 01:38:34161 void set_texcoord_rect(float tx1, float ty1, float tx2, float ty2) {
162 // Texture coordinates are flipped vertically so they can be drawn on
163 // a projection with a flipped y-axis (origin is top left).
164 verts_[0].set_texcoord(tx1, ty2);
165 verts_[1].set_texcoord(tx1, ty1);
166 verts_[2].set_texcoord(tx2, ty1);
167 verts_[3].set_texcoord(tx2, ty2);
168 }
[email protected]77a3bbbb2012-04-05 19:39:32169 SurfaceVertex verts_[4];
170 };
171
[email protected]a02f64e42012-09-24 21:32:41172 // Keeps track of states and buffers for asynchronous readback of IOSurface.
173 struct CopyContext {
174 CopyContext();
175 ~CopyContext();
176
177 void Reset() {
178 started = false;
179 cycles_elapsed = 0;
180 frame_buffer = 0;
181 frame_buffer_texture = 0;
182 pixel_buffer = 0;
183 use_fence = false;
184 fence = 0;
[email protected]da1b5fa2013-03-02 03:57:47185 map_buffer_callback.Reset();
[email protected]a02f64e42012-09-24 21:32:41186 }
187
188 bool started;
189 int cycles_elapsed;
190 GLuint frame_buffer;
191 GLuint frame_buffer_texture;
192 GLuint pixel_buffer;
193 bool use_fence;
194 GLuint fence;
195 gfx::Rect src_rect;
196 gfx::Size dest_size;
[email protected]da1b5fa2013-03-02 03:57:47197 base::Callback<base::Closure(void*)> map_buffer_callback;
[email protected]a02f64e42012-09-24 21:32:41198 };
199
[email protected]77a3bbbb2012-04-05 19:39:32200 CompositingIOSurfaceMac(IOSurfaceSupport* io_surface_support,
201 NSOpenGLContext* glContext,
[email protected]8c498442012-05-09 01:29:39202 CGLContextObj cglContext,
203 GLuint shader_program_blit_rgb,
204 GLint blit_rgb_sampler_location,
[email protected]2c38e472012-05-24 20:53:43205 GLuint shader_program_white,
[email protected]bd1200b2012-08-05 21:58:08206 bool is_vsync_disabled,
207 CVDisplayLinkRef display_link);
[email protected]77a3bbbb2012-04-05 19:39:32208
[email protected]0be98f32013-01-24 01:43:12209 bool IsVendorIntel();
210
[email protected]77a3bbbb2012-04-05 19:39:32211 // Returns true if IOSurface is ready to render. False otherwise.
212 bool MapIOSurfaceToTexture(uint64 io_surface_handle);
213
214 void UnrefIOSurfaceWithContextCurrent();
215
[email protected]a2a1f482012-04-11 03:58:59216 void DrawQuad(const SurfaceQuad& quad);
217
[email protected]bd1200b2012-08-05 21:58:08218 // Called on display-link thread.
219 void DisplayLinkTick(CVDisplayLinkRef display_link,
[email protected]db2a3c02012-08-17 17:26:18220 const CVTimeStamp* time);
[email protected]bd1200b2012-08-05 21:58:08221
222 void CalculateVsyncParametersLockHeld(const CVTimeStamp* time);
223
224 // Prevent from spinning on CGLFlushDrawable when it fails to throttle to
225 // VSync frequency.
226 void RateLimitDraws();
227
228 void StartOrContinueDisplayLink();
229 void StopDisplayLink();
230
[email protected]661b1452012-09-27 21:13:43231 // Two implementations of CopyTo() in synchronous and asynchronous mode.
[email protected]feed7e42013-02-28 02:13:27232 // These may copy regions smaller than the requested |src_pixel_subrect| if
233 // the iosurface is smaller than |src_pixel_subrect|.
[email protected]661b1452012-09-27 21:13:43234 bool SynchronousCopyTo(const gfx::Rect& src_pixel_subrect,
[email protected]da1b5fa2013-03-02 03:57:47235 float src_scale_factor,
[email protected]661b1452012-09-27 21:13:43236 const gfx::Size& dst_pixel_size,
[email protected]d748d0f2013-02-02 23:31:07237 const SkBitmap& out);
238 bool AsynchronousCopyTo(
239 const gfx::Rect& src_pixel_subrect,
[email protected]da1b5fa2013-03-02 03:57:47240 float src_scale_factor,
[email protected]d748d0f2013-02-02 23:31:07241 const gfx::Size& dst_pixel_size,
[email protected]da1b5fa2013-03-02 03:57:47242 const base::Callback<base::Closure(void*)>& map_buffer_callback);
[email protected]a02f64e42012-09-24 21:32:41243 void FinishCopy();
244 void CleanupResourcesForCopy();
245
[email protected]da1b5fa2013-03-02 03:57:47246 gfx::Rect IntersectWithIOSurface(const gfx::Rect& rect,
247 float scale_factor) const;
[email protected]feed7e42013-02-28 02:13:27248
[email protected]77a3bbbb2012-04-05 19:39:32249 // Cached pointer to IOSurfaceSupport Singleton.
250 IOSurfaceSupport* io_surface_support_;
251
252 // GL context
253 scoped_nsobject<NSOpenGLContext> glContext_;
254 CGLContextObj cglContext_; // weak, backed by |glContext_|.
255
256 // IOSurface data.
257 uint64 io_surface_handle_;
258 base::mac::ScopedCFTypeRef<CFTypeRef> io_surface_;
259
260 // The width and height of the io surface.
[email protected]b44642b2012-06-12 17:18:27261 gfx::Size pixel_io_surface_size_; // In pixels.
262 gfx::Size io_surface_size_; // In view units.
[email protected]77a3bbbb2012-04-05 19:39:32263
264 // The "live" OpenGL texture referring to this IOSurfaceRef. Note
265 // that per the CGLTexImageIOSurface2D API we do not need to
266 // explicitly update this texture's contents once created. All we
267 // need to do is ensure it is re-bound before attempting to draw
268 // with it.
269 GLuint texture_;
270
[email protected]a02f64e42012-09-24 21:32:41271 CopyContext copy_context_;
272
273 // Timer for finishing a copy operation.
274 base::RepeatingTimer<CompositingIOSurfaceMac> copy_timer_;
275
[email protected]8c498442012-05-09 01:29:39276 // Shader parameters.
277 GLuint shader_program_blit_rgb_;
278 GLint blit_rgb_sampler_location_;
279 GLuint shader_program_white_;
280
[email protected]77a3bbbb2012-04-05 19:39:32281 SurfaceQuad quad_;
[email protected]2c38e472012-05-24 20:53:43282
283 bool is_vsync_disabled_;
[email protected]bd1200b2012-08-05 21:58:08284
285 // CVDisplayLink for querying Vsync timing info and throttling swaps.
286 CVDisplayLinkRef display_link_;
287
288 // Timer for stopping display link after a timeout with no swaps.
289 base::DelayTimer<CompositingIOSurfaceMac> display_link_stop_timer_;
290
291 // Lock for sharing data between UI thread and display-link thread.
292 base::Lock lock_;
293
294 // Counts for throttling swaps.
295 int64 vsync_count_;
296 int64 swap_count_;
297
298 // Vsync timing data.
299 base::TimeTicks vsync_timebase_;
300 uint32 vsync_interval_numerator_;
301 uint32 vsync_interval_denominator_;
[email protected]0be98f32013-01-24 01:43:12302
303 bool initialized_is_intel_;
304 bool is_intel_;
305 GLint screen_;
[email protected]77a3bbbb2012-04-05 19:39:32306};
307
[email protected]fc4616f2012-07-21 01:29:58308} // namespace content
309
[email protected]77a3bbbb2012-04-05 19:39:32310#endif // CONTENT_BROWSER_RENDERER_HOST_ACCELERATED_COMPOSITING_VIEW_MAC_H