| Index: content/browser/compositor/surface_utils.cc
|
| diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc
|
| index 7ae05912a656db51831f62a90dd1adf149700f08..71601d0dfa37c556cd59a56cd1328b47480b4702 100644
|
| --- a/content/browser/compositor/surface_utils.cc
|
| +++ b/content/browser/compositor/surface_utils.cc
|
| @@ -4,8 +4,20 @@
|
|
|
| #include "content/browser/compositor/surface_utils.h"
|
|
|
| +#include "base/callback_helpers.h"
|
| +#include "base/memory/ref_counted.h"
|
| #include "build/build_config.h"
|
| +#include "cc/output/copy_output_result.h"
|
| +#include "cc/resources/single_release_callback.h"
|
| #include "cc/surfaces/surface_id_allocator.h"
|
| +#include "content/common/gpu/client/gl_helper.h"
|
| +#include "skia/ext/image_operations.h"
|
| +#include "skia/ext/refptr.h"
|
| +#include "third_party/skia/include/core/SkCanvas.h"
|
| +#include "third_party/skia/include/core/SkColorFilter.h"
|
| +#include "third_party/skia/include/core/SkPaint.h"
|
| +#include "third_party/skia/include/effects/SkLumaColorFilter.h"
|
| +#include "ui/gfx/geometry/rect.h"
|
|
|
| #if defined(OS_ANDROID) && !defined(USE_AURA)
|
| #include "content/browser/renderer_host/compositor_impl_android.h"
|
| @@ -14,6 +26,139 @@
|
| #include "ui/compositor/compositor.h"
|
| #endif
|
|
|
| +namespace {
|
| +
|
| +#if !defined(OS_ANDROID) || defined(USE_AURA)
|
| +void CopyFromCompositingSurfaceFinished(
|
| + const content::ReadbackRequestCallback& callback,
|
| + scoped_ptr<cc::SingleReleaseCallback> release_callback,
|
| + scoped_ptr<SkBitmap> bitmap,
|
| + scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
|
| + bool result) {
|
| + bitmap_pixels_lock.reset();
|
| +
|
| + gpu::SyncToken sync_token;
|
| + if (result) {
|
| + content::GLHelper* gl_helper =
|
| + content::ImageTransportFactory::GetInstance()->GetGLHelper();
|
| + if (gl_helper)
|
| + gl_helper->GenerateSyncToken(&sync_token);
|
| + }
|
| + const bool lost_resource = !sync_token.HasData();
|
| + release_callback->Run(sync_token, lost_resource);
|
| +
|
| + callback.Run(*bitmap,
|
| + result ? content::READBACK_SUCCESS : content::READBACK_FAILED);
|
| +}
|
| +#endif
|
| +
|
| +// TODO(wjmaclean): There is significant overlap between
|
| +// PrepareTextureCopyOutputResult and CopyFromCompositingSurfaceFinished in
|
| +// this file, and the versions in RenderWidgetHostViewAndroid. They should
|
| +// be merged. See https://crbug.com/582955
|
| +void PrepareTextureCopyOutputResult(
|
| + const gfx::Size& dst_size_in_pixel,
|
| + const SkColorType color_type,
|
| + const content::ReadbackRequestCallback& callback,
|
| + scoped_ptr<cc::CopyOutputResult> result) {
|
| +#if defined(OS_ANDROID) && !defined(USE_AURA)
|
| + // TODO(wjmaclean): See if there's an equivalent pathway for Android and
|
| + // implement it here.
|
| + callback.Run(SkBitmap(), content::READBACK_FAILED);
|
| +#else
|
| + DCHECK(result->HasTexture());
|
| + base::ScopedClosureRunner scoped_callback_runner(
|
| + base::Bind(callback, SkBitmap(), content::READBACK_FAILED));
|
| +
|
| + // TODO(siva.gunturi): We should be able to validate the format here using
|
| + // GLHelper::IsReadbackConfigSupported before we processs the result.
|
| + // See crbug.com/415682 and crbug.com/415131.
|
| + scoped_ptr<SkBitmap> bitmap(new SkBitmap);
|
| + if (!bitmap->tryAllocPixels(SkImageInfo::Make(
|
| + dst_size_in_pixel.width(), dst_size_in_pixel.height(), color_type,
|
| + kOpaque_SkAlphaType))) {
|
| + scoped_callback_runner.Reset(base::Bind(
|
| + callback, SkBitmap(), content::READBACK_BITMAP_ALLOCATION_FAILURE));
|
| + return;
|
| + }
|
| +
|
| + content::ImageTransportFactory* factory =
|
| + content::ImageTransportFactory::GetInstance();
|
| + content::GLHelper* gl_helper = factory->GetGLHelper();
|
| + if (!gl_helper)
|
| + return;
|
| +
|
| + scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
|
| + new SkAutoLockPixels(*bitmap));
|
| + uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
|
| +
|
| + cc::TextureMailbox texture_mailbox;
|
| + scoped_ptr<cc::SingleReleaseCallback> release_callback;
|
| + result->TakeTexture(&texture_mailbox, &release_callback);
|
| + DCHECK(texture_mailbox.IsTexture());
|
| +
|
| + ignore_result(scoped_callback_runner.Release());
|
| +
|
| + gl_helper->CropScaleReadbackAndCleanMailbox(
|
| + texture_mailbox.mailbox(), texture_mailbox.sync_token(), result->size(),
|
| + gfx::Rect(result->size()), dst_size_in_pixel, pixels, color_type,
|
| + base::Bind(&CopyFromCompositingSurfaceFinished, callback,
|
| + base::Passed(&release_callback), base::Passed(&bitmap),
|
| + base::Passed(&bitmap_pixels_lock)),
|
| + content::GLHelper::SCALER_QUALITY_GOOD);
|
| +#endif
|
| +}
|
| +
|
| +void PrepareBitmapCopyOutputResult(
|
| + const gfx::Size& dst_size_in_pixel,
|
| + const SkColorType preferred_color_type,
|
| + const content::ReadbackRequestCallback& callback,
|
| + scoped_ptr<cc::CopyOutputResult> result) {
|
| + SkColorType color_type = preferred_color_type;
|
| + if (color_type != kN32_SkColorType && color_type != kAlpha_8_SkColorType) {
|
| + // Switch back to default colortype if format not supported.
|
| + color_type = kN32_SkColorType;
|
| + }
|
| + DCHECK(result->HasBitmap());
|
| + scoped_ptr<SkBitmap> source = result->TakeBitmap();
|
| + DCHECK(source);
|
| + SkBitmap scaled_bitmap;
|
| + if (source->width() != dst_size_in_pixel.width() ||
|
| + source->height() != dst_size_in_pixel.height()) {
|
| + scaled_bitmap = skia::ImageOperations::Resize(
|
| + *source, skia::ImageOperations::RESIZE_BEST, dst_size_in_pixel.width(),
|
| + dst_size_in_pixel.height());
|
| + } else {
|
| + scaled_bitmap = *source;
|
| + }
|
| + if (color_type == kN32_SkColorType) {
|
| + DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
|
| + callback.Run(scaled_bitmap, content::READBACK_SUCCESS);
|
| + return;
|
| + }
|
| + DCHECK_EQ(color_type, kAlpha_8_SkColorType);
|
| + // The software path currently always returns N32 bitmap regardless of the
|
| + // |color_type| we ask for.
|
| + DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
|
| + // Paint |scaledBitmap| to alpha-only |grayscale_bitmap|.
|
| + SkBitmap grayscale_bitmap;
|
| + bool success = grayscale_bitmap.tryAllocPixels(
|
| + SkImageInfo::MakeA8(scaled_bitmap.width(), scaled_bitmap.height()));
|
| + if (!success) {
|
| + callback.Run(SkBitmap(), content::READBACK_BITMAP_ALLOCATION_FAILURE);
|
| + return;
|
| + }
|
| + SkCanvas canvas(grayscale_bitmap);
|
| + SkPaint paint;
|
| + skia::RefPtr<SkColorFilter> filter =
|
| + skia::AdoptRef(SkLumaColorFilter::Create());
|
| + paint.setColorFilter(filter.get());
|
| + canvas.drawBitmap(scaled_bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
|
| + callback.Run(grayscale_bitmap, content::READBACK_SUCCESS);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| namespace content {
|
|
|
| scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() {
|
| @@ -34,4 +179,33 @@ cc::SurfaceManager* GetSurfaceManager() {
|
| #endif
|
| }
|
|
|
| +void CopyFromCompositingSurfaceHasResult(
|
| + const gfx::Size& dst_size_in_pixel,
|
| + const SkColorType color_type,
|
| + const ReadbackRequestCallback& callback,
|
| + scoped_ptr<cc::CopyOutputResult> result) {
|
| + if (result->IsEmpty() || result->size().IsEmpty()) {
|
| + callback.Run(SkBitmap(), READBACK_FAILED);
|
| + return;
|
| + }
|
| +
|
| + gfx::Size output_size_in_pixel;
|
| + if (dst_size_in_pixel.IsEmpty())
|
| + output_size_in_pixel = result->size();
|
| + else
|
| + output_size_in_pixel = dst_size_in_pixel;
|
| +
|
| + if (result->HasTexture()) {
|
| + // GPU-accelerated path
|
| + PrepareTextureCopyOutputResult(output_size_in_pixel, color_type, callback,
|
| + std::move(result));
|
| + return;
|
| + }
|
| +
|
| + DCHECK(result->HasBitmap());
|
| + // Software path
|
| + PrepareBitmapCopyOutputResult(output_size_in_pixel, color_type, callback,
|
| + std::move(result));
|
| +}
|
| +
|
| } // namespace content
|
|
|