OLD | NEW |
| (Empty) |
1 // 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_COMPOSITING_IOSURFACE_MAC_H_ | |
6 #define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_ | |
7 | |
8 #include <deque> | |
9 #include <list> | |
10 #include <vector> | |
11 | |
12 #import <Cocoa/Cocoa.h> | |
13 #include <IOSurface/IOSurfaceAPI.h> | |
14 #include <QuartzCore/QuartzCore.h> | |
15 | |
16 #include "base/callback.h" | |
17 #include "base/lazy_instance.h" | |
18 #include "base/mac/scoped_cftyperef.h" | |
19 #include "base/memory/ref_counted.h" | |
20 #include "base/memory/scoped_ptr.h" | |
21 #include "base/time/time.h" | |
22 #include "base/timer/timer.h" | |
23 #include "media/base/video_frame.h" | |
24 #include "ui/gfx/native_widget_types.h" | |
25 #include "ui/gfx/rect.h" | |
26 #include "ui/gfx/rect_conversions.h" | |
27 #include "ui/gfx/size.h" | |
28 | |
29 class SkBitmap; | |
30 | |
31 namespace gfx { | |
32 class Rect; | |
33 } | |
34 | |
35 namespace content { | |
36 | |
37 class CompositingIOSurfaceContext; | |
38 class CompositingIOSurfaceShaderPrograms; | |
39 class CompositingIOSurfaceTransformer; | |
40 class RenderWidgetHostViewFrameSubscriber; | |
41 class RenderWidgetHostViewMac; | |
42 | |
43 // 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. | |
46 class CompositingIOSurfaceMac | |
47 : public base::RefCounted<CompositingIOSurfaceMac> { | |
48 public: | |
49 // Returns NULL if IOSurface or GL API calls fail. | |
50 static scoped_refptr<CompositingIOSurfaceMac> Create(); | |
51 | |
52 // Set IOSurface that will be drawn on the next NSView drawRect. | |
53 bool SetIOSurfaceWithContextCurrent( | |
54 scoped_refptr<CompositingIOSurfaceContext> current_context, | |
55 IOSurfaceID io_surface_handle, | |
56 const gfx::Size& size, | |
57 float scale_factor) WARN_UNUSED_RESULT; | |
58 | |
59 // Get the CGL renderer ID currently associated with this context. | |
60 int GetRendererID(); | |
61 | |
62 // Blit the IOSurface to the rectangle specified by |window_rect| in DIPs, | |
63 // with the origin in the lower left corner. If the window rect's size is | |
64 // larger than the IOSurface, the remaining right and bottom edges will be | |
65 // white. |window_scale_factor| is 1 in normal views, 2 in HiDPI views. | |
66 bool DrawIOSurface( | |
67 scoped_refptr<CompositingIOSurfaceContext> drawing_context, | |
68 const gfx::Rect& window_rect, | |
69 float window_scale_factor) WARN_UNUSED_RESULT; | |
70 | |
71 // Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef | |
72 // into |out|. The copied region is specified with |src_pixel_subrect| and | |
73 // the data is transformed so that it fits in |dst_pixel_size|. | |
74 // |src_pixel_subrect| and |dst_pixel_size| are not in DIP but in pixel. | |
75 // Caller must ensure that |out| is allocated to dimensions that match | |
76 // dst_pixel_size, with no additional padding. | |
77 // |callback| is invoked when the operation is completed or failed. | |
78 // Do no call this method again before |callback| is invoked. | |
79 void CopyTo(const gfx::Rect& src_pixel_subrect, | |
80 const gfx::Size& dst_pixel_size, | |
81 const base::Callback<void(bool, const SkBitmap&)>& callback); | |
82 | |
83 // Transfer the contents of the surface to an already-allocated YV12 | |
84 // VideoFrame, and invoke a callback to indicate success or failure. | |
85 void CopyToVideoFrame( | |
86 const gfx::Rect& src_subrect, | |
87 const scoped_refptr<media::VideoFrame>& target, | |
88 const base::Callback<void(bool)>& callback); | |
89 | |
90 // Unref the IOSurface and delete the associated GL texture. If the GPU | |
91 // process is no longer referencing it, this will delete the IOSurface. | |
92 void UnrefIOSurface(); | |
93 | |
94 bool HasIOSurface() { return !!io_surface_.get(); } | |
95 | |
96 const gfx::Size& pixel_io_surface_size() const { | |
97 return pixel_io_surface_size_; | |
98 } | |
99 // In cocoa view units / DIPs. | |
100 const gfx::Size& dip_io_surface_size() const { return dip_io_surface_size_; } | |
101 float scale_factor() const { return scale_factor_; } | |
102 | |
103 // Returns true if asynchronous readback is supported on this system. | |
104 bool IsAsynchronousReadbackSupported(); | |
105 | |
106 // Scan the list of started asynchronous copies and test if each one has | |
107 // completed. If |block_until_finished| is true, then block until all | |
108 // pending copies are finished. | |
109 void CheckIfAllCopiesAreFinished(bool block_until_finished); | |
110 | |
111 // Returns true if the offscreen context used by this surface has been | |
112 // poisoned. | |
113 bool HasBeenPoisoned() const; | |
114 | |
115 private: | |
116 friend class base::RefCounted<CompositingIOSurfaceMac>; | |
117 | |
118 // Vertex structure for use in glDraw calls. | |
119 struct SurfaceVertex { | |
120 SurfaceVertex() : x_(0.0f), y_(0.0f), tx_(0.0f), ty_(0.0f) { } | |
121 void set(float x, float y, float tx, float ty) { | |
122 x_ = x; | |
123 y_ = y; | |
124 tx_ = tx; | |
125 ty_ = ty; | |
126 } | |
127 void set_position(float x, float y) { | |
128 x_ = x; | |
129 y_ = y; | |
130 } | |
131 void set_texcoord(float tx, float ty) { | |
132 tx_ = tx; | |
133 ty_ = ty; | |
134 } | |
135 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 { | |
143 void set_size(gfx::Size vertex_size, gfx::Size texcoord_size) { | |
144 // Texture coordinates are flipped vertically so they can be drawn on | |
145 // a projection with a flipped y-axis (origin is top left). | |
146 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); | |
154 } | |
155 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 } | |
161 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 } | |
169 SurfaceVertex verts_[4]; | |
170 }; | |
171 | |
172 CompositingIOSurfaceMac( | |
173 const scoped_refptr<CompositingIOSurfaceContext>& context); | |
174 ~CompositingIOSurfaceMac(); | |
175 | |
176 // Returns true if IOSurface is ready to render. False otherwise. | |
177 bool MapIOSurfaceToTextureWithContextCurrent( | |
178 const scoped_refptr<CompositingIOSurfaceContext>& current_context, | |
179 const gfx::Size pixel_size, | |
180 float scale_factor, | |
181 IOSurfaceID io_surface_handle) WARN_UNUSED_RESULT; | |
182 | |
183 void UnrefIOSurfaceWithContextCurrent(); | |
184 | |
185 void DrawQuad(const SurfaceQuad& quad); | |
186 | |
187 // Check for GL errors and store the result in error_. Only return new | |
188 // errors | |
189 GLenum GetAndSaveGLError(); | |
190 | |
191 // Offscreen context used for all operations other than drawing to the | |
192 // screen. This is in the same share group as the contexts used for | |
193 // drawing, and is the same for all IOSurfaces in all windows. | |
194 scoped_refptr<CompositingIOSurfaceContext> offscreen_context_; | |
195 | |
196 // IOSurface data. | |
197 IOSurfaceID io_surface_handle_; | |
198 base::ScopedCFTypeRef<IOSurfaceRef> io_surface_; | |
199 | |
200 // The width and height of the io surface. | |
201 gfx::Size pixel_io_surface_size_; // In pixels. | |
202 gfx::Size dip_io_surface_size_; // In view / density independent pixels. | |
203 float scale_factor_; | |
204 | |
205 // The "live" OpenGL texture referring to this IOSurfaceRef. Note | |
206 // that per the CGLTexImageIOSurface2D API we do not need to | |
207 // explicitly update this texture's contents once created. All we | |
208 // need to do is ensure it is re-bound before attempting to draw | |
209 // with it. | |
210 GLuint texture_; | |
211 | |
212 // Error saved by GetAndSaveGLError | |
213 GLint gl_error_; | |
214 | |
215 // Aggressive IOSurface eviction logic. When using CoreAnimation, IOSurfaces | |
216 // are used only transiently to transfer from the GPU process to the browser | |
217 // process. Once the IOSurface has been drawn to its CALayer, the CALayer | |
218 // will not need updating again until its view is hidden and re-shown. | |
219 // Aggressively evict surfaces when more than 8 (the number allowed by the | |
220 // memory manager for fast tab switching) are allocated. | |
221 enum { | |
222 kMaximumUnevictedSurfaces = 8, | |
223 }; | |
224 typedef std::list<CompositingIOSurfaceMac*> EvictionQueue; | |
225 void EvictionMarkUpdated(); | |
226 void EvictionMarkEvicted(); | |
227 EvictionQueue::iterator eviction_queue_iterator_; | |
228 bool eviction_has_been_drawn_since_updated_; | |
229 | |
230 static void EvictionScheduleDoEvict(); | |
231 static void EvictionDoEvict(); | |
232 static base::LazyInstance<EvictionQueue> eviction_queue_; | |
233 static bool eviction_scheduled_; | |
234 }; | |
235 | |
236 } // namespace content | |
237 | |
238 #endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_ | |
OLD | NEW |