Chromium Code Reviews| 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 |