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 |