Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: content/browser/readback_request_helpers.cc

Issue 1582053002: Implement webview.captureVisibleRegion() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move captureVisibleRegion() to experimental API. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/readback_request_helpers.h"
6
7 #include "base/callback_helpers.h"
8 #include "base/memory/ref_counted.h"
9 #include "cc/output/copy_output_result.h"
10 #include "cc/resources/single_release_callback.h"
11 #include "content/browser/compositor/image_transport_factory.h"
12 #include "content/common/gpu/client/gl_helper.h"
13 #include "skia/ext/image_operations.h"
14 #include "skia/ext/refptr.h"
15 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkColorFilter.h"
17 #include "third_party/skia/include/core/SkPaint.h"
18 #include "third_party/skia/include/effects/SkLumaColorFilter.h"
19 #include "ui/gfx/geometry/rect.h"
20
21 namespace content {
22
23 void CopyFromCompositingSurfaceFinished(
24 const ReadbackRequestCallback& callback,
25 scoped_ptr<cc::SingleReleaseCallback> release_callback,
26 scoped_ptr<SkBitmap> bitmap,
27 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
28 bool result) {
29 bitmap_pixels_lock.reset();
30
31 gpu::SyncToken sync_token;
32 if (result) {
33 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
34 if (gl_helper)
35 gl_helper->GenerateSyncToken(&sync_token);
36 }
37 const bool lost_resource = !sync_token.HasData();
38 release_callback->Run(sync_token, lost_resource);
39
40 callback.Run(*bitmap, result ? READBACK_SUCCESS : READBACK_FAILED);
41 }
42
43 void PrepareTextureCopyOutputResult(const gfx::Size& dst_size_in_pixel,
44 const SkColorType color_type,
45 const ReadbackRequestCallback& callback,
46 scoped_ptr<cc::CopyOutputResult> result) {
47 DCHECK(result->HasTexture());
48 base::ScopedClosureRunner scoped_callback_runner(
49 base::Bind(callback, SkBitmap(), READBACK_FAILED));
50
51 // TODO(siva.gunturi): We should be able to validate the format here using
52 // GLHelper::IsReadbackConfigSupported before we processs the result.
53 // See crbug.com/415682 and crbug.com/415131.
54 scoped_ptr<SkBitmap> bitmap(new SkBitmap);
55 if (!bitmap->tryAllocPixels(SkImageInfo::Make(
56 dst_size_in_pixel.width(), dst_size_in_pixel.height(), color_type,
57 kOpaque_SkAlphaType))) {
58 scoped_callback_runner.Reset(
59 base::Bind(callback, SkBitmap(), READBACK_BITMAP_ALLOCATION_FAILURE));
60 return;
61 }
62
63 ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
64 GLHelper* gl_helper = factory->GetGLHelper();
65 if (!gl_helper)
66 return;
67
68 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
69 new SkAutoLockPixels(*bitmap));
70 uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
71
72 cc::TextureMailbox texture_mailbox;
73 scoped_ptr<cc::SingleReleaseCallback> release_callback;
74 result->TakeTexture(&texture_mailbox, &release_callback);
75 DCHECK(texture_mailbox.IsTexture());
76
77 ignore_result(scoped_callback_runner.Release());
78
79 gl_helper->CropScaleReadbackAndCleanMailbox(
80 texture_mailbox.mailbox(), texture_mailbox.sync_token(), result->size(),
81 gfx::Rect(result->size()), dst_size_in_pixel, pixels, color_type,
82 base::Bind(&CopyFromCompositingSurfaceFinished, callback,
83 base::Passed(&release_callback), base::Passed(&bitmap),
84 base::Passed(&bitmap_pixels_lock)),
85 GLHelper::SCALER_QUALITY_GOOD);
86 }
87
88 void PrepareBitmapCopyOutputResult(const gfx::Size& dst_size_in_pixel,
89 const SkColorType preferred_color_type,
90 const ReadbackRequestCallback& callback,
91 scoped_ptr<cc::CopyOutputResult> result) {
92 SkColorType color_type = preferred_color_type;
93 if (color_type != kN32_SkColorType && color_type != kAlpha_8_SkColorType) {
94 // Switch back to default colortype if format not supported.
95 color_type = kN32_SkColorType;
96 }
97 DCHECK(result->HasBitmap());
98 scoped_ptr<SkBitmap> source = result->TakeBitmap();
99 DCHECK(source);
100 SkBitmap scaled_bitmap;
101 if (source->width() != dst_size_in_pixel.width() ||
102 source->height() != dst_size_in_pixel.height()) {
103 scaled_bitmap = skia::ImageOperations::Resize(
104 *source, skia::ImageOperations::RESIZE_BEST, dst_size_in_pixel.width(),
105 dst_size_in_pixel.height());
106 } else {
107 scaled_bitmap = *source;
108 }
109 if (color_type == kN32_SkColorType) {
110 DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
111 callback.Run(scaled_bitmap, READBACK_SUCCESS);
112 return;
113 }
114 DCHECK_EQ(color_type, kAlpha_8_SkColorType);
115 // The software path currently always returns N32 bitmap regardless of the
116 // |color_type| we ask for.
117 DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
118 // Paint |scaledBitmap| to alpha-only |grayscale_bitmap|.
119 SkBitmap grayscale_bitmap;
120 bool success = grayscale_bitmap.tryAllocPixels(
121 SkImageInfo::MakeA8(scaled_bitmap.width(), scaled_bitmap.height()));
122 if (!success) {
123 callback.Run(SkBitmap(), READBACK_BITMAP_ALLOCATION_FAILURE);
124 return;
125 }
126 SkCanvas canvas(grayscale_bitmap);
127 SkPaint paint;
128 skia::RefPtr<SkColorFilter> filter =
129 skia::AdoptRef(SkLumaColorFilter::Create());
130 paint.setColorFilter(filter.get());
131 canvas.drawBitmap(scaled_bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
132 callback.Run(grayscale_bitmap, READBACK_SUCCESS);
133 }
134
135 void CopyFromCompositingSurfaceHasResult(
136 const gfx::Size& dst_size_in_pixel,
137 const SkColorType color_type,
138 const ReadbackRequestCallback& callback,
139 scoped_ptr<cc::CopyOutputResult> result) {
140 if (result->IsEmpty() || result->size().IsEmpty()) {
141 callback.Run(SkBitmap(), READBACK_FAILED);
142 return;
143 }
144
145 gfx::Size output_size_in_pixel;
146 if (dst_size_in_pixel.IsEmpty())
147 output_size_in_pixel = result->size();
148 else
149 output_size_in_pixel = dst_size_in_pixel;
150
151 if (result->HasTexture()) {
152 // GPU-accelerated path
153 PrepareTextureCopyOutputResult(output_size_in_pixel, color_type, callback,
154 std::move(result));
155 return;
156 }
157
158 DCHECK(result->HasBitmap());
159 // Software path
160 PrepareBitmapCopyOutputResult(output_size_in_pixel, color_type, callback,
161 std::move(result));
162 }
163
164 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698