OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/renderers/skcanvas_video_renderer.h" | 5 #include "media/renderers/skcanvas_video_renderer.h" |
6 | 6 |
7 #include <GLES3/gl3.h> | 7 #include <GLES3/gl3.h> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "cc/paint/paint_canvas.h" | 12 #include "cc/paint/paint_canvas.h" |
13 #include "cc/paint/paint_flags.h" | 13 #include "cc/paint/paint_flags.h" |
14 #include "cc/paint/paint_image.h" | 14 #include "cc/paint/paint_image.h" |
15 #include "gpu/GLES2/gl2extchromium.h" | 15 #include "gpu/GLES2/gl2extchromium.h" |
16 #include "gpu/command_buffer/client/gles2_interface.h" | 16 #include "gpu/command_buffer/client/gles2_interface.h" |
| 17 #include "gpu/command_buffer/common/capabilities.h" |
17 #include "gpu/command_buffer/common/mailbox_holder.h" | 18 #include "gpu/command_buffer/common/mailbox_holder.h" |
18 #include "media/base/data_buffer.h" | 19 #include "media/base/data_buffer.h" |
19 #include "media/base/video_frame.h" | 20 #include "media/base/video_frame.h" |
20 #include "skia/ext/texture_handle.h" | 21 #include "skia/ext/texture_handle.h" |
21 #include "third_party/libyuv/include/libyuv.h" | 22 #include "third_party/libyuv/include/libyuv.h" |
22 #include "third_party/skia/include/core/SkImage.h" | 23 #include "third_party/skia/include/core/SkImage.h" |
23 #include "third_party/skia/include/core/SkImageGenerator.h" | 24 #include "third_party/skia/include/core/SkImageGenerator.h" |
24 #include "third_party/skia/include/gpu/GrContext.h" | 25 #include "third_party/skia/include/gpu/GrContext.h" |
25 #include "third_party/skia/include/gpu/gl/GrGLTypes.h" | 26 #include "third_party/skia/include/gpu/gl/GrGLTypes.h" |
26 #include "ui/gfx/geometry/rect_f.h" | 27 #include "ui/gfx/geometry/rect_f.h" |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 *out_row++ = gray_value; | 569 *out_row++ = gray_value; |
569 *out_row++ = gray_value; | 570 *out_row++ = gray_value; |
570 *out_row++ = 1.0f; | 571 *out_row++ = 1.0f; |
571 } | 572 } |
572 continue; | 573 continue; |
573 } else if (format == GL_RED) { | 574 } else if (format == GL_RED) { |
574 while (row < row_end) | 575 while (row < row_end) |
575 *out_row++ = *row++ / 65535.f; | 576 *out_row++ = *row++ / 65535.f; |
576 continue; | 577 continue; |
577 } | 578 } |
578 // For other formats, hit NOTREACHED bellow. | 579 // For other formats, hit NOTREACHED below. |
579 } else if (type == GL_UNSIGNED_BYTE) { | 580 } else if (type == GL_UNSIGNED_BYTE) { |
580 // We take the upper 8 bits of 16-bit data and convert it as luminance to | 581 // We take the upper 8 bits of 16-bit data and convert it as luminance to |
581 // ARGB. We loose the precision here, but it is important not to render | 582 // ARGB. We loose the precision here, but it is important not to render |
582 // Y16 as RG_88. To get the full precision use float textures with WebGL1 | 583 // Y16 as RG_88. To get the full precision use float textures with WebGL1 |
583 // and e.g. R16UI or R32F textures with WebGL2. | 584 // and e.g. R16UI or R32F textures with WebGL2. |
584 DCHECK_EQ(static_cast<unsigned>(GL_RGBA), format); | 585 DCHECK_EQ(static_cast<unsigned>(GL_RGBA), format); |
585 uint32_t* rgba = reinterpret_cast<uint32_t*>(out_row_head); | 586 uint32_t* rgba = reinterpret_cast<uint32_t*>(out_row_head); |
586 while (row < row_end) { | 587 while (row < row_end) { |
587 uint32_t gray_value = *row++ >> 8; | 588 uint32_t gray_value = *row++ >> 8; |
588 *rgba++ = SkColorSetRGB(gray_value, gray_value, gray_value); | 589 *rgba++ = SkColorSetRGB(gray_value, gray_value, gray_value); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 | 632 |
632 size_t output_row_bytes = | 633 size_t output_row_bytes = |
633 frame->visible_rect().width() * output_bytes_per_pixel; | 634 frame->visible_rect().width() * output_bytes_per_pixel; |
634 *temp_buffer = | 635 *temp_buffer = |
635 new DataBuffer(output_row_bytes * frame->visible_rect().height()); | 636 new DataBuffer(output_row_bytes * frame->visible_rect().height()); |
636 FlipAndConvertY16(frame, (*temp_buffer)->writable_data(), format, type, | 637 FlipAndConvertY16(frame, (*temp_buffer)->writable_data(), format, type, |
637 flip_y, output_row_bytes); | 638 flip_y, output_row_bytes); |
638 return true; | 639 return true; |
639 } | 640 } |
640 | 641 |
| 642 // Upload the |frame| data to temporary texture of |temp_format|, |
| 643 // |temp_internalformat| and |temp_type| and then copy intermediate texture |
| 644 // subimage to destination |texture|. The destination |texture| is bound to the |
| 645 // |target| before the call. |
| 646 void TextureSubImageUsingIntermediate(unsigned target, |
| 647 unsigned texture, |
| 648 gpu::gles2::GLES2Interface* gl, |
| 649 VideoFrame* frame, |
| 650 int temp_internalformat, |
| 651 unsigned temp_format, |
| 652 unsigned temp_type, |
| 653 int level, |
| 654 int xoffset, |
| 655 int yoffset, |
| 656 bool flip_y, |
| 657 bool premultiply_alpha) { |
| 658 unsigned temp_texture = 0; |
| 659 gl->GenTextures(1, &temp_texture); |
| 660 gl->BindTexture(target, temp_texture); |
| 661 gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 662 gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 663 gl->TexImage2D(target, 0, temp_internalformat, frame->visible_rect().width(), |
| 664 frame->visible_rect().height(), 0, temp_format, temp_type, |
| 665 frame->visible_data(0)); |
| 666 gl->BindTexture(target, texture); |
| 667 gl->CopySubTextureCHROMIUM(temp_texture, 0, target, texture, level, 0, 0, |
| 668 xoffset, yoffset, frame->visible_rect().width(), |
| 669 frame->visible_rect().height(), flip_y, |
| 670 premultiply_alpha, false); |
| 671 gl->DeleteTextures(1, &temp_texture); |
| 672 } |
| 673 |
641 } // anonymous namespace | 674 } // anonymous namespace |
642 | 675 |
643 // static | 676 // static |
644 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( | 677 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( |
645 const VideoFrame* video_frame, | 678 const VideoFrame* video_frame, |
646 void* rgb_pixels, | 679 void* rgb_pixels, |
647 size_t row_bytes) { | 680 size_t row_bytes) { |
648 if (!video_frame->IsMappable()) { | 681 if (!video_frame->IsMappable()) { |
649 NOTREACHED() << "Cannot extract pixels from non-CPU frame formats."; | 682 NOTREACHED() << "Cannot extract pixels from non-CPU frame formats."; |
650 return; | 683 return; |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 video_frame->UpdateReleaseSyncToken(&client); | 953 video_frame->UpdateReleaseSyncToken(&client); |
921 } else { | 954 } else { |
922 CopyVideoFrameSingleTextureToGLTexture( | 955 CopyVideoFrameSingleTextureToGLTexture( |
923 destination_gl, video_frame.get(), SingleFrameForWebGL, texture, | 956 destination_gl, video_frame.get(), SingleFrameForWebGL, texture, |
924 internal_format, format, type, premultiply_alpha, flip_y); | 957 internal_format, format, type, premultiply_alpha, flip_y); |
925 } | 958 } |
926 | 959 |
927 return true; | 960 return true; |
928 } | 961 } |
929 | 962 |
930 bool SkCanvasVideoRenderer::TexImage2D(unsigned target, | 963 bool SkCanvasVideoRenderer::TexImage2D( |
931 gpu::gles2::GLES2Interface* gl, | 964 unsigned target, |
932 VideoFrame* frame, | 965 unsigned texture, |
933 int level, | 966 gpu::gles2::GLES2Interface* gl, |
934 int internalformat, | 967 const gpu::Capabilities& gpu_capabilities, |
935 unsigned format, | 968 VideoFrame* frame, |
936 unsigned type, | 969 int level, |
937 bool flip_y, | 970 int internalformat, |
938 bool premultiply_alpha) { | 971 unsigned format, |
| 972 unsigned type, |
| 973 bool flip_y, |
| 974 bool premultiply_alpha) { |
939 DCHECK(frame); | 975 DCHECK(frame); |
940 DCHECK(!frame->HasTextures()); | 976 DCHECK(!frame->HasTextures()); |
941 | 977 |
| 978 // Note: CopyTextureCHROMIUM uses mediump for color computation. Don't use |
| 979 // it if the precision would lead to data loss when converting 16-bit |
| 980 // normalized to float. medium_float.precision > 15 means that the approach |
| 981 // below is not used on Android, where the extension EXT_texture_norm16 is |
| 982 // not widely supported. It is used on Windows, Linux and OSX. |
| 983 // Android support is not required for now because Tango depth camera already |
| 984 // provides floating point data (projected point cloud). See crbug.com/674440. |
| 985 if (gpu_capabilities.texture_norm16 && |
| 986 gpu_capabilities.fragment_shader_precisions.medium_float.precision > 15 && |
| 987 target == GL_TEXTURE_2D && |
| 988 (type == GL_FLOAT || type == GL_UNSIGNED_BYTE)) { |
| 989 // TODO(aleksandar.stojiljkovic): Extend the approach to TexSubImage2D |
| 990 // implementation and other types. See https://crbug.com/624436. |
| 991 |
| 992 // Allocate the destination texture. |
| 993 gl->TexImage2D(target, level, internalformat, frame->visible_rect().width(), |
| 994 frame->visible_rect().height(), 0, format, type, nullptr); |
| 995 // We use sized internal format GL_R16_EXT instead of unsized GL_RED. |
| 996 // See angleproject:1952 |
| 997 TextureSubImageUsingIntermediate(target, texture, gl, frame, GL_R16_EXT, |
| 998 GL_RED, GL_UNSIGNED_SHORT, level, 0, 0, |
| 999 flip_y, premultiply_alpha); |
| 1000 return true; |
| 1001 } |
942 scoped_refptr<DataBuffer> temp_buffer; | 1002 scoped_refptr<DataBuffer> temp_buffer; |
943 if (!TexImageHelper(frame, format, type, flip_y, &temp_buffer)) | 1003 if (!TexImageHelper(frame, format, type, flip_y, &temp_buffer)) |
944 return false; | 1004 return false; |
945 | 1005 |
946 gl->TexImage2D(target, level, internalformat, frame->visible_rect().width(), | 1006 gl->TexImage2D(target, level, internalformat, frame->visible_rect().width(), |
947 frame->visible_rect().height(), 0, format, type, | 1007 frame->visible_rect().height(), 0, format, type, |
948 temp_buffer->data()); | 1008 temp_buffer->data()); |
949 return true; | 1009 return true; |
950 } | 1010 } |
951 | 1011 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 last_image_->bounds().contains(visible_rect)) { | 1082 last_image_->bounds().contains(visible_rect)) { |
1023 last_image_ = last_image_->makeSubset(visible_rect); | 1083 last_image_ = last_image_->makeSubset(visible_rect); |
1024 } | 1084 } |
1025 } | 1085 } |
1026 | 1086 |
1027 SkISize SkCanvasVideoRenderer::LastImageDimensionsForTesting() { | 1087 SkISize SkCanvasVideoRenderer::LastImageDimensionsForTesting() { |
1028 return last_image_dimensions_for_testing_; | 1088 return last_image_dimensions_for_testing_; |
1029 } | 1089 } |
1030 | 1090 |
1031 } // namespace media | 1091 } // namespace media |
OLD | NEW |