Chromium Code Reviews| 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 <limits> | 8 #include <limits> |
| 8 | 9 |
| 9 #include "base/macros.h" | 10 #include "base/macros.h" |
| 10 #include "gpu/GLES2/gl2extchromium.h" | 11 #include "gpu/GLES2/gl2extchromium.h" |
| 11 #include "gpu/command_buffer/client/gles2_interface.h" | 12 #include "gpu/command_buffer/client/gles2_interface.h" |
| 12 #include "gpu/command_buffer/common/mailbox_holder.h" | 13 #include "gpu/command_buffer/common/mailbox_holder.h" |
| 14 #include "media/base/data_buffer.h" | |
| 13 #include "media/base/video_frame.h" | 15 #include "media/base/video_frame.h" |
| 14 #include "media/base/yuv_convert.h" | 16 #include "media/base/yuv_convert.h" |
| 15 #include "skia/ext/texture_handle.h" | 17 #include "skia/ext/texture_handle.h" |
| 16 #include "third_party/libyuv/include/libyuv.h" | 18 #include "third_party/libyuv/include/libyuv.h" |
| 17 #include "third_party/skia/include/core/SkCanvas.h" | 19 #include "third_party/skia/include/core/SkCanvas.h" |
| 18 #include "third_party/skia/include/core/SkImage.h" | 20 #include "third_party/skia/include/core/SkImage.h" |
| 19 #include "third_party/skia/include/core/SkImageGenerator.h" | 21 #include "third_party/skia/include/core/SkImageGenerator.h" |
| 20 #include "third_party/skia/include/gpu/GrContext.h" | 22 #include "third_party/skia/include/gpu/GrContext.h" |
| 21 #include "third_party/skia/include/gpu/GrPaint.h" | 23 #include "third_party/skia/include/gpu/GrPaint.h" |
| 22 #include "third_party/skia/include/gpu/GrTexture.h" | 24 #include "third_party/skia/include/gpu/GrTexture.h" |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 return img; | 160 return img; |
| 159 } | 161 } |
| 160 | 162 |
| 161 // Creates a SkImage from a |video_frame| backed by native resources. | 163 // Creates a SkImage from a |video_frame| backed by native resources. |
| 162 // The SkImage will take ownership of the underlying resource. | 164 // The SkImage will take ownership of the underlying resource. |
| 163 sk_sp<SkImage> NewSkImageFromVideoFrameNative(VideoFrame* video_frame, | 165 sk_sp<SkImage> NewSkImageFromVideoFrameNative(VideoFrame* video_frame, |
| 164 const Context3D& context_3d) { | 166 const Context3D& context_3d) { |
| 165 DCHECK(PIXEL_FORMAT_ARGB == video_frame->format() || | 167 DCHECK(PIXEL_FORMAT_ARGB == video_frame->format() || |
| 166 PIXEL_FORMAT_XRGB == video_frame->format() || | 168 PIXEL_FORMAT_XRGB == video_frame->format() || |
| 167 PIXEL_FORMAT_NV12 == video_frame->format() || | 169 PIXEL_FORMAT_NV12 == video_frame->format() || |
| 168 PIXEL_FORMAT_UYVY == video_frame->format()); | 170 PIXEL_FORMAT_UYVY == video_frame->format() || |
| 171 PIXEL_FORMAT_Y8 == video_frame->format() || | |
| 172 PIXEL_FORMAT_Y16 == video_frame->format()); | |
| 169 | 173 |
| 170 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0); | 174 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0); |
| 171 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || | 175 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D || |
| 172 mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB || | 176 mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB || |
| 173 mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES) | 177 mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES) |
| 174 << mailbox_holder.texture_target; | 178 << mailbox_holder.texture_target; |
| 175 | 179 |
| 176 gpu::gles2::GLES2Interface* gl = context_3d.gl; | 180 gpu::gles2::GLES2Interface* gl = context_3d.gl; |
| 177 unsigned source_texture = 0; | 181 unsigned source_texture = 0; |
| 178 if (mailbox_holder.texture_target != GL_TEXTURE_2D) { | 182 if (mailbox_holder.texture_target != GL_TEXTURE_2D) { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 scoped_refptr<VideoFrame> frame_; | 320 scoped_refptr<VideoFrame> frame_; |
| 317 | 321 |
| 318 DISALLOW_IMPLICIT_CONSTRUCTORS(VideoImageGenerator); | 322 DISALLOW_IMPLICIT_CONSTRUCTORS(VideoImageGenerator); |
| 319 }; | 323 }; |
| 320 | 324 |
| 321 SkCanvasVideoRenderer::SkCanvasVideoRenderer() | 325 SkCanvasVideoRenderer::SkCanvasVideoRenderer() |
| 322 : last_image_deleting_timer_( | 326 : last_image_deleting_timer_( |
| 323 FROM_HERE, | 327 FROM_HERE, |
| 324 base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay), | 328 base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay), |
| 325 this, | 329 this, |
| 326 &SkCanvasVideoRenderer::ResetCache) {} | 330 &SkCanvasVideoRenderer::ResetCache), |
| 331 rg8_to_red_program_(0) {} | |
| 327 | 332 |
| 328 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() { | 333 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() { |
| 329 ResetCache(); | 334 ResetCache(); |
| 330 } | 335 } |
| 331 | 336 |
| 332 void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame, | 337 void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame, |
| 333 SkCanvas* canvas, | 338 SkCanvas* canvas, |
| 334 const gfx::RectF& dest_rect, | 339 const gfx::RectF& dest_rect, |
| 335 uint8_t alpha, | 340 uint8_t alpha, |
| 336 SkXfermode::Mode mode, | 341 SkXfermode::Mode mode, |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 483 for (int row = 0; row < video_frame->rows(plane); row++) { | 488 for (int row = 0; row < video_frame->rows(plane); row++) { |
| 484 for (int x = 0; x < width; x++) { | 489 for (int x = 0; x < width; x++) { |
| 485 dst[x] = src[x] >> shift; | 490 dst[x] = src[x] >> shift; |
| 486 } | 491 } |
| 487 src += video_frame->stride(plane) / 2; | 492 src += video_frame->stride(plane) / 2; |
| 488 dst += ret->stride(plane); | 493 dst += ret->stride(plane); |
| 489 } | 494 } |
| 490 } | 495 } |
| 491 return ret; | 496 return ret; |
| 492 } | 497 } |
| 498 | |
| 499 void FlipAndConvertY16(const uint8_t* input, | |
| 500 uint8_t* output, | |
| 501 unsigned format, | |
| 502 unsigned type, | |
| 503 bool flip_y, | |
| 504 size_t row_bytes, | |
| 505 size_t stride, | |
| 506 size_t output_row_bytes, | |
| 507 size_t height) { | |
| 508 DCHECK(input != output); | |
| 509 for (size_t i = 0; i < height; ++i) { | |
| 510 const uint16_t* in = reinterpret_cast<const uint16_t*>(input + i * stride); | |
| 511 uint8_t* out = flip_y ? output + output_row_bytes * (height - i - 1) | |
| 512 : output + output_row_bytes * height; | |
| 513 if ((format == GL_RG && type == GL_UNSIGNED_BYTE) || | |
| 514 (format == GL_RED_INTEGER && type == GL_UNSIGNED_SHORT)) { | |
| 515 memcpy(out, input + i * stride, row_bytes); | |
| 516 } else if (format == GL_RED && type == GL_FLOAT) { | |
| 517 float* out_row = reinterpret_cast<float*>(out); | |
| 518 const uint16_t* in_end = in + row_bytes / 2; | |
| 519 while (in < in_end) | |
| 520 *out_row++ = *in++ / 65536.f; | |
| 521 } else { | |
| 522 NOTREACHED(); | |
| 523 } | |
| 524 } | |
| 525 } | |
| 526 | |
| 527 bool isSingleRedComponentFormat(unsigned internal_format) { | |
| 528 switch (internal_format) { | |
| 529 case GL_R8: | |
| 530 case GL_R16F: | |
| 531 case GL_R32F: | |
| 532 case GL_R8UI: | |
| 533 case GL_R8I: | |
| 534 case GL_R16UI: | |
| 535 case GL_R16I: | |
| 536 case GL_R32UI: | |
| 537 case GL_R32I: | |
| 538 return true; | |
| 539 default: | |
| 540 return false; | |
| 541 } | |
| 542 } | |
| 493 } | 543 } |
| 494 | 544 |
| 495 // static | 545 // static |
| 496 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( | 546 void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( |
| 497 const VideoFrame* video_frame, | 547 const VideoFrame* video_frame, |
| 498 void* rgb_pixels, | 548 void* rgb_pixels, |
| 499 size_t row_bytes) { | 549 size_t row_bytes) { |
| 500 if (!video_frame->IsMappable()) { | 550 if (!video_frame->IsMappable()) { |
| 501 NOTREACHED() << "Cannot extract pixels from non-CPU frame formats."; | 551 NOTREACHED() << "Cannot extract pixels from non-CPU frame formats."; |
| 502 return; | 552 return; |
| 503 } | 553 } |
| 504 if (!media::IsYuvPlanar(video_frame->format())) { | |
| 505 NOTREACHED() << "Non YUV formats are not supported"; | |
| 506 return; | |
| 507 } | |
| 508 | 554 |
| 509 switch (video_frame->format()) { | 555 switch (video_frame->format()) { |
| 510 case PIXEL_FORMAT_YV12: | 556 case PIXEL_FORMAT_YV12: |
| 511 case PIXEL_FORMAT_I420: | 557 case PIXEL_FORMAT_I420: |
| 512 if (CheckColorSpace(video_frame, COLOR_SPACE_JPEG)) { | 558 if (CheckColorSpace(video_frame, COLOR_SPACE_JPEG)) { |
| 513 LIBYUV_J420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane), | 559 LIBYUV_J420_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane), |
| 514 video_frame->stride(VideoFrame::kYPlane), | 560 video_frame->stride(VideoFrame::kYPlane), |
| 515 video_frame->visible_data(VideoFrame::kUPlane), | 561 video_frame->visible_data(VideoFrame::kUPlane), |
| 516 video_frame->stride(VideoFrame::kUPlane), | 562 video_frame->stride(VideoFrame::kUPlane), |
| 517 video_frame->visible_data(VideoFrame::kVPlane), | 563 video_frame->visible_data(VideoFrame::kVPlane), |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 597 case PIXEL_FORMAT_NV12: | 643 case PIXEL_FORMAT_NV12: |
| 598 case PIXEL_FORMAT_NV21: | 644 case PIXEL_FORMAT_NV21: |
| 599 case PIXEL_FORMAT_UYVY: | 645 case PIXEL_FORMAT_UYVY: |
| 600 case PIXEL_FORMAT_YUY2: | 646 case PIXEL_FORMAT_YUY2: |
| 601 case PIXEL_FORMAT_ARGB: | 647 case PIXEL_FORMAT_ARGB: |
| 602 case PIXEL_FORMAT_XRGB: | 648 case PIXEL_FORMAT_XRGB: |
| 603 case PIXEL_FORMAT_RGB24: | 649 case PIXEL_FORMAT_RGB24: |
| 604 case PIXEL_FORMAT_RGB32: | 650 case PIXEL_FORMAT_RGB32: |
| 605 case PIXEL_FORMAT_MJPEG: | 651 case PIXEL_FORMAT_MJPEG: |
| 606 case PIXEL_FORMAT_MT21: | 652 case PIXEL_FORMAT_MT21: |
| 653 case PIXEL_FORMAT_Y8: | |
| 654 case PIXEL_FORMAT_Y16: | |
| 607 case PIXEL_FORMAT_UNKNOWN: | 655 case PIXEL_FORMAT_UNKNOWN: |
| 608 NOTREACHED(); | 656 NOTREACHED() << "Only YUV formats and Y16 are supported."; |
| 609 } | 657 } |
| 610 } | 658 } |
| 611 | 659 |
| 612 // static | 660 // static |
| 613 void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture( | 661 void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture( |
| 614 gpu::gles2::GLES2Interface* gl, | 662 gpu::gles2::GLES2Interface* gl, |
| 615 VideoFrame* video_frame, | 663 VideoFrame* video_frame, |
| 616 unsigned int texture, | 664 unsigned int texture, |
| 617 unsigned int internal_format, | 665 unsigned int internal_format, |
| 618 unsigned int type, | 666 unsigned int type, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 698 // canvas context. | 746 // canvas context. |
| 699 const GLuint64 dest_fence_sync = destination_gl->InsertFenceSyncCHROMIUM(); | 747 const GLuint64 dest_fence_sync = destination_gl->InsertFenceSyncCHROMIUM(); |
| 700 destination_gl->ShallowFlushCHROMIUM(); | 748 destination_gl->ShallowFlushCHROMIUM(); |
| 701 gpu::SyncToken dest_sync_token; | 749 gpu::SyncToken dest_sync_token; |
| 702 destination_gl->GenSyncTokenCHROMIUM(dest_fence_sync, | 750 destination_gl->GenSyncTokenCHROMIUM(dest_fence_sync, |
| 703 dest_sync_token.GetData()); | 751 dest_sync_token.GetData()); |
| 704 canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData()); | 752 canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData()); |
| 705 | 753 |
| 706 SyncTokenClientImpl client(canvas_gl); | 754 SyncTokenClientImpl client(canvas_gl); |
| 707 video_frame->UpdateReleaseSyncToken(&client); | 755 video_frame->UpdateReleaseSyncToken(&client); |
| 756 } else if (video_frame->format() == PIXEL_FORMAT_Y16 && | |
| 757 isSingleRedComponentFormat(internal_format)) { | |
| 758 CopyRG8ToRedTextureData(context_3d, destination_gl, video_frame.get(), | |
| 759 texture, internal_format, type, flip_y); | |
| 708 } else { | 760 } else { |
| 709 CopyVideoFrameSingleTextureToGLTexture(destination_gl, video_frame.get(), | 761 CopyVideoFrameSingleTextureToGLTexture(destination_gl, video_frame.get(), |
| 710 texture, internal_format, type, | 762 texture, internal_format, type, |
| 711 premultiply_alpha, flip_y); | 763 premultiply_alpha, flip_y); |
| 712 } | 764 } |
| 713 | |
| 714 return true; | 765 return true; |
| 715 } | 766 } |
| 716 | 767 |
| 768 bool SkCanvasVideoRenderer::TexImageImpl(const char* functionID, | |
| 769 unsigned target, | |
| 770 gpu::gles2::GLES2Interface* gl, | |
| 771 VideoFrame* frame, | |
| 772 int level, | |
| 773 int internalformat, | |
| 774 unsigned format, | |
| 775 unsigned type, | |
| 776 int xoffset, | |
| 777 int yoffset, | |
| 778 int zoffset, | |
| 779 bool flip_y, | |
| 780 bool premultiplyAlpha) { | |
| 781 DCHECK(frame); | |
| 782 DCHECK(!frame->HasTextures()); | |
| 783 | |
| 784 bool has_alpha = false; | |
| 785 bool need_conversion = false; | |
| 786 unsigned output_bits_per_pixel; | |
| 787 switch (frame->format()) { | |
| 788 case PIXEL_FORMAT_Y16: | |
| 789 // Allow reinterpreting RG8 buffer here as R16 or FLOAT. | |
| 790 if ((format != GL_RED_INTEGER || type != GL_UNSIGNED_SHORT) && | |
| 791 (format != GL_RG || type != GL_UNSIGNED_BYTE) && | |
| 792 (format != GL_RED || type != GL_FLOAT)) | |
| 793 return false; | |
| 794 need_conversion = | |
| 795 !(format == GL_RED_INTEGER && type == GL_UNSIGNED_SHORT) && | |
| 796 !(format == GL_RG && type == GL_UNSIGNED_BYTE); | |
| 797 output_bits_per_pixel = (type == GL_FLOAT) ? 32 : 16; | |
| 798 break; | |
| 799 case PIXEL_FORMAT_Y8: | |
| 800 if (format != GL_RED || type != GL_UNSIGNED_BYTE) | |
| 801 return false; | |
| 802 output_bits_per_pixel = 8; | |
| 803 break; | |
| 804 default: | |
| 805 return false; | |
| 806 } | |
| 807 need_conversion = | |
| 808 need_conversion || (frame->stride(0) != frame->row_bytes(0)); | |
| 809 unsigned source_bits_per_pixel = | |
| 810 VideoFrame::PlaneBitsPerPixel(frame->format(), 0); | |
| 811 DCHECK_EQ(source_bits_per_pixel % 8, 0U); | |
| 812 | |
| 813 if (has_alpha && premultiplyAlpha) { | |
| 814 NOTREACHED() << "Premultiply alpha is not supported."; | |
| 815 return false; | |
| 816 } | |
| 817 if (xoffset || yoffset || zoffset) { | |
| 818 NOTREACHED() << "Offsets are not supported."; | |
| 819 return false; | |
| 820 } | |
| 821 | |
| 822 // Handle other than Y16 formats here only if there is no repacking required. | |
| 823 // The reason for this is that this method handles Y16 specifics and provides | |
| 824 // optimization (compared to default implementation in | |
| 825 // WebGLRenderingContextBase::texImageImpl) for situations where there is no | |
| 826 // need to do repacking pixel data. | |
| 827 if (frame->format() != PIXEL_FORMAT_Y16 && (flip_y || need_conversion)) | |
| 828 return false; | |
| 829 | |
| 830 uint8_t* data; | |
| 831 scoped_refptr<DataBuffer> temp_buffer; | |
| 832 size_t width = frame->visible_rect().width(); | |
| 833 size_t height = frame->visible_rect().height(); | |
| 834 if (flip_y || need_conversion) { | |
| 835 size_t output_row_bytes = | |
| 836 frame->row_bytes(0) * output_bits_per_pixel / source_bits_per_pixel; | |
| 837 temp_buffer = new DataBuffer(output_row_bytes * height); | |
| 838 data = temp_buffer->writable_data(); | |
| 839 DCHECK_EQ(frame->format(), PIXEL_FORMAT_Y16); | |
| 840 FlipAndConvertY16(frame->visible_data(0), data, format, type, flip_y, | |
| 841 frame->row_bytes(0), frame->stride(0), output_row_bytes, | |
| 842 height); | |
| 843 } else { | |
| 844 data = frame->visible_data(0); | |
| 845 } | |
| 846 | |
| 847 if (!strcmp(functionID, "texImage2D")) { | |
| 848 gl->TexImage2D(target, level, internalformat, width, height, 0, format, | |
| 849 type, data); | |
| 850 } else if (!strcmp(functionID, "texSubImage2D")) { | |
| 851 gl->TexSubImage2D(target, level, xoffset, yoffset, width, height, format, | |
| 852 type, data); | |
| 853 } else { | |
| 854 DCHECK(!strcmp(functionID, "texSubImage3D")); | |
| 855 gl->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, | |
| 856 1, format, type, data); | |
| 857 } | |
| 858 return true; | |
| 859 } | |
| 860 | |
| 861 void SkCanvasVideoRenderer::CopyRG8ToRedTextureData( | |
| 862 const Context3D& context_3d, | |
| 863 gpu::gles2::GLES2Interface* target_gl, | |
| 864 VideoFrame* frame, | |
| 865 unsigned texture, | |
| 866 unsigned internal_format, | |
| 867 unsigned type, | |
| 868 bool flip_y) { | |
| 869 // TODO(astojilj): After GLES 3.2, use glCopyImageSubData for RG8 to R16UI | |
| 870 // conversion. glCopyImageSubData is already available as extension on some of | |
| 871 // the Android devices (GL_EXT_COPY_IMAGE). | |
| 872 gpu::gles2::GLES2Interface* local_gl = context_3d.gl; | |
| 873 | |
| 874 // Get source texture on local_gl. | |
| 875 unsigned source_texture; | |
| 876 { | |
| 877 const gpu::MailboxHolder& mailbox_holder = frame->mailbox_holder(0); | |
| 878 DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D) | |
| 879 << mailbox_holder.texture_target; | |
| 880 | |
| 881 local_gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); | |
| 882 source_texture = local_gl->CreateAndConsumeTextureCHROMIUM( | |
| 883 mailbox_holder.texture_target, mailbox_holder.mailbox.name); | |
| 884 } | |
| 885 | |
| 886 // Reinterpret RG8 to R32F on local_gl. Later, do the copy on target_gl. | |
| 887 unsigned intermediate_texture; | |
| 888 local_gl->GenTextures(1, &intermediate_texture); | |
| 889 DoCopyRG8ToRedTextureData(local_gl, source_texture, intermediate_texture, | |
|
aleksandar.stojiljkovic
2016/09/20 12:22:55
https://codereview.chromium.org/2121043002/diff/60
| |
| 890 GL_R32F, GL_FLOAT, frame->visible_rect().width(), | |
| 891 frame->visible_rect().height(), flip_y); | |
| 892 local_gl->DeleteTextures(1, &source_texture); | |
| 893 | |
| 894 // Get intermediate_texture to target_gl. | |
| 895 { | |
| 896 gpu::MailboxHolder mailbox_holder; | |
| 897 mailbox_holder.texture_target = GL_TEXTURE_2D; | |
| 898 local_gl->GenMailboxCHROMIUM(mailbox_holder.mailbox.name); | |
| 899 local_gl->ProduceTextureDirectCHROMIUM(intermediate_texture, | |
| 900 mailbox_holder.texture_target, | |
| 901 mailbox_holder.mailbox.name); | |
| 902 // Wait for mailbox creation on local context before consuming it and | |
| 903 // copying from it on the consumer context. | |
| 904 const GLuint64 fence_sync = local_gl->InsertFenceSyncCHROMIUM(); | |
| 905 local_gl->ShallowFlushCHROMIUM(); | |
| 906 local_gl->GenSyncTokenCHROMIUM(fence_sync, | |
| 907 mailbox_holder.sync_token.GetData()); | |
| 908 | |
| 909 target_gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); | |
| 910 uint32_t target_intermediate_texture = | |
| 911 target_gl->CreateAndConsumeTextureCHROMIUM( | |
| 912 mailbox_holder.texture_target, mailbox_holder.mailbox.name); | |
| 913 | |
| 914 local_gl->DeleteTextures(1, &intermediate_texture); | |
| 915 intermediate_texture = target_intermediate_texture; | |
| 916 } | |
| 917 | |
| 918 // Copy intermediate_texture to texture. | |
| 919 target_gl->CopyTextureCHROMIUM(intermediate_texture, texture, internal_format, | |
| 920 type, false, false, false); | |
| 921 target_gl->DeleteTextures(1, &intermediate_texture); | |
| 922 | |
| 923 // Undo gr_context state changes introduced in this function. | |
| 924 context_3d.gr_context->resetContext( | |
| 925 kMisc_GrGLBackendState | kBlend_GrGLBackendState | | |
| 926 kView_GrGLBackendState | kStencil_GrGLBackendState | | |
| 927 kVertex_GrGLBackendState | kProgram_GrGLBackendState | | |
| 928 kTextureBinding_GrGLBackendState); | |
| 929 SyncTokenClientImpl client(target_gl); | |
| 930 frame->UpdateReleaseSyncToken(&client); | |
| 931 } | |
| 932 | |
| 933 void SkCanvasVideoRenderer::DoCopyRG8ToRedTextureData( | |
| 934 gpu::gles2::GLES2Interface* gl, | |
| 935 unsigned source_texture, | |
| 936 unsigned texture, | |
| 937 unsigned internal_format, | |
| 938 unsigned type, | |
| 939 unsigned width, | |
| 940 unsigned height, | |
| 941 bool flip_y) { | |
| 942 GLuint buffer; | |
| 943 gl->GenBuffers(1, &buffer); | |
| 944 gl->BindBuffer(GL_ARRAY_BUFFER, buffer); | |
| 945 const GLfloat vertices[] = {-1.f, -1.f, 1.f, -1.f, -1.0f, 1.f, 1.f, 1.f}; | |
| 946 gl->BufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | |
| 947 gl->EnableVertexAttribArray(0); | |
| 948 gl->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); | |
| 949 | |
| 950 if (!rg8_to_red_program_) { | |
| 951 rg8_to_red_program_ = gl->CreateProgram(); | |
|
jbauman
2016/09/20 20:51:22
I don't think the lifetime of this is correct if t
aleksandar.stojiljkovic
2016/09/30 14:26:32
Done.
Using GrContext::uniqueID to control the lif
| |
| 952 GLuint vertex_shader = gl->CreateShader(GL_VERTEX_SHADER); | |
| 953 std::string source = std::string( | |
| 954 "\ | |
| 955 #ifdef GL_ES\n\ | |
| 956 precision mediump float;\n\ | |
| 957 #define TexCoordPrecision mediump\n\ | |
| 958 #else\n\ | |
| 959 #define TexCoordPrecision\n\ | |
| 960 #endif\n\ | |
| 961 uniform vec2 coord_transform;\n\ | |
| 962 attribute vec2 a_pos;\n\ | |
| 963 varying TexCoordPrecision vec2 v_uv;\n\ | |
| 964 void main(void) {\n\ | |
| 965 gl_Position = vec4(a_pos, 0, 1.0);\n\ | |
| 966 v_uv = (a_pos * coord_transform) + 0.5;\n\ | |
| 967 }\n"); | |
| 968 const char* vertex_source = source.c_str(); | |
| 969 gl->ShaderSource(vertex_shader, 1, &vertex_source, 0); | |
| 970 gl->CompileShader(vertex_shader); | |
| 971 gl->AttachShader(rg8_to_red_program_, vertex_shader); | |
| 972 | |
| 973 GLuint fragment_shader = gl->CreateShader(GL_FRAGMENT_SHADER); | |
| 974 source = std::string( | |
| 975 "\ | |
| 976 #ifdef GL_ES\n\ | |
| 977 precision mediump float;\n\ | |
| 978 #define TexCoordPrecision mediump\n\ | |
| 979 #else\n\ | |
| 980 #define TexCoordPrecision\n\ | |
| 981 #endif\n\ | |
| 982 uniform sampler2D u_sampler;\n\ | |
| 983 varying TexCoordPrecision vec2 v_uv;\n\ | |
| 984 void main(void) {\n\ | |
| 985 vec4 color = texture2D(u_sampler, v_uv);\n\ | |
| 986 gl_FragColor.r = (color.r * 0.00390625) + color.g;\n\ | |
| 987 }\n"); | |
| 988 const char* fragment_source = source.c_str(); | |
| 989 gl->ShaderSource(fragment_shader, 1, &fragment_source, 0); | |
| 990 gl->CompileShader(fragment_shader); | |
| 991 | |
| 992 gl->AttachShader(rg8_to_red_program_, fragment_shader); | |
| 993 | |
| 994 gl->BindAttribLocation(rg8_to_red_program_, 0, "a_pos"); | |
| 995 gl->LinkProgram(rg8_to_red_program_); | |
| 996 } | |
| 997 | |
| 998 gl->UseProgram(rg8_to_red_program_); | |
| 999 gl->Uniform1i(gl->GetUniformLocation(rg8_to_red_program_, "u_sampler"), 0); | |
| 1000 gl->Uniform2f(gl->GetUniformLocation(rg8_to_red_program_, "coord_transform"), | |
| 1001 0.5, flip_y ? -0.5 : 0.5); | |
| 1002 | |
| 1003 GLuint fbo; | |
| 1004 gl->GenFramebuffers(1, &fbo); | |
| 1005 gl->ActiveTexture(GL_TEXTURE0); | |
| 1006 unsigned target = GL_TEXTURE_2D; | |
| 1007 gl->BindTexture(target, texture); | |
| 1008 gl->TexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, GL_RED, | |
| 1009 type, 0); | |
| 1010 | |
| 1011 gl->TexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 1012 gl->TexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 1013 gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 1014 gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 1015 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo); | |
| 1016 gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, | |
| 1017 texture, 0); | |
| 1018 | |
| 1019 gl->BindTexture(target, source_texture); | |
| 1020 gl->TexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 1021 gl->TexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 1022 gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 1023 gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 1024 | |
| 1025 gl->Disable(GL_DEPTH_TEST); | |
| 1026 gl->Disable(GL_STENCIL_TEST); | |
| 1027 gl->Disable(GL_CULL_FACE); | |
| 1028 gl->ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
| 1029 gl->DepthMask(GL_FALSE); | |
| 1030 gl->Disable(GL_BLEND); | |
| 1031 gl->Disable(GL_SCISSOR_TEST); | |
| 1032 gl->Viewport(0, 0, width, height); | |
| 1033 gl->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
| 1034 gl->Flush(); | |
| 1035 gl->BindFramebuffer(GL_FRAMEBUFFER, 0); | |
| 1036 gl->DeleteBuffers(1, &buffer); | |
| 1037 gl->DeleteFramebuffers(1, &fbo); | |
| 1038 } | |
| 1039 | |
| 717 void SkCanvasVideoRenderer::ResetCache() { | 1040 void SkCanvasVideoRenderer::ResetCache() { |
| 718 DCHECK(thread_checker_.CalledOnValidThread()); | 1041 DCHECK(thread_checker_.CalledOnValidThread()); |
| 719 // Clear cached values. | 1042 // Clear cached values. |
| 720 last_image_ = nullptr; | 1043 last_image_ = nullptr; |
| 721 last_timestamp_ = kNoTimestamp; | 1044 last_timestamp_ = kNoTimestamp; |
| 722 } | 1045 } |
| 723 | 1046 |
| 724 bool SkCanvasVideoRenderer::UpdateLastImage( | 1047 bool SkCanvasVideoRenderer::UpdateLastImage( |
| 725 const scoped_refptr<VideoFrame>& video_frame, | 1048 const scoped_refptr<VideoFrame>& video_frame, |
| 726 const Context3D& context_3d) { | 1049 const Context3D& context_3d) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 748 if (!last_image_) // Couldn't create the SkImage. | 1071 if (!last_image_) // Couldn't create the SkImage. |
| 749 return false; | 1072 return false; |
| 750 last_timestamp_ = video_frame->timestamp(); | 1073 last_timestamp_ = video_frame->timestamp(); |
| 751 } | 1074 } |
| 752 last_image_deleting_timer_.Reset(); | 1075 last_image_deleting_timer_.Reset(); |
| 753 DCHECK(!!last_image_); | 1076 DCHECK(!!last_image_); |
| 754 return true; | 1077 return true; |
| 755 } | 1078 } |
| 756 | 1079 |
| 757 } // namespace media | 1080 } // namespace media |
| OLD | NEW |