| 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 |