| 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 |