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

Side by Side Diff: components/display_compositor/gl_helper.cc

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

Powered by Google App Engine
This is Rietveld 408576698