OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/image_transport_surface_overlay_mac.h" | 5 #include "content/common/gpu/image_transport_surface_overlay_mac.h" |
6 | 6 |
7 #include <OpenGL/gl.h> | 7 #include <OpenGL/gl.h> |
8 #include <OpenGL/glext.h> | 8 #include <OpenGL/glext.h> |
9 | 9 |
10 #include "content/common/gpu/gpu_messages.h" | 10 #include "content/common/gpu/gpu_messages.h" |
11 #include "ui/accelerated_widget_mac/surface_handle_types.h" | 11 #include "ui/accelerated_widget_mac/surface_handle_types.h" |
12 #include "ui/base/cocoa/animation_utils.h" | 12 #include "ui/base/cocoa/animation_utils.h" |
13 #include "ui/base/cocoa/remote_layer_api.h" | 13 #include "ui/base/cocoa/remote_layer_api.h" |
14 #include "ui/gfx/geometry/dip_util.h" | 14 #include "ui/gfx/geometry/dip_util.h" |
15 #include "ui/gl/gl_image_io_surface.h" | 15 #include "ui/gl/gl_image_io_surface.h" |
16 #include "ui/gl/scoped_api.h" | 16 #include "ui/gl/scoped_api.h" |
17 #include "ui/gl/scoped_cgl.h" | 17 #include "ui/gl/scoped_cgl.h" |
18 | 18 |
19 #define LOG_GL_ERRORS(msg) \ | 19 #define LOG_GL_ERRORS(msg) \ |
20 do { \ | 20 do { \ |
21 for (GLenum gl_error = glGetError(); gl_error != GL_NO_ERROR; \ | 21 for (GLenum gl_error = glGetError(); gl_error != GL_NO_ERROR; \ |
22 gl_error = glGetError()) { \ | 22 gl_error = glGetError()) { \ |
23 LOG(ERROR) << "OpenGL error hit " << msg << ": " << gl_error; \ | 23 LOG(ERROR) << "OpenGL error hit " << msg << ": " << gl_error; \ |
24 } \ | 24 } \ |
25 } while (0) | 25 } while (0) |
26 | 26 |
27 @interface CALayer(Private) | |
28 -(void) setContentsChanged; | |
Andre
2015/08/05 17:59:30
- (void)set...
ccameron
2015/08/06 18:55:18
Done.
| |
29 @end | |
30 | |
27 namespace content { | 31 namespace content { |
28 | 32 |
29 ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac( | 33 ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac( |
30 GpuChannelManager* manager, | 34 GpuChannelManager* manager, |
31 GpuCommandBufferStub* stub, | 35 GpuCommandBufferStub* stub, |
32 gfx::PluginWindowHandle handle) | 36 gfx::PluginWindowHandle handle) |
33 : scale_factor_(1), pending_overlay_image_(nullptr), weak_factory_(this) { | 37 : scale_factor_(1), pending_overlay_image_(nullptr), weak_factory_(this) { |
34 helper_.reset(new ImageTransportHelper(this, manager, stub, handle)); | 38 helper_.reset(new ImageTransportHelper(this, manager, stub, handle)); |
35 } | 39 } |
36 | 40 |
37 ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() { | 41 ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() { |
38 } | 42 } |
39 | 43 |
40 bool ImageTransportSurfaceOverlayMac::Initialize() { | 44 bool ImageTransportSurfaceOverlayMac::Initialize() { |
41 if (!helper_->Initialize()) | 45 if (!helper_->Initialize()) |
42 return false; | 46 return false; |
43 | 47 |
44 // Create the CAContext to send this to the GPU process, and the layer for | 48 // Create the CAContext to send this to the GPU process, and the layer for |
45 // the context. | 49 // the context. |
46 CGSConnectionID connection_id = CGSMainConnectionID(); | 50 CGSConnectionID connection_id = CGSMainConnectionID(); |
47 ca_context_.reset( | 51 ca_context_.reset( |
48 [[CAContext contextWithCGSConnection:connection_id options:@{}] retain]); | 52 [[CAContext contextWithCGSConnection:connection_id options:@{}] retain]); |
49 layer_.reset([[CALayer alloc] init]); | 53 layer_.reset([[CALayer alloc] init]); |
50 [layer_ setGeometryFlipped:YES]; | 54 [layer_ setGeometryFlipped:YES]; |
55 partial_damage_layer_.reset([[CALayer alloc] init]); | |
51 [ca_context_ setLayer:layer_]; | 56 [ca_context_ setLayer:layer_]; |
52 | 57 |
53 return true; | 58 return true; |
54 } | 59 } |
55 | 60 |
56 void ImageTransportSurfaceOverlayMac::Destroy() { | 61 void ImageTransportSurfaceOverlayMac::Destroy() { |
57 CheckAndDisplayPendingSwaps(true); | 62 CheckAndDisplayPendingSwaps(true); |
58 } | 63 } |
59 | 64 |
60 bool ImageTransportSurfaceOverlayMac::IsOffscreen() { | 65 bool ImageTransportSurfaceOverlayMac::IsOffscreen() { |
(...skipping 25 matching lines...) Expand all Loading... | |
86 this_swap.io_surface.get()); | 91 this_swap.io_surface.get()); |
87 LOG_GL_ERRORS("before flushing frame"); | 92 LOG_GL_ERRORS("before flushing frame"); |
88 this_swap.cgl_context.reset(CGLGetCurrentContext(), | 93 this_swap.cgl_context.reset(CGLGetCurrentContext(), |
89 base::scoped_policy::RETAIN); | 94 base::scoped_policy::RETAIN); |
90 glGenFencesAPPLE(1, &this_swap.fence); | 95 glGenFencesAPPLE(1, &this_swap.fence); |
91 glSetFenceAPPLE(this_swap.fence); | 96 glSetFenceAPPLE(this_swap.fence); |
92 glFlush(); | 97 glFlush(); |
93 LOG_GL_ERRORS("while flushing frame"); | 98 LOG_GL_ERRORS("while flushing frame"); |
94 } | 99 } |
95 | 100 |
96 this_swap.dip_size = gfx::ConvertSizeToDIP(scale_factor_, pixel_size_); | 101 // Determine if this will be a full or partial damage, and compute the rects |
102 // for the damage. | |
103 { | |
104 this_swap.dip_size = gfx::ConvertSizeToDIP(scale_factor_, pixel_size_); | |
105 | |
106 // Grow the partial damage rect to include the new damage. | |
107 accumulated_partial_damage_pixel_rect_.Union(pixel_damage_rect); | |
108 // Compute the fraction of the full layer that has been damaged. If this | |
109 // fraction is very large (>85%), just damage the full layer, and don't | |
110 // bother with the partial layer. | |
111 double kMaximumFractionOfFullDamage = 0.85; | |
Andre
2015/08/05 17:59:30
nit: const
ccameron
2015/08/06 18:55:18
Done.
| |
112 double fraction_of_full_damage = | |
Andre
2015/08/05 17:59:30
nit: const
ccameron
2015/08/06 18:55:18
Done.
| |
113 accumulated_partial_damage_pixel_rect_.size().GetArea() / | |
114 static_cast<double>(pixel_size_.GetArea()); | |
115 // Compute the fraction of the accumulated partial damage rect that has been | |
116 // damaged. If this gets too small (<75%), just re-damage the full window, | |
117 // so we can re-create a smaller partial damage layer next frame. | |
118 double kMinimumFractionOfPartialDamage = 0.75; | |
119 double fraction_of_partial_damage = | |
120 pixel_damage_rect.size().GetArea() / static_cast<double>( | |
121 accumulated_partial_damage_pixel_rect_.size().GetArea()); | |
122 if (fraction_of_full_damage < kMaximumFractionOfFullDamage && | |
123 fraction_of_partial_damage > kMinimumFractionOfPartialDamage) { | |
124 this_swap.use_partial_damage = true; | |
125 this_swap.dip_partial_damage_rect = gfx::ConvertRectToDIP( | |
126 scale_factor_, accumulated_partial_damage_pixel_rect_); | |
127 } else { | |
128 this_swap.use_partial_damage = false; | |
129 accumulated_partial_damage_pixel_rect_ = gfx::Rect(); | |
130 } | |
131 } | |
132 | |
97 pending_swaps_.push_back(this_swap); | 133 pending_swaps_.push_back(this_swap); |
98 | |
99 PostCheckAndDisplayPendingSwaps(); | 134 PostCheckAndDisplayPendingSwaps(); |
100 return gfx::SwapResult::SWAP_ACK; | 135 return gfx::SwapResult::SWAP_ACK; |
101 } | 136 } |
102 | 137 |
103 void ImageTransportSurfaceOverlayMac::CheckAndDisplayPendingSwaps( | 138 void ImageTransportSurfaceOverlayMac::CheckAndDisplayPendingSwaps( |
104 bool force_immediate_display) { | 139 bool force_immediate_display) { |
105 TRACE_EVENT0("gpu", | 140 TRACE_EVENT0("gpu", |
106 "ImageTransportSurfaceOverlayMac::CheckAndDisplayPendingSwaps"); | 141 "ImageTransportSurfaceOverlayMac::CheckAndDisplayPendingSwaps"); |
107 if (pending_swaps_.empty()) | 142 if (pending_swaps_.empty()) |
108 return; | 143 return; |
(...skipping 15 matching lines...) Expand all Loading... | |
124 } | 159 } |
125 glDeleteFencesAPPLE(1, &this_swap.fence); | 160 glDeleteFencesAPPLE(1, &this_swap.fence); |
126 LOG_GL_ERRORS("while deleting fence"); | 161 LOG_GL_ERRORS("while deleting fence"); |
127 } | 162 } |
128 | 163 |
129 // Update the CALayer hierarchy. | 164 // Update the CALayer hierarchy. |
130 { | 165 { |
131 TRACE_EVENT1("gpu", "ImageTransportSurfaceOverlayMac::setContents", | 166 TRACE_EVENT1("gpu", "ImageTransportSurfaceOverlayMac::setContents", |
132 "surface", this_swap.io_surface.get()); | 167 "surface", this_swap.io_surface.get()); |
133 ScopedCAActionDisabler disabler; | 168 ScopedCAActionDisabler disabler; |
134 id new_contents = static_cast<id>(this_swap.io_surface.get()); | 169 if (this_swap.use_partial_damage) { |
135 [layer_ setContents:new_contents]; | 170 if (![partial_damage_layer_ superlayer]) |
136 [layer_ setFrame:gfx::Rect(this_swap.dip_size).ToCGRect()]; | 171 [layer_ addSublayer:partial_damage_layer_]; |
172 | |
173 [partial_damage_layer_ | |
174 setContents:static_cast<id>(this_swap.io_surface.get())]; | |
175 [partial_damage_layer_ | |
176 setFrame:this_swap.dip_partial_damage_rect.ToCGRect()]; | |
177 gfx::RectF content_bounds_rect = | |
178 gfx::RectF(this_swap.dip_partial_damage_rect); | |
179 content_bounds_rect.Scale( | |
180 1. / this_swap.dip_size.width(), 1. / this_swap.dip_size.height()); | |
181 [partial_damage_layer_ setContentsRect:CGRectMake( | |
182 content_bounds_rect.x(), | |
183 content_bounds_rect.y(), | |
184 content_bounds_rect.width(), | |
185 content_bounds_rect.height())]; | |
Andre
2015/08/05 17:59:30
How about something like:
CGRect damage_rect = thi
ccameron
2015/08/06 18:55:18
Actually, gfx::RectF should have a ToCGRect functi
| |
186 } else { | |
187 if ([partial_damage_layer_ superlayer]) { | |
188 [partial_damage_layer_ removeFromSuperlayer]; | |
189 [partial_damage_layer_ setContents:nil]; | |
190 } | |
191 | |
192 // Note that calling setContents with the same IOSurface twice will result | |
193 // in the screen not being updated, even if the IOSurface's content has | |
194 // changed. Avoid this by calling setContentsChanged. | |
195 id new_contents = static_cast<id>(this_swap.io_surface.get()); | |
196 if ([layer_ contents] == new_contents) | |
197 [layer_ setContentsChanged]; | |
198 else | |
199 [layer_ setContents:static_cast<id>(this_swap.io_surface.get())]; | |
Andre
2015/08/05 17:59:30
setContents:new_contents
ccameron
2015/08/06 18:55:18
Done.
| |
200 [layer_ setFrame:gfx::Rect(this_swap.dip_size).ToCGRect()]; | |
201 } | |
137 } | 202 } |
138 | 203 |
139 // Remove this swap from the queue. | 204 // Remove this swap from the queue. |
140 pending_swaps_.pop_front(); | 205 pending_swaps_.pop_front(); |
141 | 206 |
142 // Send acknowledgement to the browser. | 207 // Send acknowledgement to the browser. |
143 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | 208 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; |
144 params.surface_handle = | 209 params.surface_handle = |
145 ui::SurfaceHandleFromCAContextID([ca_context_ contextId]); | 210 ui::SurfaceHandleFromCAContextID([ca_context_ contextId]); |
146 params.size = pixel_size_; | 211 params.size = pixel_size_; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 void ImageTransportSurfaceOverlayMac::SetLatencyInfo( | 310 void ImageTransportSurfaceOverlayMac::SetLatencyInfo( |
246 const std::vector<ui::LatencyInfo>& latency_info) { | 311 const std::vector<ui::LatencyInfo>& latency_info) { |
247 latency_info_.insert( | 312 latency_info_.insert( |
248 latency_info_.end(), latency_info.begin(), latency_info.end()); | 313 latency_info_.end(), latency_info.begin(), latency_info.end()); |
249 } | 314 } |
250 | 315 |
251 void ImageTransportSurfaceOverlayMac::WakeUpGpu() {} | 316 void ImageTransportSurfaceOverlayMac::WakeUpGpu() {} |
252 | 317 |
253 | 318 |
254 ImageTransportSurfaceOverlayMac::PendingSwap::PendingSwap() | 319 ImageTransportSurfaceOverlayMac::PendingSwap::PendingSwap() |
255 : fence(0) { | 320 : fence(0), use_partial_damage(false) { |
256 } | 321 } |
257 | 322 |
258 ImageTransportSurfaceOverlayMac::PendingSwap::~PendingSwap() { | 323 ImageTransportSurfaceOverlayMac::PendingSwap::~PendingSwap() { |
259 } | 324 } |
260 | 325 |
261 } // namespace content | 326 } // namespace content |
OLD | NEW |