Title: [131719] trunk/Source/WebCore
Revision
131719
Author
[email protected]
Date
2012-10-18 02:44:11 -0700 (Thu, 18 Oct 2012)

Log Message

GraphicsSurface should not modify the current GL context.
https://bugs.webkit.org/show_bug.cgi?id=99320

Instead of reusing the currently bound GL context for drawing
the texture onto the GraphicsSurface, GraphicsSurface should
create a new context that shares the texture names with a context
provided by the caller.
This way the OpenGL states are clearly separated and we do not
risk interfeering with the currently bound GL context.

Reviewed by Noam Rosenthal.

* platform/graphics/qt/GraphicsContext3DQt.cpp:
(WebCore::GraphicsContext3DPrivate::GraphicsContext3DPrivate):
    When creating a GraphicsSurface pass the platform GL context
    as a parameter, so it can be used for sharing textures with.
(WebCore::GraphicsContext3DPrivate::copyToGraphicsSurface):
    Pass the texture instead of the FBO. A Texture can be drawn
    directly or bound to another FBO, where a framebuffer
    always needs to be blit onto the surface.
(WebCore::GraphicsContext3DPrivate::createGraphicsSurfaces):
    Pass the platform GL context as a parameter.
* platform/graphics/surfaces/GraphicsSurface.cpp:
(WebCore::GraphicsSurface::create):
(WebCore::GraphicsSurface::copyFromTexture):
* platform/graphics/surfaces/GraphicsSurface.h:
(GraphicsSurface):
* platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp:
(WebCore::GraphicsSurfacePrivate::GraphicsSurfacePrivate):
    Create a new GL context that shares the textures with the
    context provided by the caller.
(WebCore::GraphicsSurfacePrivate::~GraphicsSurfacePrivate):
(WebCore::GraphicsSurfacePrivate::makeCurrent):
    Add a convenience function to make the context that
    belongs to the surface current.
(GraphicsSurfacePrivate):
(WebCore::GraphicsSurfacePrivate::doneCurrent):
    Add a convenience function to make the previously
    bound context current again.
(WebCore::GraphicsSurfacePrivate::copyFromTexture):
    Move blitting of the texture onto the surface
    into a separate function within GraphicsSurfacePrivate.
(WebCore::GraphicsSurface::platformCopyFromTexture):
    Rename function platformCopyFromFramebuffer to
    platformCopyFromTexture, as we are now passing the texture only.
(WebCore::GraphicsSurface::platformCreate):
* platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp:
(WebCore):
(WebCore::GraphicsSurfacePrivate::GraphicsSurfacePrivate):
(WebCore::GraphicsSurfacePrivate::makeCurrent):
    Add a convenience function to make the context that
    belongs to the surface current.
(GraphicsSurfacePrivate):
(WebCore::GraphicsSurfacePrivate::doneCurrent):
    Add a convenience function to make the previously
(WebCore::GraphicsSurfacePrivate::copyFromTexture):
    Move blitting of the texture onto the surface
    into a separate function within GraphicsSurfacePrivate.
(WebCore::resolveGLMethods):
    Resolve additional GL methods necessary for this change.
(WebCore::GraphicsSurface::platformCopyFromTexture):
    Rename function platformCopyFromFramebuffer to
    platformCopyFromTexture, as we are now passing the texture only.
(WebCore::GraphicsSurface::platformCreate):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (131718 => 131719)


--- trunk/Source/WebCore/ChangeLog	2012-10-18 08:53:48 UTC (rev 131718)
+++ trunk/Source/WebCore/ChangeLog	2012-10-18 09:44:11 UTC (rev 131719)
@@ -1,3 +1,70 @@
+2012-10-18  Zeno Albisser  <[email protected]>
+
+        GraphicsSurface should not modify the current GL context.
+        https://bugs.webkit.org/show_bug.cgi?id=99320
+
+        Instead of reusing the currently bound GL context for drawing
+        the texture onto the GraphicsSurface, GraphicsSurface should
+        create a new context that shares the texture names with a context
+        provided by the caller.
+        This way the OpenGL states are clearly separated and we do not
+        risk interfeering with the currently bound GL context.
+
+        Reviewed by Noam Rosenthal.
+
+        * platform/graphics/qt/GraphicsContext3DQt.cpp:
+        (WebCore::GraphicsContext3DPrivate::GraphicsContext3DPrivate):
+            When creating a GraphicsSurface pass the platform GL context
+            as a parameter, so it can be used for sharing textures with.
+        (WebCore::GraphicsContext3DPrivate::copyToGraphicsSurface):
+            Pass the texture instead of the FBO. A Texture can be drawn
+            directly or bound to another FBO, where a framebuffer
+            always needs to be blit onto the surface.
+        (WebCore::GraphicsContext3DPrivate::createGraphicsSurfaces):
+            Pass the platform GL context as a parameter.
+        * platform/graphics/surfaces/GraphicsSurface.cpp:
+        (WebCore::GraphicsSurface::create):
+        (WebCore::GraphicsSurface::copyFromTexture):
+        * platform/graphics/surfaces/GraphicsSurface.h:
+        (GraphicsSurface):
+        * platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp:
+        (WebCore::GraphicsSurfacePrivate::GraphicsSurfacePrivate):
+            Create a new GL context that shares the textures with the
+            context provided by the caller.
+        (WebCore::GraphicsSurfacePrivate::~GraphicsSurfacePrivate):
+        (WebCore::GraphicsSurfacePrivate::makeCurrent):
+            Add a convenience function to make the context that
+            belongs to the surface current.
+        (GraphicsSurfacePrivate):
+        (WebCore::GraphicsSurfacePrivate::doneCurrent):
+            Add a convenience function to make the previously
+            bound context current again.
+        (WebCore::GraphicsSurfacePrivate::copyFromTexture):
+            Move blitting of the texture onto the surface
+            into a separate function within GraphicsSurfacePrivate.
+        (WebCore::GraphicsSurface::platformCopyFromTexture):
+            Rename function platformCopyFromFramebuffer to
+            platformCopyFromTexture, as we are now passing the texture only.
+        (WebCore::GraphicsSurface::platformCreate):
+        * platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp:
+        (WebCore):
+        (WebCore::GraphicsSurfacePrivate::GraphicsSurfacePrivate):
+        (WebCore::GraphicsSurfacePrivate::makeCurrent):
+            Add a convenience function to make the context that
+            belongs to the surface current.
+        (GraphicsSurfacePrivate):
+        (WebCore::GraphicsSurfacePrivate::doneCurrent):
+            Add a convenience function to make the previously
+        (WebCore::GraphicsSurfacePrivate::copyFromTexture):
+            Move blitting of the texture onto the surface
+            into a separate function within GraphicsSurfacePrivate.
+        (WebCore::resolveGLMethods):
+            Resolve additional GL methods necessary for this change.
+        (WebCore::GraphicsSurface::platformCopyFromTexture):
+            Rename function platformCopyFromFramebuffer to
+            platformCopyFromTexture, as we are now passing the texture only.
+        (WebCore::GraphicsSurface::platformCreate):
+
 2012-10-18  Kent Tamura  <[email protected]>
 
         Set min-width property instead of width property for date/time fields

Modified: trunk/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp (131718 => 131719)


--- trunk/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp	2012-10-18 08:53:48 UTC (rev 131718)
+++ trunk/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp	2012-10-18 09:44:11 UTC (rev 131719)
@@ -144,7 +144,7 @@
                     | GraphicsSurface::SupportsSharing;
 
     if (!surfaceSize.isEmpty()) {
-        m_graphicsSurface = GraphicsSurface::create(surfaceSize, m_surfaceFlags);
+        m_graphicsSurface = GraphicsSurface::create(surfaceSize, m_surfaceFlags, m_platformContext);
     }
 #endif
 }
@@ -284,7 +284,7 @@
 
     blitMultisampleFramebufferAndRestoreContext();
     makeCurrentIfNeeded();
-    m_graphicsSurface->copyFromFramebuffer(m_context->m_fbo, IntRect(0, 0, m_context->m_currentWidth, m_context->m_currentHeight));
+    m_graphicsSurface->copyFromTexture(m_context->m_texture, IntRect(0, 0, m_context->m_currentWidth, m_context->m_currentHeight));
     uint32_t frontBuffer = m_graphicsSurface->swapBuffers();
     return frontBuffer;
 }
@@ -342,7 +342,7 @@
     if (size.isEmpty())
         m_graphicsSurface.clear();
     else
-        m_graphicsSurface = GraphicsSurface::create(size, m_surfaceFlags);
+        m_graphicsSurface = GraphicsSurface::create(size, m_surfaceFlags, m_platformContext);
 #endif
 }
 

Modified: trunk/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp (131718 => 131719)


--- trunk/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp	2012-10-18 08:53:48 UTC (rev 131718)
+++ trunk/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp	2012-10-18 09:44:11 UTC (rev 131719)
@@ -30,9 +30,9 @@
     return platformImport(size, flags, token);
 }
 
-PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, GraphicsSurface::Flags flags)
+PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, GraphicsSurface::Flags flags, const PlatformGraphicsContext3D shareContext)
 {
-    return platformCreate(size, flags);
+    return platformCreate(size, flags, shareContext);
 }
 
 GraphicsSurfaceToken GraphicsSurface::exportToken()
@@ -58,9 +58,9 @@
     platformCopyToGLTexture(target, texture, targetRect, offset);
 }
 
-void GraphicsSurface::copyFromFramebuffer(uint32_t fbo, const IntRect& sourceRect)
+void GraphicsSurface::copyFromTexture(uint32_t texture, const IntRect& sourceRect)
 {
-    platformCopyFromFramebuffer(fbo, sourceRect);
+    platformCopyFromTexture(texture, sourceRect);
 }
 
 void GraphicsSurface::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)

Modified: trunk/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h (131718 => 131719)


--- trunk/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h	2012-10-18 08:53:48 UTC (rev 131718)
+++ trunk/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h	2012-10-18 09:44:11 UTC (rev 131719)
@@ -21,6 +21,7 @@
 #define GraphicsSurface_h
 
 #include "GraphicsContext.h"
+#include "GraphicsContext3D.h"
 #include "GraphicsSurfaceToken.h"
 #include "IntRect.h"
 #include <wtf/OwnPtr.h>
@@ -70,10 +71,10 @@
     PlatformGraphicsSurface platformSurface() const { return m_platformSurface; }
     IntSize size() const { return m_size; }
 
-    static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags);
+    static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags, const PlatformGraphicsContext3D shareContext = 0);
     static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags, const GraphicsSurfaceToken&);
     void copyToGLTexture(uint32_t target, uint32_t texture, const IntRect& targetRect, const IntPoint& sourceOffset);
-    void copyFromFramebuffer(uint32_t fbo, const IntRect& sourceRect);
+    void copyFromTexture(uint32_t texture, const IntRect& sourceRect);
     void paintToTextureMapper(TextureMapper*, const FloatRect& targetRect, const TransformationMatrix&, float opacity, BitmapTexture* mask);
     uint32_t frontBuffer();
     uint32_t swapBuffers();
@@ -84,7 +85,7 @@
     ~GraphicsSurface();
 
 protected:
-    static PassRefPtr<GraphicsSurface> platformCreate(const IntSize&, Flags);
+    static PassRefPtr<GraphicsSurface> platformCreate(const IntSize&, Flags, const PlatformGraphicsContext3D);
     static PassRefPtr<GraphicsSurface> platformImport(const IntSize&, Flags, const GraphicsSurfaceToken&);
     GraphicsSurfaceToken platformExport();
     void platformDestroy();
@@ -93,7 +94,7 @@
     char* platformLock(const IntRect&, int* stride, LockOptions);
     void platformUnlock();
     void platformCopyToGLTexture(uint32_t target, uint32_t texture, const IntRect&, const IntPoint&);
-    void platformCopyFromFramebuffer(uint32_t fbo, const IntRect& sourceRect);
+    void platformCopyFromTexture(uint32_t texture, const IntRect& sourceRect);
     void platformPaintToTextureMapper(TextureMapper*, const FloatRect& targetRect, const TransformationMatrix&, float opacity, BitmapTexture* mask);
     uint32_t platformFrontBuffer() const;
     uint32_t platformSwapBuffers();

Modified: trunk/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp (131718 => 131719)


--- trunk/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp	2012-10-18 08:53:48 UTC (rev 131718)
+++ trunk/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp	2012-10-18 09:44:11 UTC (rev 131719)
@@ -27,8 +27,15 @@
 #include <CGLCurrent.h>
 #include <CGLIOSurface.h>
 #include <IOSurface/IOSurface.h>
+#include <OpenGL/OpenGL.h>
 #include <OpenGL/gl.h>
 
+#if PLATFORM(QT)
+#include <QGuiApplication>
+#include <QOpenGLContext>
+#include <qpa/qplatformnativeinterface.h>
+#endif
+
 namespace WebCore {
 
 static uint32_t createTexture(IOSurfaceRef handle)
@@ -65,18 +72,37 @@
 struct GraphicsSurfacePrivate {
 public:
     GraphicsSurfacePrivate(const GraphicsSurfaceToken& token)
-        : m_token(token)
+        : m_context(0)
+        , m_token(token)
         , m_frontBufferTexture(0)
         , m_backBufferTexture(0)
+        , m_readFbo(0)
+        , m_drawFbo(0)
     {
         m_frontBuffer = IOSurfaceLookup(m_token.frontBufferHandle);
         m_backBuffer = IOSurfaceLookup(m_token.backBufferHandle);
     }
 
-    GraphicsSurfacePrivate(const IntSize& size, GraphicsSurface::Flags flags)
-        : m_frontBufferTexture(0)
+    GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext, const IntSize& size, GraphicsSurface::Flags flags)
+        : m_context(0)
+        , m_frontBufferTexture(0)
         , m_backBufferTexture(0)
+        , m_readFbo(0)
+        , m_drawFbo(0)
     {
+#if PLATFORM(QT)
+        QPlatformNativeInterface* nativeInterface = QGuiApplication::platformNativeInterface();
+        CGLContextObj shareContextObject = static_cast<CGLContextObj>(nativeInterface->nativeResourceForContext(QByteArrayLiteral("cglContextObj"), shareContext));
+        if (!shareContextObject)
+            return;
+
+        CGLPixelFormatObj pixelFormatObject = CGLGetPixelFormat(shareContextObject);
+        if (kCGLNoError != CGLCreateContext(pixelFormatObject, shareContextObject, &m_context))
+            return;
+
+        CGLRetainContext(m_context);
+#endif
+
         unsigned pixelFormat = 'BGRA';
         unsigned bytesPerElement = 4;
         int width = size.width();
@@ -130,6 +156,16 @@
 
         if (m_backBuffer)
             CFRelease(IOSurfaceRef(m_backBuffer));
+
+        if (m_readFbo)
+            glDeleteFramebuffers(1, &m_readFbo);
+
+        if (m_drawFbo)
+            glDeleteFramebuffers(1, &m_drawFbo);
+
+        if (m_context)
+            CGLReleaseContext(m_context);
+
     }
 
     uint32_t swapBuffers()
@@ -140,6 +176,61 @@
         return IOSurfaceGetID(m_frontBuffer);
     }
 
+    void makeCurrent()
+    {
+        m_detachedContext = CGLGetCurrentContext();
+
+        if (m_context)
+            CGLSetCurrentContext(m_context);
+    }
+
+    void doneCurrent()
+    {
+        CGLSetCurrentContext(m_detachedContext);
+        m_detachedContext = 0;
+    }
+
+    void copyFromTexture(uint32_t texture, const IntRect& sourceRect)
+    {
+        // FIXME: The following glFlush can possibly be replaced by using the GL_ARB_sync extension.
+        glFlush(); // Make sure the texture has actually been completely written in the original context.
+
+        makeCurrent();
+        glEnable(GL_TEXTURE_RECTANGLE_ARB);
+
+        int x = sourceRect.x();
+        int y = sourceRect.y();
+        int width = sourceRect.width();
+        int height = sourceRect.height();
+
+        glPushAttrib(GL_ALL_ATTRIB_BITS);
+        GLint previousFBO;
+        glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previousFBO);
+
+        if (!m_drawFbo)
+            glGenFramebuffers(1, &m_drawFbo);
+
+        if (!m_readFbo)
+            glGenFramebuffers(1, &m_readFbo);
+
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, m_readFbo);
+        glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_drawFbo);
+        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, backBufferTextureID(), 0);
+        glBlitFramebuffer(x, y, width, height, x, x+height, y+width, y, GL_COLOR_BUFFER_BIT, GL_LINEAR); // Flip the texture upside down.
+
+        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
+        glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+        glBindFramebuffer(GL_FRAMEBUFFER, previousFBO);
+        glPopAttrib();
+
+        // Flushing the gl command buffer is necessary to ensure the texture has correctly been bound to the IOSurface.
+        glFlush();
+
+        doneCurrent();
+    }
+
     GraphicsSurfaceToken token() const
     {
         return m_token;
@@ -172,10 +263,14 @@
     }
 
 private:
+    CGLContextObj m_context;
+    CGLContextObj m_detachedContext;
     PlatformGraphicsSurface m_frontBuffer;
     PlatformGraphicsSurface m_backBuffer;
     uint32_t m_frontBufferTexture;
     uint32_t m_backBufferTexture;
+    uint32_t m_readFbo;
+    uint32_t m_drawFbo;
     GraphicsSurfaceToken m_token;
 };
 
@@ -212,25 +307,9 @@
     glFlush();
 }
 
-void GraphicsSurface::platformCopyFromFramebuffer(uint32_t originFbo, const IntRect& sourceRect)
+void GraphicsSurface::platformCopyFromTexture(uint32_t texture, const IntRect& sourceRect)
 {
-    glPushAttrib(GL_ALL_ATTRIB_BITS);
-    if (!m_fbo)
-        glGenFramebuffers(1, &m_fbo);
-
-    GLint oldFBO;
-    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO);
-    glEnable(GL_TEXTURE_RECTANGLE_ARB);
-    glBindFramebuffer(GL_READ_FRAMEBUFFER, originFbo);
-    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
-    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, m_private->backBufferTextureID(), 0);
-    glBlitFramebuffer(0, 0, sourceRect.width(), sourceRect.height(), 0, sourceRect.height(), sourceRect.width(), 0, GL_COLOR_BUFFER_BIT, GL_LINEAR); // Flip the texture upside down.
-    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
-    glBindFramebuffer(GL_FRAMEBUFFER, oldFBO);
-    glPopAttrib();
-
-    // Flushing the gl command buffer is necessary to ensure the texture has correctly been bound to the IOSurface.
-    glFlush();
+    m_private->copyFromTexture(texture, sourceRect);
 }
 
 void GraphicsSurface::platformPaintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)
@@ -250,7 +329,7 @@
     return m_private->swapBuffers();
 }
 
-PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, Flags flags)
+PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, Flags flags, const PlatformGraphicsContext3D shareContext)
 {
     // We currently disable support for CopyToTexture on Mac, because this is used for single buffered Tiles.
     // The single buffered nature of this requires a call to glFlush, as described in platformCopyToTexture.
@@ -259,7 +338,7 @@
         return PassRefPtr<GraphicsSurface>();
 
     RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags));
-    surface->m_private = new GraphicsSurfacePrivate(size, flags);
+    surface->m_private = new GraphicsSurfacePrivate(shareContext, size, flags);
 
     if (!surface->m_private->frontBuffer() || !surface->m_private->backBuffer())
         return PassRefPtr<GraphicsSurface>();

Modified: trunk/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp (131718 => 131719)


--- trunk/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp	2012-10-18 08:53:48 UTC (rev 131718)
+++ trunk/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp	2012-10-18 09:44:11 UTC (rev 131719)
@@ -42,6 +42,9 @@
 static PFNGLXRELEASETEXIMAGEEXTPROC pGlXReleaseTexImageEXT = 0;
 static PFNGLBINDFRAMEBUFFERPROC pGlBindFramebuffer = 0;
 static PFNGLBLITFRAMEBUFFERPROC pGlBlitFramebuffer = 0;
+static PFNGLGENFRAMEBUFFERSPROC pGlGenFramebuffers = 0;
+static PFNGLDELETEFRAMEBUFFERSPROC pGlDeleteFramebuffers = 0;
+static PFNGLFRAMEBUFFERTEXTURE2DPROC pGlFramebufferTexture2D = 0;
 
 class OffScreenRootWindow {
 public:
@@ -99,11 +102,13 @@
 };
 
 struct GraphicsSurfacePrivate {
-    GraphicsSurfacePrivate()
+    GraphicsSurfacePrivate(const PlatformGraphicsContext3D shareContext = 0)
         : m_display(0)
         , m_xPixmap(0)
         , m_glxPixmap(0)
         , m_glContext(adoptPtr(new QOpenGLContext))
+        , m_detachedContext(0)
+        , m_detachedSurface(0)
         , m_textureIsYInverted(false)
         , m_hasAlpha(false)
     {
@@ -113,6 +118,7 @@
             currentSurface = currentContext->surface();
 
         m_display = XOpenDisplay(0);
+        m_glContext->setShareContext(shareContext);
         m_glContext->create();
 
         // The GLX implementation of QOpenGLContext will reset the current context when create is being called.
@@ -178,11 +184,20 @@
 
     void makeCurrent()
     {
-        QOpenGLContext* glContext = QOpenGLContext::currentContext();
-        if (m_surface && glContext)
-            glContext->makeCurrent(m_surface.get());
+        m_detachedContext = QOpenGLContext::currentContext();
+        if (m_detachedContext)
+            m_detachedSurface = m_detachedContext->surface();
+
+        if (m_surface && m_glContext)
+            m_glContext->makeCurrent(m_surface.get());
     }
 
+    void doneCurrent()
+    {
+        if (m_detachedContext)
+            m_detachedContext->makeCurrent(m_detachedSurface);
+    }
+
     void swapBuffers()
     {
         // If there is a xpixmap, we are on the reading side and do not want to swap any buffers.
@@ -209,7 +224,37 @@
         }
     }
 
+    void copyFromTexture(uint32_t texture, const IntRect& sourceRect)
+    {
+        makeCurrent();
+        int x = sourceRect.x();
+        int y = sourceRect.y();
+        int width = sourceRect.width();
+        int height = sourceRect.height();
 
+        glPushAttrib(GL_ALL_ATTRIB_BITS);
+        GLint previousFBO;
+        glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previousFBO);
+
+        GLuint originFBO;
+        pGlGenFramebuffers(1, &originFBO);
+        pGlBindFramebuffer(GL_READ_FRAMEBUFFER, originFBO);
+        glBindTexture(GL_TEXTURE_2D, texture);
+        pGlFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+        pGlBindFramebuffer(GL_DRAW_FRAMEBUFFER, glContext()->defaultFramebufferObject());
+        pGlBlitFramebuffer(x, y, width, height, x, y, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+        pGlFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+        glBindTexture(GL_TEXTURE_2D, 0);
+        pGlBindFramebuffer(GL_FRAMEBUFFER, previousFBO);
+        pGlDeleteFramebuffers(1, &originFBO);
+
+        glPopAttrib();
+        doneCurrent();
+    }
+
+
     Display* display() const { return m_display; }
 
     GLXPixmap glxPixmap() const { return m_glxPixmap; }
@@ -226,6 +271,8 @@
     GLXPixmap m_glxPixmap;
     OwnPtr<QWindow> m_surface;
     OwnPtr<QOpenGLContext> m_glContext;
+    QOpenGLContext* m_detachedContext;
+    QSurface* m_detachedSurface;
     bool m_textureIsYInverted;
     bool m_hasAlpha;
 };
@@ -242,6 +289,10 @@
     pGlBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFERPROC>(glContext->getProcAddress("glBindFramebuffer"));
     pGlBlitFramebuffer = reinterpret_cast<PFNGLBLITFRAMEBUFFERPROC>(glContext->getProcAddress("glBlitFramebuffer"));
 
+    pGlGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSPROC>(glContext->getProcAddress("glGenFramebuffers"));
+    pGlDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSPROC>(glContext->getProcAddress("glDeleteFramebuffers"));
+    pGlFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DPROC>(glContext->getProcAddress("glFramebufferTexture2D"));
+
     resolved = pGlBlitFramebuffer && pGlBindFramebuffer && pGlXBindTexImageEXT && pGlXReleaseTexImageEXT;
 
     return resolved;
@@ -272,20 +323,9 @@
     // This is not supported by GLX/Xcomposite.
 }
 
-void GraphicsSurface::platformCopyFromFramebuffer(uint32_t originFbo, const IntRect& sourceRect)
+void GraphicsSurface::platformCopyFromTexture(uint32_t texture, const IntRect& sourceRect)
 {
-    m_private->makeCurrent();
-    int width = m_size.width();
-    int height = m_size.height();
-
-    glPushAttrib(GL_ALL_ATTRIB_BITS);
-    GLint oldFBO;
-    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFBO);
-    pGlBindFramebuffer(GL_READ_FRAMEBUFFER, originFbo);
-    pGlBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_private->glContext()->defaultFramebufferObject());
-    pGlBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-    pGlBindFramebuffer(GL_FRAMEBUFFER, oldFBO);
-    glPopAttrib();
+    m_private->copyFromTexture(texture, sourceRect);
 }
 
 
@@ -307,7 +347,7 @@
     return 0;
 }
 
-PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, Flags flags)
+PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, Flags flags, const PlatformGraphicsContext3D shareContext)
 {
     // X11 does not support CopyToTexture, so we do not create a GraphicsSurface if this is requested.
     // GraphicsSurfaceGLX uses an XWindow as native surface. This one always has a front and a back buffer.
@@ -317,7 +357,7 @@
 
     RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags));
 
-    surface->m_private = new GraphicsSurfacePrivate();
+    surface->m_private = new GraphicsSurfacePrivate(shareContext);
     if (!resolveGLMethods(surface->m_private))
         return PassRefPtr<GraphicsSurface>();
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to