<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[192607] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/192607">192607</a></dd>
<dt>Author</dt> <dd>jer.noble@apple.com</dd>
<dt>Date</dt> <dd>2015-11-18 19:20:11 -0800 (Wed, 18 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebGL slow video to texture
https://bugs.webkit.org/show_bug.cgi?id=129626

Reviewed by Dean Jackson.

Support a direct GPU-to-GPU copy of video textures. Add a new AVPlayerItemVideoOutput which,
when lazily-created, will emit CVPixelBuffers which are guaranteed to be compatible with
OpenGL framebuffers. Then, use a CVOpenGLTextureCache object to convert those CVPixelBuffers
to OpenGL textures. Once the video frame is in an OpenGL texture, use an OpenGL framebuffer
to copy the underlying video texture memory to the destination texture.

The copy step uses glTexImage2D, which requires format and type parameters, so change the
signature of copyVideoTextureToPlatformTexture() to pass those parameters in.

* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::copyVideoTextureToPlatformTexture): Changed signature.
* html/HTMLVideoElement.h:
* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::texImage2D): Changed signature.
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::copyVideoTextureToPlatformTexture): Changed signature.
* platform/graphics/MediaPlayer.h:
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::copyVideoTextureToPlatformTexture): Changed signature.
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::createOpenGLVideoOutput): Create an OpenGL-compatible
    AVPlayerItemVideoOutput.
(WebCore::MediaPlayerPrivateAVFoundationObjC::destroyOpenGLVideoOutput): Destroy same.
(WebCore::MediaPlayerPrivateAVFoundationObjC::updateLastOpenGLImage): Cache the current frame, if available.
(WebCore::MediaPlayerPrivateAVFoundationObjC::copyVideoTextureToPlatformTexture): Convert the
    current frame to a texture, and use that texture to render into the destination texture.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLVideoElementcpp">trunk/Source/WebCore/html/HTMLVideoElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLVideoElementh">trunk/Source/WebCore/html/HTMLVideoElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlcanvasWebGLRenderingContextBasecpp">trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp</a></li>
<li><a href="#trunkSourceWebCorepageChromeClienth">trunk/Source/WebCore/page/ChromeClient.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayercpp">trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayerh">trunk/Source/WebCore/platform/graphics/MediaPlayer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsMediaPlayerPrivateh">trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCh">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCmm">trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/ChangeLog        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2015-11-18  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+        WebGL slow video to texture
+        https://bugs.webkit.org/show_bug.cgi?id=129626
+
+        Reviewed by Dean Jackson.
+
+        Support a direct GPU-to-GPU copy of video textures. Add a new AVPlayerItemVideoOutput which,
+        when lazily-created, will emit CVPixelBuffers which are guaranteed to be compatible with
+        OpenGL framebuffers. Then, use a CVOpenGLTextureCache object to convert those CVPixelBuffers
+        to OpenGL textures. Once the video frame is in an OpenGL texture, use an OpenGL framebuffer
+        to copy the underlying video texture memory to the destination texture.
+
+        The copy step uses glTexImage2D, which requires format and type parameters, so change the
+        signature of copyVideoTextureToPlatformTexture() to pass those parameters in.
+
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::copyVideoTextureToPlatformTexture): Changed signature.
+        * html/HTMLVideoElement.h:
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::texImage2D): Changed signature.
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::copyVideoTextureToPlatformTexture): Changed signature.
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::copyVideoTextureToPlatformTexture): Changed signature.
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createOpenGLVideoOutput): Create an OpenGL-compatible
+            AVPlayerItemVideoOutput.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::destroyOpenGLVideoOutput): Destroy same.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::updateLastOpenGLImage): Cache the current frame, if available.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::copyVideoTextureToPlatformTexture): Convert the
+            current frame to a texture, and use that texture to render into the destination texture.
+
</ins><span class="cx"> 2015-11-18  Jiewen Tan  &lt;jiewen_tan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WK1] Crash loading Blink layout test fast/dom/Window/property-access-on-cached-window-after-frame-removed.html
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLVideoElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLVideoElement.cpp (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLVideoElement.cpp        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/html/HTMLVideoElement.cpp        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -248,11 +248,11 @@
</span><span class="cx">     player-&gt;paintCurrentFrameInContext(context, destRect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool HTMLVideoElement::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY)
</del><ins>+bool HTMLVideoElement::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject texture, GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY)
</ins><span class="cx"> {
</span><span class="cx">     if (!player())
</span><span class="cx">         return false;
</span><del>-    return player()-&gt;copyVideoTextureToPlatformTexture(context, texture, level, type, internalFormat, premultiplyAlpha, flipY);
</del><ins>+    return player()-&gt;copyVideoTextureToPlatformTexture(context, texture, target, level, internalFormat, format, type, premultiplyAlpha, flipY);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool HTMLVideoElement::hasAvailableVideoFrame() const
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLVideoElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLVideoElement.h (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLVideoElement.h        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/html/HTMLVideoElement.h        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Used by WebGL to do GPU-GPU textures copy if possible.
</span><span class="cx">     // See more details at MediaPlayer::copyVideoTextureToPlatformTexture() defined in Source/WebCore/platform/graphics/MediaPlayer.h.
</span><del>-    bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY);
</del><ins>+    bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject texture, GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY);
</ins><span class="cx"> 
</span><span class="cx">     bool shouldDisplayPosterImage() const { return displayMode() == Poster || displayMode() == PosterWaitingForVideo; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasWebGLRenderingContextBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -3264,7 +3264,7 @@
</span><span class="cx">         &amp;&amp; type == GraphicsContext3D::UNSIGNED_BYTE
</span><span class="cx">         &amp;&amp; (texture-&gt;getType(target, level) == GraphicsContext3D::UNSIGNED_BYTE || !texture-&gt;isValid(target, level))
</span><span class="cx">         &amp;&amp; !level) {
</span><del>-        if (video-&gt;copyVideoTextureToPlatformTexture(m_context.get(), texture-&gt;object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
</del><ins>+        if (video-&gt;copyVideoTextureToPlatformTexture(m_context.get(), texture-&gt;object(), target, level, internalformat, format, type, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
</ins><span class="cx">             texture-&gt;setLevelInfo(target, level, internalformat, video-&gt;videoWidth(), video-&gt;videoHeight(), type);
</span><span class="cx">             return;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebCorepageChromeClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/ChromeClient.h (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/ChromeClient.h        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/page/ChromeClient.h        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -84,6 +84,7 @@
</span><span class="cx"> class GraphicsLayer;
</span><span class="cx"> class GraphicsLayerFactory;
</span><span class="cx"> class HTMLInputElement;
</span><ins>+class HTMLMediaElement;
</ins><span class="cx"> class HTMLVideoElement;
</span><span class="cx"> class HitTestResult;
</span><span class="cx"> class IntRect;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -822,9 +822,9 @@
</span><span class="cx">     m_private-&gt;paintCurrentFrameInContext(p, r);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool MediaPlayer::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY)
</del><ins>+bool MediaPlayer::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject texture, GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY)
</ins><span class="cx"> {
</span><del>-    return m_private-&gt;copyVideoTextureToPlatformTexture(context, texture, level, type, internalFormat, premultiplyAlpha, flipY);
</del><ins>+    return m_private-&gt;copyVideoTextureToPlatformTexture(context, texture, target, level, internalFormat, format, type, premultiplyAlpha, flipY);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassNativeImagePtr MediaPlayer::nativeImageForCurrentTime()
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -421,7 +421,7 @@
</span><span class="cx">     // In chromium, the implementation is based on GL_CHROMIUM_copy_texture extension which is documented at
</span><span class="cx">     // http://src.chromium.org/viewvc/chrome/trunk/src/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_copy_texture.txt and implemented at
</span><span class="cx">     // http://src.chromium.org/viewvc/chrome/trunk/src/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc via shaders.
</span><del>-    bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject texture, GC3Dint level, GC3Denum type, GC3Denum internalFormat, bool premultiplyAlpha, bool flipY);
</del><ins>+    bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject texture, GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY);
</ins><span class="cx"> 
</span><span class="cx">     PassNativeImagePtr nativeImageForCurrentTime();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsMediaPlayerPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx">     virtual void paint(GraphicsContext&amp;, const FloatRect&amp;) = 0;
</span><span class="cx"> 
</span><span class="cx">     virtual void paintCurrentFrameInContext(GraphicsContext&amp; c, const FloatRect&amp; r) { paint(c, r); }
</span><del>-    virtual bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject, GC3Dint, GC3Denum, GC3Denum, bool, bool) { return false; }
</del><ins>+    virtual bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject, GC3Denum, GC3Dint, GC3Denum, GC3Denum, GC3Denum, bool, bool) { return false; }
</ins><span class="cx">     virtual PassNativeImagePtr nativeImageForCurrentTime() { return nullptr; }
</span><span class="cx"> 
</span><span class="cx">     virtual void setPreload(MediaPlayer::Preload) { }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -58,6 +58,11 @@
</span><span class="cx"> typedef struct CGImage *CGImageRef;
</span><span class="cx"> typedef struct __CVBuffer *CVPixelBufferRef;
</span><span class="cx"> typedef struct OpaqueVTPixelTransferSession* VTPixelTransferSessionRef;
</span><ins>+#if PLATFORM(IOS)
+typedef struct  __CVOpenGLESTextureCache *CVOpenGLESTextureCacheRef;
+#else
+typedef struct __CVOpenGLTextureCache* CVOpenGLTextureCacheRef;
+#endif
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -235,6 +240,12 @@
</span><span class="cx">     void paintWithVideoOutput(GraphicsContext&amp;, const FloatRect&amp;);
</span><span class="cx">     virtual PassNativeImagePtr nativeImageForCurrentTime() override;
</span><span class="cx">     void waitForVideoOutputMediaDataWillChange();
</span><ins>+
+    void createOpenGLVideoOutput();
+    void destroyOpenGLVideoOutput();
+    void updateLastOpenGLImage();
+
+    bool copyVideoTextureToPlatformTexture(GraphicsContext3D*, Platform3DObject, GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY) override;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA)
</span><span class="lines">@@ -327,7 +338,15 @@
</span><span class="cx">     RetainPtr&lt;WebCoreAVFPullDelegate&gt; m_videoOutputDelegate;
</span><span class="cx">     RetainPtr&lt;CGImageRef&gt; m_lastImage;
</span><span class="cx">     dispatch_semaphore_t m_videoOutputSemaphore;
</span><ins>+
+    RetainPtr&lt;AVPlayerItemVideoOutput&gt; m_openGLVideoOutput;
+#if PLATFORM(IOS)
+    RetainPtr&lt;CVOpenGLESTextureCacheRef&gt; m_openGLTextureCache;
+#else
+    RetainPtr&lt;CVOpenGLTextureCacheRef&gt; m_openGLTextureCache;
</ins><span class="cx"> #endif
</span><ins>+    RetainPtr&lt;CVPixelBufferRef&gt; m_lastOpenGLImage;
+#endif
</ins><span class="cx"> 
</span><span class="cx"> #if USE(VIDEOTOOLBOX)
</span><span class="cx">     RetainPtr&lt;VTPixelTransferSessionRef&gt; m_pixelTransferSession;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateAVFoundationObjCmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (192606 => 192607)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm        2015-11-19 03:09:51 UTC (rev 192606)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm        2015-11-19 03:20:11 UTC (rev 192607)
</span><span class="lines">@@ -37,9 +37,11 @@
</span><span class="cx"> #import &quot;CDMSessionAVFoundationObjC.h&quot;
</span><span class="cx"> #import &quot;Cookie.h&quot;
</span><span class="cx"> #import &quot;ExceptionCodePlaceholder.h&quot;
</span><ins>+#import &quot;Extensions3D.h&quot;
</ins><span class="cx"> #import &quot;FloatConversion.h&quot;
</span><span class="cx"> #import &quot;FloatConversion.h&quot;
</span><span class="cx"> #import &quot;GraphicsContext.h&quot;
</span><ins>+#import &quot;GraphicsContext3D.h&quot;
</ins><span class="cx"> #import &quot;GraphicsContextCG.h&quot;
</span><span class="cx"> #import &quot;InbandMetadataTextTrackPrivateAVF.h&quot;
</span><span class="cx"> #import &quot;InbandTextTrackPrivateAVFObjC.h&quot;
</span><span class="lines">@@ -63,6 +65,7 @@
</span><span class="cx"> #import &quot;WebCoreCALayerExtras.h&quot;
</span><span class="cx"> #import &quot;WebCoreSystemInterface.h&quot;
</span><span class="cx"> #import &lt;functional&gt;
</span><ins>+#import &lt;map&gt;
</ins><span class="cx"> #import &lt;objc/runtime.h&gt;
</span><span class="cx"> #import &lt;runtime/DataView.h&gt;
</span><span class="cx"> #import &lt;runtime/JSCInlines.h&gt;
</span><span class="lines">@@ -100,6 +103,10 @@
</span><span class="cx"> #include &quot;CFNSURLConnectionSPI.h&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS)
+#include &lt;OpenGLES/ES3/glext.h&gt;
+#endif
+
</ins><span class="cx"> namespace std {
</span><span class="cx"> template &lt;&gt; struct iterator_traits&lt;HashSet&lt;RefPtr&lt;WebCore::MediaSelectionOptionAVFObjC&gt;&gt;::iterator&gt; {
</span><span class="cx">     typedef RefPtr&lt;WebCore::MediaSelectionOptionAVFObjC&gt; value_type;
</span><span class="lines">@@ -296,6 +303,24 @@
</span><span class="cx"> #define AVURLAssetBoundNetworkInterfaceName getAVURLAssetBoundNetworkInterfaceName()
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS)
+SOFT_LINK(CoreVideo, CVOpenGLESTextureCacheCreate, CVReturn, (CFAllocatorRef allocator, CFDictionaryRef cacheAttributes, CVEAGLContext eaglContext, CFDictionaryRef textureAttributes, CVOpenGLESTextureCacheRef* cacheOut), (allocator, cacheAttributes, eaglContext, textureAttributes, cacheOut))
+SOFT_LINK(CoreVideo, CVOpenGLESTextureCacheCreateTextureFromImage, CVReturn, (CFAllocatorRef allocator, CVOpenGLESTextureCacheRef textureCache, CVImageBufferRef sourceImage, CFDictionaryRef textureAttributes, GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, size_t planeIndex, CVOpenGLESTextureRef* textureOut), (allocator, textureCache, sourceImage, textureAttributes, target, internalFormat, width, height, format, type, planeIndex, textureOut))
+SOFT_LINK(CoreVideo, CVOpenGLESTextureCacheFlush, void, (CVOpenGLESTextureCacheRef textureCache, CVOptionFlags options), (textureCache, options))
+SOFT_LINK(CoreVideo, CVOpenGLESTextureGetTarget, GLenum, (CVOpenGLESTextureRef image), (image))
+SOFT_LINK(CoreVideo, CVOpenGLESTextureGetName, GLuint, (CVOpenGLESTextureRef image), (image))
+SOFT_LINK_POINTER(CoreVideo, kCVPixelBufferIOSurfaceOpenGLESFBOCompatibilityKey, NSString *)
+#define kCVPixelBufferIOSurfaceOpenGLESFBOCompatibilityKey getkCVPixelBufferIOSurfaceOpenGLESFBOCompatibilityKey()
+#else
+SOFT_LINK(CoreVideo, CVOpenGLTextureCacheCreate, CVReturn, (CFAllocatorRef allocator, CFDictionaryRef cacheAttributes, CGLContextObj cglContext, CGLPixelFormatObj cglPixelFormat, CFDictionaryRef textureAttributes, CVOpenGLTextureCacheRef* cacheOut), (allocator, cacheAttributes, cglContext, cglPixelFormat, textureAttributes, cacheOut))
+SOFT_LINK(CoreVideo, CVOpenGLTextureCacheCreateTextureFromImage, CVReturn, (CFAllocatorRef allocator, CVOpenGLTextureCacheRef textureCache, CVImageBufferRef sourceImage, CFDictionaryRef attributes, CVOpenGLTextureRef* textureOut), (allocator, textureCache, sourceImage, attributes, textureOut))
+SOFT_LINK(CoreVideo, CVOpenGLTextureCacheFlush, void, (CVOpenGLTextureCacheRef textureCache, CVOptionFlags options), (textureCache, options))
+SOFT_LINK(CoreVideo, CVOpenGLTextureGetTarget, GLenum, (CVOpenGLTextureRef image), (image))
+SOFT_LINK(CoreVideo, CVOpenGLTextureGetName, GLuint, (CVOpenGLTextureRef image), (image))
+SOFT_LINK_POINTER(CoreVideo, kCVPixelBufferIOSurfaceOpenGLFBOCompatibilityKey, NSString *)
+#define kCVPixelBufferIOSurfaceOpenGLFBOCompatibilityKey getkCVPixelBufferIOSurfaceOpenGLFBOCompatibilityKey()
+#endif
+
</ins><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="cx"> enum MediaPlayerAVFoundationObservationContext {
</span><span class="lines">@@ -624,6 +649,7 @@
</span><span class="cx"> {
</span><span class="cx"> #if HAVE(AVFOUNDATION_VIDEO_OUTPUT)
</span><span class="cx">     destroyVideoOutput();
</span><ins>+    destroyOpenGLVideoOutput();
</ins><span class="cx"> #endif
</span><span class="cx">     destroyImageGenerator();
</span><span class="cx"> }
</span><span class="lines">@@ -2357,6 +2383,260 @@
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaPlayerPrivateAVFoundationObjC::createOpenGLVideoOutput()
+{
+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::createOpenGLVideoOutput(%p)&quot;, this);
+
+    if (!m_avPlayerItem || m_openGLVideoOutput)
+        return;
+
+#if PLATFORM(IOS)
+    NSDictionary* attributes = @{(NSString *)kCVPixelBufferIOSurfaceOpenGLESFBOCompatibilityKey: @YES};
+#else
+    NSDictionary* attributes = @{(NSString *)kCVPixelBufferIOSurfaceOpenGLFBOCompatibilityKey: @YES};
+#endif
+    m_openGLVideoOutput = adoptNS([allocAVPlayerItemVideoOutputInstance() initWithPixelBufferAttributes:attributes]);
+    ASSERT(m_openGLVideoOutput);
+
+    [m_avPlayerItem.get() addOutput:m_openGLVideoOutput.get()];
+
+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::createOpenGLVideoOutput(%p) - returning %p&quot;, this, m_openGLVideoOutput.get());
+}
+
+void MediaPlayerPrivateAVFoundationObjC::destroyOpenGLVideoOutput()
+{
+    if (!m_openGLVideoOutput)
+        return;
+
+    if (m_avPlayerItem)
+        [m_avPlayerItem.get() removeOutput:m_openGLVideoOutput.get()];
+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::destroyOpenGLVideoOutput(%p) - destroying  %p&quot;, this, m_videoOutput.get());
+
+    m_openGLVideoOutput = 0;
+}
+
+void MediaPlayerPrivateAVFoundationObjC::updateLastOpenGLImage()
+{
+    if (!m_openGLVideoOutput)
+        return;
+
+    CMTime currentTime = [m_openGLVideoOutput itemTimeForHostTime:CACurrentMediaTime()];
+    if (![m_openGLVideoOutput hasNewPixelBufferForItemTime:currentTime])
+        return;
+
+    m_lastOpenGLImage = adoptCF([m_openGLVideoOutput copyPixelBufferForItemTime:currentTime itemTimeForDisplay:nil]);
+}
+
+#if !LOG_DISABLED
+
+#define STRINGIFY_PAIR(e) e, #e
+static std::map&lt;uint32_t, const char*&gt;&amp; enumToStringMap()
+{
+    static NeverDestroyed&lt;std::map&lt;uint32_t, const char*&gt;&gt; map;
+    if (map.get().empty()) {
+        std::map&lt;uint32_t, const char*&gt; stringMap;
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA));
+        map.get().emplace(STRINGIFY_PAIR(GL_LUMINANCE_ALPHA));
+        map.get().emplace(STRINGIFY_PAIR(GL_LUMINANCE));
+        map.get().emplace(STRINGIFY_PAIR(GL_ALPHA));
+        map.get().emplace(STRINGIFY_PAIR(GL_R8));
+        map.get().emplace(STRINGIFY_PAIR(GL_R16F));
+        map.get().emplace(STRINGIFY_PAIR(GL_R32F));
+        map.get().emplace(STRINGIFY_PAIR(GL_R8UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_R8I));
+        map.get().emplace(STRINGIFY_PAIR(GL_R16UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_R16I));
+        map.get().emplace(STRINGIFY_PAIR(GL_R32UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_R32I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG8));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG16F));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG32F));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG8UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG8I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG16UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG16I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG32UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG32I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB8));
+        map.get().emplace(STRINGIFY_PAIR(GL_SRGB8));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA8));
+        map.get().emplace(STRINGIFY_PAIR(GL_SRGB8_ALPHA8));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA4));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB10_A2));
+        map.get().emplace(STRINGIFY_PAIR(GL_DEPTH_COMPONENT16));
+        map.get().emplace(STRINGIFY_PAIR(GL_DEPTH_COMPONENT24));
+        map.get().emplace(STRINGIFY_PAIR(GL_DEPTH_COMPONENT32F));
+        map.get().emplace(STRINGIFY_PAIR(GL_DEPTH24_STENCIL8));
+        map.get().emplace(STRINGIFY_PAIR(GL_DEPTH32F_STENCIL8));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA));
+        map.get().emplace(STRINGIFY_PAIR(GL_LUMINANCE_ALPHA));
+        map.get().emplace(STRINGIFY_PAIR(GL_LUMINANCE));
+        map.get().emplace(STRINGIFY_PAIR(GL_ALPHA));
+        map.get().emplace(STRINGIFY_PAIR(GL_RED));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG_INTEGER));
+        map.get().emplace(STRINGIFY_PAIR(GL_DEPTH_STENCIL));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_BYTE));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_SHORT_5_6_5));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_SHORT_4_4_4_4));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_SHORT_5_5_5_1));
+        map.get().emplace(STRINGIFY_PAIR(GL_BYTE));
+        map.get().emplace(STRINGIFY_PAIR(GL_HALF_FLOAT));
+        map.get().emplace(STRINGIFY_PAIR(GL_FLOAT));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_SHORT));
+        map.get().emplace(STRINGIFY_PAIR(GL_SHORT));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_INT));
+        map.get().emplace(STRINGIFY_PAIR(GL_INT));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_INT_2_10_10_10_REV));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_INT_24_8));
+        map.get().emplace(STRINGIFY_PAIR(GL_FLOAT_32_UNSIGNED_INT_24_8_REV));
+
+#if PLATFORM(IOS)
+        map.get().emplace(STRINGIFY_PAIR(GL_RED_INTEGER));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB_INTEGER));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG8_SNORM));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB565));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB8_SNORM));
+        map.get().emplace(STRINGIFY_PAIR(GL_R11F_G11F_B10F));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB9_E5));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB16F));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB32F));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB8UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB8I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB16UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB16I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB32UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB32I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA8_SNORM));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA16F));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA32F));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA8UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA8I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB10_A2UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA16UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA16I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA32I));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA32UI));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGB5_A1));
+        map.get().emplace(STRINGIFY_PAIR(GL_RG));
+        map.get().emplace(STRINGIFY_PAIR(GL_RGBA_INTEGER));
+        map.get().emplace(STRINGIFY_PAIR(GL_DEPTH_COMPONENT));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_INT_10F_11F_11F_REV));
+        map.get().emplace(STRINGIFY_PAIR(GL_UNSIGNED_INT_5_9_9_9_REV));
+#endif
+    }
+    return map.get();
+}
+
+#endif // !LOG_DISABLED
+
+bool MediaPlayerPrivateAVFoundationObjC::copyVideoTextureToPlatformTexture(GraphicsContext3D* context, Platform3DObject outputTexture, GC3Denum outputTarget, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY)
+{
+    if (flipY || premultiplyAlpha)
+        return false;
+
+    ASSERT(context);
+
+    if (!m_openGLVideoOutput)
+        createOpenGLVideoOutput();
+
+    updateLastOpenGLImage();
+
+    if (!m_lastOpenGLImage)
+        return false;
+
+    if (!m_openGLTextureCache) {
+#if PLATFORM(IOS)
+        CVOpenGLESTextureCacheRef cache = nullptr;
+        CVReturn error = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, nullptr, context-&gt;platformGraphicsContext3D(), nullptr, &amp;cache);
+#else
+        CVOpenGLTextureCacheRef cache = nullptr;
+        CVReturn error = CVOpenGLTextureCacheCreate(kCFAllocatorDefault, nullptr, context-&gt;platformGraphicsContext3D(), CGLGetPixelFormat(context-&gt;platformGraphicsContext3D()), nullptr, &amp;cache);
+#endif
+        if (error != kCVReturnSuccess)
+            return false;
+        m_openGLTextureCache = adoptCF(cache);
+    }
+
+    size_t width = CVPixelBufferGetWidth(m_lastOpenGLImage.get());
+    size_t height = CVPixelBufferGetHeight(m_lastOpenGLImage.get());
+
+#if PLATFORM(IOS)
+    CVOpenGLESTextureRef bareVideoTexture = nullptr;
+    if (kCVReturnSuccess != CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, m_openGLTextureCache.get(), m_lastOpenGLImage.get(), nullptr, outputTarget, internalFormat, width, height, format, type, level, &amp;bareVideoTexture))
+        return false;
+    RetainPtr&lt;CVOpenGLESTextureRef&gt; videoTexture = adoptCF(bareVideoTexture);
+    Platform3DObject videoTextureName = CVOpenGLESTextureGetName(videoTexture.get());
+    GC3Denum videoTextureTarget = CVOpenGLESTextureGetTarget(videoTexture.get());
+#else
+    CVOpenGLTextureRef bareVideoTexture = nullptr;
+    if (kCVReturnSuccess != CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault, m_openGLTextureCache.get(), m_lastOpenGLImage.get(), nullptr, &amp;bareVideoTexture))
+        return false;
+    RetainPtr&lt;CVOpenGLTextureRef&gt; videoTexture = adoptCF(bareVideoTexture);
+    Platform3DObject videoTextureName = CVOpenGLTextureGetName(videoTexture.get());
+    GC3Denum videoTextureTarget = CVOpenGLTextureGetTarget(videoTexture.get());
+#endif
+
+    auto weakThis = createWeakPtr();
+    dispatch_async(dispatch_get_main_queue(), [weakThis] {
+        if (!weakThis)
+            return;
+
+        if (auto cache = weakThis-&gt;m_openGLTextureCache.get())
+#if PLATFORM(IOS)
+            CVOpenGLESTextureCacheFlush(cache, 0);
+#else
+            CVOpenGLTextureCacheFlush(cache, 0);
+#endif
+    });
+
+    LOG(Media, &quot;MediaPlayerPrivateAVFoundationObjC::copyVideoTextureToPlatformTexture(%p) - internalFormat: %s, format: %s, type: %s&quot;, this, enumToStringMap()[internalFormat], enumToStringMap()[format], enumToStringMap()[type]);
+
+    // Save the origial bound texture &amp; framebuffer names so we can re-bind them after copying the video texture.
+    GC3Dint boundTexture = 0;
+    GC3Dint boundReadFramebuffer = 0;
+    context-&gt;getIntegerv(GraphicsContext3D::TEXTURE_BINDING_2D, &amp;boundTexture);
+    context-&gt;getIntegerv(GraphicsContext3D::READ_FRAMEBUFFER_BINDING, &amp;boundReadFramebuffer);
+
+    context-&gt;bindTexture(videoTextureTarget, videoTextureName);
+    context-&gt;texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+    context-&gt;texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+    context-&gt;texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+
+    // Create a framebuffer object to represent the video texture's memory.
+    Platform3DObject readFramebuffer = context-&gt;createFramebuffer();
+
+    // Make that framebuffer the read source from which drawing commands will read voxels.
+    context-&gt;bindFramebuffer(GraphicsContext3D::READ_FRAMEBUFFER, readFramebuffer);
+
+    // Allocate uninitialized memory for the output texture.
+    context-&gt;bindTexture(outputTarget, outputTexture);
+    context-&gt;texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+    context-&gt;texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+    context-&gt;texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+    context-&gt;texImage2DDirect(outputTarget, level, internalFormat, width, height, 0, format, type, nullptr);
+
+    // Attach the video texture to the framebuffer.
+    context-&gt;framebufferTexture2D(GraphicsContext3D::READ_FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, videoTextureTarget, videoTextureName, level);
+
+    GC3Denum status = context-&gt;checkFramebufferStatus(GraphicsContext3D::READ_FRAMEBUFFER);
+    if (status != GraphicsContext3D::FRAMEBUFFER_COMPLETE)
+        return false;
+
+    // Copy texture from the read framebuffer (and thus the video texture) to the output texture.
+    context-&gt;copyTexImage2D(outputTarget, level, internalFormat, 0, 0, width, height, 0);
+
+    // Restore the previous texture and framebuffer bindings.
+    context-&gt;bindTexture(outputTarget, boundTexture);
+    context-&gt;bindFramebuffer(GraphicsContext3D::READ_FRAMEBUFFER, boundReadFramebuffer);
+
+    // Clean up after ourselves.
+    context-&gt;deleteFramebuffer(readFramebuffer);
+
+    return !context-&gt;getError();
+}
+
</ins><span class="cx"> PassNativeImagePtr MediaPlayerPrivateAVFoundationObjC::nativeImageForCurrentTime()
</span><span class="cx"> {
</span><span class="cx">     updateLastImage();
</span></span></pre>
</div>
</div>

</body>
</html>