| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/browser/compositor/software_output_device_mac.h" |
| 6 |
| 5 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 6 | 8 |
| 7 #include "content/browser/compositor/software_output_device_mac.h" | 9 #include "base/mac/foundation_util.h" |
| 8 | 10 #include "third_party/skia/include/core/SkCanvas.h" |
| 9 #include "ui/accelerated_widget_mac/accelerated_widget_mac.h" | 11 #include "ui/accelerated_widget_mac/accelerated_widget_mac.h" |
| 10 #include "ui/compositor/compositor.h" | 12 #include "ui/compositor/compositor.h" |
| 13 #include "ui/gfx/skia_util.h" |
| 11 | 14 |
| 12 namespace content { | 15 namespace content { |
| 13 | 16 |
| 14 SoftwareOutputDeviceMac::SoftwareOutputDeviceMac(ui::Compositor* compositor) | 17 SoftwareOutputDeviceMac::SoftwareOutputDeviceMac(ui::Compositor* compositor) |
| 15 : compositor_(compositor) { | 18 : compositor_(compositor), scale_factor_(1), current_index_(0) {} |
| 16 } | |
| 17 | 19 |
| 18 SoftwareOutputDeviceMac::~SoftwareOutputDeviceMac() { | 20 SoftwareOutputDeviceMac::~SoftwareOutputDeviceMac() { |
| 19 } | 21 } |
| 20 | 22 |
| 23 void SoftwareOutputDeviceMac::Resize(const gfx::Size& pixel_size, |
| 24 float scale_factor) { |
| 25 if (pixel_size_ == pixel_size && scale_factor_ == scale_factor) |
| 26 return; |
| 27 |
| 28 pixel_size_ = pixel_size; |
| 29 scale_factor_ = scale_factor; |
| 30 |
| 31 DiscardBackbuffer(); |
| 32 } |
| 33 |
| 34 void SoftwareOutputDeviceMac::CopyPreviousBufferDamage( |
| 35 const SkRegion& new_damage_region) { |
| 36 TRACE_EVENT0("browser", "CopyPreviousBufferDamage"); |
| 37 |
| 38 // The region to copy is the region drawn last frame, minus the region that |
| 39 // is drawn this frame. |
| 40 SkRegion copy_region = previous_buffer_damage_region_; |
| 41 bool copy_region_nonempty = |
| 42 copy_region.op(new_damage_region, SkRegion::kDifference_Op); |
| 43 previous_buffer_damage_region_ = new_damage_region; |
| 44 |
| 45 if (!copy_region_nonempty) |
| 46 return; |
| 47 |
| 48 IOSurfaceRef previous_io_surface = io_surfaces_[!current_index_].get(); |
| 49 |
| 50 { |
| 51 TRACE_EVENT0("browser", "IOSurfaceLock"); |
| 52 IOReturn io_result = IOSurfaceLock( |
| 53 previous_io_surface, kIOSurfaceLockReadOnly | kIOSurfaceLockAvoidSync, |
| 54 nullptr); |
| 55 if (io_result) { |
| 56 DLOG(ERROR) << "Failed to lock previous IOSurface " << io_result; |
| 57 return; |
| 58 } |
| 59 } |
| 60 |
| 61 uint8_t* pixels = |
| 62 static_cast<uint8_t*>(IOSurfaceGetBaseAddress(previous_io_surface)); |
| 63 size_t stride = IOSurfaceGetBytesPerRow(previous_io_surface); |
| 64 size_t bytes_per_element = 4; |
| 65 for (SkRegion::Iterator it(copy_region); !it.done(); it.next()) { |
| 66 const SkIRect& rect = it.rect(); |
| 67 canvas_->writePixels( |
| 68 SkImageInfo::MakeN32Premul(rect.width(), rect.height()), |
| 69 pixels + bytes_per_element * rect.x() + stride * rect.y(), stride, |
| 70 rect.x(), rect.y()); |
| 71 } |
| 72 |
| 73 { |
| 74 TRACE_EVENT0("browser", "IOSurfaceUnlock"); |
| 75 IOReturn io_result = IOSurfaceUnlock( |
| 76 previous_io_surface, kIOSurfaceLockReadOnly | kIOSurfaceLockAvoidSync, |
| 77 nullptr); |
| 78 if (io_result) |
| 79 DLOG(ERROR) << "Failed to unlock previous IOSurface " << io_result; |
| 80 } |
| 81 } |
| 82 |
| 83 bool SoftwareOutputDeviceMac::EnsureBuffersExist() { |
| 84 for (int i = 0; i < 2; ++i) { |
| 85 if (!io_surfaces_[i]) { |
| 86 TRACE_EVENT0("browser", "IOSurfaceCreate"); |
| 87 unsigned pixel_format = 'BGRA'; |
| 88 unsigned bytes_per_element = 4; |
| 89 NSDictionary* options = @{ |
| 90 static_cast<id>(kIOSurfaceWidth) : @(pixel_size_.width()), |
| 91 static_cast<id>(kIOSurfaceHeight) : @(pixel_size_.height()), |
| 92 static_cast<id>(kIOSurfacePixelFormat) : @(pixel_format), |
| 93 static_cast<id>(kIOSurfaceBytesPerElement) : @(bytes_per_element), |
| 94 }; |
| 95 io_surfaces_[i].reset(IOSurfaceCreate(base::mac::NSToCFCast(options))); |
| 96 } |
| 97 if (!io_surfaces_[i]) { |
| 98 DLOG(ERROR) << "Failed to allocate IOSurface"; |
| 99 return false; |
| 100 } |
| 101 } |
| 102 return true; |
| 103 } |
| 104 |
| 105 SkCanvas* SoftwareOutputDeviceMac::BeginPaint( |
| 106 const gfx::Rect& new_damage_rect) { |
| 107 if (!EnsureBuffersExist()) |
| 108 return nullptr; |
| 109 |
| 110 { |
| 111 TRACE_EVENT0("browser", "IOSurfaceLock"); |
| 112 IOReturn io_result = IOSurfaceLock(io_surfaces_[current_index_], |
| 113 kIOSurfaceLockAvoidSync, nullptr); |
| 114 if (io_result) { |
| 115 DLOG(ERROR) << "Failed to lock IOSurface " << io_result; |
| 116 return nullptr; |
| 117 } |
| 118 } |
| 119 |
| 120 SkPMColor* pixels = static_cast<SkPMColor*>( |
| 121 IOSurfaceGetBaseAddress(io_surfaces_[current_index_])); |
| 122 size_t stride = IOSurfaceGetBytesPerRow(io_surfaces_[current_index_]); |
| 123 |
| 124 canvas_ = skia::AdoptRef(SkCanvas::NewRasterDirectN32( |
| 125 pixel_size_.width(), pixel_size_.height(), pixels, stride)); |
| 126 |
| 127 CopyPreviousBufferDamage(SkRegion(gfx::RectToSkIRect(new_damage_rect))); |
| 128 |
| 129 return canvas_.get(); |
| 130 } |
| 131 |
| 21 void SoftwareOutputDeviceMac::EndPaint() { | 132 void SoftwareOutputDeviceMac::EndPaint() { |
| 22 SoftwareOutputDevice::EndPaint(); | 133 SoftwareOutputDevice::EndPaint(); |
| 23 ui::AcceleratedWidgetMacGotSoftwareFrame( | 134 { |
| 24 compositor_->widget(), scale_factor_, surface_->getCanvas()); | 135 TRACE_EVENT0("browser", "IOSurfaceUnlock"); |
| 136 IOReturn io_result = IOSurfaceUnlock(io_surfaces_[current_index_], |
| 137 kIOSurfaceLockAvoidSync, nullptr); |
| 138 if (io_result) |
| 139 DLOG(ERROR) << "Failed to unlock IOSurface " << io_result; |
| 140 } |
| 141 |
| 142 canvas_ = nullptr; |
| 143 ui::AcceleratedWidgetMacGotIOSurfaceFrame(compositor_->widget(), |
| 144 io_surfaces_[current_index_], |
| 145 pixel_size_, scale_factor_, false); |
| 146 |
| 147 current_index_ = !current_index_; |
| 25 } | 148 } |
| 26 | 149 |
| 150 void SoftwareOutputDeviceMac::DiscardBackbuffer() { |
| 151 for (int i = 0; i < 2; ++i) |
| 152 io_surfaces_[i].reset(); |
| 153 } |
| 154 |
| 155 void SoftwareOutputDeviceMac::EnsureBackbuffer() {} |
| 156 |
| 27 } // namespace content | 157 } // namespace content |
| OLD | NEW |