Changeset 206257 in webkit
- Timestamp:
- Sep 22, 2016 5:43:55 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r206256 r206257 1 2016-09-22 Olivier Blin <olivier.blin@softathome.com> 2 3 [GStreamer] Support a direct GPU-to-GPU copy of video textures to WebGL 4 https://bugs.webkit.org/show_bug.cgi?id=159928 5 6 Reviewed by Carlos Garcia Campos. 7 8 Copy of GStreamer video frames to WebGL textures was not accelerated. 9 10 WebGLRenderingContextBase::texImage2D(HTMLVideoElement) went 11 through a slow software paint() wrapping the video frame into 12 cairo surface (ImageGStreamer), downloading it to draw to the 13 image cache context, copying it again in software, and uploading 14 it back to an OpenGL texture. 15 16 This patch implements copyVideoTextureToPlatformTexture() for 17 the GStreamer media player backend, to do GPU-to-GPU copy, by 18 extracting code from nativeImageForCurrentTime(). 19 20 Doing this also fixes bug #159621: red and blue colors were 21 swapped in video rendered through WebGL with GSTREAMER_GL enabled. 22 23 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp: 24 (WebCore::MediaPlayerPrivateGStreamerBase::prepareContextForCairoPaint): 25 (WebCore::MediaPlayerPrivateGStreamerBase::paintToCairoSurface): 26 (WebCore::MediaPlayerPrivateGStreamerBase::copyVideoTextureToPlatformTexture): 27 (WebCore::MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime): 28 * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h: 29 1 30 2016-09-22 Carlos Garcia Campos <cgarcia@igalia.com> 2 31 -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
r206213 r206257 698 698 699 699 #if USE(GSTREAMER_GL) 700 NativeImagePtr MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime() 701 { 702 #if USE(CAIRO) && ENABLE(ACCELERATED_2D_CANVAS) 703 if (m_usingFallbackVideoSink) 704 return nullptr; 705 706 WTF::GMutexLocker<GMutex> lock(m_sampleMutex); 707 708 GstVideoInfo videoInfo; 700 // This should be called with the sample mutex locked. 701 GLContext* MediaPlayerPrivateGStreamerBase::prepareContextForCairoPaint(GstVideoInfo& videoInfo, IntSize& size, IntSize& rotatedSize) 702 { 709 703 if (!getSampleVideoInfo(m_sample.get(), videoInfo)) 710 704 return nullptr; 711 705 706 GLContext* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext(); 707 context->makeContextCurrent(); 708 709 // Thread-awareness is a huge performance hit on non-Intel drivers. 710 cairo_gl_device_set_thread_aware(context->cairoDevice(), FALSE); 711 712 size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo)); 713 rotatedSize = m_videoSourceOrientation.usesWidthAsHeight() ? size.transposedSize() : size; 714 715 return context; 716 } 717 718 // This should be called with the sample mutex locked. 719 bool MediaPlayerPrivateGStreamerBase::paintToCairoSurface(cairo_surface_t* outputSurface, cairo_device_t* device, GstVideoInfo& videoInfo, const IntSize& size, const IntSize& rotatedSize) 720 { 712 721 GstBuffer* buffer = gst_sample_get_buffer(m_sample.get()); 713 722 GstVideoFrame videoFrame; 714 723 if (!gst_video_frame_map(&videoFrame, &videoInfo, buffer, static_cast<GstMapFlags>(GST_MAP_READ | GST_MAP_GL))) 715 return nullptr; 716 717 GLContext* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext(); 718 context->makeContextCurrent(); 719 cairo_device_t* device = context->cairoDevice(); 720 721 // Thread-awareness is a huge performance hit on non-Intel drivers. 722 cairo_gl_device_set_thread_aware(device, FALSE); 724 return false; 723 725 724 726 unsigned textureID = *reinterpret_cast<unsigned*>(videoFrame.data[0]); 725 IntSize size = IntSize(GST_VIDEO_INFO_WIDTH(&videoInfo), GST_VIDEO_INFO_HEIGHT(&videoInfo));726 727 RefPtr<cairo_surface_t> surface = adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, textureID, size.width(), size.height())); 727 728 IntSize rotatedSize = m_videoSourceOrientation.usesWidthAsHeight() ? size.transposedSize() : size; 729 RefPtr<cairo_surface_t> rotatedSurface = adoptRef(cairo_gl_surface_create(device, CAIRO_CONTENT_COLOR_ALPHA, rotatedSize.width(), rotatedSize.height())); 730 RefPtr<cairo_t> cr = adoptRef(cairo_create(rotatedSurface.get())); 728 RefPtr<cairo_t> cr = adoptRef(cairo_create(outputSurface)); 731 729 732 730 switch (m_videoSourceOrientation) { … … 758 756 gst_video_frame_unmap(&videoFrame); 759 757 758 return true; 759 } 760 761 bool MediaPlayerPrivateGStreamerBase::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject outputTexture, GC3Denum outputTarget, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY) 762 { 763 #if !USE(CAIRO) 764 return false; 765 #endif 766 767 if (m_usingFallbackVideoSink) 768 return false; 769 770 if (flipY || premultiplyAlpha) 771 return false; 772 773 GstVideoInfo videoInfo; 774 IntSize size, rotatedSize; 775 WTF::GMutexLocker<GMutex> lock(m_sampleMutex); 776 GLContext* glContext = prepareContextForCairoPaint(videoInfo, size, rotatedSize); 777 if (!glContext) 778 return false; 779 780 // Allocate uninitialized memory for the output texture. 781 context->bindTexture(outputTarget, outputTexture); 782 context->texImage2DDirect(outputTarget, level, internalFormat, rotatedSize.width(), rotatedSize.height(), 0, format, type, nullptr); 783 784 // cairo_gl_surface_create_for_texture sets these parameters to GL_NEAREST, so we need to backup them. 785 GC3Dint minFilter, magFilter; 786 context->getTexParameteriv(outputTarget, GL_TEXTURE_MIN_FILTER, &minFilter); 787 context->getTexParameteriv(outputTarget, GL_TEXTURE_MAG_FILTER, &magFilter); 788 789 RefPtr<cairo_surface_t> outputSurface = adoptRef(cairo_gl_surface_create_for_texture(glContext->cairoDevice(), CAIRO_CONTENT_COLOR_ALPHA, outputTexture, rotatedSize.width(), rotatedSize.height())); 790 if (!paintToCairoSurface(outputSurface.get(), glContext->cairoDevice(), videoInfo, size, rotatedSize)) 791 return false; 792 793 context->bindTexture(outputTarget, outputTexture); 794 context->texParameteri(outputTarget, GraphicsContext3D::TEXTURE_MIN_FILTER, minFilter); 795 context->texParameteri(outputTarget, GraphicsContext3D::TEXTURE_MAG_FILTER, magFilter); 796 797 return true; 798 } 799 800 NativeImagePtr MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime() 801 { 802 #if USE(CAIRO) && ENABLE(ACCELERATED_2D_CANVAS) 803 if (m_usingFallbackVideoSink) 804 return nullptr; 805 806 GstVideoInfo videoInfo; 807 IntSize size, rotatedSize; 808 WTF::GMutexLocker<GMutex> lock(m_sampleMutex); 809 GLContext* context = prepareContextForCairoPaint(videoInfo, size, rotatedSize); 810 if (!context) 811 return nullptr; 812 813 RefPtr<cairo_surface_t> rotatedSurface = adoptRef(cairo_gl_surface_create(context->cairoDevice(), CAIRO_CONTENT_COLOR_ALPHA, rotatedSize.width(), rotatedSize.height())); 814 if (!paintToCairoSurface(rotatedSurface.get(), context->cairoDevice(), videoInfo, size, rotatedSize)) 815 return nullptr; 816 760 817 return rotatedSurface; 761 818 #else -
trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h
r206202 r206257 48 48 49 49 class BitmapTextureGL; 50 class GLContext; 50 51 class GraphicsContext; 51 52 class GraphicsContext3D; … … 117 118 118 119 #if USE(GSTREAMER_GL) 120 bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject, GC3Denum, GC3Dint, GC3Denum, GC3Denum, GC3Denum, bool, bool) override; 119 121 NativeImagePtr nativeImageForCurrentTime() override; 120 122 #endif … … 131 133 GstElement* createGLAppSink(); 132 134 GstElement* createVideoSinkGL(); 135 GLContext* prepareContextForCairoPaint(GstVideoInfo&, IntSize&, IntSize&); 136 bool paintToCairoSurface(cairo_surface_t*, cairo_device_t*, GstVideoInfo&, const IntSize&, const IntSize&); 133 137 #endif 134 138
Note: See TracChangeset
for help on using the changeset viewer.