1// Copyright 2013 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_LAYER_MAC_H_ 6#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_ 7 8#import <Cocoa/Cocoa.h> 9 10#include "base/mac/scoped_cftyperef.h" 11#include "base/memory/ref_counted.h" 12#include "base/timer/timer.h" 13#include "ui/gfx/size.h" 14 15@class IOSurfaceLayer; 16 17namespace content { 18class CompositingIOSurfaceMac; 19class CompositingIOSurfaceContext; 20 21// The interface through which the IOSurfaceLayer calls back into 22// the structrue that created it (RenderWidgetHostViewMac or 23// BrowserCompositorViewMac). 24class IOSurfaceLayerClient { 25 public: 26 // Used to indicate that the layer should attempt to draw immediately and 27 // should (even if the draw is elided by the system), ack the frame 28 // immediately. 29 virtual bool IOSurfaceLayerShouldAckImmediately() const = 0; 30 31 // Called when a frame is drawn or when, because the layer is not visible, it 32 // is known that the frame will never drawn. 33 virtual void IOSurfaceLayerDidDrawFrame() = 0; 34 35 // Called when an error prevents the frame from being drawn. 36 virtual void IOSurfaceLayerHitError() = 0; 37}; 38 39// IOSurfaceLayerHelper provides C++ functionality needed for the 40// IOSurfaceLayer class, and does most of the heavy lifting for the 41// class. 42// TODO(ccameron): This class should own IOSurfaceLayer, rather than 43// vice versa. 44class IOSurfaceLayerHelper { 45 public: 46 IOSurfaceLayerHelper(IOSurfaceLayerClient* client, 47 IOSurfaceLayer* layer); 48 ~IOSurfaceLayerHelper(); 49 50 // Called when the IOSurfaceLayer gets a new frame. 51 void GotNewFrame(); 52 53 // Called whenever -[IOSurfaceLayer setNeedsDisplay] is called. 54 void SetNeedsDisplay(); 55 56 // Called whenever -[IOSurfaceLayer canDrawInCGLContext] is called, 57 // to determine if a new frame should be drawn. 58 bool CanDraw(); 59 60 // Called whenever -[IOSurfaceLayer drawInCGLContext] draws a 61 // frame. 62 void DidDraw(bool success); 63 64 // Immediately re-draw the layer, even if the content has not changed, and 65 // ensure that the frame be acked. 66 void SetNeedsDisplayAndDisplayAndAck(); 67 68 // Immediately draw the layer, only if one is pending, and ensure that the 69 // frame be acked. 70 void DisplayIfNeededAndAck(); 71 72 // Mark a bracket in which new frames are being pumped in a restricted nested 73 // run loop. During this time frames are acked immediately and draws are 74 // deferred until the bracket ends. 75 void BeginPumpingFrames(); 76 void EndPumpingFrames(); 77 78 private: 79 // Called whenever the frame provided in GotNewFrame should be acknowledged 80 // (this may be because it was drawn, or it may be to unblock the 81 // compositor). 82 void AckPendingFrame(bool success); 83 84 void TimerFired(); 85 86 // The client that the owning layer was created with. 87 content::IOSurfaceLayerClient* const client_; 88 89 // The layer that owns this helper. 90 IOSurfaceLayer* const layer_; 91 92 // Used to track when canDrawInCGLContext should return YES. This can be 93 // in response to receiving a new compositor frame, or from any of the events 94 // that cause setNeedsDisplay to be called on the layer. 95 bool needs_display_; 96 97 // This is set when a frame is received, and un-set when the frame is drawn. 98 bool has_pending_frame_; 99 100 // Incremented every time that this layer is asked to draw but does not have 101 // new content to draw. 102 uint64 did_not_draw_counter_; 103 104 // Set when inside a BeginPumpingFrames/EndPumpingFrames block. 105 bool is_pumping_frames_; 106 107 // The browser places back-pressure on the GPU by not acknowledging swap 108 // calls until they appear on the screen. This can lead to hangs if the 109 // view is moved offscreen (among other things). Prevent hangs by always 110 // acknowledging the frame after timeout of 1/6th of a second has passed. 111 base::DelayTimer<IOSurfaceLayerHelper> timer_; 112}; 113 114} // namespace content 115 116// The CoreAnimation layer for drawing accelerated content. 117@interface IOSurfaceLayer : CAOpenGLLayer { 118 @private 119 scoped_refptr<content::CompositingIOSurfaceMac> iosurface_; 120 scoped_refptr<content::CompositingIOSurfaceContext> context_; 121 122 scoped_ptr<content::IOSurfaceLayerHelper> helper_; 123} 124 125- (id)initWithClient:(content::IOSurfaceLayerClient*)client 126 withScaleFactor:(float)scale_factor; 127 128- (bool)gotFrameWithIOSurface:(IOSurfaceID)io_surface_id 129 withPixelSize:(gfx::Size)pixel_size 130 withScaleFactor:(float)scale_factor; 131 132// Context poison accessors. 133- (void)poisonContextAndSharegroup; 134- (bool)hasBeenPoisoned; 135 136- (float)scaleFactor; 137 138// The CGL renderer ID. 139- (int)rendererID; 140 141// Mark that the client is no longer valid and cannot be called back into. This 142// must be called before the layer is destroyed. 143- (void)resetClient; 144 145// Called when a new frame is received. 146- (void)gotNewFrame; 147 148// Force a draw immediately (even if this means re-displaying a previously 149// displayed frame). 150- (void)setNeedsDisplayAndDisplayAndAck; 151 152// Force a draw immediately, but only if one was requested. 153- (void)displayIfNeededAndAck; 154 155// Mark a bracket in which new frames are being pumped in a restricted nested 156// run loop. 157- (void)beginPumpingFrames; 158- (void)endPumpingFrames; 159@end 160 161#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_ 162