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

Side by Side Diff: content/browser/compositor/gl_helper.cc

Issue 1904773004: Revert of Introduce components/display_compositor (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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 (c) 2012 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/compositor/gl_helper.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <queue>
11 #include <string>
12
13 #include "base/bind.h"
14 #include "base/lazy_instance.h"
15 #include "base/logging.h"
16 #include "base/macros.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/strings/string_util.h"
20 #include "base/time/time.h"
21 #include "base/trace_event/trace_event.h"
22 #include "content/browser/compositor/gl_helper_readback_support.h"
23 #include "content/browser/compositor/gl_helper_scaling.h"
24 #include "gpu/GLES2/gl2extchromium.h"
25 #include "gpu/command_buffer/client/context_support.h"
26 #include "gpu/command_buffer/common/mailbox.h"
27 #include "gpu/command_buffer/common/mailbox_holder.h"
28 #include "third_party/skia/include/core/SkRegion.h"
29 #include "ui/gfx/geometry/point.h"
30 #include "ui/gfx/geometry/rect.h"
31 #include "ui/gfx/geometry/size.h"
32
33 using gpu::gles2::GLES2Interface;
34
35 namespace {
36
37 class ScopedFlush {
38 public:
39 explicit ScopedFlush(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
40
41 ~ScopedFlush() { gl_->Flush(); }
42
43 private:
44 gpu::gles2::GLES2Interface* gl_;
45
46 DISALLOW_COPY_AND_ASSIGN(ScopedFlush);
47 };
48
49 // Helper class for allocating and holding an RGBA texture of a given
50 // size and an associated framebuffer.
51 class TextureFrameBufferPair {
52 public:
53 TextureFrameBufferPair(GLES2Interface* gl, gfx::Size size)
54 : texture_(gl), framebuffer_(gl), size_(size) {
55 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, texture_);
56 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
57 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
58 content::ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
59 gl, framebuffer_);
60 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
61 GL_TEXTURE_2D, texture_, 0);
62 }
63
64 GLuint texture() const { return texture_.id(); }
65 GLuint framebuffer() const { return framebuffer_.id(); }
66 gfx::Size size() const { return size_; }
67
68 private:
69 content::ScopedTexture texture_;
70 content::ScopedFramebuffer framebuffer_;
71 gfx::Size size_;
72
73 DISALLOW_COPY_AND_ASSIGN(TextureFrameBufferPair);
74 };
75
76 // Helper class for holding a scaler, a texture for the output of that
77 // scaler and an associated frame buffer. This is inteded to be used
78 // when the output of a scaler is to be sent to a readback.
79 class ScalerHolder {
80 public:
81 ScalerHolder(GLES2Interface* gl, content::GLHelper::ScalerInterface* scaler)
82 : texture_and_framebuffer_(gl, scaler->DstSize()), scaler_(scaler) {}
83
84 void Scale(GLuint src_texture) {
85 scaler_->Scale(src_texture, texture_and_framebuffer_.texture());
86 }
87
88 content::GLHelper::ScalerInterface* scaler() const { return scaler_.get(); }
89 TextureFrameBufferPair* texture_and_framebuffer() {
90 return &texture_and_framebuffer_;
91 }
92 GLuint texture() const { return texture_and_framebuffer_.texture(); }
93
94 private:
95 TextureFrameBufferPair texture_and_framebuffer_;
96 std::unique_ptr<content::GLHelper::ScalerInterface> scaler_;
97
98 DISALLOW_COPY_AND_ASSIGN(ScalerHolder);
99 };
100
101 } // namespace
102
103 namespace content {
104 typedef GLHelperReadbackSupport::FormatSupport FormatSupport;
105
106 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates
107 // the data needed for it.
108 class GLHelper::CopyTextureToImpl
109 : public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> {
110 public:
111 CopyTextureToImpl(GLES2Interface* gl,
112 gpu::ContextSupport* context_support,
113 GLHelper* helper)
114 : gl_(gl),
115 context_support_(context_support),
116 helper_(helper),
117 flush_(gl),
118 max_draw_buffers_(0) {
119 const GLubyte* extensions = gl_->GetString(GL_EXTENSIONS);
120 if (!extensions)
121 return;
122 std::string extensions_string =
123 " " + std::string(reinterpret_cast<const char*>(extensions)) + " ";
124 if (extensions_string.find(" GL_EXT_draw_buffers ") != std::string::npos) {
125 gl_->GetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max_draw_buffers_);
126 }
127 }
128 ~CopyTextureToImpl() { CancelRequests(); }
129
130 GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
131 const gpu::SyncToken& sync_token) {
132 return helper_->ConsumeMailboxToTexture(mailbox, sync_token);
133 }
134
135 void CropScaleReadbackAndCleanTexture(
136 GLuint src_texture,
137 const gfx::Size& src_size,
138 const gfx::Rect& src_subrect,
139 const gfx::Size& dst_size,
140 unsigned char* out,
141 const SkColorType out_color_type,
142 const base::Callback<void(bool)>& callback,
143 GLHelper::ScalerQuality quality);
144
145 void ReadbackTextureSync(GLuint texture,
146 const gfx::Rect& src_rect,
147 unsigned char* out,
148 SkColorType format);
149
150 void ReadbackTextureAsync(GLuint texture,
151 const gfx::Size& dst_size,
152 unsigned char* out,
153 SkColorType color_type,
154 const base::Callback<void(bool)>& callback);
155
156 // Reads back bytes from the currently bound frame buffer.
157 // Note that dst_size is specified in bytes, not pixels.
158 void ReadbackAsync(
159 const gfx::Size& dst_size,
160 int32_t bytes_per_row, // generally dst_size.width() * 4
161 int32_t row_stride_bytes, // generally dst_size.width() * 4
162 unsigned char* out,
163 GLenum format,
164 GLenum type,
165 size_t bytes_per_pixel,
166 const base::Callback<void(bool)>& callback);
167
168 void ReadbackPlane(TextureFrameBufferPair* source,
169 int row_stride_bytes,
170 unsigned char* data,
171 int size_shift,
172 const gfx::Rect& paste_rect,
173 ReadbackSwizzle swizzle,
174 const base::Callback<void(bool)>& callback);
175
176 GLuint CopyAndScaleTexture(GLuint texture,
177 const gfx::Size& src_size,
178 const gfx::Size& dst_size,
179 bool vertically_flip_texture,
180 GLHelper::ScalerQuality quality);
181
182 ReadbackYUVInterface* CreateReadbackPipelineYUV(
183 GLHelper::ScalerQuality quality,
184 const gfx::Size& src_size,
185 const gfx::Rect& src_subrect,
186 const gfx::Size& dst_size,
187 bool flip_vertically,
188 bool use_mrt);
189
190 // Returns the maximum number of draw buffers available,
191 // 0 if GL_EXT_draw_buffers is not available.
192 GLint MaxDrawBuffers() const { return max_draw_buffers_; }
193
194 FormatSupport GetReadbackConfig(SkColorType color_type,
195 bool can_swizzle,
196 GLenum* format,
197 GLenum* type,
198 size_t* bytes_per_pixel);
199
200 private:
201 // A single request to CropScaleReadbackAndCleanTexture.
202 // The main thread can cancel the request, before it's handled by the helper
203 // thread, by resetting the texture and pixels fields. Alternatively, the
204 // thread marks that it handles the request by resetting the pixels field
205 // (meaning it guarantees that the callback with be called).
206 // In either case, the callback must be called exactly once, and the texture
207 // must be deleted by the main thread gl.
208 struct Request {
209 Request(const gfx::Size& size_,
210 int32_t bytes_per_row_,
211 int32_t row_stride_bytes_,
212 unsigned char* pixels_,
213 const base::Callback<void(bool)>& callback_)
214 : done(false),
215 size(size_),
216 bytes_per_row(bytes_per_row_),
217 row_stride_bytes(row_stride_bytes_),
218 pixels(pixels_),
219 callback(callback_),
220 buffer(0),
221 query(0) {}
222
223 bool done;
224 bool result;
225 gfx::Size size;
226 int bytes_per_row;
227 int row_stride_bytes;
228 unsigned char* pixels;
229 base::Callback<void(bool)> callback;
230 GLuint buffer;
231 GLuint query;
232 };
233
234 // We must take care to call the callbacks last, as they may
235 // end up destroying the gl_helper and make *this invalid.
236 // We stick the finished requests in a stack object that calls
237 // the callbacks when it goes out of scope.
238 class FinishRequestHelper {
239 public:
240 FinishRequestHelper() {}
241 ~FinishRequestHelper() {
242 while (!requests_.empty()) {
243 Request* request = requests_.front();
244 requests_.pop();
245 request->callback.Run(request->result);
246 delete request;
247 }
248 }
249 void Add(Request* r) { requests_.push(r); }
250
251 private:
252 std::queue<Request*> requests_;
253 DISALLOW_COPY_AND_ASSIGN(FinishRequestHelper);
254 };
255
256 // A readback pipeline that also converts the data to YUV before
257 // reading it back.
258 class ReadbackYUVImpl : public ReadbackYUVInterface {
259 public:
260 ReadbackYUVImpl(GLES2Interface* gl,
261 CopyTextureToImpl* copy_impl,
262 GLHelperScaling* scaler_impl,
263 GLHelper::ScalerQuality quality,
264 const gfx::Size& src_size,
265 const gfx::Rect& src_subrect,
266 const gfx::Size& dst_size,
267 bool flip_vertically,
268 ReadbackSwizzle swizzle);
269
270 void ReadbackYUV(const gpu::Mailbox& mailbox,
271 const gpu::SyncToken& sync_token,
272 const gfx::Rect& target_visible_rect,
273 int y_plane_row_stride_bytes,
274 unsigned char* y_plane_data,
275 int u_plane_row_stride_bytes,
276 unsigned char* u_plane_data,
277 int v_plane_row_stride_bytes,
278 unsigned char* v_plane_data,
279 const gfx::Point& paste_location,
280 const base::Callback<void(bool)>& callback) override;
281
282 ScalerInterface* scaler() override { return scaler_.scaler(); }
283
284 private:
285 GLES2Interface* gl_;
286 CopyTextureToImpl* copy_impl_;
287 gfx::Size dst_size_;
288 ReadbackSwizzle swizzle_;
289 ScalerHolder scaler_;
290 ScalerHolder y_;
291 ScalerHolder u_;
292 ScalerHolder v_;
293
294 DISALLOW_COPY_AND_ASSIGN(ReadbackYUVImpl);
295 };
296
297 // A readback pipeline that also converts the data to YUV before
298 // reading it back. This one uses Multiple Render Targets, which
299 // may not be supported on all platforms.
300 class ReadbackYUV_MRT : public ReadbackYUVInterface {
301 public:
302 ReadbackYUV_MRT(GLES2Interface* gl,
303 CopyTextureToImpl* copy_impl,
304 GLHelperScaling* scaler_impl,
305 GLHelper::ScalerQuality quality,
306 const gfx::Size& src_size,
307 const gfx::Rect& src_subrect,
308 const gfx::Size& dst_size,
309 bool flip_vertically,
310 ReadbackSwizzle swizzle);
311
312 void ReadbackYUV(const gpu::Mailbox& mailbox,
313 const gpu::SyncToken& sync_token,
314 const gfx::Rect& target_visible_rect,
315 int y_plane_row_stride_bytes,
316 unsigned char* y_plane_data,
317 int u_plane_row_stride_bytes,
318 unsigned char* u_plane_data,
319 int v_plane_row_stride_bytes,
320 unsigned char* v_plane_data,
321 const gfx::Point& paste_location,
322 const base::Callback<void(bool)>& callback) override;
323
324 ScalerInterface* scaler() override { return scaler_.scaler(); }
325
326 private:
327 GLES2Interface* gl_;
328 CopyTextureToImpl* copy_impl_;
329 gfx::Size dst_size_;
330 GLHelper::ScalerQuality quality_;
331 ReadbackSwizzle swizzle_;
332 ScalerHolder scaler_;
333 std::unique_ptr<content::GLHelperScaling::ShaderInterface> pass1_shader_;
334 std::unique_ptr<content::GLHelperScaling::ShaderInterface> pass2_shader_;
335 TextureFrameBufferPair y_;
336 ScopedTexture uv_;
337 TextureFrameBufferPair u_;
338 TextureFrameBufferPair v_;
339
340 DISALLOW_COPY_AND_ASSIGN(ReadbackYUV_MRT);
341 };
342
343 // Copies the block of pixels specified with |src_subrect| from |src_texture|,
344 // scales it to |dst_size|, writes it into a texture, and returns its ID.
345 // |src_size| is the size of |src_texture|.
346 GLuint ScaleTexture(GLuint src_texture,
347 const gfx::Size& src_size,
348 const gfx::Rect& src_subrect,
349 const gfx::Size& dst_size,
350 bool vertically_flip_texture,
351 bool swizzle,
352 SkColorType color_type,
353 GLHelper::ScalerQuality quality);
354
355 // Converts each four consecutive pixels of the source texture into one pixel
356 // in the result texture with each pixel channel representing the grayscale
357 // color of one of the four original pixels:
358 // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X1X2X3X4
359 // The resulting texture is still an RGBA texture (which is ~4 times narrower
360 // than the original). If rendered directly, it wouldn't show anything useful,
361 // but the data in it can be used to construct a grayscale image.
362 // |encoded_texture_size| is the exact size of the resulting RGBA texture. It
363 // is equal to src_size.width()/4 rounded upwards. Some channels in the last
364 // pixel ((-src_size.width()) % 4) to be exact) are padding and don't contain
365 // useful data.
366 // If swizzle is set to true, the transformed pixels are reordered:
367 // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X3X2X1X4.
368 GLuint EncodeTextureAsGrayscale(GLuint src_texture,
369 const gfx::Size& src_size,
370 gfx::Size* const encoded_texture_size,
371 bool vertically_flip_texture,
372 bool swizzle);
373
374 static void nullcallback(bool success) {}
375 void ReadbackDone(Request* request, int bytes_per_pixel);
376 void FinishRequest(Request* request,
377 bool result,
378 FinishRequestHelper* helper);
379 void CancelRequests();
380
381 static const float kRGBtoYColorWeights[];
382 static const float kRGBtoUColorWeights[];
383 static const float kRGBtoVColorWeights[];
384 static const float kRGBtoGrayscaleColorWeights[];
385
386 GLES2Interface* gl_;
387 gpu::ContextSupport* context_support_;
388 GLHelper* helper_;
389
390 // A scoped flush that will ensure all resource deletions are flushed when
391 // this object is destroyed. Must be declared before other Scoped* fields.
392 ScopedFlush flush_;
393
394 std::queue<Request*> request_queue_;
395 GLint max_draw_buffers_;
396 };
397
398 GLHelper::ScalerInterface* GLHelper::CreateScaler(ScalerQuality quality,
399 const gfx::Size& src_size,
400 const gfx::Rect& src_subrect,
401 const gfx::Size& dst_size,
402 bool vertically_flip_texture,
403 bool swizzle) {
404 InitScalerImpl();
405 return scaler_impl_->CreateScaler(quality, src_size, src_subrect, dst_size,
406 vertically_flip_texture, swizzle);
407 }
408
409 GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
410 GLuint src_texture,
411 const gfx::Size& src_size,
412 const gfx::Rect& src_subrect,
413 const gfx::Size& dst_size,
414 bool vertically_flip_texture,
415 bool swizzle,
416 SkColorType color_type,
417 GLHelper::ScalerQuality quality) {
418 GLuint dst_texture = 0u;
419 gl_->GenTextures(1, &dst_texture);
420 {
421 GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
422 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
423
424 // Use GL_RGBA for destination/temporary texture unless we're working with
425 // 16-bit data
426 if (color_type == kRGB_565_SkColorType) {
427 format = GL_RGB;
428 type = GL_UNSIGNED_SHORT_5_6_5;
429 }
430
431 gl_->TexImage2D(GL_TEXTURE_2D, 0, format, dst_size.width(),
432 dst_size.height(), 0, format, type, NULL);
433 }
434 std::unique_ptr<ScalerInterface> scaler(
435 helper_->CreateScaler(quality, src_size, src_subrect, dst_size,
436 vertically_flip_texture, swizzle));
437 scaler->Scale(src_texture, dst_texture);
438 return dst_texture;
439 }
440
441 GLuint GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale(
442 GLuint src_texture,
443 const gfx::Size& src_size,
444 gfx::Size* const encoded_texture_size,
445 bool vertically_flip_texture,
446 bool swizzle) {
447 GLuint dst_texture = 0u;
448 gl_->GenTextures(1, &dst_texture);
449 // The size of the encoded texture.
450 *encoded_texture_size =
451 gfx::Size((src_size.width() + 3) / 4, src_size.height());
452 {
453 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
454 gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, encoded_texture_size->width(),
455 encoded_texture_size->height(), 0, GL_RGBA,
456 GL_UNSIGNED_BYTE, NULL);
457 }
458
459 helper_->InitScalerImpl();
460 std::unique_ptr<ScalerInterface> grayscale_scaler(
461 helper_->scaler_impl_.get()->CreatePlanarScaler(
462 src_size,
463 gfx::Rect(0, 0, (src_size.width() + 3) & ~3, src_size.height()),
464 *encoded_texture_size, vertically_flip_texture, swizzle,
465 kRGBtoGrayscaleColorWeights));
466 grayscale_scaler->Scale(src_texture, dst_texture);
467 return dst_texture;
468 }
469
470 void GLHelper::CopyTextureToImpl::ReadbackAsync(
471 const gfx::Size& dst_size,
472 int32_t bytes_per_row,
473 int32_t row_stride_bytes,
474 unsigned char* out,
475 GLenum format,
476 GLenum type,
477 size_t bytes_per_pixel,
478 const base::Callback<void(bool)>& callback) {
479 TRACE_EVENT0("gpu.capture", "GLHelper::CopyTextureToImpl::ReadbackAsync");
480 Request* request =
481 new Request(dst_size, bytes_per_row, row_stride_bytes, out, callback);
482 request_queue_.push(request);
483 request->buffer = 0u;
484
485 gl_->GenBuffers(1, &request->buffer);
486 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
487 gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
488 bytes_per_pixel * dst_size.GetArea(), NULL, GL_STREAM_READ);
489
490 request->query = 0u;
491 gl_->GenQueriesEXT(1, &request->query);
492 gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, request->query);
493 gl_->ReadPixels(0, 0, dst_size.width(), dst_size.height(), format, type,
494 NULL);
495 gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
496 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
497 context_support_->SignalQuery(
498 request->query, base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(),
499 request, bytes_per_pixel));
500 }
501
502 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
503 GLuint src_texture,
504 const gfx::Size& src_size,
505 const gfx::Rect& src_subrect,
506 const gfx::Size& dst_size,
507 unsigned char* out,
508 const SkColorType out_color_type,
509 const base::Callback<void(bool)>& callback,
510 GLHelper::ScalerQuality quality) {
511 GLenum format, type;
512 size_t bytes_per_pixel;
513 SkColorType readback_color_type = out_color_type;
514 // Single-component textures are not supported by all GPUs, so we implement
515 // kAlpha_8_SkColorType support here via a special encoding (see below) using
516 // a 32-bit texture to represent an 8-bit image.
517 // Thus we use generic 32-bit readback in this case.
518 if (out_color_type == kAlpha_8_SkColorType) {
519 readback_color_type = kRGBA_8888_SkColorType;
520 }
521
522 FormatSupport supported = GetReadbackConfig(readback_color_type, true,
523 &format, &type, &bytes_per_pixel);
524
525 if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
526 callback.Run(false);
527 return;
528 }
529
530 GLuint texture = src_texture;
531
532 // Scale texture if needed
533 // Optimization: SCALER_QUALITY_FAST is just a single bilinear pass, which we
534 // can do just as well in EncodeTextureAsGrayscale, which we will do if
535 // out_color_type is kAlpha_8_SkColorType, so let's skip the scaling step
536 // in that case.
537 bool scale_texture = out_color_type != kAlpha_8_SkColorType ||
538 quality != GLHelper::SCALER_QUALITY_FAST;
539 if (scale_texture) {
540 // Don't swizzle during the scale step for kAlpha_8_SkColorType.
541 // We will swizzle in the encode step below if needed.
542 bool scale_swizzle = out_color_type == kAlpha_8_SkColorType
543 ? false
544 : supported == GLHelperReadbackSupport::SWIZZLE;
545 texture = ScaleTexture(src_texture, src_size, src_subrect, dst_size, true,
546 scale_swizzle, out_color_type == kAlpha_8_SkColorType
547 ? kN32_SkColorType
548 : out_color_type,
549 quality);
550 DCHECK(texture);
551 }
552
553 gfx::Size readback_texture_size = dst_size;
554 // Encode texture to grayscale if needed.
555 if (out_color_type == kAlpha_8_SkColorType) {
556 // Do the vertical flip here if we haven't already done it when we scaled
557 // the texture.
558 bool encode_as_grayscale_vertical_flip = !scale_texture;
559 // EncodeTextureAsGrayscale by default creates a texture which should be
560 // read back as RGBA, so need to swizzle if the readback format is BGRA.
561 bool encode_as_grayscale_swizzle = format == GL_BGRA_EXT;
562 GLuint tmp_texture = EncodeTextureAsGrayscale(
563 texture, dst_size, &readback_texture_size,
564 encode_as_grayscale_vertical_flip, encode_as_grayscale_swizzle);
565 // If the scaled texture was created - delete it
566 if (scale_texture)
567 gl_->DeleteTextures(1, &texture);
568 texture = tmp_texture;
569 DCHECK(texture);
570 }
571
572 // Readback the pixels of the resulting texture
573 ScopedFramebuffer dst_framebuffer(gl_);
574 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
575 dst_framebuffer);
576 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
577 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
578 texture, 0);
579
580 int32_t bytes_per_row = out_color_type == kAlpha_8_SkColorType
581 ? dst_size.width()
582 : dst_size.width() * bytes_per_pixel;
583
584 ReadbackAsync(readback_texture_size, bytes_per_row, bytes_per_row, out,
585 format, type, bytes_per_pixel, callback);
586 gl_->DeleteTextures(1, &texture);
587 }
588
589 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(GLuint texture,
590 const gfx::Rect& src_rect,
591 unsigned char* out,
592 SkColorType color_type) {
593 GLenum format, type;
594 size_t bytes_per_pixel;
595 FormatSupport supported =
596 GetReadbackConfig(color_type, false, &format, &type, &bytes_per_pixel);
597 if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
598 return;
599 }
600
601 ScopedFramebuffer dst_framebuffer(gl_);
602 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
603 dst_framebuffer);
604 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
605 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
606 texture, 0);
607 gl_->ReadPixels(src_rect.x(), src_rect.y(), src_rect.width(),
608 src_rect.height(), format, type, out);
609 }
610
611 void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
612 GLuint texture,
613 const gfx::Size& dst_size,
614 unsigned char* out,
615 SkColorType color_type,
616 const base::Callback<void(bool)>& callback) {
617 GLenum format, type;
618 size_t bytes_per_pixel;
619 FormatSupport supported =
620 GetReadbackConfig(color_type, false, &format, &type, &bytes_per_pixel);
621 if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
622 callback.Run(false);
623 return;
624 }
625
626 ScopedFramebuffer dst_framebuffer(gl_);
627 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
628 dst_framebuffer);
629 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
630 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
631 texture, 0);
632 ReadbackAsync(dst_size, dst_size.width() * bytes_per_pixel,
633 dst_size.width() * bytes_per_pixel, out, format, type,
634 bytes_per_pixel, callback);
635 }
636
637 GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
638 GLuint src_texture,
639 const gfx::Size& src_size,
640 const gfx::Size& dst_size,
641 bool vertically_flip_texture,
642 GLHelper::ScalerQuality quality) {
643 return ScaleTexture(src_texture, src_size, gfx::Rect(src_size), dst_size,
644 vertically_flip_texture, false,
645 kRGBA_8888_SkColorType, // GL_RGBA
646 quality);
647 }
648
649 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request,
650 int bytes_per_pixel) {
651 TRACE_EVENT0("gpu.capture",
652 "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete");
653 finished_request->done = true;
654
655 FinishRequestHelper finish_request_helper;
656
657 // We process transfer requests in the order they were received, regardless
658 // of the order we get the callbacks in.
659 while (!request_queue_.empty()) {
660 Request* request = request_queue_.front();
661 if (!request->done) {
662 break;
663 }
664
665 bool result = false;
666 if (request->buffer != 0) {
667 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
668 unsigned char* data = static_cast<unsigned char*>(gl_->MapBufferCHROMIUM(
669 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
670 if (data) {
671 result = true;
672 if (request->bytes_per_row == request->size.width() * bytes_per_pixel &&
673 request->bytes_per_row == request->row_stride_bytes) {
674 memcpy(request->pixels, data,
675 request->size.GetArea() * bytes_per_pixel);
676 } else {
677 unsigned char* out = request->pixels;
678 for (int y = 0; y < request->size.height(); y++) {
679 memcpy(out, data, request->bytes_per_row);
680 out += request->row_stride_bytes;
681 data += request->size.width() * bytes_per_pixel;
682 }
683 }
684 gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
685 }
686 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
687 }
688 FinishRequest(request, result, &finish_request_helper);
689 }
690 }
691
692 void GLHelper::CopyTextureToImpl::FinishRequest(
693 Request* request,
694 bool result,
695 FinishRequestHelper* finish_request_helper) {
696 TRACE_EVENT0("gpu.capture", "GLHelper::CopyTextureToImpl::FinishRequest");
697 DCHECK(request_queue_.front() == request);
698 request_queue_.pop();
699 request->result = result;
700 ScopedFlush flush(gl_);
701 if (request->query != 0) {
702 gl_->DeleteQueriesEXT(1, &request->query);
703 request->query = 0;
704 }
705 if (request->buffer != 0) {
706 gl_->DeleteBuffers(1, &request->buffer);
707 request->buffer = 0;
708 }
709 finish_request_helper->Add(request);
710 }
711
712 void GLHelper::CopyTextureToImpl::CancelRequests() {
713 FinishRequestHelper finish_request_helper;
714 while (!request_queue_.empty()) {
715 Request* request = request_queue_.front();
716 FinishRequest(request, false, &finish_request_helper);
717 }
718 }
719
720 FormatSupport GLHelper::CopyTextureToImpl::GetReadbackConfig(
721 SkColorType color_type,
722 bool can_swizzle,
723 GLenum* format,
724 GLenum* type,
725 size_t* bytes_per_pixel) {
726 return helper_->readback_support_->GetReadbackConfig(
727 color_type, can_swizzle, format, type, bytes_per_pixel);
728 }
729
730 GLHelper::GLHelper(GLES2Interface* gl, gpu::ContextSupport* context_support)
731 : gl_(gl),
732 context_support_(context_support),
733 readback_support_(new GLHelperReadbackSupport(gl)) {}
734
735 GLHelper::~GLHelper() {}
736
737 void GLHelper::CropScaleReadbackAndCleanTexture(
738 GLuint src_texture,
739 const gfx::Size& src_size,
740 const gfx::Rect& src_subrect,
741 const gfx::Size& dst_size,
742 unsigned char* out,
743 const SkColorType out_color_type,
744 const base::Callback<void(bool)>& callback,
745 GLHelper::ScalerQuality quality) {
746 InitCopyTextToImpl();
747 copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(
748 src_texture, src_size, src_subrect, dst_size, out, out_color_type,
749 callback, quality);
750 }
751
752 void GLHelper::CropScaleReadbackAndCleanMailbox(
753 const gpu::Mailbox& src_mailbox,
754 const gpu::SyncToken& sync_token,
755 const gfx::Size& src_size,
756 const gfx::Rect& src_subrect,
757 const gfx::Size& dst_size,
758 unsigned char* out,
759 const SkColorType out_color_type,
760 const base::Callback<void(bool)>& callback,
761 GLHelper::ScalerQuality quality) {
762 GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_token);
763 CropScaleReadbackAndCleanTexture(mailbox_texture, src_size, src_subrect,
764 dst_size, out, out_color_type, callback,
765 quality);
766 gl_->DeleteTextures(1, &mailbox_texture);
767 }
768
769 void GLHelper::ReadbackTextureSync(GLuint texture,
770 const gfx::Rect& src_rect,
771 unsigned char* out,
772 SkColorType format) {
773 InitCopyTextToImpl();
774 copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format);
775 }
776
777 void GLHelper::ReadbackTextureAsync(
778 GLuint texture,
779 const gfx::Size& dst_size,
780 unsigned char* out,
781 SkColorType color_type,
782 const base::Callback<void(bool)>& callback) {
783 InitCopyTextToImpl();
784 copy_texture_to_impl_->ReadbackTextureAsync(texture, dst_size, out,
785 color_type, callback);
786 }
787
788 GLuint GLHelper::CopyTexture(GLuint texture, const gfx::Size& size) {
789 InitCopyTextToImpl();
790 return copy_texture_to_impl_->CopyAndScaleTexture(
791 texture, size, size, false, GLHelper::SCALER_QUALITY_FAST);
792 }
793
794 GLuint GLHelper::CopyAndScaleTexture(GLuint texture,
795 const gfx::Size& src_size,
796 const gfx::Size& dst_size,
797 bool vertically_flip_texture,
798 ScalerQuality quality) {
799 InitCopyTextToImpl();
800 return copy_texture_to_impl_->CopyAndScaleTexture(
801 texture, src_size, dst_size, vertically_flip_texture, quality);
802 }
803
804 GLuint GLHelper::CompileShaderFromSource(const GLchar* source, GLenum type) {
805 GLuint shader = gl_->CreateShader(type);
806 GLint length = strlen(source);
807 gl_->ShaderSource(shader, 1, &source, &length);
808 gl_->CompileShader(shader);
809 GLint compile_status = 0;
810 gl_->GetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
811 if (!compile_status) {
812 GLint log_length = 0;
813 gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
814 if (log_length) {
815 std::unique_ptr<GLchar[]> log(new GLchar[log_length]);
816 GLsizei returned_log_length = 0;
817 gl_->GetShaderInfoLog(shader, log_length, &returned_log_length,
818 log.get());
819 LOG(ERROR) << std::string(log.get(), returned_log_length);
820 }
821 gl_->DeleteShader(shader);
822 return 0;
823 }
824 return shader;
825 }
826
827 void GLHelper::InitCopyTextToImpl() {
828 // Lazily initialize |copy_texture_to_impl_|
829 if (!copy_texture_to_impl_)
830 copy_texture_to_impl_.reset(
831 new CopyTextureToImpl(gl_, context_support_, this));
832 }
833
834 void GLHelper::InitScalerImpl() {
835 // Lazily initialize |scaler_impl_|
836 if (!scaler_impl_)
837 scaler_impl_.reset(new GLHelperScaling(gl_, this));
838 }
839
840 GLint GLHelper::MaxDrawBuffers() {
841 InitCopyTextToImpl();
842 return copy_texture_to_impl_->MaxDrawBuffers();
843 }
844
845 void GLHelper::CopySubBufferDamage(GLenum target,
846 GLuint texture,
847 GLuint previous_texture,
848 const SkRegion& new_damage,
849 const SkRegion& old_damage) {
850 SkRegion region(old_damage);
851 if (region.op(new_damage, SkRegion::kDifference_Op)) {
852 ScopedFramebuffer dst_framebuffer(gl_);
853 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
854 dst_framebuffer);
855 gl_->BindTexture(target, texture);
856 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
857 previous_texture, 0);
858 for (SkRegion::Iterator it(region); !it.done(); it.next()) {
859 const SkIRect& rect = it.rect();
860 gl_->CopyTexSubImage2D(target, 0, rect.x(), rect.y(), rect.x(), rect.y(),
861 rect.width(), rect.height());
862 }
863 gl_->BindTexture(target, 0);
864 gl_->Flush();
865 }
866 }
867
868 GLuint GLHelper::CreateTexture() {
869 GLuint texture = 0u;
870 gl_->GenTextures(1, &texture);
871 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
872 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
873 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
874 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
875 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
876 return texture;
877 }
878
879 void GLHelper::DeleteTexture(GLuint texture_id) {
880 gl_->DeleteTextures(1, &texture_id);
881 }
882
883 void GLHelper::GenerateSyncToken(gpu::SyncToken* sync_token) {
884 const uint64_t fence_sync = gl_->InsertFenceSyncCHROMIUM();
885 gl_->ShallowFlushCHROMIUM();
886 gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token->GetData());
887 }
888
889 void GLHelper::WaitSyncToken(const gpu::SyncToken& sync_token) {
890 gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
891 }
892
893 gpu::MailboxHolder GLHelper::ProduceMailboxHolderFromTexture(
894 GLuint texture_id) {
895 gpu::Mailbox mailbox;
896 gl_->GenMailboxCHROMIUM(mailbox.name);
897 gl_->ProduceTextureDirectCHROMIUM(texture_id, GL_TEXTURE_2D, mailbox.name);
898
899 gpu::SyncToken sync_token;
900 GenerateSyncToken(&sync_token);
901
902 return gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D);
903 }
904
905 GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
906 const gpu::SyncToken& sync_token) {
907 if (mailbox.IsZero())
908 return 0;
909 if (sync_token.HasData())
910 WaitSyncToken(sync_token);
911 GLuint texture =
912 gl_->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
913 return texture;
914 }
915
916 void GLHelper::ResizeTexture(GLuint texture, const gfx::Size& size) {
917 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
918 gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0,
919 GL_RGB, GL_UNSIGNED_BYTE, NULL);
920 }
921
922 void GLHelper::CopyTextureSubImage(GLuint texture, const gfx::Rect& rect) {
923 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
924 gl_->CopyTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.x(),
925 rect.y(), rect.width(), rect.height());
926 }
927
928 void GLHelper::CopyTextureFullImage(GLuint texture, const gfx::Size& size) {
929 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
930 gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(),
931 size.height(), 0);
932 }
933
934 void GLHelper::Flush() {
935 gl_->Flush();
936 }
937
938 void GLHelper::InsertOrderingBarrier() {
939 gl_->OrderingBarrierCHROMIUM();
940 }
941
942 void GLHelper::CopyTextureToImpl::ReadbackPlane(
943 TextureFrameBufferPair* source,
944 int row_stride_bytes,
945 unsigned char* data,
946 int size_shift,
947 const gfx::Rect& paste_rect,
948 ReadbackSwizzle swizzle,
949 const base::Callback<void(bool)>& callback) {
950 gl_->BindFramebuffer(GL_FRAMEBUFFER, source->framebuffer());
951 const size_t offset = row_stride_bytes * (paste_rect.y() >> size_shift) +
952 (paste_rect.x() >> size_shift);
953 ReadbackAsync(source->size(), paste_rect.width() >> size_shift,
954 row_stride_bytes, data + offset,
955 (swizzle == kSwizzleBGRA) ? GL_BGRA_EXT : GL_RGBA,
956 GL_UNSIGNED_BYTE, 4, callback);
957 }
958
959 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = {
960 0.257f, 0.504f, 0.098f, 0.0625f};
961 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = {
962 -0.148f, -0.291f, 0.439f, 0.5f};
963 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = {
964 0.439f, -0.368f, -0.071f, 0.5f};
965 const float GLHelper::CopyTextureToImpl::kRGBtoGrayscaleColorWeights[] = {
966 0.213f, 0.715f, 0.072f, 0.0f};
967
968 // YUV readback constructors. Initiates the main scaler pipeline and
969 // one planar scaler for each of the Y, U and V planes.
970 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
971 GLES2Interface* gl,
972 CopyTextureToImpl* copy_impl,
973 GLHelperScaling* scaler_impl,
974 GLHelper::ScalerQuality quality,
975 const gfx::Size& src_size,
976 const gfx::Rect& src_subrect,
977 const gfx::Size& dst_size,
978 bool flip_vertically,
979 ReadbackSwizzle swizzle)
980 : gl_(gl),
981 copy_impl_(copy_impl),
982 dst_size_(dst_size),
983 swizzle_(swizzle),
984 scaler_(gl,
985 scaler_impl->CreateScaler(quality,
986 src_size,
987 src_subrect,
988 dst_size,
989 flip_vertically,
990 false)),
991 y_(gl,
992 scaler_impl->CreatePlanarScaler(
993 dst_size,
994 gfx::Rect(0, 0, (dst_size.width() + 3) & ~3, dst_size.height()),
995 gfx::Size((dst_size.width() + 3) / 4, dst_size.height()),
996 false,
997 (swizzle == kSwizzleBGRA),
998 kRGBtoYColorWeights)),
999 u_(gl,
1000 scaler_impl->CreatePlanarScaler(
1001 dst_size,
1002 gfx::Rect(0,
1003 0,
1004 (dst_size.width() + 7) & ~7,
1005 (dst_size.height() + 1) & ~1),
1006 gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2),
1007 false,
1008 (swizzle == kSwizzleBGRA),
1009 kRGBtoUColorWeights)),
1010 v_(gl,
1011 scaler_impl->CreatePlanarScaler(
1012 dst_size,
1013 gfx::Rect(0,
1014 0,
1015 (dst_size.width() + 7) & ~7,
1016 (dst_size.height() + 1) & ~1),
1017 gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2),
1018 false,
1019 (swizzle == kSwizzleBGRA),
1020 kRGBtoVColorWeights)) {
1021 DCHECK(!(dst_size.width() & 1));
1022 DCHECK(!(dst_size.height() & 1));
1023 }
1024
1025 void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV(
1026 const gpu::Mailbox& mailbox,
1027 const gpu::SyncToken& sync_token,
1028 const gfx::Rect& target_visible_rect,
1029 int y_plane_row_stride_bytes,
1030 unsigned char* y_plane_data,
1031 int u_plane_row_stride_bytes,
1032 unsigned char* u_plane_data,
1033 int v_plane_row_stride_bytes,
1034 unsigned char* v_plane_data,
1035 const gfx::Point& paste_location,
1036 const base::Callback<void(bool)>& callback) {
1037 DCHECK(!(paste_location.x() & 1));
1038 DCHECK(!(paste_location.y() & 1));
1039
1040 GLuint mailbox_texture =
1041 copy_impl_->ConsumeMailboxToTexture(mailbox, sync_token);
1042
1043 // Scale texture to right size.
1044 scaler_.Scale(mailbox_texture);
1045 gl_->DeleteTextures(1, &mailbox_texture);
1046
1047 // Convert the scaled texture in to Y, U and V planes.
1048 y_.Scale(scaler_.texture());
1049 u_.Scale(scaler_.texture());
1050 v_.Scale(scaler_.texture());
1051
1052 const gfx::Rect paste_rect(paste_location, dst_size_);
1053 if (!target_visible_rect.Contains(paste_rect)) {
1054 LOG(DFATAL) << "Paste rect not inside VideoFrame's visible rect!";
1055 callback.Run(false);
1056 return;
1057 }
1058
1059 // Read back planes, one at a time. Keep the video frame alive while doing the
1060 // readback.
1061 copy_impl_->ReadbackPlane(y_.texture_and_framebuffer(),
1062 y_plane_row_stride_bytes, y_plane_data, 0,
1063 paste_rect, swizzle_, base::Bind(&nullcallback));
1064 copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(),
1065 u_plane_row_stride_bytes, u_plane_data, 1,
1066 paste_rect, swizzle_, base::Bind(&nullcallback));
1067 copy_impl_->ReadbackPlane(v_.texture_and_framebuffer(),
1068 v_plane_row_stride_bytes, v_plane_data, 1,
1069 paste_rect, swizzle_, callback);
1070 gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
1071 }
1072
1073 // YUV readback constructors. Initiates the main scaler pipeline and
1074 // one planar scaler for each of the Y, U and V planes.
1075 GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
1076 GLES2Interface* gl,
1077 CopyTextureToImpl* copy_impl,
1078 GLHelperScaling* scaler_impl,
1079 GLHelper::ScalerQuality quality,
1080 const gfx::Size& src_size,
1081 const gfx::Rect& src_subrect,
1082 const gfx::Size& dst_size,
1083 bool flip_vertically,
1084 ReadbackSwizzle swizzle)
1085 : gl_(gl),
1086 copy_impl_(copy_impl),
1087 dst_size_(dst_size),
1088 quality_(quality),
1089 swizzle_(swizzle),
1090 scaler_(gl,
1091 scaler_impl->CreateScaler(quality,
1092 src_size,
1093 src_subrect,
1094 dst_size,
1095 false,
1096 false)),
1097 pass1_shader_(scaler_impl->CreateYuvMrtShader(
1098 dst_size,
1099 gfx::Rect(0, 0, (dst_size.width() + 3) & ~3, dst_size.height()),
1100 gfx::Size((dst_size.width() + 3) / 4, dst_size.height()),
1101 flip_vertically,
1102 (swizzle == kSwizzleBGRA),
1103 GLHelperScaling::SHADER_YUV_MRT_PASS1)),
1104 pass2_shader_(scaler_impl->CreateYuvMrtShader(
1105 gfx::Size((dst_size.width() + 3) / 4, dst_size.height()),
1106 gfx::Rect(0, 0, (dst_size.width() + 7) / 8 * 2, dst_size.height()),
1107 gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2),
1108 false,
1109 (swizzle == kSwizzleBGRA),
1110 GLHelperScaling::SHADER_YUV_MRT_PASS2)),
1111 y_(gl, gfx::Size((dst_size.width() + 3) / 4, dst_size.height())),
1112 uv_(gl),
1113 u_(gl,
1114 gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2)),
1115 v_(gl,
1116 gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2)) {
1117 DCHECK(!(dst_size.width() & 1));
1118 DCHECK(!(dst_size.height() & 1));
1119
1120 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, uv_);
1121 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (dst_size.width() + 3) / 4,
1122 dst_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1123 }
1124
1125 void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
1126 const gpu::Mailbox& mailbox,
1127 const gpu::SyncToken& sync_token,
1128 const gfx::Rect& target_visible_rect,
1129 int y_plane_row_stride_bytes,
1130 unsigned char* y_plane_data,
1131 int u_plane_row_stride_bytes,
1132 unsigned char* u_plane_data,
1133 int v_plane_row_stride_bytes,
1134 unsigned char* v_plane_data,
1135 const gfx::Point& paste_location,
1136 const base::Callback<void(bool)>& callback) {
1137 DCHECK(!(paste_location.x() & 1));
1138 DCHECK(!(paste_location.y() & 1));
1139
1140 GLuint mailbox_texture =
1141 copy_impl_->ConsumeMailboxToTexture(mailbox, sync_token);
1142
1143 GLuint texture;
1144 if (quality_ == GLHelper::SCALER_QUALITY_FAST) {
1145 // Optimization: SCALER_QUALITY_FAST is just a single bilinear
1146 // pass, which pass1_shader_ can do just as well, so let's skip
1147 // the actual scaling in that case.
1148 texture = mailbox_texture;
1149 } else {
1150 // Scale texture to right size.
1151 scaler_.Scale(mailbox_texture);
1152 texture = scaler_.texture();
1153 }
1154
1155 std::vector<GLuint> outputs(2);
1156 // Convert the scaled texture in to Y, U and V planes.
1157 outputs[0] = y_.texture();
1158 outputs[1] = uv_;
1159 pass1_shader_->Execute(texture, outputs);
1160
1161 gl_->DeleteTextures(1, &mailbox_texture);
1162
1163 outputs[0] = u_.texture();
1164 outputs[1] = v_.texture();
1165 pass2_shader_->Execute(uv_, outputs);
1166
1167 const gfx::Rect paste_rect(paste_location, dst_size_);
1168 if (!target_visible_rect.Contains(paste_rect)) {
1169 LOG(DFATAL) << "Paste rect not inside VideoFrame's visible rect!";
1170 callback.Run(false);
1171 return;
1172 }
1173
1174 // Read back planes, one at a time.
1175 copy_impl_->ReadbackPlane(&y_, y_plane_row_stride_bytes, y_plane_data, 0,
1176 paste_rect, swizzle_, base::Bind(&nullcallback));
1177 copy_impl_->ReadbackPlane(&u_, u_plane_row_stride_bytes, u_plane_data, 1,
1178 paste_rect, swizzle_, base::Bind(&nullcallback));
1179 copy_impl_->ReadbackPlane(&v_, v_plane_row_stride_bytes, v_plane_data, 1,
1180 paste_rect, swizzle_, callback);
1181 gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
1182 }
1183
1184 bool GLHelper::IsReadbackConfigSupported(SkColorType color_type) {
1185 DCHECK(readback_support_.get());
1186 GLenum format, type;
1187 size_t bytes_per_pixel;
1188 FormatSupport support = readback_support_->GetReadbackConfig(
1189 color_type, false, &format, &type, &bytes_per_pixel);
1190
1191 return (support == GLHelperReadbackSupport::SUPPORTED);
1192 }
1193
1194 ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
1195 GLHelper::ScalerQuality quality,
1196 const gfx::Size& src_size,
1197 const gfx::Rect& src_subrect,
1198 const gfx::Size& dst_size,
1199 bool flip_vertically,
1200 bool use_mrt) {
1201 helper_->InitScalerImpl();
1202 // Just query if the best readback configuration needs a swizzle In
1203 // ReadbackPlane() we will choose GL_RGBA/GL_BGRA_EXT based on swizzle
1204 GLenum format, type;
1205 size_t bytes_per_pixel;
1206 FormatSupport supported = GetReadbackConfig(kRGBA_8888_SkColorType, true,
1207 &format, &type, &bytes_per_pixel);
1208 DCHECK((format == GL_RGBA || format == GL_BGRA_EXT) &&
1209 type == GL_UNSIGNED_BYTE);
1210
1211 ReadbackSwizzle swizzle = kSwizzleNone;
1212 if (supported == GLHelperReadbackSupport::SWIZZLE)
1213 swizzle = kSwizzleBGRA;
1214
1215 if (max_draw_buffers_ >= 2 && use_mrt) {
1216 return new ReadbackYUV_MRT(gl_, this, helper_->scaler_impl_.get(), quality,
1217 src_size, src_subrect, dst_size, flip_vertically,
1218 swizzle);
1219 }
1220 return new ReadbackYUVImpl(gl_, this, helper_->scaler_impl_.get(), quality,
1221 src_size, src_subrect, dst_size, flip_vertically,
1222 swizzle);
1223 }
1224
1225 ReadbackYUVInterface* GLHelper::CreateReadbackPipelineYUV(
1226 ScalerQuality quality,
1227 const gfx::Size& src_size,
1228 const gfx::Rect& src_subrect,
1229 const gfx::Size& dst_size,
1230 bool flip_vertically,
1231 bool use_mrt) {
1232 InitCopyTextToImpl();
1233 return copy_texture_to_impl_->CreateReadbackPipelineYUV(
1234 quality, src_size, src_subrect, dst_size, flip_vertically, use_mrt);
1235 }
1236
1237 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/compositor/gl_helper.h ('k') | content/browser/compositor/gl_helper_benchmark.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698