blob: 22d674981e2646156fa4274db9985b81ae36e9f4 [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
[email protected]ea2e5412013-03-21 23:07:545#ifndef CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_
6#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_
[email protected]77a3bbbb2012-04-05 19:39:327
[email protected]520376b2013-03-24 03:18:178#include <deque>
[email protected]5c307f92013-04-16 18:44:569#include <vector>
[email protected]520376b2013-03-24 03:18:1710
[email protected]77a3bbbb2012-04-05 19:39:3211#import <Cocoa/Cocoa.h>
[email protected]bd1200b2012-08-05 21:58:0812#import <QuartzCore/CVDisplayLink.h>
[email protected]77a3bbbb2012-04-05 19:39:3213#include <QuartzCore/QuartzCore.h>
14
[email protected]a02f64e42012-09-24 21:32:4115#include "base/callback.h"
[email protected]77a3bbbb2012-04-05 19:39:3216#include "base/mac/scoped_cftyperef.h"
[email protected]ea2e5412013-03-21 23:07:5417#include "base/memory/scoped_ptr.h"
[email protected]bd1200b2012-08-05 21:58:0818#include "base/synchronization/lock.h"
[email protected]a43858f2013-06-28 15:18:3719#include "base/time/time.h"
20#include "base/timer/timer.h"
[email protected]da1b5fa2013-03-02 03:57:4721#include "media/base/video_frame.h"
[email protected]9cc888e2013-06-06 02:54:5222#include "ui/base/latency_info.h"
[email protected]77a3bbbb2012-04-05 19:39:3223#include "ui/gfx/native_widget_types.h"
[email protected]a02f64e42012-09-24 21:32:4124#include "ui/gfx/rect.h"
[email protected]da1b5fa2013-03-02 03:57:4725#include "ui/gfx/rect_conversions.h"
[email protected]77a3bbbb2012-04-05 19:39:3226#include "ui/gfx/size.h"
27
28class IOSurfaceSupport;
[email protected]ea2e5412013-03-21 23:07:5429class SkBitmap;
[email protected]77a3bbbb2012-04-05 19:39:3230
[email protected]474e4dc2012-07-27 01:38:3431namespace gfx {
32class Rect;
33}
34
[email protected]fc4616f2012-07-21 01:29:5835namespace content {
36
[email protected]f78ac522013-04-02 23:45:1637class CompositingIOSurfaceContext;
[email protected]ea2e5412013-03-21 23:07:5438class CompositingIOSurfaceShaderPrograms;
39class CompositingIOSurfaceTransformer;
[email protected]1d3d39a2013-03-05 06:03:0040class RenderWidgetHostViewFrameSubscriber;
[email protected]f9f4d2d2013-06-07 15:20:1841class RenderWidgetHostViewMac;
[email protected]1d3d39a2013-03-05 06:03:0042
[email protected]77a3bbbb2012-04-05 19:39:3243// This class manages an OpenGL context and IOSurface for the accelerated
44// compositing code path. The GL context is attached to
45// RenderWidgetHostViewCocoa for blitting the IOSurface.
46class CompositingIOSurfaceMac {
47 public:
[email protected]9c481fa2012-11-30 19:21:1648 // Passed to Create() to specify the ordering of the surface relative to the
49 // containing window.
50 enum SurfaceOrder {
[email protected]2906f852013-04-09 19:35:0751 SURFACE_ORDER_ABOVE_WINDOW = 0,
52 SURFACE_ORDER_BELOW_WINDOW = 1,
[email protected]9c481fa2012-11-30 19:21:1653 };
54
55 // Returns NULL if IOSurface support is missing or GL APIs fail. Specify in
56 // |order| the desired ordering relationship of the surface to the containing
57 // window.
[email protected]b386b97e2013-06-06 20:31:0858 static CompositingIOSurfaceMac* Create(int window_number);
[email protected]f9f4d2d2013-06-07 15:20:1859 static CompositingIOSurfaceMac* Create(
60 const scoped_refptr<CompositingIOSurfaceContext>& context);
[email protected]77a3bbbb2012-04-05 19:39:3261 ~CompositingIOSurfaceMac();
62
63 // Set IOSurface that will be drawn on the next NSView drawRect.
[email protected]58469852013-06-18 12:12:2164 bool SetIOSurface(uint64 io_surface_handle,
[email protected]eca216c2013-05-27 05:48:3365 const gfx::Size& size,
[email protected]9cc888e2013-06-06 02:54:5266 float scale_factor,
67 const ui::LatencyInfo& latency_info);
[email protected]77a3bbbb2012-04-05 19:39:3268
[email protected]cd195afe2013-03-06 09:31:3769 // Get the CGL renderer ID currently associated with this context.
70 int GetRendererID();
71
[email protected]f9f4d2d2013-06-07 15:20:1872 // Blit the IOSurface at the upper-left corner of the of the specified
73 // window_size. If the window size is larger than the IOSurface, the
74 // remaining right and bottom edges will be white. |scaleFactor| is 1
75 // in normal views, 2 in HiDPI views. |frame_subscriber| listens to
76 // this draw event and provides output buffer for copying this frame into.
[email protected]58469852013-06-18 12:12:2177 bool DrawIOSurface(const gfx::Size& window_size,
[email protected]f9f4d2d2013-06-07 15:20:1878 float window_scale_factor,
79 RenderWidgetHostViewFrameSubscriber* frame_subscriber,
80 bool using_core_animation);
[email protected]58469852013-06-18 12:12:2181 bool DrawIOSurface(RenderWidgetHostViewMac* render_widget_host_view);
[email protected]77a3bbbb2012-04-05 19:39:3282
[email protected]a2a1f482012-04-11 03:58:5983 // Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef
[email protected]474e4dc2012-07-27 01:38:3484 // into |out|. The copied region is specified with |src_pixel_subrect| and
85 // the data is transformed so that it fits in |dst_pixel_size|.
86 // |src_pixel_subrect| and |dst_pixel_size| are not in DIP but in pixel.
[email protected]d748d0f2013-02-02 23:31:0787 // Caller must ensure that |out| is allocated to dimensions that match
88 // dst_pixel_size, with no additional padding.
[email protected]a02f64e42012-09-24 21:32:4189 // |callback| is invoked when the operation is completed or failed.
90 // Do no call this method again before |callback| is invoked.
91 void CopyTo(const gfx::Rect& src_pixel_subrect,
[email protected]474e4dc2012-07-27 01:38:3492 const gfx::Size& dst_pixel_size,
[email protected]d748d0f2013-02-02 23:31:0793 const base::Callback<void(bool, const SkBitmap&)>& callback);
[email protected]a2a1f482012-04-11 03:58:5994
[email protected]da1b5fa2013-03-02 03:57:4795 // Transfer the contents of the surface to an already-allocated YV12
96 // VideoFrame, and invoke a callback to indicate success or failure.
97 void CopyToVideoFrame(
98 const gfx::Rect& src_subrect,
[email protected]da1b5fa2013-03-02 03:57:4799 const scoped_refptr<media::VideoFrame>& target,
100 const base::Callback<void(bool)>& callback);
101
[email protected]77a3bbbb2012-04-05 19:39:32102 // Unref the IOSurface and delete the associated GL texture. If the GPU
103 // process is no longer referencing it, this will delete the IOSurface.
104 void UnrefIOSurface();
105
106 // Call when globalFrameDidChange is received on the NSView.
107 void GlobalFrameDidChange();
108
109 // Disassociate the GL context with the NSView and unref the IOSurface. Do
110 // this to switch to software drawing mode.
111 void ClearDrawable();
112
113 bool HasIOSurface() { return !!io_surface_.get(); }
114
[email protected]4abb018e2012-06-11 17:38:24115 const gfx::Size& pixel_io_surface_size() const {
116 return pixel_io_surface_size_;
117 }
[email protected]b44642b2012-06-12 17:18:27118 // In cocoa view units / DIPs.
[email protected]eca216c2013-05-27 05:48:33119 const gfx::Size& dip_io_surface_size() const { return dip_io_surface_size_; }
[email protected]f9f4d2d2013-06-07 15:20:18120 float scale_factor() const { return scale_factor_; }
[email protected]42852902013-05-07 20:05:22121
[email protected]f78ac522013-04-02 23:45:16122 bool is_vsync_disabled() const;
[email protected]2c38e472012-05-24 20:53:43123
[email protected]f9f4d2d2013-06-07 15:20:18124 const scoped_refptr<CompositingIOSurfaceContext>& context() {
125 return context_;
126 }
127
[email protected]bd1200b2012-08-05 21:58:08128 // Get vsync scheduling parameters.
[email protected]db2a3c02012-08-17 17:26:18129 // |interval_numerator/interval_denominator| equates to fractional number of
130 // seconds between vsyncs.
[email protected]bd1200b2012-08-05 21:58:08131 void GetVSyncParameters(base::TimeTicks* timebase,
132 uint32* interval_numerator,
133 uint32* interval_denominator);
134
[email protected]ea2e5412013-03-21 23:07:54135 // Returns true if asynchronous readback is supported on this system.
136 bool IsAsynchronousReadbackSupported();
137
[email protected]77a3bbbb2012-04-05 19:39:32138 private:
[email protected]bd1200b2012-08-05 21:58:08139 friend CVReturn DisplayLinkCallback(CVDisplayLinkRef,
140 const CVTimeStamp*,
141 const CVTimeStamp*,
142 CVOptionFlags,
143 CVOptionFlags*,
144 void*);
145
[email protected]77a3bbbb2012-04-05 19:39:32146 // Vertex structure for use in glDraw calls.
147 struct SurfaceVertex {
148 SurfaceVertex() : x_(0.0f), y_(0.0f), tx_(0.0f), ty_(0.0f) { }
[email protected]77a3bbbb2012-04-05 19:39:32149 void set(float x, float y, float tx, float ty) {
150 x_ = x;
151 y_ = y;
152 tx_ = tx;
153 ty_ = ty;
154 }
[email protected]8c498442012-05-09 01:29:39155 void set_position(float x, float y) {
156 x_ = x;
157 y_ = y;
158 }
[email protected]474e4dc2012-07-27 01:38:34159 void set_texcoord(float tx, float ty) {
160 tx_ = tx;
161 ty_ = ty;
162 }
[email protected]77a3bbbb2012-04-05 19:39:32163 float x_;
164 float y_;
165 float tx_;
166 float ty_;
167 };
168
169 // Counter-clockwise verts starting from upper-left corner (0, 0).
170 struct SurfaceQuad {
[email protected]a2a1f482012-04-11 03:58:59171 void set_size(gfx::Size vertex_size, gfx::Size texcoord_size) {
[email protected]77a3bbbb2012-04-05 19:39:32172 // Texture coordinates are flipped vertically so they can be drawn on
173 // a projection with a flipped y-axis (origin is top left).
[email protected]a2a1f482012-04-11 03:58:59174 float vw = static_cast<float>(vertex_size.width());
175 float vh = static_cast<float>(vertex_size.height());
176 float tw = static_cast<float>(texcoord_size.width());
177 float th = static_cast<float>(texcoord_size.height());
178 verts_[0].set(0.0f, 0.0f, 0.0f, th);
179 verts_[1].set(0.0f, vh, 0.0f, 0.0f);
180 verts_[2].set(vw, vh, tw, 0.0f);
181 verts_[3].set(vw, 0.0f, tw, th);
[email protected]77a3bbbb2012-04-05 19:39:32182 }
[email protected]8c498442012-05-09 01:29:39183 void set_rect(float x1, float y1, float x2, float y2) {
184 verts_[0].set_position(x1, y1);
185 verts_[1].set_position(x1, y2);
186 verts_[2].set_position(x2, y2);
187 verts_[3].set_position(x2, y1);
188 }
[email protected]474e4dc2012-07-27 01:38:34189 void set_texcoord_rect(float tx1, float ty1, float tx2, float ty2) {
190 // Texture coordinates are flipped vertically so they can be drawn on
191 // a projection with a flipped y-axis (origin is top left).
192 verts_[0].set_texcoord(tx1, ty2);
193 verts_[1].set_texcoord(tx1, ty1);
194 verts_[2].set_texcoord(tx2, ty1);
195 verts_[3].set_texcoord(tx2, ty2);
196 }
[email protected]77a3bbbb2012-04-05 19:39:32197 SurfaceVertex verts_[4];
198 };
199
[email protected]ea2e5412013-03-21 23:07:54200 // Keeps track of states and buffers for readback of IOSurface.
[email protected]5c307f92013-04-16 18:44:56201 //
202 // TODO(miu): Major code refactoring is badly needed! To be done in a
203 // soon-upcoming change. For now, we blatantly violate the style guide with
204 // respect to struct vs. class usage:
[email protected]a02f64e42012-09-24 21:32:41205 struct CopyContext {
[email protected]5c307f92013-04-16 18:44:56206 explicit CopyContext(const scoped_refptr<CompositingIOSurfaceContext>& ctx);
[email protected]a02f64e42012-09-24 21:32:41207 ~CopyContext();
208
[email protected]5c307f92013-04-16 18:44:56209 // Delete any references to owned OpenGL objects. This must be called
210 // within the OpenGL context just before destruction.
211 void ReleaseCachedGLObjects();
212
213 // The following two methods assume |num_outputs| has been set, and are
214 // being called within the OpenGL context.
215 void PrepareReadbackFramebuffers();
216 void PrepareForAsynchronousReadback();
217
218 const scoped_ptr<CompositingIOSurfaceTransformer> transformer;
[email protected]ea2e5412013-03-21 23:07:54219 int num_outputs;
[email protected]5c307f92013-04-16 18:44:56220 GLuint output_textures[3]; // Not owned.
[email protected]ea2e5412013-03-21 23:07:54221 // Note: For YUV, the |output_texture_sizes| widths are in terms of 4-byte
222 // quads, not pixels.
223 gfx::Size output_texture_sizes[3];
224 GLuint frame_buffers[3];
225 GLuint pixel_buffers[3];
226 GLuint fence; // When non-zero, doing an asynchronous copy.
[email protected]a02f64e42012-09-24 21:32:41227 int cycles_elapsed;
[email protected]ea2e5412013-03-21 23:07:54228 base::Callback<bool(const void*, int)> map_buffer_callback;
229 base::Callback<void(bool)> done_callback;
[email protected]a02f64e42012-09-24 21:32:41230 };
231
[email protected]ea2e5412013-03-21 23:07:54232 CompositingIOSurfaceMac(
233 IOSurfaceSupport* io_surface_support,
[email protected]f9f4d2d2013-06-07 15:20:18234 const scoped_refptr<CompositingIOSurfaceContext>& context);
[email protected]4d23fa72013-05-09 09:20:18235
236 void SetupCVDisplayLink();
[email protected]77a3bbbb2012-04-05 19:39:32237
[email protected]2906f852013-04-09 19:35:07238 // If this IOSurface has moved to a different window, use that window's
239 // GL context (if multiple visible windows are using the same GL context
240 // then call to setView call can stall and prevent reaching 60fps).
[email protected]c13aa782013-05-15 00:34:51241 void SwitchToContextOnNewWindow(NSView* view,
[email protected]b386b97e2013-06-06 20:31:08242 int window_number);
[email protected]2906f852013-04-09 19:35:07243
[email protected]0be98f32013-01-24 01:43:12244 bool IsVendorIntel();
245
[email protected]77a3bbbb2012-04-05 19:39:32246 // Returns true if IOSurface is ready to render. False otherwise.
247 bool MapIOSurfaceToTexture(uint64 io_surface_handle);
248
249 void UnrefIOSurfaceWithContextCurrent();
250
[email protected]a2a1f482012-04-11 03:58:59251 void DrawQuad(const SurfaceQuad& quad);
252
[email protected]bd1200b2012-08-05 21:58:08253 // Called on display-link thread.
254 void DisplayLinkTick(CVDisplayLinkRef display_link,
[email protected]db2a3c02012-08-17 17:26:18255 const CVTimeStamp* time);
[email protected]bd1200b2012-08-05 21:58:08256
257 void CalculateVsyncParametersLockHeld(const CVTimeStamp* time);
258
259 // Prevent from spinning on CGLFlushDrawable when it fails to throttle to
260 // VSync frequency.
261 void RateLimitDraws();
262
263 void StartOrContinueDisplayLink();
264 void StopDisplayLink();
265
[email protected]1d3d39a2013-03-05 06:03:00266 // Copy current frame to |target| video frame. This method must be called
267 // within a CGL context. Returns a callback that should be called outside
268 // of the CGL context.
[email protected]520376b2013-03-24 03:18:17269 // If |called_within_draw| is true this method is called within a drawing
270 // operations. This allow certain optimizations.
[email protected]ea2e5412013-03-21 23:07:54271 base::Closure CopyToVideoFrameWithinContext(
[email protected]1d3d39a2013-03-05 06:03:00272 const gfx::Rect& src_subrect,
[email protected]520376b2013-03-24 03:18:17273 bool called_within_draw,
[email protected]1d3d39a2013-03-05 06:03:00274 const scoped_refptr<media::VideoFrame>& target,
275 const base::Callback<void(bool)>& callback);
276
[email protected]ea2e5412013-03-21 23:07:54277 // Common GPU-readback copy path. Only one of |bitmap_output| or
278 // |video_frame_output| may be specified: Either ARGB is written to
279 // |bitmap_output| or letter-boxed YV12 is written to |video_frame_output|.
280 base::Closure CopyToSelectedOutputWithinContext(
[email protected]d748d0f2013-02-02 23:31:07281 const gfx::Rect& src_pixel_subrect,
[email protected]ea2e5412013-03-21 23:07:54282 const gfx::Rect& dst_pixel_rect,
[email protected]520376b2013-03-24 03:18:17283 bool called_within_draw,
[email protected]ea2e5412013-03-21 23:07:54284 const SkBitmap* bitmap_output,
285 const scoped_refptr<media::VideoFrame>& video_frame_output,
286 const base::Callback<void(bool)>& done_callback);
[email protected]520376b2013-03-24 03:18:17287
288 // TODO(hclam): These two methods should be static.
[email protected]ea2e5412013-03-21 23:07:54289 void AsynchronousReadbackForCopy(
290 const gfx::Rect& dst_pixel_rect,
[email protected]520376b2013-03-24 03:18:17291 bool called_within_draw,
292 CopyContext* copy_context,
[email protected]ea2e5412013-03-21 23:07:54293 const SkBitmap* bitmap_output,
294 const scoped_refptr<media::VideoFrame>& video_frame_output);
295 bool SynchronousReadbackForCopy(
296 const gfx::Rect& dst_pixel_rect,
[email protected]520376b2013-03-24 03:18:17297 CopyContext* copy_context,
[email protected]ea2e5412013-03-21 23:07:54298 const SkBitmap* bitmap_output,
299 const scoped_refptr<media::VideoFrame>& video_frame_output);
[email protected]520376b2013-03-24 03:18:17300
301 // Scan the list of started asynchronous copies and test if each one has
302 // completed.
303 void FinishAllCopies();
304 void FinishAllCopiesWithinContext(
305 std::vector<base::Closure>* done_callbacks);
306
[email protected]520376b2013-03-24 03:18:17307 void FailAllCopies();
[email protected]5c307f92013-04-16 18:44:56308 void DestroyAllCopyContextsWithinContext();
[email protected]a02f64e42012-09-24 21:32:41309
[email protected]58469852013-06-18 12:12:21310 // Check for GL errors and store the result in error_. Only return new
311 // errors
312 GLenum GetAndSaveGLError();
313
[email protected]eca216c2013-05-27 05:48:33314 gfx::Rect IntersectWithIOSurface(const gfx::Rect& rect) const;
[email protected]feed7e42013-02-28 02:13:27315
[email protected]77a3bbbb2012-04-05 19:39:32316 // Cached pointer to IOSurfaceSupport Singleton.
317 IOSurfaceSupport* io_surface_support_;
318
[email protected]2906f852013-04-09 19:35:07319 // GL context, and parameters for context sharing. This may change when
320 // moving between windows, but will never be NULL.
[email protected]f78ac522013-04-02 23:45:16321 scoped_refptr<CompositingIOSurfaceContext> context_;
[email protected]77a3bbbb2012-04-05 19:39:32322
323 // IOSurface data.
324 uint64 io_surface_handle_;
[email protected]3df79f42013-06-24 18:49:05325 base::ScopedCFTypeRef<CFTypeRef> io_surface_;
[email protected]77a3bbbb2012-04-05 19:39:32326
327 // The width and height of the io surface.
[email protected]b44642b2012-06-12 17:18:27328 gfx::Size pixel_io_surface_size_; // In pixels.
[email protected]eca216c2013-05-27 05:48:33329 gfx::Size dip_io_surface_size_; // In view / density independent pixels.
[email protected]f9f4d2d2013-06-07 15:20:18330 float scale_factor_;
[email protected]77a3bbbb2012-04-05 19:39:32331
332 // The "live" OpenGL texture referring to this IOSurfaceRef. Note
333 // that per the CGLTexImageIOSurface2D API we do not need to
334 // explicitly update this texture's contents once created. All we
335 // need to do is ensure it is re-bound before attempting to draw
336 // with it.
337 GLuint texture_;
338
[email protected]5c307f92013-04-16 18:44:56339 // A pool of CopyContexts with OpenGL objects ready for re-use. Prefer to
340 // pull one from the pool before creating a new CopyContext.
341 std::vector<CopyContext*> copy_context_pool_;
342
343 // CopyContexts being used for in-flight copy operations.
344 std::deque<CopyContext*> copy_requests_;
[email protected]a02f64e42012-09-24 21:32:41345
346 // Timer for finishing a copy operation.
[email protected]520376b2013-03-24 03:18:17347 base::Timer finish_copy_timer_;
[email protected]a02f64e42012-09-24 21:32:41348
[email protected]bd1200b2012-08-05 21:58:08349 // CVDisplayLink for querying Vsync timing info and throttling swaps.
350 CVDisplayLinkRef display_link_;
351
352 // Timer for stopping display link after a timeout with no swaps.
353 base::DelayTimer<CompositingIOSurfaceMac> display_link_stop_timer_;
354
355 // Lock for sharing data between UI thread and display-link thread.
356 base::Lock lock_;
357
[email protected]bd1200b2012-08-05 21:58:08358 // Vsync timing data.
359 base::TimeTicks vsync_timebase_;
360 uint32 vsync_interval_numerator_;
361 uint32 vsync_interval_denominator_;
[email protected]0be98f32013-01-24 01:43:12362
363 bool initialized_is_intel_;
364 bool is_intel_;
365 GLint screen_;
[email protected]9cc888e2013-06-06 02:54:52366
[email protected]58469852013-06-18 12:12:21367 // Error saved by GetAndSaveGLError
368 GLint gl_error_;
369
[email protected]9cc888e2013-06-06 02:54:52370 ui::LatencyInfo latency_info_;
[email protected]77a3bbbb2012-04-05 19:39:32371};
372
[email protected]fc4616f2012-07-21 01:29:58373} // namespace content
374
[email protected]ea2e5412013-03-21 23:07:54375#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_