Bug 640082 - Part 4 - Create TextureImageGLX which uses texture_from_pixmap. r=joe
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 07 Apr 2011 16:58:08 -0700
changeset 67636 6f831c7a1990d880af0b9837793570bb57dfaa87
parent 67635 ea1b21a2bf821009cc2f2585a997586b85461cff
child 67637 24a6d10dd3a2eb0aa2cebf11e843ac07ae6810ca
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs640082
milestone2.2a1pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 640082 - Part 4 - Create TextureImageGLX which uses texture_from_pixmap. r=joe
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/thebes/GLContextProviderGLX.cpp
gfx/thebes/GLXLibrary.h
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -237,18 +237,17 @@ ThebesLayerBufferOGL::RenderTo(const nsI
       alphaProgram->Activate();
       alphaProgram->SetBlackTextureUnit(0);
       alphaProgram->SetWhiteTextureUnit(1);
       program = alphaProgram;
     } else {
       // Note BGR: Cairo's image surfaces are always in what
       // OpenGL and our shaders consider BGR format.
       ColorTextureLayerProgram *basicProgram =
-        aManager->GetBasicLayerProgram(mTexImage->GetContentType() == gfxASurface::CONTENT_COLOR,
-                                       mTexImage->IsRGB());
+        aManager->GetColorTextureLayerProgram(mTexImage->GetShaderProgramType());
 
       basicProgram->Activate();
       basicProgram->SetTextureUnit(0);
       program = basicProgram;
     }
 
     program->SetLayerOpacity(mLayer->GetEffectiveOpacity());
     program->SetLayerTransform(mLayer->GetEffectiveTransform());
--- a/gfx/thebes/GLContextProviderGLX.cpp
+++ b/gfx/thebes/GLContextProviderGLX.cpp
@@ -54,16 +54,17 @@
 #include "nsDebug.h"
 #include "nsIWidget.h"
 #include "GLXLibrary.h"
 #include "gfxXlibSurface.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "GLContext.h"
+#include "gfxUtils.h"
 
 #include "gfxCrashReporterUtils.h"
 
 namespace mozilla {
 namespace gl {
 
 static PRBool gIsATI = PR_FALSE;
 static PRBool gIsChromium = PR_FALSE;
@@ -507,16 +508,27 @@ TRY_AGAIN_NO_SHARING:
     {
         if (!mDoubleBuffered)
             return PR_FALSE;
         sGLXLibrary.xSwapBuffers(mDisplay, mDrawable);
         sGLXLibrary.xWaitGL();
         return PR_TRUE;
     }
 
+    PRBool TextureImageSupportsGetBackingSurface()
+    {
+        return sGLXLibrary.HasTextureFromPixmap();
+    }
+
+    virtual already_AddRefed<TextureImage>
+    CreateTextureImage(const nsIntSize& aSize,
+                       TextureImage::ContentType aContentType,
+                       GLenum aWrapMode,
+                       PRBool aUseNearestFilter = PR_FALSE);
+
 private:
     friend class GLContextProviderGLX;
 
     GLContextGLX(const ContextFormat& aFormat,
                  GLContext *aShareContext,
                  Display *aDisplay,
                  GLXDrawable aDrawable,
                  GLXContext aContext,
@@ -536,16 +548,157 @@ private:
     Display *mDisplay;
     GLXDrawable mDrawable;
     PRPackedBool mDeleteDrawable;
     PRPackedBool mDoubleBuffered;
 
     nsRefPtr<gfxXlibSurface> mPixmap;
 };
 
+class TextureImageGLX : public TextureImage
+{
+    friend already_AddRefed<TextureImage>
+    GLContextGLX::CreateTextureImage(const nsIntSize&,
+                                     ContentType,
+                                     GLenum,
+                                     PRBool);
+
+public:
+    virtual ~TextureImageGLX()
+    {
+        mGLContext->MakeCurrent();
+        mGLContext->fDeleteTextures(1, &mTexture);
+        sGLXLibrary.DestroyPixmap(mPixmap);
+    }
+
+    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
+    {
+        mInUpdate = PR_TRUE;
+        return mUpdateSurface;
+    }
+
+    virtual void EndUpdate()
+    {
+        mInUpdate = PR_FALSE;
+    }
+
+    virtual bool DirectUpdate(gfxASurface* aSurface, const nsIntRegion& aRegion)
+    {
+        nsRefPtr<gfxContext> ctx = new gfxContext(mUpdateSurface);
+        gfxUtils::ClipToRegion(ctx, aRegion);
+        ctx->SetSource(aSurface);
+        ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+        ctx->Paint();
+        return true;
+    }
+
+    virtual void BindTexture(GLenum aTextureUnit)
+    {
+        mGLContext->fActiveTexture(aTextureUnit);
+        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, Texture());
+        sGLXLibrary.BindTexImage(mPixmap);
+        mGLContext->fActiveTexture(LOCAL_GL_TEXTURE);
+    }
+
+    virtual void ReleaseTexture()
+    {
+        sGLXLibrary.ReleaseTexImage(mPixmap);
+    }
+
+    virtual already_AddRefed<gfxASurface> GetBackingSurface()
+    {
+        NS_ADDREF(mUpdateSurface);
+        return mUpdateSurface.get();
+    }
+
+    virtual PRBool InUpdate() const { return !mInUpdate; }
+
+private:
+   TextureImageGLX(GLuint aTexture,
+                   const nsIntSize& aSize,
+                   GLenum aWrapMode,
+                   ContentType aContentType,
+                   GLContext* aContext,
+                   gfxASurface* aSurface,
+                   GLXPixmap aPixmap)
+        : TextureImage(aTexture, aSize, aWrapMode, aContentType)
+        , mGLContext(aContext)
+        , mUpdateSurface(aSurface)
+        , mPixmap(aPixmap)
+        , mInUpdate(PR_FALSE)
+    {
+        if (aSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA) {
+            mShaderType = gl::RGBALayerProgramType;
+        } else {
+            mShaderType = gl::RGBXLayerProgramType;
+        }
+    }
+
+    GLContext* mGLContext;
+    nsRefPtr<gfxASurface> mUpdateSurface;
+    GLXPixmap mPixmap;
+    PRPackedBool mInUpdate;
+};
+
+already_AddRefed<TextureImage>
+GLContextGLX::CreateTextureImage(const nsIntSize& aSize,
+                                 TextureImage::ContentType aContentType,
+                                 GLenum aWrapMode,
+                                 PRBool aUseNearestFilter)
+{
+    if (!TextureImageSupportsGetBackingSurface()) {
+        return GLContext::CreateTextureImage(aSize, 
+                                             aContentType, 
+                                             aWrapMode, 
+                                             aUseNearestFilter);
+    }
+
+    Display *display = DefaultXDisplay();
+    int xscreen = DefaultScreen(display);
+    gfxASurface::gfxImageFormat imageFormat = gfxASurface::FormatFromContent(aContentType);
+
+    XRenderPictFormat* xrenderFormat =
+        gfxXlibSurface::FindRenderFormat(display, imageFormat);
+    NS_ASSERTION(xrenderFormat, "Could not find a render format for our display!");
+
+
+    nsRefPtr<gfxXlibSurface> surface =
+        gfxXlibSurface::Create(ScreenOfDisplay(display, xscreen),
+                               xrenderFormat,
+                               gfxIntSize(aSize.width, aSize.height));
+    NS_ASSERTION(surface, "Failed to create xlib surface!");
+
+    if (aContentType == gfxASurface::CONTENT_COLOR_ALPHA) {
+        nsRefPtr<gfxContext> ctx = new gfxContext(surface);
+        ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
+        ctx->Paint();
+    }
+
+    MakeCurrent();
+    GLXPixmap pixmap = sGLXLibrary.CreatePixmap(surface);
+    NS_ASSERTION(pixmap, "Failed to create pixmap!");
+
+    GLuint texture;
+    fGenTextures(1, &texture);
+
+    fActiveTexture(LOCAL_GL_TEXTURE0);
+    fBindTexture(LOCAL_GL_TEXTURE_2D, texture);
+
+    nsRefPtr<TextureImageGLX> teximage =
+        new TextureImageGLX(texture, aSize, aWrapMode, aContentType, this, surface, pixmap);
+
+    GLint texfilter = aUseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
+    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
+    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
+    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
+    fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
+
+    return teximage.forget();
+}
+
 static GLContextGLX *
 GetGlobalContextGLX()
 {
     return static_cast<GLContextGLX*>(GLContextProviderGLX::GetGlobalContext());
 }
 
 static PRBool
 AreCompatibleVisuals(XVisualInfo *one, XVisualInfo *two)
--- a/gfx/thebes/GLXLibrary.h
+++ b/gfx/thebes/GLXLibrary.h
@@ -139,16 +139,18 @@ public:
 
     PRBool EnsureInitialized();
 
     GLXPixmap CreatePixmap(gfxASurface* aSurface);
     void DestroyPixmap(GLXPixmap aPixmap);
     void BindTexImage(GLXPixmap aPixmap);
     void ReleaseTexImage(GLXPixmap aPixmap);
 
+    PRBool HasTextureFromPixmap() { return mHasTextureFromPixmap; }
+
 private:
     PRBool mInitialized;
     PRBool mTriedInitializing;
     PRBool mHasTextureFromPixmap;
     PRLibrary *mOGLLibrary;
 };
 
 // a global GLXLibrary instance