Chromium Code Reviews| 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 #import <Cocoa/Cocoa.h> | 5 #import <Cocoa/Cocoa.h> |
| 6 | 6 |
| 7 #include "content/browser/compositor/software_output_device_mac.h" | 7 #import "content/browser/compositor/software_output_device_mac.h" |
|
tapted
2015/10/26 06:59:42
I think this can stay #include if you like (one co
ccameron
2015/10/26 20:21:59
Ah, okay. Flipped it back.
| |
| 8 | 8 |
| 9 #include "base/mac/foundation_util.h" | |
| 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 |