Remove implicit conversions from scoped_refptr to T* in content/browser/service_worker
[chromium-blink-merge.git] / content / browser / compositor / browser_compositor_view_private_mac.mm
blob90c834054313df4d868f3e913cf59c09f8a70d05
1 // Copyright 2014 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.
5 #include "content/browser/compositor/browser_compositor_view_private_mac.h"
7 #include <map>
9 #include "base/debug/trace_event.h"
10 #include "base/lazy_instance.h"
11 #include "base/message_loop/message_loop.h"
12 #include "content/browser/compositor/gpu_process_transport_factory.h"
13 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
14 #include "content/browser/renderer_host/compositing_iosurface_mac.h"
15 #include "content/browser/renderer_host/dip_util.h"
16 #include "content/browser/renderer_host/render_widget_resize_helper.h"
17 #include "content/browser/renderer_host/software_layer_mac.h"
18 #include "content/common/gpu/surface_handle_types_mac.h"
19 #include "content/public/browser/context_factory.h"
20 #include "ui/base/cocoa/animation_utils.h"
21 #include "ui/gl/scoped_cgl.h"
23 namespace content {
24 namespace {
26 typedef std::map<gfx::AcceleratedWidget,BrowserCompositorViewMacInternal*>
27     WidgetToInternalsMap;
28 base::LazyInstance<WidgetToInternalsMap> g_widget_to_internals_map;
32 ////////////////////////////////////////////////////////////////////////////////
33 // BrowserCompositorViewMacInternal
35 BrowserCompositorViewMacInternal::BrowserCompositorViewMacInternal()
36     : client_(NULL),
37       accelerated_output_surface_id_(0) {
38   // Disable the fade-in animation as the layers are added.
39   ScopedCAActionDisabler disabler;
41   // Add a flipped transparent layer as a child, so that we don't need to
42   // fiddle with the position of sub-layers -- they will always be at the
43   // origin.
44   flipped_layer_.reset([[CALayer alloc] init]);
45   [flipped_layer_ setGeometryFlipped:YES];
46   [flipped_layer_ setAnchorPoint:CGPointMake(0, 0)];
47   [flipped_layer_
48       setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
50   // Use a sequence number as the accelerated widget handle that we can use
51   // to look up the internals structure.
52   static uintptr_t last_sequence_number = 0;
53   last_sequence_number += 1;
54   native_widget_ = reinterpret_cast<gfx::AcceleratedWidget>(
55       last_sequence_number);
56   g_widget_to_internals_map.Pointer()->insert(
57       std::make_pair(native_widget_, this));
59   // Create a compositor to draw the contents of this view.
60   compositor_.reset(new ui::Compositor(
61       native_widget_,
62       content::GetContextFactory(),
63       RenderWidgetResizeHelper::Get()->task_runner()));
66 BrowserCompositorViewMacInternal::~BrowserCompositorViewMacInternal() {
67   DCHECK(!client_);
68   g_widget_to_internals_map.Pointer()->erase(native_widget_);
71 void BrowserCompositorViewMacInternal::SetClient(
72     BrowserCompositorViewMacClient* client) {
73   // Disable the fade-in animation as the view is added.
74   ScopedCAActionDisabler disabler;
76   DCHECK(client && !client_);
77   client_ = client;
78   compositor_->SetRootLayer(client_->BrowserCompositorRootLayer());
80   CALayer* background_layer = [client_->BrowserCompositorSuperview() layer];
81   DCHECK(background_layer);
82   [flipped_layer_ setBounds:[background_layer bounds]];
83   [background_layer addSublayer:flipped_layer_];
86 void BrowserCompositorViewMacInternal::ResetClient() {
87   if (!client_)
88     return;
90   // Disable the fade-out animation as the view is removed.
91   ScopedCAActionDisabler disabler;
93   [flipped_layer_ removeFromSuperlayer];
94   DestroyIOSurfaceLayer(io_surface_layer_);
95   DestroyCAContextLayer(ca_context_layer_);
96   DestroySoftwareLayer();
98   accelerated_output_surface_id_ = 0;
99   last_swap_size_dip_ = gfx::Size();
101   compositor_->SetScaleAndSize(1.0, gfx::Size(0, 0));
102   compositor_->SetRootLayer(NULL);
103   client_ = NULL;
106 bool BrowserCompositorViewMacInternal::HasFrameOfSize(
107     const gfx::Size& dip_size) const {
108   return last_swap_size_dip_ == dip_size;
111 int BrowserCompositorViewMacInternal::GetRendererID() const {
112   if (io_surface_layer_)
113     return [io_surface_layer_ iosurface]->GetRendererID();
114   return 0;
117 void BrowserCompositorViewMacInternal::BeginPumpingFrames() {
118   [io_surface_layer_ beginPumpingFrames];
121 void BrowserCompositorViewMacInternal::EndPumpingFrames() {
122   [io_surface_layer_ endPumpingFrames];
125 void BrowserCompositorViewMacInternal::GotAcceleratedFrame(
126     uint64 surface_handle, int output_surface_id,
127     const std::vector<ui::LatencyInfo>& latency_info,
128     gfx::Size pixel_size, float scale_factor) {
129   // Record the surface and latency info to use when acknowledging this frame.
130   DCHECK(!accelerated_output_surface_id_);
131   accelerated_output_surface_id_ = output_surface_id;
132   accelerated_latency_info_.insert(accelerated_latency_info_.end(),
133                                    latency_info.begin(), latency_info.end());
135   // If there is no client and therefore no superview to draw into, early-out.
136   if (!client_) {
137     AcceleratedLayerDidDrawFrame();
138     return;
139   }
141   // Disable the fade-in or fade-out effect if we create or remove layers.
142   ScopedCAActionDisabler disabler;
144   last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size);
145   switch (GetSurfaceHandleType(surface_handle)) {
146     case kSurfaceHandleTypeIOSurface: {
147       IOSurfaceID io_surface_id = IOSurfaceIDFromSurfaceHandle(surface_handle);
148       GotAcceleratedIOSurfaceFrame(io_surface_id, pixel_size, scale_factor);
149       break;
150     }
151     case kSurfaceHandleTypeCAContext: {
152       CAContextID ca_context_id = CAContextIDFromSurfaceHandle(surface_handle);
153       GotAcceleratedCAContextFrame(ca_context_id, pixel_size, scale_factor);
154       break;
155     }
156     default:
157       LOG(ERROR) << "Unrecognized accelerated frame type.";
158       return;
159   }
162 void BrowserCompositorViewMacInternal::GotAcceleratedCAContextFrame(
163     CAContextID ca_context_id,
164     gfx::Size pixel_size,
165     float scale_factor) {
166   // In the layer is replaced, keep the old one around until after the new one
167   // is installed to avoid flashes.
168   base::scoped_nsobject<CALayerHost> old_ca_context_layer =
169       ca_context_layer_;
171   // Create the layer to host the layer exported by the GPU process with this
172   // particular CAContext ID.
173   if ([ca_context_layer_ contextId] != ca_context_id) {
174     ca_context_layer_.reset([[CALayerHost alloc] init]);
175     [ca_context_layer_ setContextId:ca_context_id];
176     [ca_context_layer_
177         setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin];
178     [flipped_layer_ addSublayer:ca_context_layer_];
179   }
181   // Acknowledge the frame to unblock the compositor immediately (the GPU
182   // process will do any required throttling).
183   AcceleratedLayerDidDrawFrame();
185   // If this replacing a same-type layer, remove it now that the new layer is
186   // in the hierarchy.
187   if (old_ca_context_layer != ca_context_layer_)
188     DestroyCAContextLayer(old_ca_context_layer);
190   // Remove any different-type layers that this is replacing.
191   DestroyIOSurfaceLayer(io_surface_layer_);
192   DestroySoftwareLayer();
195 void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame(
196     IOSurfaceID io_surface_id,
197     gfx::Size pixel_size,
198     float scale_factor) {
199   // In the layer is replaced, keep the old one around until after the new one
200   // is installed to avoid flashes.
201   base::scoped_nsobject<CompositingIOSurfaceLayer> old_io_surface_layer =
202       io_surface_layer_;
204   // Create or re-create an IOSurface layer if needed. If there already exists
205   // a layer but it has the wrong scale factor or it was poisoned, re-create the
206   // layer.
207   bool needs_new_layer =
208       !io_surface_layer_ ||
209       [io_surface_layer_ context]->HasBeenPoisoned() ||
210       [io_surface_layer_ iosurface]->scale_factor() != scale_factor;
211   if (needs_new_layer) {
212     scoped_refptr<content::CompositingIOSurfaceMac> iosurface =
213         content::CompositingIOSurfaceMac::Create();
214     if (!iosurface) {
215       LOG(ERROR) << "Failed to create CompositingIOSurfaceMac";
216     } else {
217       io_surface_layer_.reset([[CompositingIOSurfaceLayer alloc]
218           initWithIOSurface:iosurface
219             withScaleFactor:scale_factor
220                  withClient:this]);
221       if (io_surface_layer_)
222         [flipped_layer_ addSublayer:io_surface_layer_];
223       else
224         LOG(ERROR) << "Failed to create CompositingIOSurfaceLayer";
225     }
226   }
228   // Open the provided IOSurface.
229   if (io_surface_layer_) {
230     bool result = true;
231     gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
232         [io_surface_layer_ context]->cgl_context());
233     result = [io_surface_layer_ iosurface]->SetIOSurfaceWithContextCurrent(
234         [io_surface_layer_ context], io_surface_id, pixel_size, scale_factor);
235     if (!result) {
236       DestroyIOSurfaceLayer(io_surface_layer_);
237       LOG(ERROR) << "Failed open IOSurface in CompositingIOSurfaceLayer";
238     }
239   }
241   // Give a final complaint if anything with the layer's creation went wrong.
242   // This frame will appear blank, the compositor will try to create another,
243   // and maybe that will go better.
244   if (!io_surface_layer_) {
245     LOG(ERROR) << "CompositingIOSurfaceLayer is nil, tab will be blank";
246     AcceleratedLayerHitError();
247   }
249   // Make the CALayer draw and set its size appropriately.
250   if (io_surface_layer_) {
251     [io_surface_layer_ gotNewFrame];
253     // Set the bounds of the accelerated layer to match the size of the frame.
254     // If the bounds changed, force the content to be displayed immediately.
255     CGRect new_layer_bounds = CGRectMake(
256         0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height());
257     bool bounds_changed = !CGRectEqualToRect(
258         new_layer_bounds, [io_surface_layer_ bounds]);
259     [io_surface_layer_ setBounds:new_layer_bounds];
260     if (bounds_changed)
261       [io_surface_layer_ setNeedsDisplayAndDisplayAndAck];
262   }
264   // If this replacing a same-type layer, remove it now that the new layer is
265   // in the hierarchy.
266   if (old_io_surface_layer != io_surface_layer_)
267     DestroyIOSurfaceLayer(old_io_surface_layer);
269   // Remove any different-type layers that this is replacing.
270   DestroyCAContextLayer(ca_context_layer_);
271   DestroySoftwareLayer();
274 void BrowserCompositorViewMacInternal::GotSoftwareFrame(
275     cc::SoftwareFrameData* frame_data,
276     float scale_factor,
277     SkCanvas* canvas) {
278   if (!frame_data || !canvas || !client_)
279     return;
281   // Disable the fade-in or fade-out effect if we create or remove layers.
282   ScopedCAActionDisabler disabler;
284   // If there is not a layer for software frames, create one.
285   if (!software_layer_) {
286     software_layer_.reset([[SoftwareLayer alloc] init]);
287     [flipped_layer_ addSublayer:software_layer_];
288   }
290   // Set the software layer to draw the provided canvas.
291   SkImageInfo info;
292   size_t row_bytes;
293   const void* pixels = canvas->peekPixels(&info, &row_bytes);
294   gfx::Size pixel_size(info.fWidth, info.fHeight);
295   [software_layer_ setContentsToData:pixels
296                         withRowBytes:row_bytes
297                        withPixelSize:pixel_size
298                      withScaleFactor:scale_factor];
299   last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size);
301   // Remove any different-type layers that this is replacing.
302   DestroyCAContextLayer(ca_context_layer_);
303   DestroyIOSurfaceLayer(io_surface_layer_);
306 void BrowserCompositorViewMacInternal::DestroyCAContextLayer(
307     base::scoped_nsobject<CALayerHost> ca_context_layer) {
308   if (!ca_context_layer)
309     return;
310   [ca_context_layer removeFromSuperlayer];
311   if (ca_context_layer == ca_context_layer_)
312     ca_context_layer_.reset();
315 void BrowserCompositorViewMacInternal::DestroyIOSurfaceLayer(
316     base::scoped_nsobject<CompositingIOSurfaceLayer> io_surface_layer) {
317   if (!io_surface_layer)
318     return;
319   [io_surface_layer resetClient];
320   [io_surface_layer removeFromSuperlayer];
321   if (io_surface_layer == io_surface_layer_)
322     io_surface_layer_.reset();
325 void BrowserCompositorViewMacInternal::DestroySoftwareLayer() {
326   if (!software_layer_)
327     return;
328   [software_layer_ removeFromSuperlayer];
329   software_layer_.reset();
332 bool BrowserCompositorViewMacInternal::AcceleratedLayerShouldAckImmediately()
333     const {
334   // If there is no client then the accelerated layer is not in the hierarchy
335   // and will never draw.
336   if (!client_)
337     return true;
338   return client_->BrowserCompositorViewShouldAckImmediately();
341 void BrowserCompositorViewMacInternal::AcceleratedLayerDidDrawFrame() {
342   if (accelerated_output_surface_id_) {
343     content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed(
344         accelerated_output_surface_id_);
345     accelerated_output_surface_id_ = 0;
346   }
348   if (client_)
349     client_->BrowserCompositorViewFrameSwapped(accelerated_latency_info_);
351   accelerated_latency_info_.clear();
354 void BrowserCompositorViewMacInternal::AcceleratedLayerHitError() {
355   // Perform all acks that would have been done if the frame had succeeded, to
356   // un-block the compositor and renderer.
357   AcceleratedLayerDidDrawFrame();
359   // Poison the context being used and request a mulligan.
360   if (io_surface_layer_)
361     [io_surface_layer_ context]->PoisonContextAndSharegroup();
362   compositor_->ScheduleFullRedraw();
365 // static
366 BrowserCompositorViewMacInternal* BrowserCompositorViewMacInternal::
367     FromAcceleratedWidget(gfx::AcceleratedWidget widget) {
368   WidgetToInternalsMap::const_iterator found =
369       g_widget_to_internals_map.Pointer()->find(widget);
370   // This can end up being accessed after the underlying widget has been
371   // destroyed, but while the ui::Compositor is still being destroyed.
372   // Return NULL in these cases.
373   if (found == g_widget_to_internals_map.Pointer()->end())
374     return NULL;
375   return found->second;
378 }  // namespace content