mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-25 09:57:32 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
73
gfx/layers/opengl/Composer2D.h
Normal file
73
gfx/layers/opengl/Composer2D.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_layers_Composer2D_h
|
||||
#define mozilla_layers_Composer2D_h
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
/**
|
||||
* Many platforms have dedicated hardware for simple composition.
|
||||
* This hardware is usually faster or more power efficient than the
|
||||
* GPU. However, in exchange for this better performance, generality
|
||||
* has to be sacrificed: no 3d transforms, no intermediate surfaces,
|
||||
* no special shader effects, loss of other goodies depending on the
|
||||
* platform.
|
||||
*
|
||||
* Composer2D is a very simple interface to this class of hardware
|
||||
* that allows an implementation to "try rendering" with the fast
|
||||
* path. If the given layer tree requires more generality than the
|
||||
* hardware provides, the implementation should bail and have the
|
||||
* layer manager fall back on full GPU composition.
|
||||
*/
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Layer;
|
||||
|
||||
class Composer2D {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Composer2D)
|
||||
|
||||
protected:
|
||||
// Protected destructor, to discourage deletion outside of Release():
|
||||
virtual ~Composer2D() {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Return true if |aRoot| met the implementation's criteria for fast
|
||||
* composition and the render was successful. Return false to fall
|
||||
* back on the GPU.
|
||||
*
|
||||
* Currently, when TryRender() returns true, the entire framebuffer
|
||||
* must have been rendered.
|
||||
*/
|
||||
virtual bool TryRenderWithHwc(Layer* aRoot,
|
||||
nsIWidget* aWidget,
|
||||
bool aGeometryChanged,
|
||||
bool aHasImageHostOverlays) = 0;
|
||||
|
||||
/**
|
||||
* Return true if Composer2D does composition. Return false if Composer2D
|
||||
* failed the composition.
|
||||
*/
|
||||
virtual bool Render(nsIWidget* aWidget) = 0;
|
||||
|
||||
/**
|
||||
* Return true if Composer2D has a fast composition hardware.
|
||||
* Return false if Composer2D does not have a fast composition hardware.
|
||||
*/
|
||||
virtual bool HasHwc() = 0;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_layers_Composer2D_h
|
||||
120
gfx/layers/opengl/CompositingRenderTargetOGL.cpp
Normal file
120
gfx/layers/opengl/CompositingRenderTargetOGL.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CompositingRenderTargetOGL.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLReadTexImageHelper.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
CompositingRenderTargetOGL::~CompositingRenderTargetOGL()
|
||||
{
|
||||
if (mGL && mGL->MakeCurrent()) {
|
||||
mGL->fDeleteTextures(1, &mTextureHandle);
|
||||
mGL->fDeleteFramebuffers(1, &mFBO);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompositingRenderTargetOGL::BindTexture(GLenum aTextureUnit, GLenum aTextureTarget)
|
||||
{
|
||||
MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
|
||||
MOZ_ASSERT(mTextureHandle != 0);
|
||||
mGL->fActiveTexture(aTextureUnit);
|
||||
mGL->fBindTexture(aTextureTarget, mTextureHandle);
|
||||
}
|
||||
|
||||
void
|
||||
CompositingRenderTargetOGL::BindRenderTarget()
|
||||
{
|
||||
bool needsClear = false;
|
||||
|
||||
if (mInitParams.mStatus != InitParams::INITIALIZED) {
|
||||
InitializeImpl();
|
||||
if (mInitParams.mInit == INIT_MODE_CLEAR) {
|
||||
needsClear = true;
|
||||
mClearOnBind = false;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
|
||||
GLuint fbo = mFBO == 0 ? mGL->GetDefaultFramebuffer() : mFBO;
|
||||
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo);
|
||||
GLenum result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
// The main framebuffer (0) of non-offscreen contexts
|
||||
// might be backed by a EGLSurface that needs to be renewed.
|
||||
if (mFBO == 0 && !mGL->IsOffscreen()) {
|
||||
mGL->RenewSurface(mCompositor->GetWidget()->RealWidget());
|
||||
result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
}
|
||||
if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
nsAutoCString msg;
|
||||
msg.AppendPrintf("Framebuffer not complete -- CheckFramebufferStatus returned 0x%x, "
|
||||
"GLContext=%p, IsOffscreen()=%d, mFBO=%d, aFBOTextureTarget=0x%x, "
|
||||
"aRect.width=%d, aRect.height=%d",
|
||||
result, mGL, mGL->IsOffscreen(), mFBO, mInitParams.mFBOTextureTarget,
|
||||
mInitParams.mSize.width, mInitParams.mSize.height);
|
||||
NS_WARNING(msg.get());
|
||||
}
|
||||
}
|
||||
|
||||
needsClear = mClearOnBind;
|
||||
}
|
||||
|
||||
if (needsClear) {
|
||||
ScopedGLState scopedScissorTestState(mGL, LOCAL_GL_SCISSOR_TEST, true);
|
||||
ScopedScissorRect autoScissorRect(mGL, 0, 0, mInitParams.mSize.width,
|
||||
mInitParams.mSize.height);
|
||||
mGL->fClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
mGL->fClearDepth(0.0);
|
||||
mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
already_AddRefed<DataSourceSurface>
|
||||
CompositingRenderTargetOGL::Dump(Compositor* aCompositor)
|
||||
{
|
||||
MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
|
||||
CompositorOGL* compositorOGL = aCompositor->AsCompositorOGL();
|
||||
return ReadBackSurface(mGL, mTextureHandle, true, compositorOGL->GetFBOFormat());
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CompositingRenderTargetOGL::InitializeImpl()
|
||||
{
|
||||
MOZ_ASSERT(mInitParams.mStatus == InitParams::READY);
|
||||
|
||||
//TODO: call mGL->GetBackbufferFB(), use that
|
||||
GLuint fbo = mFBO == 0 ? mGL->GetDefaultFramebuffer() : mFBO;
|
||||
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo);
|
||||
mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
mInitParams.mFBOTextureTarget,
|
||||
mTextureHandle,
|
||||
0);
|
||||
|
||||
// Making this call to fCheckFramebufferStatus prevents a crash on
|
||||
// PowerVR. See bug 695246.
|
||||
GLenum result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
nsAutoCString msg;
|
||||
msg.AppendPrintf("Framebuffer not complete -- error 0x%x, aFBOTextureTarget 0x%x, mFBO %d, mTextureHandle %d, aRect.width %d, aRect.height %d",
|
||||
result, mInitParams.mFBOTextureTarget, mFBO, mTextureHandle, mInitParams.mSize.width, mInitParams.mSize.height);
|
||||
NS_ERROR(msg.get());
|
||||
}
|
||||
|
||||
mInitParams.mStatus = InitParams::INITIALIZED;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
195
gfx/layers/opengl/CompositingRenderTargetOGL.h
Normal file
195
gfx/layers/opengl/CompositingRenderTargetOGL.h
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_COMPOSITINGRENDERTARGETOGL_H
|
||||
#define MOZILLA_GFX_COMPOSITINGRENDERTARGETOGL_H
|
||||
|
||||
#include "GLContextTypes.h" // for GLContext
|
||||
#include "GLDefs.h" // for GLenum, LOCAL_GL_FRAMEBUFFER, etc
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed
|
||||
#include "mozilla/gfx/Point.h" // for IntSize, IntSizeTyped
|
||||
#include "mozilla/gfx/Types.h" // for SurfaceFormat, etc
|
||||
#include "mozilla/layers/Compositor.h" // for SurfaceInitMode, etc
|
||||
#include "mozilla/layers/TextureHost.h" // for CompositingRenderTarget
|
||||
#include "mozilla/layers/CompositorOGL.h" // for CompositorOGL
|
||||
#include "mozilla/mozalloc.h" // for operator new
|
||||
#include "nsAString.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_ERROR, NS_WARNING
|
||||
#include "nsString.h" // for nsAutoCString
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class BindableTexture;
|
||||
} // namespace gl
|
||||
namespace gfx {
|
||||
class DataSourceSurface;
|
||||
} // namespace gfx
|
||||
|
||||
namespace layers {
|
||||
|
||||
class TextureSource;
|
||||
|
||||
class CompositingRenderTargetOGL : public CompositingRenderTarget
|
||||
{
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
friend class CompositorOGL;
|
||||
|
||||
// For lazy initialisation of the GL stuff
|
||||
struct InitParams
|
||||
{
|
||||
InitParams() : mStatus(NO_PARAMS) {}
|
||||
InitParams(const gfx::IntSize& aSize,
|
||||
const gfx::IntSize& aPhySize,
|
||||
GLenum aFBOTextureTarget,
|
||||
SurfaceInitMode aInit)
|
||||
: mStatus(READY)
|
||||
, mSize(aSize)
|
||||
, mPhySize(aPhySize)
|
||||
, mFBOTextureTarget(aFBOTextureTarget)
|
||||
, mInit(aInit)
|
||||
{}
|
||||
|
||||
enum {
|
||||
NO_PARAMS,
|
||||
READY,
|
||||
INITIALIZED
|
||||
} mStatus;
|
||||
/*
|
||||
* Users of render target would draw in logical size, but it is
|
||||
* actually drawn to a surface in physical size. GL surfaces have
|
||||
* a limitation on their size, a smaller surface would be
|
||||
* allocated for the render target if the caller requests in a
|
||||
* size too big.
|
||||
*/
|
||||
gfx::IntSize mSize; // Logical size, the expected by callers.
|
||||
gfx::IntSize mPhySize; // Physical size, the real size of the surface.
|
||||
GLenum mFBOTextureTarget;
|
||||
SurfaceInitMode mInit;
|
||||
};
|
||||
|
||||
public:
|
||||
CompositingRenderTargetOGL(CompositorOGL* aCompositor, const gfx::IntPoint& aOrigin,
|
||||
GLuint aTexure, GLuint aFBO)
|
||||
: CompositingRenderTarget(aOrigin)
|
||||
, mInitParams()
|
||||
, mCompositor(aCompositor)
|
||||
, mGL(aCompositor->gl())
|
||||
, mTextureHandle(aTexure)
|
||||
, mFBO(aFBO)
|
||||
{
|
||||
MOZ_ASSERT(mGL);
|
||||
}
|
||||
|
||||
~CompositingRenderTargetOGL();
|
||||
|
||||
virtual const char* Name() const override { return "CompositingRenderTargetOGL"; }
|
||||
|
||||
/**
|
||||
* Create a render target around the default FBO, for rendering straight to
|
||||
* the window.
|
||||
*/
|
||||
static already_AddRefed<CompositingRenderTargetOGL>
|
||||
RenderTargetForWindow(CompositorOGL* aCompositor,
|
||||
const gfx::IntSize& aSize)
|
||||
{
|
||||
RefPtr<CompositingRenderTargetOGL> result
|
||||
= new CompositingRenderTargetOGL(aCompositor, gfx::IntPoint(), 0, 0);
|
||||
result->mInitParams = InitParams(aSize, aSize, 0, INIT_MODE_NONE);
|
||||
result->mInitParams.mStatus = InitParams::INITIALIZED;
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Some initialisation work on the backing FBO and texture.
|
||||
* We do this lazily so that when we first set this render target on the
|
||||
* compositor we do not have to re-bind the FBO after unbinding it, or
|
||||
* alternatively leave the FBO bound after creation.
|
||||
*/
|
||||
void Initialize(const gfx::IntSize& aSize,
|
||||
const gfx::IntSize& aPhySize,
|
||||
GLenum aFBOTextureTarget,
|
||||
SurfaceInitMode aInit)
|
||||
{
|
||||
MOZ_ASSERT(mInitParams.mStatus == InitParams::NO_PARAMS, "Initialized twice?");
|
||||
// postpone initialization until we actually want to use this render target
|
||||
mInitParams = InitParams(aSize, aPhySize, aFBOTextureTarget, aInit);
|
||||
}
|
||||
|
||||
void BindTexture(GLenum aTextureUnit, GLenum aTextureTarget);
|
||||
|
||||
/**
|
||||
* Call when we want to draw into our FBO
|
||||
*/
|
||||
void BindRenderTarget();
|
||||
|
||||
bool IsWindow() { return GetFBO() == 0; }
|
||||
|
||||
GLuint GetFBO() const
|
||||
{
|
||||
MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
|
||||
return mFBO;
|
||||
}
|
||||
|
||||
GLuint GetTextureHandle() const
|
||||
{
|
||||
MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
|
||||
return mTextureHandle;
|
||||
}
|
||||
|
||||
// TextureSourceOGL
|
||||
TextureSourceOGL* AsSourceOGL() override
|
||||
{
|
||||
// XXX - Bug 900770
|
||||
MOZ_ASSERT(false, "CompositingRenderTargetOGL should not be used as a TextureSource");
|
||||
return nullptr;
|
||||
}
|
||||
gfx::IntSize GetSize() const override
|
||||
{
|
||||
return mInitParams.mSize;
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat GetFormat() const override
|
||||
{
|
||||
// XXX - Should it be implemented ? is the above assert true ?
|
||||
MOZ_ASSERT(false, "Not implemented");
|
||||
return gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual already_AddRefed<gfx::DataSourceSurface> Dump(Compositor* aCompositor) override;
|
||||
#endif
|
||||
|
||||
const gfx::IntSize& GetInitSize() const {
|
||||
return mInitParams.mSize;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Actually do the initialisation. Note that we leave our FBO bound, and so
|
||||
* calling this method is only suitable when about to use this render target.
|
||||
*/
|
||||
void InitializeImpl();
|
||||
|
||||
InitParams mInitParams;
|
||||
/**
|
||||
* There is temporary a cycle between the compositor and the render target,
|
||||
* each having a strong ref to the other. The compositor's reference to
|
||||
* the target is always cleared at the end of a frame.
|
||||
*/
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
GLContext* mGL;
|
||||
GLuint mTextureHandle;
|
||||
GLuint mFBO;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* MOZILLA_GFX_SURFACEOGL_H */
|
||||
1916
gfx/layers/opengl/CompositorOGL.cpp
Normal file
1916
gfx/layers/opengl/CompositorOGL.cpp
Normal file
File diff suppressed because it is too large
Load diff
502
gfx/layers/opengl/CompositorOGL.h
Normal file
502
gfx/layers/opengl/CompositorOGL.h
Normal file
|
|
@ -0,0 +1,502 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_COMPOSITOROGL_H
|
||||
#define MOZILLA_GFX_COMPOSITOROGL_H
|
||||
|
||||
#include "ContextStateTracker.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "GLContextTypes.h" // for GLContext, etc
|
||||
#include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc
|
||||
#include "OGLShaderProgram.h" // for ShaderProgramOGL, etc
|
||||
#include "Units.h" // for ScreenPoint
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Attributes.h" // for override, final
|
||||
#include "mozilla/RefPtr.h" // for already_AddRefed, RefPtr
|
||||
#include "mozilla/gfx/2D.h" // for DrawTarget
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
|
||||
#include "mozilla/gfx/Point.h" // for IntSize, Point
|
||||
#include "mozilla/gfx/Rect.h" // for Rect, IntRect
|
||||
#include "mozilla/gfx/Triangle.h" // for Triangle
|
||||
#include "mozilla/gfx/Types.h" // for Float, SurfaceFormat, etc
|
||||
#include "mozilla/layers/Compositor.h" // for SurfaceInitMode, Compositor, etc
|
||||
#include "mozilla/layers/CompositorTypes.h" // for MaskType::MaskType::NumMaskTypes, etc
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "nsTArray.h" // for AutoTArray, nsTArray, etc
|
||||
#include "nsThreadUtils.h" // for nsRunnable
|
||||
#include "nsXULAppAPI.h" // for XRE_GetProcessType
|
||||
#include "nscore.h" // for NS_IMETHOD
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
|
||||
class CompositingRenderTarget;
|
||||
class CompositingRenderTargetOGL;
|
||||
class DataTextureSource;
|
||||
class GLManagerCompositor;
|
||||
class TextureSource;
|
||||
struct Effect;
|
||||
struct EffectChain;
|
||||
class GLBlitTextureImageHelper;
|
||||
|
||||
/**
|
||||
* Interface for pools of temporary gl textures for the compositor.
|
||||
* The textures are fully owned by the pool, so the latter is responsible
|
||||
* calling fDeleteTextures accordingly.
|
||||
* Users of GetTexture receive a texture that is only valid for the duration
|
||||
* of the current frame.
|
||||
* This is primarily intended for direct texturing APIs that need to attach
|
||||
* shared objects (such as an EGLImage) to a gl texture.
|
||||
*/
|
||||
class CompositorTexturePoolOGL
|
||||
{
|
||||
protected:
|
||||
virtual ~CompositorTexturePoolOGL() {}
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(CompositorTexturePoolOGL)
|
||||
|
||||
virtual void Clear() = 0;
|
||||
|
||||
virtual GLuint GetTexture(GLenum aTarget, GLenum aEnum) = 0;
|
||||
|
||||
virtual void EndFrame() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Agressively reuses textures. One gl texture per texture unit in total.
|
||||
* So far this hasn't shown the best results on b2g.
|
||||
*/
|
||||
class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL
|
||||
{
|
||||
public:
|
||||
explicit PerUnitTexturePoolOGL(gl::GLContext* aGL)
|
||||
: mTextureTarget(0) // zero is never a valid texture target
|
||||
, mGL(aGL)
|
||||
{}
|
||||
|
||||
virtual ~PerUnitTexturePoolOGL()
|
||||
{
|
||||
DestroyTextures();
|
||||
}
|
||||
|
||||
virtual void Clear() override
|
||||
{
|
||||
DestroyTextures();
|
||||
}
|
||||
|
||||
virtual GLuint GetTexture(GLenum aTarget, GLenum aUnit) override;
|
||||
|
||||
virtual void EndFrame() override {}
|
||||
|
||||
protected:
|
||||
void DestroyTextures();
|
||||
|
||||
GLenum mTextureTarget;
|
||||
nsTArray<GLuint> mTextures;
|
||||
RefPtr<gl::GLContext> mGL;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reuse gl textures from a pool of textures that haven't yet been
|
||||
* used during the current frame.
|
||||
* All the textures that are not used at the end of a frame are
|
||||
* deleted.
|
||||
* This strategy seems to work well with gralloc textures because destroying
|
||||
* unused textures which are bound to gralloc buffers let drivers know that it
|
||||
* can unlock the gralloc buffers.
|
||||
*/
|
||||
class PerFrameTexturePoolOGL : public CompositorTexturePoolOGL
|
||||
{
|
||||
public:
|
||||
explicit PerFrameTexturePoolOGL(gl::GLContext* aGL)
|
||||
: mTextureTarget(0) // zero is never a valid texture target
|
||||
, mGL(aGL)
|
||||
{}
|
||||
|
||||
virtual ~PerFrameTexturePoolOGL()
|
||||
{
|
||||
DestroyTextures();
|
||||
}
|
||||
|
||||
virtual void Clear() override
|
||||
{
|
||||
DestroyTextures();
|
||||
}
|
||||
|
||||
virtual GLuint GetTexture(GLenum aTarget, GLenum aUnit) override;
|
||||
|
||||
virtual void EndFrame() override;
|
||||
|
||||
protected:
|
||||
void DestroyTextures();
|
||||
|
||||
GLenum mTextureTarget;
|
||||
RefPtr<gl::GLContext> mGL;
|
||||
nsTArray<GLuint> mCreatedTextures;
|
||||
nsTArray<GLuint> mUnusedTextures;
|
||||
};
|
||||
|
||||
// If you want to make this class not final, first remove calls to virtual
|
||||
// methods (Destroy) that are made in the destructor.
|
||||
class CompositorOGL final : public Compositor
|
||||
{
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
friend class GLManagerCompositor;
|
||||
friend class CompositingRenderTargetOGL;
|
||||
|
||||
std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms;
|
||||
public:
|
||||
explicit CompositorOGL(CompositorBridgeParent* aParent,
|
||||
widget::CompositorWidget* aWidget,
|
||||
int aSurfaceWidth = -1, int aSurfaceHeight = -1,
|
||||
bool aUseExternalSurfaceSize = false);
|
||||
|
||||
protected:
|
||||
virtual ~CompositorOGL();
|
||||
|
||||
public:
|
||||
virtual CompositorOGL* AsCompositorOGL() override { return this; }
|
||||
|
||||
virtual already_AddRefed<DataTextureSource>
|
||||
CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
|
||||
|
||||
virtual bool Initialize(nsCString* const out_failureReason) override;
|
||||
|
||||
virtual void Destroy() override;
|
||||
|
||||
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override
|
||||
{
|
||||
TextureFactoryIdentifier result =
|
||||
TextureFactoryIdentifier(LayersBackend::LAYERS_OPENGL,
|
||||
XRE_GetProcessType(),
|
||||
GetMaxTextureSize(),
|
||||
mFBOTextureTarget == LOCAL_GL_TEXTURE_2D,
|
||||
SupportsPartialTextureUpdate());
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<CompositingRenderTarget>
|
||||
CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) override;
|
||||
|
||||
virtual already_AddRefed<CompositingRenderTarget>
|
||||
CreateRenderTargetFromSource(const gfx::IntRect &aRect,
|
||||
const CompositingRenderTarget *aSource,
|
||||
const gfx::IntPoint &aSourcePoint) override;
|
||||
|
||||
virtual void SetRenderTarget(CompositingRenderTarget *aSurface) override;
|
||||
virtual CompositingRenderTarget* GetCurrentRenderTarget() const override;
|
||||
|
||||
virtual void DrawQuad(const gfx::Rect& aRect,
|
||||
const gfx::IntRect& aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect) override;
|
||||
|
||||
virtual void DrawTriangle(const gfx::TexturedTriangle& aTriangle,
|
||||
const gfx::IntRect& aClipRect,
|
||||
const EffectChain& aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect) override;
|
||||
|
||||
virtual void EndFrame() override;
|
||||
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override;
|
||||
|
||||
virtual bool SupportsPartialTextureUpdate() override;
|
||||
|
||||
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override
|
||||
{
|
||||
if (!mGLContext)
|
||||
return false;
|
||||
int32_t maxSize = GetMaxTextureSize();
|
||||
return aSize <= gfx::IntSize(maxSize, maxSize);
|
||||
}
|
||||
|
||||
virtual int32_t GetMaxTextureSize() const override;
|
||||
|
||||
/**
|
||||
* Set the size of the EGL surface we're rendering to, if we're rendering to
|
||||
* an EGL surface.
|
||||
*/
|
||||
virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override;
|
||||
|
||||
virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) override {
|
||||
mRenderOffset = aOffset;
|
||||
}
|
||||
|
||||
virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override;
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
virtual const char* Name() const override { return "OGL"; }
|
||||
#endif // MOZ_DUMP_PAINTING
|
||||
|
||||
virtual LayersBackend GetBackendType() const override {
|
||||
return LayersBackend::LAYERS_OPENGL;
|
||||
}
|
||||
|
||||
virtual void Pause() override;
|
||||
virtual bool Resume() override;
|
||||
|
||||
virtual bool HasImageHostOverlays() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void AddImageHostOverlay(ImageHostOverlay* aOverlay) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void RemoveImageHostOverlay(ImageHostOverlay* aOverlay) override
|
||||
{
|
||||
}
|
||||
|
||||
GLContext* gl() const { return mGLContext; }
|
||||
/**
|
||||
* Clear the program state. This must be called
|
||||
* before operating on the GLContext directly. */
|
||||
void ResetProgram();
|
||||
|
||||
gfx::SurfaceFormat GetFBOFormat() const {
|
||||
return gfx::SurfaceFormat::R8G8B8A8;
|
||||
}
|
||||
|
||||
GLBlitTextureImageHelper* BlitTextureImageHelper();
|
||||
|
||||
/**
|
||||
* The compositor provides with temporary textures for use with direct
|
||||
* textruing like gralloc texture.
|
||||
* Doing so lets us use gralloc the way it has been designed to be used
|
||||
* (see https://wiki.mozilla.org/Platform/GFX/Gralloc)
|
||||
*/
|
||||
GLuint GetTemporaryTexture(GLenum aTarget, GLenum aUnit);
|
||||
|
||||
const gfx::Matrix4x4& GetProjMatrix() const {
|
||||
return mProjMatrix;
|
||||
}
|
||||
|
||||
void SetProjMatrix(const gfx::Matrix4x4& aProjMatrix) {
|
||||
mProjMatrix = aProjMatrix;
|
||||
}
|
||||
|
||||
const gfx::IntSize GetDestinationSurfaceSize() const {
|
||||
return gfx::IntSize (mSurfaceSize.width, mSurfaceSize.height);
|
||||
}
|
||||
|
||||
const ScreenPoint& GetScreenRenderOffset() const {
|
||||
return mRenderOffset;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Geometry>
|
||||
void DrawGeometry(const Geometry& aGeometry,
|
||||
const gfx::IntRect& aClipRect,
|
||||
const EffectChain &aEffectChain,
|
||||
gfx::Float aOpacity,
|
||||
const gfx::Matrix4x4& aTransform,
|
||||
const gfx::Rect& aVisibleRect);
|
||||
|
||||
void PrepareViewport(CompositingRenderTargetOGL *aRenderTarget);
|
||||
|
||||
/** Widget associated with this compositor */
|
||||
LayoutDeviceIntSize mWidgetSize;
|
||||
RefPtr<GLContext> mGLContext;
|
||||
UniquePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
|
||||
gfx::Matrix4x4 mProjMatrix;
|
||||
|
||||
/** The size of the surface we are rendering to */
|
||||
gfx::IntSize mSurfaceSize;
|
||||
|
||||
ScreenPoint mRenderOffset;
|
||||
|
||||
already_AddRefed<mozilla::gl::GLContext> CreateContext();
|
||||
|
||||
/** Texture target to use for FBOs */
|
||||
GLenum mFBOTextureTarget;
|
||||
|
||||
/** Currently bound render target */
|
||||
RefPtr<CompositingRenderTargetOGL> mCurrentRenderTarget;
|
||||
#ifdef DEBUG
|
||||
CompositingRenderTargetOGL* mWindowRenderTarget;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* VBO that has some basics in it for a textured quad, including vertex
|
||||
* coords and texcoords.
|
||||
*/
|
||||
GLuint mQuadVBO;
|
||||
|
||||
|
||||
/**
|
||||
* VBO that stores dynamic triangle geometry.
|
||||
*/
|
||||
GLuint mTriangleVBO;
|
||||
|
||||
bool mHasBGRA;
|
||||
|
||||
/**
|
||||
* When rendering to some EGL surfaces (e.g. on Android), we rely on being told
|
||||
* about size changes (via SetSurfaceSize) rather than pulling this information
|
||||
* from the widget.
|
||||
*/
|
||||
bool mUseExternalSurfaceSize;
|
||||
|
||||
/**
|
||||
* Have we had DrawQuad calls since the last frame was rendered?
|
||||
*/
|
||||
bool mFrameInProgress;
|
||||
|
||||
/*
|
||||
* Clear aRect on current render target.
|
||||
*/
|
||||
virtual void ClearRect(const gfx::Rect& aRect) override;
|
||||
|
||||
/* Start a new frame. If aClipRectIn is null and aClipRectOut is non-null,
|
||||
* sets *aClipRectOut to the screen dimensions.
|
||||
*/
|
||||
virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
const gfx::IntRect *aClipRectIn,
|
||||
const gfx::IntRect& aRenderBounds,
|
||||
const nsIntRegion& aOpaqueRegion,
|
||||
gfx::IntRect *aClipRectOut = nullptr,
|
||||
gfx::IntRect *aRenderBoundsOut = nullptr) override;
|
||||
|
||||
ShaderConfigOGL GetShaderConfigFor(Effect *aEffect,
|
||||
MaskType aMask = MaskType::MaskNone,
|
||||
gfx::CompositionOp aOp = gfx::CompositionOp::OP_OVER,
|
||||
bool aColorMatrix = false,
|
||||
bool aDEAAEnabled = false) const;
|
||||
|
||||
ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig);
|
||||
|
||||
void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig,
|
||||
const gfx::Rect&)
|
||||
{
|
||||
aConfig.SetDynamicGeometry(false);
|
||||
}
|
||||
|
||||
void ApplyPrimitiveConfig(ShaderConfigOGL& aConfig,
|
||||
const gfx::TexturedTriangle&)
|
||||
{
|
||||
aConfig.SetDynamicGeometry(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FBO backed by a texture.
|
||||
* Note that the texture target type will be
|
||||
* of the type returned by FBOTextureTarget; different
|
||||
* shaders are required to sample from the different
|
||||
* texture types.
|
||||
*/
|
||||
void CreateFBOWithTexture(const gfx::IntRect& aRect, bool aCopyFromSource,
|
||||
GLuint aSourceFrameBuffer,
|
||||
GLuint *aFBO, GLuint *aTexture,
|
||||
gfx::IntSize* aAllocSize = nullptr);
|
||||
|
||||
GLuint CreateTexture(const gfx::IntRect& aRect, bool aCopyFromSource,
|
||||
GLuint aSourceFrameBuffer,
|
||||
gfx::IntSize* aAllocSize = nullptr);
|
||||
|
||||
gfx::Point3D GetLineCoefficients(const gfx::Point& aPoint1,
|
||||
const gfx::Point& aPoint2);
|
||||
|
||||
void ActivateProgram(ShaderProgramOGL *aProg);
|
||||
|
||||
void CleanupResources();
|
||||
|
||||
void BindAndDrawQuads(ShaderProgramOGL *aProg,
|
||||
int aQuads,
|
||||
const gfx::Rect* aLayerRect,
|
||||
const gfx::Rect* aTextureRect);
|
||||
|
||||
void BindAndDrawQuad(ShaderProgramOGL *aProg,
|
||||
const gfx::Rect& aLayerRect,
|
||||
const gfx::Rect& aTextureRect =
|
||||
gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f))
|
||||
{
|
||||
gfx::Rect layerRects[4];
|
||||
gfx::Rect textureRects[4];
|
||||
layerRects[0] = aLayerRect;
|
||||
textureRects[0] = aTextureRect;
|
||||
BindAndDrawQuads(aProg, 1, layerRects, textureRects);
|
||||
}
|
||||
|
||||
void BindAndDrawGeometry(ShaderProgramOGL* aProgram,
|
||||
const gfx::Rect& aRect,
|
||||
const gfx::Rect& aTextureRect =
|
||||
gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
|
||||
void BindAndDrawGeometry(ShaderProgramOGL* aProgram,
|
||||
const gfx::TexturedTriangle& aTriangle,
|
||||
const gfx::Rect& aTextureRect =
|
||||
gfx::Rect(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
|
||||
void BindAndDrawGeometryWithTextureRect(ShaderProgramOGL *aProg,
|
||||
const gfx::Rect& aRect,
|
||||
const gfx::Rect& aTexCoordRect,
|
||||
TextureSource *aTexture);
|
||||
|
||||
void BindAndDrawGeometryWithTextureRect(ShaderProgramOGL *aProg,
|
||||
const gfx::TexturedTriangle& aTriangle,
|
||||
const gfx::Rect& aTexCoordRect,
|
||||
TextureSource *aTexture);
|
||||
|
||||
void InitializeVAO(const GLuint aAttribIndex, const GLint aComponents,
|
||||
const GLsizei aStride, const size_t aOffset);
|
||||
|
||||
gfx::Rect GetTextureCoordinates(gfx::Rect textureRect,
|
||||
TextureSource* aTexture);
|
||||
|
||||
/**
|
||||
* Bind the texture behind the current render target as the backdrop for a
|
||||
* mix-blend shader.
|
||||
*/
|
||||
void BindBackdrop(ShaderProgramOGL* aProgram, GLuint aBackdrop, GLenum aTexUnit);
|
||||
|
||||
/**
|
||||
* Copies the content of our backbuffer to the set transaction target.
|
||||
* Does not restore the target FBO, so only call from EndFrame.
|
||||
*/
|
||||
void CopyToTarget(gfx::DrawTarget* aTarget, const nsIntPoint& aTopLeft, const gfx::Matrix& aWorldMatrix);
|
||||
|
||||
/**
|
||||
* Implements the flipping of the y-axis to convert from layers/compositor
|
||||
* coordinates to OpenGL coordinates.
|
||||
*
|
||||
* Indeed, the only coordinate system that OpenGL knows has the y-axis
|
||||
* pointing upwards, but the layers/compositor coordinate system has the
|
||||
* y-axis pointing downwards, for good reason as Web pages are typically
|
||||
* scrolled downwards. So, some flipping has to take place; FlippedY does it.
|
||||
*/
|
||||
GLint FlipY(GLint y) const { return mViewportSize.height - y; }
|
||||
|
||||
RefPtr<CompositorTexturePoolOGL> mTexturePool;
|
||||
|
||||
ContextStateTrackerOGL mContextStateTracker;
|
||||
|
||||
bool mDestroyed;
|
||||
|
||||
/**
|
||||
* Size of the OpenGL context's primary framebuffer in pixels. Used by
|
||||
* FlipY for the y-flipping calculation and by the DEAA shader.
|
||||
*/
|
||||
gfx::IntSize mViewportSize;
|
||||
|
||||
ShaderProgramOGL *mCurrentProgram;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* MOZILLA_GFX_COMPOSITOROGL_H */
|
||||
53
gfx/layers/opengl/EGLImageHelpers.cpp
Normal file
53
gfx/layers/opengl/EGLImageHelpers.cpp
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "EGLImageHelpers.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
namespace layers {
|
||||
|
||||
using namespace gl;
|
||||
|
||||
EGLImage
|
||||
EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer, const gfx::IntSize& aCropSize)
|
||||
{
|
||||
EGLint attrs[] = {
|
||||
LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
|
||||
LOCAL_EGL_NONE, LOCAL_EGL_NONE,
|
||||
};
|
||||
|
||||
EGLint cropAttrs[] = {
|
||||
LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
|
||||
LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID, 0,
|
||||
LOCAL_EGL_IMAGE_CROP_TOP_ANDROID, 0,
|
||||
LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID, aCropSize.width,
|
||||
LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID, aCropSize.height,
|
||||
LOCAL_EGL_NONE, LOCAL_EGL_NONE,
|
||||
};
|
||||
|
||||
bool hasCropRect = (aCropSize.width != 0 && aCropSize.height != 0);
|
||||
EGLint* usedAttrs = attrs;
|
||||
if (hasCropRect && sEGLLibrary.IsExtensionSupported(GLLibraryEGL::EGL_ANDROID_image_crop)) {
|
||||
usedAttrs = cropAttrs;
|
||||
}
|
||||
|
||||
return sEGLLibrary.fCreateImage(sEGLLibrary.Display(),
|
||||
EGL_NO_CONTEXT,
|
||||
LOCAL_EGL_NATIVE_BUFFER_ANDROID,
|
||||
aBuffer, usedAttrs);
|
||||
}
|
||||
|
||||
void
|
||||
EGLImageDestroy(GLContext* aGL, EGLImage aImage)
|
||||
{
|
||||
sEGLLibrary.fDestroyImage(sEGLLibrary.Display(), aImage);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
27
gfx/layers/opengl/EGLImageHelpers.h
Normal file
27
gfx/layers/opengl/EGLImageHelpers.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef EGLIMAGEHELPERS_H_
|
||||
#define EGLIMAGEHELPERS_H_
|
||||
|
||||
#include "mozilla/gfx/Point.h"
|
||||
|
||||
typedef void* EGLImage;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
||||
EGLImage EGLImageCreateFromNativeBuffer(gl::GLContext* aGL, void* aBuffer, const gfx::IntSize& aCropSize);
|
||||
void EGLImageDestroy(gl::GLContext* aGL, EGLImage aImage);
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // EGLIMAGEHELPERS_H_
|
||||
280
gfx/layers/opengl/GLBlitTextureImageHelper.cpp
Normal file
280
gfx/layers/opengl/GLBlitTextureImageHelper.cpp
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GLBlitTextureImageHelper.h"
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "DecomposeIntoNoRepeatTriangles.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLTextureImage.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "nsRect.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "CompositorOGL.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
|
||||
using namespace mozilla::gl;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
GLBlitTextureImageHelper::GLBlitTextureImageHelper(CompositorOGL* aCompositor)
|
||||
: mCompositor(aCompositor)
|
||||
, mBlitProgram(0)
|
||||
, mBlitFramebuffer(0)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
GLBlitTextureImageHelper::~GLBlitTextureImageHelper()
|
||||
{
|
||||
GLContext *gl = mCompositor->gl();
|
||||
// Likely used by OGL Layers.
|
||||
gl->fDeleteProgram(mBlitProgram);
|
||||
gl->fDeleteFramebuffers(1, &mBlitFramebuffer);
|
||||
}
|
||||
|
||||
void
|
||||
GLBlitTextureImageHelper::BlitTextureImage(TextureImage *aSrc, const gfx::IntRect& aSrcRect,
|
||||
TextureImage *aDst, const gfx::IntRect& aDstRect)
|
||||
{
|
||||
GLContext *gl = mCompositor->gl();
|
||||
|
||||
if (!aSrc || !aDst || aSrcRect.IsEmpty() || aDstRect.IsEmpty())
|
||||
return;
|
||||
|
||||
int savedFb = 0;
|
||||
gl->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &savedFb);
|
||||
|
||||
ScopedGLState scopedScissorTestState(gl, LOCAL_GL_SCISSOR_TEST, false);
|
||||
ScopedGLState scopedBlendState(gl, LOCAL_GL_BLEND, false);
|
||||
|
||||
// 2.0 means scale up by two
|
||||
float blitScaleX = float(aDstRect.width) / float(aSrcRect.width);
|
||||
float blitScaleY = float(aDstRect.height) / float(aSrcRect.height);
|
||||
|
||||
// We start iterating over all destination tiles
|
||||
aDst->BeginBigImageIteration();
|
||||
do {
|
||||
// calculate portion of the tile that is going to be painted to
|
||||
gfx::IntRect dstSubRect;
|
||||
gfx::IntRect dstTextureRect = aDst->GetTileRect();
|
||||
dstSubRect.IntersectRect(aDstRect, dstTextureRect);
|
||||
|
||||
// this tile is not part of the destination rectangle aDstRect
|
||||
if (dstSubRect.IsEmpty())
|
||||
continue;
|
||||
|
||||
// (*) transform the rect of this tile into the rectangle defined by aSrcRect...
|
||||
gfx::IntRect dstInSrcRect(dstSubRect);
|
||||
dstInSrcRect.MoveBy(-aDstRect.TopLeft());
|
||||
// ...which might be of different size, hence scale accordingly
|
||||
dstInSrcRect.ScaleRoundOut(1.0f / blitScaleX, 1.0f / blitScaleY);
|
||||
dstInSrcRect.MoveBy(aSrcRect.TopLeft());
|
||||
|
||||
SetBlitFramebufferForDestTexture(aDst->GetTextureID());
|
||||
UseBlitProgram();
|
||||
|
||||
aSrc->BeginBigImageIteration();
|
||||
// now iterate over all tiles in the source Image...
|
||||
do {
|
||||
// calculate portion of the source tile that is in the source rect
|
||||
gfx::IntRect srcSubRect;
|
||||
gfx::IntRect srcTextureRect = aSrc->GetTileRect();
|
||||
srcSubRect.IntersectRect(aSrcRect, srcTextureRect);
|
||||
|
||||
// this tile is not part of the source rect
|
||||
if (srcSubRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// calculate intersection of source rect with destination rect
|
||||
srcSubRect.IntersectRect(srcSubRect, dstInSrcRect);
|
||||
// this tile does not overlap the current destination tile
|
||||
if (srcSubRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// We now have the intersection of
|
||||
// the current source tile
|
||||
// and the desired source rectangle
|
||||
// and the destination tile
|
||||
// and the desired destination rectange
|
||||
// in destination space.
|
||||
// We need to transform this back into destination space, inverting the transform from (*)
|
||||
gfx::IntRect srcSubInDstRect(srcSubRect);
|
||||
srcSubInDstRect.MoveBy(-aSrcRect.TopLeft());
|
||||
srcSubInDstRect.ScaleRoundOut(blitScaleX, blitScaleY);
|
||||
srcSubInDstRect.MoveBy(aDstRect.TopLeft());
|
||||
|
||||
// we transform these rectangles to be relative to the current src and dst tiles, respectively
|
||||
gfx::IntSize srcSize = srcTextureRect.Size();
|
||||
gfx::IntSize dstSize = dstTextureRect.Size();
|
||||
srcSubRect.MoveBy(-srcTextureRect.x, -srcTextureRect.y);
|
||||
srcSubInDstRect.MoveBy(-dstTextureRect.x, -dstTextureRect.y);
|
||||
|
||||
float dx0 = 2.0f * float(srcSubInDstRect.x) / float(dstSize.width) - 1.0f;
|
||||
float dy0 = 2.0f * float(srcSubInDstRect.y) / float(dstSize.height) - 1.0f;
|
||||
float dx1 = 2.0f * float(srcSubInDstRect.x + srcSubInDstRect.width) / float(dstSize.width) - 1.0f;
|
||||
float dy1 = 2.0f * float(srcSubInDstRect.y + srcSubInDstRect.height) / float(dstSize.height) - 1.0f;
|
||||
ScopedViewportRect autoViewportRect(gl, 0, 0, dstSize.width, dstSize.height);
|
||||
|
||||
RectTriangles rects;
|
||||
|
||||
gfx::IntSize realTexSize = srcSize;
|
||||
if (!CanUploadNonPowerOfTwo(gl)) {
|
||||
realTexSize = gfx::IntSize(RoundUpPow2(srcSize.width),
|
||||
RoundUpPow2(srcSize.height));
|
||||
}
|
||||
|
||||
if (aSrc->GetWrapMode() == LOCAL_GL_REPEAT) {
|
||||
rects.addRect(/* dest rectangle */
|
||||
dx0, dy0, dx1, dy1,
|
||||
/* tex coords */
|
||||
srcSubRect.x / float(realTexSize.width),
|
||||
srcSubRect.y / float(realTexSize.height),
|
||||
srcSubRect.XMost() / float(realTexSize.width),
|
||||
srcSubRect.YMost() / float(realTexSize.height));
|
||||
} else {
|
||||
DecomposeIntoNoRepeatTriangles(srcSubRect, realTexSize, rects);
|
||||
|
||||
// now put the coords into the d[xy]0 .. d[xy]1 coordinate space
|
||||
// from the 0..1 that it comes out of decompose
|
||||
InfallibleTArray<RectTriangles::coord>& coords = rects.vertCoords();
|
||||
|
||||
for (unsigned int i = 0; i < coords.Length(); ++i) {
|
||||
coords[i].x = (coords[i].x * (dx1 - dx0)) + dx0;
|
||||
coords[i].y = (coords[i].y * (dy1 - dy0)) + dy0;
|
||||
}
|
||||
}
|
||||
|
||||
ScopedBindTextureUnit autoTexUnit(gl, LOCAL_GL_TEXTURE0);
|
||||
ScopedBindTexture autoTex(gl, aSrc->GetTextureID());
|
||||
ScopedVertexAttribPointer autoAttrib0(gl, 0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0, rects.vertCoords().Elements());
|
||||
ScopedVertexAttribPointer autoAttrib1(gl, 1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0, rects.texCoords().Elements());
|
||||
|
||||
gl->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
|
||||
|
||||
} while (aSrc->NextTile());
|
||||
} while (aDst->NextTile());
|
||||
|
||||
// unbind the previous texture from the framebuffer
|
||||
SetBlitFramebufferForDestTexture(0);
|
||||
|
||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, savedFb);
|
||||
}
|
||||
|
||||
void
|
||||
GLBlitTextureImageHelper::SetBlitFramebufferForDestTexture(GLuint aTexture)
|
||||
{
|
||||
GLContext *gl = mCompositor->gl();
|
||||
if (!mBlitFramebuffer) {
|
||||
gl->fGenFramebuffers(1, &mBlitFramebuffer);
|
||||
}
|
||||
|
||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBlitFramebuffer);
|
||||
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_TEXTURE_2D,
|
||||
aTexture,
|
||||
0);
|
||||
|
||||
GLenum result = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (aTexture && (result != LOCAL_GL_FRAMEBUFFER_COMPLETE)) {
|
||||
nsAutoCString msg;
|
||||
msg.AppendLiteral("Framebuffer not complete -- error 0x");
|
||||
msg.AppendInt(result, 16);
|
||||
// Note: if you are hitting this, it is likely that
|
||||
// your texture is not texture complete -- that is, you
|
||||
// allocated a texture name, but didn't actually define its
|
||||
// size via a call to TexImage2D.
|
||||
NS_RUNTIMEABORT(msg.get());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLBlitTextureImageHelper::UseBlitProgram()
|
||||
{
|
||||
// XXX: GLBlitTextureImageHelper doesn't use ShaderProgramOGL
|
||||
// so we need to Reset the program
|
||||
mCompositor->ResetProgram();
|
||||
|
||||
GLContext *gl = mCompositor->gl();
|
||||
if (mBlitProgram) {
|
||||
gl->fUseProgram(mBlitProgram);
|
||||
return;
|
||||
}
|
||||
|
||||
mBlitProgram = gl->fCreateProgram();
|
||||
|
||||
GLuint shaders[2];
|
||||
shaders[0] = gl->fCreateShader(LOCAL_GL_VERTEX_SHADER);
|
||||
shaders[1] = gl->fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
|
||||
|
||||
const char *blitVSSrc =
|
||||
"attribute vec2 aVertex;"
|
||||
"attribute vec2 aTexCoord;"
|
||||
"varying vec2 vTexCoord;"
|
||||
"void main() {"
|
||||
" vTexCoord = aTexCoord;"
|
||||
" gl_Position = vec4(aVertex, 0.0, 1.0);"
|
||||
"}";
|
||||
const char *blitFSSrc = "#ifdef GL_ES\nprecision mediump float;\n#endif\n"
|
||||
"uniform sampler2D uSrcTexture;"
|
||||
"varying vec2 vTexCoord;"
|
||||
"void main() {"
|
||||
" gl_FragColor = texture2D(uSrcTexture, vTexCoord);"
|
||||
"}";
|
||||
|
||||
gl->fShaderSource(shaders[0], 1, (const GLchar**) &blitVSSrc, nullptr);
|
||||
gl->fShaderSource(shaders[1], 1, (const GLchar**) &blitFSSrc, nullptr);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
GLint success, len = 0;
|
||||
|
||||
gl->fCompileShader(shaders[i]);
|
||||
gl->fGetShaderiv(shaders[i], LOCAL_GL_COMPILE_STATUS, &success);
|
||||
NS_ASSERTION(success, "Shader compilation failed!");
|
||||
|
||||
if (!success) {
|
||||
nsAutoCString log;
|
||||
gl->fGetShaderiv(shaders[i], LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
log.SetCapacity(len);
|
||||
gl->fGetShaderInfoLog(shaders[i], len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
printf_stderr("Shader %d compilation failed:\n%s\n", i, log.get());
|
||||
return;
|
||||
}
|
||||
|
||||
gl->fAttachShader(mBlitProgram, shaders[i]);
|
||||
gl->fDeleteShader(shaders[i]);
|
||||
}
|
||||
|
||||
gl->fBindAttribLocation(mBlitProgram, 0, "aVertex");
|
||||
gl->fBindAttribLocation(mBlitProgram, 1, "aTexCoord");
|
||||
|
||||
gl->fLinkProgram(mBlitProgram);
|
||||
|
||||
GLint success, len = 0;
|
||||
gl->fGetProgramiv(mBlitProgram, LOCAL_GL_LINK_STATUS, &success);
|
||||
NS_ASSERTION(success, "Shader linking failed!");
|
||||
|
||||
if (!success) {
|
||||
nsAutoCString log;
|
||||
gl->fGetProgramiv(mBlitProgram, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
log.SetCapacity(len);
|
||||
gl->fGetProgramInfoLog(mBlitProgram, len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
printf_stderr("Program linking failed:\n%s\n", log.get());
|
||||
return;
|
||||
}
|
||||
|
||||
gl->fUseProgram(mBlitProgram);
|
||||
gl->fUniform1i(gl->fGetUniformLocation(mBlitProgram, "uSrcTexture"), 0);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
71
gfx/layers/opengl/GLBlitTextureImageHelper.h
Normal file
71
gfx/layers/opengl/GLBlitTextureImageHelper.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GLBLITTEXTUREIMAGEHELPER_H_
|
||||
#define GLBLITTEXTUREIMAGEHELPER_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLConsts.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
class TextureImage;
|
||||
} // namespace gl
|
||||
namespace layers {
|
||||
|
||||
class CompositorOGL;
|
||||
|
||||
class GLBlitTextureImageHelper final
|
||||
{
|
||||
// The GLContext is the sole owner of the GLBlitTextureImageHelper.
|
||||
CompositorOGL* mCompositor;
|
||||
|
||||
// lazy-initialized things
|
||||
GLuint mBlitProgram, mBlitFramebuffer;
|
||||
void UseBlitProgram();
|
||||
void SetBlitFramebufferForDestTexture(GLuint aTexture);
|
||||
|
||||
public:
|
||||
|
||||
explicit GLBlitTextureImageHelper(CompositorOGL *gl);
|
||||
~GLBlitTextureImageHelper();
|
||||
|
||||
/**
|
||||
* Copy a rectangle from one TextureImage into another. The
|
||||
* source and destination are given in integer coordinates, and
|
||||
* will be converted to texture coordinates.
|
||||
*
|
||||
* For the source texture, the wrap modes DO apply -- it's valid
|
||||
* to use REPEAT or PAD and expect appropriate behaviour if the source
|
||||
* rectangle extends beyond its bounds.
|
||||
*
|
||||
* For the destination texture, the wrap modes DO NOT apply -- the
|
||||
* destination will be clipped by the bounds of the texture.
|
||||
*
|
||||
* Note: calling this function will cause the following OpenGL state
|
||||
* to be changed:
|
||||
*
|
||||
* - current program
|
||||
* - framebuffer binding
|
||||
* - viewport
|
||||
* - blend state (will be enabled at end)
|
||||
* - scissor state (will be enabled at end)
|
||||
* - vertex attrib 0 and 1 (pointer and enable state [enable state will be disabled at exit])
|
||||
* - array buffer binding (will be 0)
|
||||
* - active texture (will be 0)
|
||||
* - texture 0 binding
|
||||
*/
|
||||
void BlitTextureImage(gl::TextureImage *aSrc, const gfx::IntRect& aSrcRect,
|
||||
gl::TextureImage *aDst, const gfx::IntRect& aDstRect);
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GLBLITTEXTUREIMAGEHELPER_H_
|
||||
70
gfx/layers/opengl/GLManager.cpp
Normal file
70
gfx/layers/opengl/GLManager.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GLManager.h"
|
||||
#include "CompositorOGL.h" // for CompositorOGL
|
||||
#include "GLContext.h" // for GLContext
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/layers/Compositor.h" // for Compositor
|
||||
#include "mozilla/layers/LayerManagerComposite.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/mozalloc.h" // for operator new, etc
|
||||
|
||||
using namespace mozilla::gl;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class GLManagerCompositor : public GLManager
|
||||
{
|
||||
public:
|
||||
explicit GLManagerCompositor(CompositorOGL* aCompositor)
|
||||
: mImpl(aCompositor)
|
||||
{}
|
||||
|
||||
virtual GLContext* gl() const override
|
||||
{
|
||||
return mImpl->gl();
|
||||
}
|
||||
|
||||
virtual void ActivateProgram(ShaderProgramOGL *aProg) override
|
||||
{
|
||||
mImpl->ActivateProgram(aProg);
|
||||
}
|
||||
|
||||
virtual ShaderProgramOGL* GetProgram(GLenum aTarget, gfx::SurfaceFormat aFormat) override
|
||||
{
|
||||
ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(aTarget, aFormat);
|
||||
return mImpl->GetShaderProgramFor(config);
|
||||
}
|
||||
|
||||
virtual const gfx::Matrix4x4& GetProjMatrix() const override
|
||||
{
|
||||
return mImpl->GetProjMatrix();
|
||||
}
|
||||
|
||||
virtual void BindAndDrawQuad(ShaderProgramOGL *aProg,
|
||||
const gfx::Rect& aLayerRect,
|
||||
const gfx::Rect& aTextureRect) override
|
||||
{
|
||||
mImpl->BindAndDrawQuad(aProg, aLayerRect, aTextureRect);
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<CompositorOGL> mImpl;
|
||||
};
|
||||
|
||||
/* static */ GLManager*
|
||||
GLManager::CreateGLManager(LayerManagerComposite* aManager)
|
||||
{
|
||||
if (aManager && aManager->GetCompositor()->GetBackendType() == LayersBackend::LAYERS_OPENGL) {
|
||||
return new GLManagerCompositor(aManager->GetCompositor()->AsCompositorOGL());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
44
gfx/layers/opengl/GLManager.h
Normal file
44
gfx/layers/opengl/GLManager.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_GLMANAGER_H
|
||||
#define MOZILLA_GFX_GLMANAGER_H
|
||||
|
||||
#include "mozilla/gfx/Types.h" // for SurfaceFormat
|
||||
#include "OGLShaderProgram.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
} // namespace gl
|
||||
|
||||
namespace layers {
|
||||
|
||||
class LayerManagerComposite;
|
||||
|
||||
/**
|
||||
* Minimal interface to allow widgets to draw using OpenGL. Abstracts
|
||||
* CompositorOGL. Call CreateGLManager with a LayerManagerComposite
|
||||
* backed by a CompositorOGL.
|
||||
*/
|
||||
class GLManager
|
||||
{
|
||||
public:
|
||||
static GLManager* CreateGLManager(LayerManagerComposite* aManager);
|
||||
|
||||
virtual ~GLManager() {}
|
||||
|
||||
virtual gl::GLContext* gl() const = 0;
|
||||
virtual ShaderProgramOGL* GetProgram(GLenum aTarget, gfx::SurfaceFormat aFormat) = 0;
|
||||
virtual void ActivateProgram(ShaderProgramOGL* aPrg) = 0;
|
||||
virtual const gfx::Matrix4x4& GetProjMatrix() const = 0;
|
||||
virtual void BindAndDrawQuad(ShaderProgramOGL *aProg, const gfx::Rect& aLayerRect,
|
||||
const gfx::Rect& aTextureRect) = 0;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
140
gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
Normal file
140
gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MacIOSurfaceTextureClientOGL.h"
|
||||
#include "mozilla/gfx/MacIOSurface.h"
|
||||
#include "MacIOSurfaceHelpers.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace gfx;
|
||||
|
||||
MacIOSurfaceTextureData::MacIOSurfaceTextureData(MacIOSurface* aSurface,
|
||||
BackendType aBackend)
|
||||
: mSurface(aSurface)
|
||||
, mBackend(aBackend)
|
||||
{
|
||||
MOZ_ASSERT(mSurface);
|
||||
}
|
||||
|
||||
MacIOSurfaceTextureData::~MacIOSurfaceTextureData()
|
||||
{}
|
||||
|
||||
// static
|
||||
MacIOSurfaceTextureData*
|
||||
MacIOSurfaceTextureData::Create(MacIOSurface* aSurface, BackendType aBackend)
|
||||
{
|
||||
MOZ_ASSERT(aSurface);
|
||||
if (!aSurface) {
|
||||
return nullptr;
|
||||
}
|
||||
return new MacIOSurfaceTextureData(aSurface, aBackend);
|
||||
}
|
||||
|
||||
MacIOSurfaceTextureData*
|
||||
MacIOSurfaceTextureData::Create(const IntSize& aSize,
|
||||
SurfaceFormat aFormat,
|
||||
BackendType aBackend)
|
||||
{
|
||||
if (aFormat != SurfaceFormat::B8G8R8A8 &&
|
||||
aFormat != SurfaceFormat::B8G8R8X8) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<MacIOSurface> surf = MacIOSurface::CreateIOSurface(aSize.width, aSize.height,
|
||||
1.0,
|
||||
aFormat == SurfaceFormat::B8G8R8A8);
|
||||
if (!surf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return Create(surf, aBackend);
|
||||
}
|
||||
|
||||
bool
|
||||
MacIOSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
aOutDescriptor = SurfaceDescriptorMacIOSurface(mSurface->GetIOSurfaceID(),
|
||||
mSurface->GetContentsScaleFactor(),
|
||||
!mSurface->HasAlpha());
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MacIOSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const
|
||||
{
|
||||
aInfo.size = gfx::IntSize(mSurface->GetDevicePixelWidth(), mSurface->GetDevicePixelHeight());
|
||||
aInfo.format = mSurface->HasAlpha() ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8;
|
||||
aInfo.hasIntermediateBuffer = false;
|
||||
aInfo.hasSynchronization = false;
|
||||
aInfo.supportsMoz2D = true;
|
||||
aInfo.canExposeMappedData = false;
|
||||
}
|
||||
|
||||
bool
|
||||
MacIOSurfaceTextureData::Lock(OpenMode)
|
||||
{
|
||||
mSurface->Lock(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MacIOSurfaceTextureData::Unlock()
|
||||
{
|
||||
mSurface->Unlock(false);
|
||||
}
|
||||
|
||||
already_AddRefed<DataSourceSurface>
|
||||
MacIOSurfaceTextureData::GetAsSurface()
|
||||
{
|
||||
RefPtr<SourceSurface> surf = CreateSourceSurfaceFromMacIOSurface(mSurface);
|
||||
return surf->GetDataSurface();
|
||||
}
|
||||
|
||||
already_AddRefed<DrawTarget>
|
||||
MacIOSurfaceTextureData::BorrowDrawTarget()
|
||||
{
|
||||
MOZ_ASSERT(mBackend != BackendType::NONE);
|
||||
if (mBackend == BackendType::NONE) {
|
||||
// shouldn't happen, but degrade gracefully
|
||||
return nullptr;
|
||||
}
|
||||
return Factory::CreateDrawTargetForData(
|
||||
mBackend,
|
||||
(unsigned char*)mSurface->GetBaseAddress(),
|
||||
IntSize(mSurface->GetWidth(), mSurface->GetHeight()),
|
||||
mSurface->GetBytesPerRow(),
|
||||
mSurface->HasAlpha() ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8,
|
||||
true);
|
||||
}
|
||||
|
||||
void
|
||||
MacIOSurfaceTextureData::Deallocate(LayersIPCChannel*)
|
||||
{
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
MacIOSurfaceTextureData::Forget(LayersIPCChannel*)
|
||||
{
|
||||
mSurface = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
MacIOSurfaceTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
||||
{
|
||||
RefPtr<DrawTarget> dt = BorrowDrawTarget();
|
||||
if (!dt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dt->CopySurface(aSurface, IntRect(IntPoint(), aSurface->GetSize()), IntPoint());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
58
gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
Normal file
58
gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_MACIOSURFACETEXTURECLIENTOGL_H
|
||||
#define MOZILLA_GFX_MACIOSURFACETEXTURECLIENTOGL_H
|
||||
|
||||
#include "mozilla/layers/TextureClientOGL.h"
|
||||
|
||||
class MacIOSurface;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class MacIOSurfaceTextureData : public TextureData
|
||||
{
|
||||
public:
|
||||
static MacIOSurfaceTextureData* Create(MacIOSurface* aSurface,
|
||||
gfx::BackendType aBackend);
|
||||
|
||||
static MacIOSurfaceTextureData*
|
||||
Create(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend);
|
||||
|
||||
~MacIOSurfaceTextureData();
|
||||
|
||||
virtual void FillInfo(TextureData::Info& aInfo) const override;
|
||||
|
||||
virtual bool Lock(OpenMode) override;
|
||||
|
||||
virtual void Unlock() override;
|
||||
|
||||
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
|
||||
|
||||
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
|
||||
|
||||
virtual void Deallocate(LayersIPCChannel*) override;
|
||||
|
||||
virtual void Forget(LayersIPCChannel*) override;
|
||||
|
||||
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
|
||||
|
||||
// For debugging purposes only.
|
||||
already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
|
||||
|
||||
protected:
|
||||
MacIOSurfaceTextureData(MacIOSurface* aSurface,
|
||||
gfx::BackendType aBackend);
|
||||
|
||||
RefPtr<MacIOSurface> mSurface;
|
||||
gfx::BackendType mBackend;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZILLA_GFX_MACIOSURFACETEXTURECLIENTOGL_H
|
||||
172
gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
Normal file
172
gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MacIOSurfaceTextureHostOGL.h"
|
||||
#include "mozilla/gfx/MacIOSurface.h"
|
||||
#include "GLContextCGL.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
MacIOSurfaceTextureHostOGL::MacIOSurfaceTextureHostOGL(TextureFlags aFlags,
|
||||
const SurfaceDescriptorMacIOSurface& aDescriptor)
|
||||
: TextureHost(aFlags)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MacIOSurfaceTextureHostOGL);
|
||||
mSurface = MacIOSurface::LookupSurface(aDescriptor.surfaceId(),
|
||||
aDescriptor.scaleFactor(),
|
||||
!aDescriptor.isOpaque());
|
||||
}
|
||||
|
||||
MacIOSurfaceTextureHostOGL::~MacIOSurfaceTextureHostOGL()
|
||||
{
|
||||
MOZ_COUNT_DTOR(MacIOSurfaceTextureHostOGL);
|
||||
}
|
||||
|
||||
GLTextureSource*
|
||||
MacIOSurfaceTextureHostOGL::CreateTextureSourceForPlane(size_t aPlane)
|
||||
{
|
||||
GLuint textureHandle;
|
||||
gl::GLContext* gl = mCompositor->gl();
|
||||
gl->fGenTextures(1, &textureHandle);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textureHandle);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
mSurface->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(gl)->GetCGLContext(), aPlane);
|
||||
|
||||
return new GLTextureSource(mCompositor, textureHandle, LOCAL_GL_TEXTURE_RECTANGLE_ARB,
|
||||
gfx::IntSize(mSurface->GetDevicePixelWidth(aPlane),
|
||||
mSurface->GetDevicePixelHeight(aPlane)),
|
||||
// XXX: This isn't really correct (but isn't used), we should be using the
|
||||
// format of the individual plane, not of the whole buffer.
|
||||
mSurface->GetFormat());
|
||||
}
|
||||
|
||||
bool
|
||||
MacIOSurfaceTextureHostOGL::Lock()
|
||||
{
|
||||
if (!gl() || !gl()->MakeCurrent() || !mSurface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mTextureSource) {
|
||||
mTextureSource = CreateTextureSourceForPlane(0);
|
||||
|
||||
RefPtr<TextureSource> prev = mTextureSource;
|
||||
for (size_t i = 1; i < mSurface->GetPlaneCount(); i++) {
|
||||
RefPtr<TextureSource> next = CreateTextureSourceForPlane(i);
|
||||
prev->SetNextSibling(next);
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MacIOSurfaceTextureHostOGL::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* glCompositor = AssertGLCompositor(aCompositor);
|
||||
if (!glCompositor) {
|
||||
mTextureSource = nullptr;
|
||||
mCompositor = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCompositor != glCompositor) {
|
||||
// Cannot share GL texture identifiers across compositors.
|
||||
mTextureSource = nullptr;
|
||||
}
|
||||
mCompositor = glCompositor;
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
MacIOSurfaceTextureHostOGL::GetFormat() const {
|
||||
return mSurface->GetFormat();
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
MacIOSurfaceTextureHostOGL::GetReadFormat() const {
|
||||
return mSurface->GetReadFormat();
|
||||
}
|
||||
|
||||
gfx::IntSize
|
||||
MacIOSurfaceTextureHostOGL::GetSize() const {
|
||||
if (!mSurface) {
|
||||
return gfx::IntSize();
|
||||
}
|
||||
return gfx::IntSize(mSurface->GetDevicePixelWidth(),
|
||||
mSurface->GetDevicePixelHeight());
|
||||
}
|
||||
|
||||
gl::GLContext*
|
||||
MacIOSurfaceTextureHostOGL::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
MacIOSurfaceTextureSourceOGL::MacIOSurfaceTextureSourceOGL(
|
||||
CompositorOGL* aCompositor,
|
||||
MacIOSurface* aSurface)
|
||||
: mCompositor(aCompositor)
|
||||
, mSurface(aSurface)
|
||||
{
|
||||
MOZ_ASSERT(aCompositor);
|
||||
MOZ_COUNT_CTOR(MacIOSurfaceTextureSourceOGL);
|
||||
}
|
||||
|
||||
MacIOSurfaceTextureSourceOGL::~MacIOSurfaceTextureSourceOGL()
|
||||
{
|
||||
MOZ_COUNT_DTOR(MacIOSurfaceTextureSourceOGL);
|
||||
}
|
||||
|
||||
gfx::IntSize
|
||||
MacIOSurfaceTextureSourceOGL::GetSize() const
|
||||
{
|
||||
return gfx::IntSize(mSurface->GetDevicePixelWidth(),
|
||||
mSurface->GetDevicePixelHeight());
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
MacIOSurfaceTextureSourceOGL::GetFormat() const
|
||||
{
|
||||
return mSurface->HasAlpha() ? gfx::SurfaceFormat::R8G8B8A8
|
||||
: gfx::SurfaceFormat::R8G8B8X8;
|
||||
}
|
||||
|
||||
void
|
||||
MacIOSurfaceTextureSourceOGL::BindTexture(GLenum aTextureUnit,
|
||||
gfx::SamplingFilter aSamplingFilter)
|
||||
{
|
||||
gl::GLContext* gl = this->gl();
|
||||
if (!gl || !gl->MakeCurrent()) {
|
||||
NS_WARNING("Trying to bind a texture without a working GLContext");
|
||||
return;
|
||||
}
|
||||
GLuint tex = mCompositor->GetTemporaryTexture(GetTextureTarget(), aTextureUnit);
|
||||
|
||||
gl->fActiveTexture(aTextureUnit);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, tex);
|
||||
mSurface->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(gl)->GetCGLContext());
|
||||
ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
|
||||
}
|
||||
|
||||
void
|
||||
MacIOSurfaceTextureSourceOGL::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
mCompositor = AssertGLCompositor(aCompositor);
|
||||
if (mCompositor && mNextSibling) {
|
||||
mNextSibling->SetCompositor(aCompositor);
|
||||
}
|
||||
}
|
||||
|
||||
gl::GLContext*
|
||||
MacIOSurfaceTextureSourceOGL::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
114
gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h
Normal file
114
gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_MACIOSURFACETEXTUREHOSTOGL_H
|
||||
#define MOZILLA_GFX_MACIOSURFACETEXTUREHOSTOGL_H
|
||||
|
||||
#include "mozilla/layers/CompositorOGL.h"
|
||||
#include "mozilla/layers/TextureHostOGL.h"
|
||||
|
||||
class MacIOSurface;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* A texture source meant for use with MacIOSurfaceTextureHostOGL.
|
||||
*
|
||||
* It does not own any GL texture, and attaches its shared handle to one of
|
||||
* the compositor's temporary textures when binding.
|
||||
*/
|
||||
class MacIOSurfaceTextureSourceOGL : public TextureSource
|
||||
, public TextureSourceOGL
|
||||
{
|
||||
public:
|
||||
MacIOSurfaceTextureSourceOGL(CompositorOGL* aCompositor,
|
||||
MacIOSurface* aSurface);
|
||||
virtual ~MacIOSurfaceTextureSourceOGL();
|
||||
|
||||
virtual const char* Name() const override { return "MacIOSurfaceTextureSourceOGL"; }
|
||||
|
||||
virtual TextureSourceOGL* AsSourceOGL() override { return this; }
|
||||
|
||||
virtual void BindTexture(GLenum activetex,
|
||||
gfx::SamplingFilter aSamplingFilter) override;
|
||||
|
||||
virtual bool IsValid() const override { return !!gl(); }
|
||||
|
||||
virtual gfx::IntSize GetSize() const override;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual GLenum GetTextureTarget() const override { return LOCAL_GL_TEXTURE_RECTANGLE_ARB; }
|
||||
|
||||
virtual GLenum GetWrapMode() const override { return LOCAL_GL_CLAMP_TO_EDGE; }
|
||||
|
||||
// MacIOSurfaceTextureSourceOGL doesn't own any gl texture
|
||||
virtual void DeallocateDeviceData() override {}
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
protected:
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<MacIOSurface> mSurface;
|
||||
};
|
||||
|
||||
/**
|
||||
* A TextureHost for shared MacIOSurface
|
||||
*
|
||||
* Most of the logic actually happens in MacIOSurfaceTextureSourceOGL.
|
||||
*/
|
||||
class MacIOSurfaceTextureHostOGL : public TextureHost
|
||||
{
|
||||
public:
|
||||
MacIOSurfaceTextureHostOGL(TextureFlags aFlags,
|
||||
const SurfaceDescriptorMacIOSurface& aDescriptor);
|
||||
virtual ~MacIOSurfaceTextureHostOGL();
|
||||
|
||||
// MacIOSurfaceTextureSourceOGL doesn't own any GL texture
|
||||
virtual void DeallocateDeviceData() override {}
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
virtual Compositor* GetCompositor() override { return mCompositor; }
|
||||
|
||||
virtual bool Lock() override;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
virtual gfx::SurfaceFormat GetReadFormat() const override;
|
||||
|
||||
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override
|
||||
{
|
||||
aTexture = mTextureSource;
|
||||
return !!aTexture;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
|
||||
{
|
||||
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
|
||||
}
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override;
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
virtual const char* Name() override { return "MacIOSurfaceTextureHostOGL"; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
GLTextureSource* CreateTextureSourceForPlane(size_t aPlane);
|
||||
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<GLTextureSource> mTextureSource;
|
||||
RefPtr<MacIOSurface> mSurface;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZILLA_GFX_MACIOSURFACETEXTUREHOSTOGL_H
|
||||
974
gfx/layers/opengl/OGLShaderProgram.cpp
Normal file
974
gfx/layers/opengl/OGLShaderProgram.cpp
Normal file
|
|
@ -0,0 +1,974 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "OGLShaderProgram.h"
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include <sstream> // for ostringstream
|
||||
#include "gfxEnv.h"
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfxUtils.h"
|
||||
#include "mozilla/DebugOnly.h" // for DebugOnly
|
||||
#include "mozilla/layers/Compositor.h" // for BlendOpIsMixBlendMode
|
||||
#include "nsAString.h"
|
||||
#include "nsString.h" // for nsAutoCString
|
||||
#include "Layers.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define GAUSSIAN_KERNEL_HALF_WIDTH 11
|
||||
#define GAUSSIAN_KERNEL_STEP 0.2
|
||||
|
||||
void
|
||||
AddUniforms(ProgramProfileOGL& aProfile)
|
||||
{
|
||||
// This needs to be kept in sync with the KnownUniformName enum
|
||||
static const char *sKnownUniformNames[] = {
|
||||
"uLayerTransform",
|
||||
"uLayerTransformInverse",
|
||||
"uMaskTransform",
|
||||
"uBackdropTransform",
|
||||
"uLayerRects",
|
||||
"uMatrixProj",
|
||||
"uTextureTransform",
|
||||
"uTextureRects",
|
||||
"uRenderTargetOffset",
|
||||
"uLayerOpacity",
|
||||
"uTexture",
|
||||
"uYTexture",
|
||||
"uCbTexture",
|
||||
"uCrTexture",
|
||||
"uBlackTexture",
|
||||
"uWhiteTexture",
|
||||
"uMaskTexture",
|
||||
"uBackdropTexture",
|
||||
"uRenderColor",
|
||||
"uTexCoordMultiplier",
|
||||
"uCbCrTexCoordMultiplier",
|
||||
"uTexturePass2",
|
||||
"uColorMatrix",
|
||||
"uColorMatrixVector",
|
||||
"uBlurRadius",
|
||||
"uBlurOffset",
|
||||
"uBlurAlpha",
|
||||
"uBlurGaussianKernel",
|
||||
"uSSEdges",
|
||||
"uViewportSize",
|
||||
"uVisibleCenter",
|
||||
"uYuvColorMatrix",
|
||||
nullptr
|
||||
};
|
||||
|
||||
for (int i = 0; sKnownUniformNames[i] != nullptr; ++i) {
|
||||
aProfile.mUniforms[i].mNameString = sKnownUniformNames[i];
|
||||
aProfile.mUniforms[i].mName = (KnownUniform::KnownUniformName) i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetRenderColor(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_RENDER_COLOR, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetTextureTarget(GLenum aTarget)
|
||||
{
|
||||
SetFeature(ENABLE_TEXTURE_EXTERNAL | ENABLE_TEXTURE_RECT, false);
|
||||
switch (aTarget) {
|
||||
case LOCAL_GL_TEXTURE_EXTERNAL:
|
||||
SetFeature(ENABLE_TEXTURE_EXTERNAL, true);
|
||||
break;
|
||||
case LOCAL_GL_TEXTURE_RECTANGLE_ARB:
|
||||
SetFeature(ENABLE_TEXTURE_RECT, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetRBSwap(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_TEXTURE_RB_SWAP, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetNoAlpha(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_TEXTURE_NO_ALPHA, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetOpacity(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_OPACITY, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetYCbCr(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_TEXTURE_YCBCR, aEnabled);
|
||||
MOZ_ASSERT(!(mFeatures & ENABLE_TEXTURE_NV12));
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetNV12(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_TEXTURE_NV12, aEnabled);
|
||||
MOZ_ASSERT(!(mFeatures & ENABLE_TEXTURE_YCBCR));
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetComponentAlpha(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_TEXTURE_COMPONENT_ALPHA, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetColorMatrix(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_COLOR_MATRIX, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetBlur(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_BLUR, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetMask(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_MASK, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetNoPremultipliedAlpha()
|
||||
{
|
||||
SetFeature(ENABLE_NO_PREMUL_ALPHA, true);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetDEAA(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_DEAA, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetCompositionOp(gfx::CompositionOp aOp)
|
||||
{
|
||||
mCompositionOp = aOp;
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetDynamicGeometry(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_DYNAMIC_GEOMETRY, aEnabled);
|
||||
}
|
||||
|
||||
/* static */ ProgramProfileOGL
|
||||
ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
||||
{
|
||||
ProgramProfileOGL result;
|
||||
ostringstream fs, vs;
|
||||
|
||||
AddUniforms(result);
|
||||
|
||||
gfx::CompositionOp blendOp = aConfig.mCompositionOp;
|
||||
|
||||
vs << "#ifdef GL_ES" << endl;
|
||||
vs << "#define EDGE_PRECISION mediump" << endl;
|
||||
vs << "#else" << endl;
|
||||
vs << "#define EDGE_PRECISION" << endl;
|
||||
vs << "#endif" << endl;
|
||||
vs << "uniform mat4 uMatrixProj;" << endl;
|
||||
vs << "uniform vec4 uLayerRects[4];" << endl;
|
||||
vs << "uniform mat4 uLayerTransform;" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
vs << "uniform mat4 uLayerTransformInverse;" << endl;
|
||||
vs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl;
|
||||
vs << "uniform vec2 uVisibleCenter;" << endl;
|
||||
vs << "uniform vec2 uViewportSize;" << endl;
|
||||
}
|
||||
vs << "uniform vec2 uRenderTargetOffset;" << endl;
|
||||
vs << "attribute vec4 aCoord;" << endl;
|
||||
result.mAttributes.AppendElement(Pair<nsCString, GLuint> {"aCoord", 0});
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
vs << "uniform mat4 uTextureTransform;" << endl;
|
||||
vs << "uniform vec4 uTextureRects[4];" << endl;
|
||||
vs << "varying vec2 vTexCoord;" << endl;
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) {
|
||||
vs << "attribute vec2 aTexCoord;" << endl;
|
||||
result.mAttributes.AppendElement(Pair<nsCString, GLuint> {"aTexCoord", 1});
|
||||
}
|
||||
}
|
||||
|
||||
if (BlendOpIsMixBlendMode(blendOp)) {
|
||||
vs << "uniform mat4 uBackdropTransform;" << endl;
|
||||
vs << "varying vec2 vBackdropCoord;" << endl;
|
||||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_MASK) {
|
||||
vs << "uniform mat4 uMaskTransform;" << endl;
|
||||
vs << "varying vec3 vMaskCoord;" << endl;
|
||||
}
|
||||
|
||||
vs << "void main() {" << endl;
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) {
|
||||
vs << " vec4 finalPosition = vec4(aCoord.xy, 0.0, 1.0);" << endl;
|
||||
} else {
|
||||
vs << " int vertexID = int(aCoord.w);" << endl;
|
||||
vs << " vec4 layerRect = uLayerRects[vertexID];" << endl;
|
||||
vs << " vec4 finalPosition = vec4(aCoord.xy * layerRect.zw + layerRect.xy, 0.0, 1.0);" << endl;
|
||||
}
|
||||
|
||||
vs << " finalPosition = uLayerTransform * finalPosition;" << endl;
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
// XXX kip - The DEAA shader could be made simpler if we switch to
|
||||
// using dynamic vertex buffers instead of sending everything
|
||||
// in through uniforms. This would enable passing information
|
||||
// about how to dilate each vertex explicitly and eliminate the
|
||||
// need to extrapolate this with the sub-pixel coverage
|
||||
// calculation in the vertex shader.
|
||||
|
||||
// Calculate the screen space position of this vertex, in screen pixels
|
||||
vs << " vec4 ssPos = finalPosition;" << endl;
|
||||
vs << " ssPos.xy -= uRenderTargetOffset * finalPosition.w;" << endl;
|
||||
vs << " ssPos = uMatrixProj * ssPos;" << endl;
|
||||
vs << " ssPos.xy = ((ssPos.xy/ssPos.w)*0.5+0.5)*uViewportSize;" << endl;
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_MASK ||
|
||||
!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
vs << " vec4 coordAdjusted;" << endl;
|
||||
vs << " coordAdjusted.xy = aCoord.xy;" << endl;
|
||||
}
|
||||
|
||||
// It is necessary to dilate edges away from uVisibleCenter to ensure that
|
||||
// fragments with less than 50% sub-pixel coverage will be shaded.
|
||||
// This offset is applied when the sub-pixel coverage of the vertex is
|
||||
// less than 100%. Expanding by 0.5 pixels in screen space is sufficient
|
||||
// to include these pixels.
|
||||
vs << " if (dot(uSSEdges[0], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl;
|
||||
vs << " dot(uSSEdges[1], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl;
|
||||
vs << " dot(uSSEdges[2], vec3(ssPos.xy, 1.0)) < 1.5 ||" << endl;
|
||||
vs << " dot(uSSEdges[3], vec3(ssPos.xy, 1.0)) < 1.5) {" << endl;
|
||||
// If the shader reaches this branch, then this vertex is on the edge of
|
||||
// the layer's visible rect and should be dilated away from the center of
|
||||
// the visible rect. We don't want to hit this for inner facing
|
||||
// edges between tiles, as the pixels may be covered twice without clipping
|
||||
// against uSSEdges. If all edges were dilated, it would result in
|
||||
// artifacts visible within semi-transparent layers with multiple tiles.
|
||||
vs << " vec4 visibleCenter = uLayerTransform * vec4(uVisibleCenter, 0.0, 1.0);" << endl;
|
||||
vs << " vec2 dilateDir = finalPosition.xy / finalPosition.w - visibleCenter.xy / visibleCenter.w;" << endl;
|
||||
vs << " vec2 offset = sign(dilateDir) * 0.5;" << endl;
|
||||
vs << " finalPosition.xy += offset * finalPosition.w;" << endl;
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
// We must adjust the texture coordinates to compensate for the dilation
|
||||
vs << " coordAdjusted = uLayerTransformInverse * finalPosition;" << endl;
|
||||
vs << " coordAdjusted /= coordAdjusted.w;" << endl;
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY)) {
|
||||
vs << " coordAdjusted.xy -= layerRect.xy;" << endl;
|
||||
vs << " coordAdjusted.xy /= layerRect.zw;" << endl;
|
||||
}
|
||||
}
|
||||
vs << " }" << endl;
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) {
|
||||
vs << " vTexCoord = (uTextureTransform * vec4(aTexCoord, 0.0, 1.0)).xy;" << endl;
|
||||
} else {
|
||||
vs << " vec4 textureRect = uTextureRects[vertexID];" << endl;
|
||||
vs << " vec2 texCoord = coordAdjusted.xy * textureRect.zw + textureRect.xy;" << endl;
|
||||
vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" << endl;
|
||||
}
|
||||
}
|
||||
} else if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
if (aConfig.mFeatures & ENABLE_DYNAMIC_GEOMETRY) {
|
||||
vs << " vTexCoord = (uTextureTransform * vec4(aTexCoord, 0.0, 1.0)).xy;" << endl;
|
||||
} else {
|
||||
vs << " vec4 textureRect = uTextureRects[vertexID];" << endl;
|
||||
vs << " vec2 texCoord = aCoord.xy * textureRect.zw + textureRect.xy;" << endl;
|
||||
vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_MASK) {
|
||||
vs << " vMaskCoord.xy = (uMaskTransform * (finalPosition / finalPosition.w)).xy;" << endl;
|
||||
// correct for perspective correct interpolation, see comment in D3D11 shader
|
||||
vs << " vMaskCoord.z = 1.0;" << endl;
|
||||
vs << " vMaskCoord *= finalPosition.w;" << endl;
|
||||
}
|
||||
vs << " finalPosition.xy -= uRenderTargetOffset * finalPosition.w;" << endl;
|
||||
vs << " finalPosition = uMatrixProj * finalPosition;" << endl;
|
||||
if (BlendOpIsMixBlendMode(blendOp)) {
|
||||
// Translate from clip space (-1, 1) to (0..1), apply the backdrop
|
||||
// transform, then invert the y-axis.
|
||||
vs << " vBackdropCoord.x = (finalPosition.x + 1.0) / 2.0;" << endl;
|
||||
vs << " vBackdropCoord.y = 1.0 - (finalPosition.y + 1.0) / 2.0;" << endl;
|
||||
vs << " vBackdropCoord = (uBackdropTransform * vec4(vBackdropCoord.xy, 0.0, 1.0)).xy;" << endl;
|
||||
vs << " vBackdropCoord.y = 1.0 - vBackdropCoord.y;" << endl;
|
||||
}
|
||||
vs << " gl_Position = finalPosition;" << endl;
|
||||
vs << "}" << endl;
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
|
||||
fs << "#extension GL_ARB_texture_rectangle : require" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_EXTERNAL) {
|
||||
fs << "#extension GL_OES_EGL_image_external : require" << endl;
|
||||
}
|
||||
fs << "#ifdef GL_ES" << endl;
|
||||
fs << "precision mediump float;" << endl;
|
||||
fs << "#define COLOR_PRECISION lowp" << endl;
|
||||
fs << "#define EDGE_PRECISION mediump" << endl;
|
||||
fs << "#else" << endl;
|
||||
fs << "#define COLOR_PRECISION" << endl;
|
||||
fs << "#define EDGE_PRECISION" << endl;
|
||||
fs << "#endif" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_RENDER_COLOR) {
|
||||
fs << "uniform COLOR_PRECISION vec4 uRenderColor;" << endl;
|
||||
} else {
|
||||
// for tiling, texcoord can be greater than the lowfp range
|
||||
fs << "varying vec2 vTexCoord;" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_BLUR) {
|
||||
fs << "uniform bool uBlurAlpha;" << endl;
|
||||
fs << "uniform vec2 uBlurRadius;" << endl;
|
||||
fs << "uniform vec2 uBlurOffset;" << endl;
|
||||
fs << "uniform float uBlurGaussianKernel[" << GAUSSIAN_KERNEL_HALF_WIDTH << "];" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_COLOR_MATRIX) {
|
||||
fs << "uniform mat4 uColorMatrix;" << endl;
|
||||
fs << "uniform vec4 uColorMatrixVector;" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_OPACITY) {
|
||||
fs << "uniform COLOR_PRECISION float uLayerOpacity;" << endl;
|
||||
}
|
||||
}
|
||||
if (BlendOpIsMixBlendMode(blendOp)) {
|
||||
fs << "varying vec2 vBackdropCoord;" << endl;
|
||||
}
|
||||
|
||||
const char *sampler2D = "sampler2D";
|
||||
const char *texture2D = "texture2D";
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
|
||||
fs << "uniform vec2 uTexCoordMultiplier;" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR ||
|
||||
aConfig.mFeatures & ENABLE_TEXTURE_NV12) {
|
||||
fs << "uniform vec2 uCbCrTexCoordMultiplier;" << endl;
|
||||
}
|
||||
sampler2D = "sampler2DRect";
|
||||
texture2D = "texture2DRect";
|
||||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_EXTERNAL) {
|
||||
sampler2D = "samplerExternalOES";
|
||||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) {
|
||||
fs << "uniform sampler2D uYTexture;" << endl;
|
||||
fs << "uniform sampler2D uCbTexture;" << endl;
|
||||
fs << "uniform sampler2D uCrTexture;" << endl;
|
||||
fs << "uniform mat3 uYuvColorMatrix;" << endl;
|
||||
} else if (aConfig.mFeatures & ENABLE_TEXTURE_NV12) {
|
||||
fs << "uniform " << sampler2D << " uYTexture;" << endl;
|
||||
fs << "uniform " << sampler2D << " uCbTexture;" << endl;
|
||||
} else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) {
|
||||
fs << "uniform " << sampler2D << " uBlackTexture;" << endl;
|
||||
fs << "uniform " << sampler2D << " uWhiteTexture;" << endl;
|
||||
fs << "uniform bool uTexturePass2;" << endl;
|
||||
} else {
|
||||
fs << "uniform " << sampler2D << " uTexture;" << endl;
|
||||
}
|
||||
|
||||
if (BlendOpIsMixBlendMode(blendOp)) {
|
||||
// Component alpha should be flattened away inside blend containers.
|
||||
MOZ_ASSERT(!(aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA));
|
||||
|
||||
fs << "uniform sampler2D uBackdropTexture;" << endl;
|
||||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_MASK) {
|
||||
fs << "varying vec3 vMaskCoord;" << endl;
|
||||
fs << "uniform sampler2D uMaskTexture;" << endl;
|
||||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
fs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl;
|
||||
}
|
||||
|
||||
if (BlendOpIsMixBlendMode(blendOp)) {
|
||||
BuildMixBlender(aConfig, fs);
|
||||
}
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
fs << "vec4 sample(vec2 coord) {" << endl;
|
||||
fs << " vec4 color;" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR ||
|
||||
aConfig.mFeatures & ENABLE_TEXTURE_NV12) {
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) {
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
|
||||
fs << " COLOR_PRECISION float y = texture2D(uYTexture, coord * uTexCoordMultiplier).r;" << endl;
|
||||
fs << " COLOR_PRECISION float cb = texture2D(uCbTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
|
||||
fs << " COLOR_PRECISION float cr = texture2D(uCrTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
|
||||
} else {
|
||||
fs << " COLOR_PRECISION float y = texture2D(uYTexture, coord).r;" << endl;
|
||||
fs << " COLOR_PRECISION float cb = texture2D(uCbTexture, coord).r;" << endl;
|
||||
fs << " COLOR_PRECISION float cr = texture2D(uCrTexture, coord).r;" << endl;
|
||||
}
|
||||
} else {
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
|
||||
fs << " COLOR_PRECISION float y = " << texture2D << "(uYTexture, coord * uTexCoordMultiplier).r;" << endl;
|
||||
fs << " COLOR_PRECISION float cb = " << texture2D << "(uCbTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
|
||||
fs << " COLOR_PRECISION float cr = " << texture2D << "(uCbTexture, coord * uCbCrTexCoordMultiplier).a;" << endl;
|
||||
} else {
|
||||
fs << " COLOR_PRECISION float y = " << texture2D << "(uYTexture, coord).r;" << endl;
|
||||
fs << " COLOR_PRECISION float cb = " << texture2D << "(uCbTexture, coord).r;" << endl;
|
||||
fs << " COLOR_PRECISION float cr = " << texture2D << "(uCbTexture, coord).a;" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
fs << " y = y - 0.06275;" << endl;
|
||||
fs << " cb = cb - 0.50196;" << endl;
|
||||
fs << " cr = cr - 0.50196;" << endl;
|
||||
fs << " vec3 yuv = vec3(y, cb, cr);" << endl;
|
||||
fs << " color.rgb = uYuvColorMatrix * yuv;" << endl;
|
||||
fs << " color.a = 1.0;" << endl;
|
||||
} else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) {
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
|
||||
fs << " COLOR_PRECISION vec3 onBlack = " << texture2D << "(uBlackTexture, coord * uTexCoordMultiplier).rgb;" << endl;
|
||||
fs << " COLOR_PRECISION vec3 onWhite = " << texture2D << "(uWhiteTexture, coord * uTexCoordMultiplier).rgb;" << endl;
|
||||
} else {
|
||||
fs << " COLOR_PRECISION vec3 onBlack = " << texture2D << "(uBlackTexture, coord).rgb;" << endl;
|
||||
fs << " COLOR_PRECISION vec3 onWhite = " << texture2D << "(uWhiteTexture, coord).rgb;" << endl;
|
||||
}
|
||||
fs << " COLOR_PRECISION vec4 alphas = (1.0 - onWhite + onBlack).rgbg;" << endl;
|
||||
fs << " if (uTexturePass2)" << endl;
|
||||
fs << " color = vec4(onBlack, alphas.a);" << endl;
|
||||
fs << " else" << endl;
|
||||
fs << " color = alphas;" << endl;
|
||||
} else {
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
|
||||
fs << " color = " << texture2D << "(uTexture, coord * uTexCoordMultiplier);" << endl;
|
||||
} else {
|
||||
fs << " color = " << texture2D << "(uTexture, coord);" << endl;
|
||||
}
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_RB_SWAP) {
|
||||
fs << " color = color.bgra;" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_NO_ALPHA) {
|
||||
fs << " color = vec4(color.rgb, 1.0);" << endl;
|
||||
}
|
||||
fs << " return color;" << endl;
|
||||
fs << "}" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_BLUR) {
|
||||
fs << "vec4 sampleAtRadius(vec2 coord, float radius) {" << endl;
|
||||
fs << " coord += uBlurOffset;" << endl;
|
||||
fs << " coord += radius * uBlurRadius;" << endl;
|
||||
fs << " if (coord.x < 0. || coord.y < 0. || coord.x > 1. || coord.y > 1.)" << endl;
|
||||
fs << " return vec4(0, 0, 0, 0);" << endl;
|
||||
fs << " return sample(coord);" << endl;
|
||||
fs << "}" << endl;
|
||||
fs << "vec4 blur(vec4 color, vec2 coord) {" << endl;
|
||||
fs << " vec4 total = color * uBlurGaussianKernel[0];" << endl;
|
||||
fs << " for (int i = 1; i < " << GAUSSIAN_KERNEL_HALF_WIDTH << "; ++i) {" << endl;
|
||||
fs << " float r = float(i) * " << GAUSSIAN_KERNEL_STEP << ";" << endl;
|
||||
fs << " float k = uBlurGaussianKernel[i];" << endl;
|
||||
fs << " total += sampleAtRadius(coord, r) * k;" << endl;
|
||||
fs << " total += sampleAtRadius(coord, -r) * k;" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << " if (uBlurAlpha) {" << endl;
|
||||
fs << " color *= total.a;" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " color = total;" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << " return color;" << endl;
|
||||
fs << "}" << endl;
|
||||
}
|
||||
}
|
||||
fs << "void main() {" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_RENDER_COLOR) {
|
||||
fs << " vec4 color = uRenderColor;" << endl;
|
||||
} else {
|
||||
fs << " vec4 color = sample(vTexCoord);" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_BLUR) {
|
||||
fs << " color = blur(color, vTexCoord);" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_COLOR_MATRIX) {
|
||||
fs << " color = uColorMatrix * vec4(color.rgb / color.a, color.a) + uColorMatrixVector;" << endl;
|
||||
fs << " color.rgb *= color.a;" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_OPACITY) {
|
||||
fs << " color *= uLayerOpacity;" << endl;
|
||||
}
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
// Calculate the sub-pixel coverage of the pixel and modulate its opacity
|
||||
// by that amount to perform DEAA.
|
||||
fs << " vec3 ssPos = vec3(gl_FragCoord.xy, 1.0);" << endl;
|
||||
fs << " float deaaCoverage = clamp(dot(uSSEdges[0], ssPos), 0.0, 1.0);" << endl;
|
||||
fs << " deaaCoverage *= clamp(dot(uSSEdges[1], ssPos), 0.0, 1.0);" << endl;
|
||||
fs << " deaaCoverage *= clamp(dot(uSSEdges[2], ssPos), 0.0, 1.0);" << endl;
|
||||
fs << " deaaCoverage *= clamp(dot(uSSEdges[3], ssPos), 0.0, 1.0);" << endl;
|
||||
fs << " color *= deaaCoverage;" << endl;
|
||||
}
|
||||
if (BlendOpIsMixBlendMode(blendOp)) {
|
||||
fs << " vec4 backdrop = texture2D(uBackdropTexture, vBackdropCoord);" << endl;
|
||||
fs << " color = mixAndBlend(backdrop, color);" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_MASK) {
|
||||
fs << " vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;" << endl;
|
||||
fs << " COLOR_PRECISION float mask = texture2D(uMaskTexture, maskCoords).r;" << endl;
|
||||
fs << " color *= mask;" << endl;
|
||||
} else {
|
||||
fs << " COLOR_PRECISION float mask = 1.0;" << endl;
|
||||
fs << " color *= mask;" << endl;
|
||||
}
|
||||
fs << " gl_FragColor = color;" << endl;
|
||||
fs << "}" << endl;
|
||||
|
||||
result.mVertexShaderString = vs.str();
|
||||
result.mFragmentShaderString = fs.str();
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_RENDER_COLOR) {
|
||||
result.mTextureCount = 0;
|
||||
} else {
|
||||
if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) {
|
||||
result.mTextureCount = 3;
|
||||
} else if (aConfig.mFeatures & ENABLE_TEXTURE_NV12) {
|
||||
result.mTextureCount = 2;
|
||||
} else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) {
|
||||
result.mTextureCount = 2;
|
||||
} else {
|
||||
result.mTextureCount = 1;
|
||||
}
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_MASK) {
|
||||
result.mTextureCount = 1;
|
||||
}
|
||||
if (BlendOpIsMixBlendMode(blendOp)) {
|
||||
result.mTextureCount += 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ProgramProfileOGL::BuildMixBlender(const ShaderConfigOGL& aConfig, std::ostringstream& fs)
|
||||
{
|
||||
// From the "Compositing and Blending Level 1" spec.
|
||||
// Generate helper functions first.
|
||||
switch (aConfig.mCompositionOp) {
|
||||
case gfx::CompositionOp::OP_OVERLAY:
|
||||
case gfx::CompositionOp::OP_HARD_LIGHT:
|
||||
// Note: we substitute (2*src-1) into the screen formula below.
|
||||
fs << "float hardlight(float dest, float src) {" << endl;
|
||||
fs << " if (src <= 0.5) {" << endl;
|
||||
fs << " return dest * (2.0 * src);" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " return 2.0*dest + 2.0*src - 1.0 - 2.0*dest*src;" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << "}" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_COLOR_DODGE:
|
||||
fs << "float dodge(float dest, float src) {" << endl;
|
||||
fs << " if (dest == 0.0) {" << endl;
|
||||
fs << " return 0.0;" << endl;
|
||||
fs << " } else if (src == 1.0) {" << endl;
|
||||
fs << " return 1.0;" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " return min(1.0, dest / (1.0 - src));" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << "}" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_COLOR_BURN:
|
||||
fs << "float burn(float dest, float src) {" << endl;
|
||||
fs << " if (dest == 1.0) {" << endl;
|
||||
fs << " return 1.0;" << endl;
|
||||
fs << " } else if (src == 0.0) {" << endl;
|
||||
fs << " return 0.0;" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " return 1.0 - min(1.0, (1.0 - dest) / src);" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << "}" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_SOFT_LIGHT:
|
||||
fs << "float darken(float dest) {" << endl;
|
||||
fs << " if (dest <= 0.25) {" << endl;
|
||||
fs << " return ((16.0 * dest - 12.0) * dest + 4.0) * dest;" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " return sqrt(dest);" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << "}" << endl;
|
||||
fs << "float softlight(float dest, float src) {" << endl;
|
||||
fs << " if (src <= 0.5) {" << endl;
|
||||
fs << " return dest - (1.0 - 2.0 * src) * dest * (1.0 - dest);" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " return dest + (2.0 * src - 1.0) * (darken(dest) - dest);" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << "}" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_HUE:
|
||||
case gfx::CompositionOp::OP_SATURATION:
|
||||
case gfx::CompositionOp::OP_COLOR:
|
||||
case gfx::CompositionOp::OP_LUMINOSITY:
|
||||
fs << "float Lum(vec3 c) {" << endl;
|
||||
fs << " return dot(vec3(0.3, 0.59, 0.11), c);" << endl;
|
||||
fs << "}" << endl;
|
||||
fs << "vec3 ClipColor(vec3 c) {" << endl;
|
||||
fs << " float L = Lum(c);" << endl;
|
||||
fs << " float n = min(min(c.r, c.g), c.b);" << endl;
|
||||
fs << " float x = max(max(c.r, c.g), c.b);" << endl;
|
||||
fs << " if (n < 0.0) {" << endl;
|
||||
fs << " c = L + (((c - L) * L) / (L - n));" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << " if (x > 1.0) {" << endl;
|
||||
fs << " c = L + (((c - L) * (1.0 - L)) / (x - L));" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << " return c;" << endl;
|
||||
fs << "}" << endl;
|
||||
fs << "vec3 SetLum(vec3 c, float L) {" << endl;
|
||||
fs << " float d = L - Lum(c);" << endl;
|
||||
fs << " return ClipColor(vec3(" << endl;
|
||||
fs << " c.r + d," << endl;
|
||||
fs << " c.g + d," << endl;
|
||||
fs << " c.b + d));" << endl;
|
||||
fs << "}" << endl;
|
||||
fs << "float Sat(vec3 c) {" << endl;
|
||||
fs << " return max(max(c.r, c.g), c.b) - min(min(c.r, c.g), c.b);" << endl;
|
||||
fs << "}" << endl;
|
||||
|
||||
// To use this helper, re-arrange rgb such that r=min, g=mid, and b=max.
|
||||
fs << "vec3 SetSatInner(vec3 c, float s) {" << endl;
|
||||
fs << " if (c.b > c.r) {" << endl;
|
||||
fs << " c.g = (((c.g - c.r) * s) / (c.b - c.r));" << endl;
|
||||
fs << " c.b = s;" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " c.gb = vec2(0.0, 0.0);" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << " return vec3(0.0, c.gb);" << endl;
|
||||
fs << "}" << endl;
|
||||
|
||||
fs << "vec3 SetSat(vec3 c, float s) {" << endl;
|
||||
fs << " if (c.r <= c.g) {" << endl;
|
||||
fs << " if (c.g <= c.b) {" << endl;
|
||||
fs << " c.rgb = SetSatInner(c.rgb, s);" << endl;
|
||||
fs << " } else if (c.r <= c.b) {" << endl;
|
||||
fs << " c.rbg = SetSatInner(c.rbg, s);" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " c.brg = SetSatInner(c.brg, s);" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << " } else if (c.r <= c.b) {" << endl;
|
||||
fs << " c.grb = SetSatInner(c.grb, s);" << endl;
|
||||
fs << " } else if (c.g <= c.b) {" << endl;
|
||||
fs << " c.gbr = SetSatInner(c.gbr, s);" << endl;
|
||||
fs << " } else {" << endl;
|
||||
fs << " c.bgr = SetSatInner(c.bgr, s);" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << " return c;" << endl;
|
||||
fs << "}" << endl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Generate the main blending helper.
|
||||
fs << "vec3 blend(vec3 dest, vec3 src) {" << endl;
|
||||
switch (aConfig.mCompositionOp) {
|
||||
case gfx::CompositionOp::OP_MULTIPLY:
|
||||
fs << " return dest * src;" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_SCREEN:
|
||||
fs << " return dest + src - (dest * src);" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_OVERLAY:
|
||||
fs << " return vec3(" << endl;
|
||||
fs << " hardlight(src.r, dest.r)," << endl;
|
||||
fs << " hardlight(src.g, dest.g)," << endl;
|
||||
fs << " hardlight(src.b, dest.b));" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_DARKEN:
|
||||
fs << " return min(dest, src);" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_LIGHTEN:
|
||||
fs << " return max(dest, src);" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_COLOR_DODGE:
|
||||
fs << " return vec3(" << endl;
|
||||
fs << " dodge(dest.r, src.r)," << endl;
|
||||
fs << " dodge(dest.g, src.g)," << endl;
|
||||
fs << " dodge(dest.b, src.b));" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_COLOR_BURN:
|
||||
fs << " return vec3(" << endl;
|
||||
fs << " burn(dest.r, src.r)," << endl;
|
||||
fs << " burn(dest.g, src.g)," << endl;
|
||||
fs << " burn(dest.b, src.b));" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_HARD_LIGHT:
|
||||
fs << " return vec3(" << endl;
|
||||
fs << " hardlight(dest.r, src.r)," << endl;
|
||||
fs << " hardlight(dest.g, src.g)," << endl;
|
||||
fs << " hardlight(dest.b, src.b));" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_SOFT_LIGHT:
|
||||
fs << " return vec3(" << endl;
|
||||
fs << " softlight(dest.r, src.r)," << endl;
|
||||
fs << " softlight(dest.g, src.g)," << endl;
|
||||
fs << " softlight(dest.b, src.b));" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_DIFFERENCE:
|
||||
fs << " return abs(dest - src);" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_EXCLUSION:
|
||||
fs << " return dest + src - 2.0*dest*src;" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_HUE:
|
||||
fs << " return SetLum(SetSat(src, Sat(dest)), Lum(dest));" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_SATURATION:
|
||||
fs << " return SetLum(SetSat(dest, Sat(src)), Lum(dest));" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_COLOR:
|
||||
fs << " return SetLum(src, Lum(dest));" << endl;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_LUMINOSITY:
|
||||
fs << " return SetLum(dest, Lum(src));" << endl;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unknown blend mode");
|
||||
}
|
||||
fs << "}" << endl;
|
||||
|
||||
// Generate the mix-blend function the fragment shader will call.
|
||||
fs << "vec4 mixAndBlend(vec4 backdrop, vec4 color) {" << endl;
|
||||
|
||||
// Shortcut when the backdrop or source alpha is 0, otherwise we may leak
|
||||
// Infinity into the blend function and return incorrect results.
|
||||
fs << " if (backdrop.a == 0.0) {" << endl;
|
||||
fs << " return color;" << endl;
|
||||
fs << " }" << endl;
|
||||
fs << " if (color.a == 0.0) {" << endl;
|
||||
fs << " return vec4(0.0, 0.0, 0.0, 0.0);" << endl;
|
||||
fs << " }" << endl;
|
||||
|
||||
// The spec assumes there is no premultiplied alpha. The backdrop is always
|
||||
// premultiplied, so undo the premultiply. If the source is premultiplied we
|
||||
// must fix that as well.
|
||||
fs << " backdrop.rgb /= backdrop.a;" << endl;
|
||||
if (!(aConfig.mFeatures & ENABLE_NO_PREMUL_ALPHA)) {
|
||||
fs << " color.rgb /= color.a;" << endl;
|
||||
}
|
||||
fs << " vec3 blended = blend(backdrop.rgb, color.rgb);" << endl;
|
||||
fs << " color.rgb = (1.0 - backdrop.a) * color.rgb + backdrop.a * blended.rgb;" << endl;
|
||||
fs << " color.rgb *= color.a;" << endl;
|
||||
fs << " return color;" << endl;
|
||||
fs << "}" << endl;
|
||||
}
|
||||
|
||||
ShaderProgramOGL::ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile)
|
||||
: mGL(aGL)
|
||||
, mProgram(0)
|
||||
, mProfile(aProfile)
|
||||
, mProgramState(STATE_NEW)
|
||||
{
|
||||
}
|
||||
|
||||
ShaderProgramOGL::~ShaderProgramOGL()
|
||||
{
|
||||
if (mProgram <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<GLContext> ctx = mGL->GetSharedContext();
|
||||
if (!ctx) {
|
||||
ctx = mGL;
|
||||
}
|
||||
ctx->MakeCurrent();
|
||||
ctx->fDeleteProgram(mProgram);
|
||||
}
|
||||
|
||||
bool
|
||||
ShaderProgramOGL::Initialize()
|
||||
{
|
||||
NS_ASSERTION(mProgramState == STATE_NEW, "Shader program has already been initialised");
|
||||
|
||||
ostringstream vs, fs;
|
||||
for (uint32_t i = 0; i < mProfile.mDefines.Length(); ++i) {
|
||||
vs << mProfile.mDefines[i] << endl;
|
||||
fs << mProfile.mDefines[i] << endl;
|
||||
}
|
||||
vs << mProfile.mVertexShaderString << endl;
|
||||
fs << mProfile.mFragmentShaderString << endl;
|
||||
|
||||
if (!CreateProgram(vs.str().c_str(), fs.str().c_str())) {
|
||||
mProgramState = STATE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
mProgramState = STATE_OK;
|
||||
|
||||
for (uint32_t i = 0; i < KnownUniform::KnownUniformCount; ++i) {
|
||||
mProfile.mUniforms[i].mLocation =
|
||||
mGL->fGetUniformLocation(mProgram, mProfile.mUniforms[i].mNameString);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLint
|
||||
ShaderProgramOGL::CreateShader(GLenum aShaderType, const char *aShaderSource)
|
||||
{
|
||||
GLint success, len = 0;
|
||||
|
||||
GLint sh = mGL->fCreateShader(aShaderType);
|
||||
mGL->fShaderSource(sh, 1, (const GLchar**)&aShaderSource, nullptr);
|
||||
mGL->fCompileShader(sh);
|
||||
mGL->fGetShaderiv(sh, LOCAL_GL_COMPILE_STATUS, &success);
|
||||
mGL->fGetShaderiv(sh, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
/* Even if compiling is successful, there may still be warnings. Print them
|
||||
* in a debug build. The > 10 is to catch silly compilers that might put
|
||||
* some whitespace in the log but otherwise leave it empty.
|
||||
*/
|
||||
if (!success
|
||||
#ifdef DEBUG
|
||||
|| (len > 10 && gfxEnv::DebugShaders())
|
||||
#endif
|
||||
)
|
||||
{
|
||||
nsAutoCString log;
|
||||
log.SetCapacity(len);
|
||||
mGL->fGetShaderInfoLog(sh, len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
if (!success) {
|
||||
printf_stderr("=== SHADER COMPILATION FAILED ===\n");
|
||||
} else {
|
||||
printf_stderr("=== SHADER COMPILATION WARNINGS ===\n");
|
||||
}
|
||||
|
||||
printf_stderr("=== Source:\n%s\n", aShaderSource);
|
||||
printf_stderr("=== Log:\n%s\n", log.get());
|
||||
printf_stderr("============\n");
|
||||
|
||||
if (!success) {
|
||||
mGL->fDeleteShader(sh);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sh;
|
||||
}
|
||||
|
||||
bool
|
||||
ShaderProgramOGL::CreateProgram(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString)
|
||||
{
|
||||
GLuint vertexShader = CreateShader(LOCAL_GL_VERTEX_SHADER, aVertexShaderString);
|
||||
GLuint fragmentShader = CreateShader(LOCAL_GL_FRAGMENT_SHADER, aFragmentShaderString);
|
||||
|
||||
if (!vertexShader || !fragmentShader)
|
||||
return false;
|
||||
|
||||
GLint result = mGL->fCreateProgram();
|
||||
mGL->fAttachShader(result, vertexShader);
|
||||
mGL->fAttachShader(result, fragmentShader);
|
||||
|
||||
for (Pair<nsCString, GLuint>& attribute : mProfile.mAttributes) {
|
||||
mGL->fBindAttribLocation(result, attribute.second(),
|
||||
attribute.first().get());
|
||||
}
|
||||
|
||||
mGL->fLinkProgram(result);
|
||||
|
||||
GLint success, len;
|
||||
mGL->fGetProgramiv(result, LOCAL_GL_LINK_STATUS, &success);
|
||||
mGL->fGetProgramiv(result, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
/* Even if linking is successful, there may still be warnings. Print them
|
||||
* in a debug build. The > 10 is to catch silly compilers that might put
|
||||
* some whitespace in the log but otherwise leave it empty.
|
||||
*/
|
||||
if (!success
|
||||
#ifdef DEBUG
|
||||
|| (len > 10 && gfxEnv::DebugShaders())
|
||||
#endif
|
||||
)
|
||||
{
|
||||
nsAutoCString log;
|
||||
log.SetCapacity(len);
|
||||
mGL->fGetProgramInfoLog(result, len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
if (!success) {
|
||||
printf_stderr("=== PROGRAM LINKING FAILED ===\n");
|
||||
} else {
|
||||
printf_stderr("=== PROGRAM LINKING WARNINGS ===\n");
|
||||
}
|
||||
printf_stderr("=== Log:\n%s\n", log.get());
|
||||
printf_stderr("============\n");
|
||||
}
|
||||
|
||||
// We can mark the shaders for deletion; they're attached to the program
|
||||
// and will remain attached.
|
||||
mGL->fDeleteShader(vertexShader);
|
||||
mGL->fDeleteShader(fragmentShader);
|
||||
|
||||
if (!success) {
|
||||
mGL->fDeleteProgram(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
mProgram = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
GLuint
|
||||
ShaderProgramOGL::GetProgram()
|
||||
{
|
||||
if (mProgramState == STATE_NEW) {
|
||||
if (!Initialize()) {
|
||||
NS_WARNING("Shader could not be initialised");
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(HasInitialized(), "Attempting to get a program that's not been initialized!");
|
||||
return mProgram;
|
||||
}
|
||||
|
||||
void
|
||||
ShaderProgramOGL::SetBlurRadius(float aRX, float aRY)
|
||||
{
|
||||
float f[] = {aRX, aRY};
|
||||
SetUniform(KnownUniform::BlurRadius, 2, f);
|
||||
|
||||
float gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
|
||||
float sum = 0.0f;
|
||||
for (int i = 0; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
|
||||
float x = i * GAUSSIAN_KERNEL_STEP;
|
||||
float sigma = 1.0f;
|
||||
gaussianKernel[i] = exp(-x * x / (2 * sigma * sigma)) / sqrt(2 * M_PI * sigma * sigma);
|
||||
sum += gaussianKernel[i] * (i == 0 ? 1 : 2);
|
||||
}
|
||||
for (int i = 0; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
|
||||
gaussianKernel[i] /= sum;
|
||||
}
|
||||
SetArrayUniform(KnownUniform::BlurGaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderProgramOGL::SetYUVColorSpace(YUVColorSpace aYUVColorSpace)
|
||||
{
|
||||
float* yuvToRgb = gfxUtils::Get3x3YuvColorMatrix(aYUVColorSpace);
|
||||
SetMatrix3fvUniform(KnownUniform::YuvColorMatrix, yuvToRgb);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
621
gfx/layers/opengl/OGLShaderProgram.h
Normal file
621
gfx/layers/opengl/OGLShaderProgram.h
Normal file
|
|
@ -0,0 +1,621 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_OGLSHADERPROGRAM_H
|
||||
#define GFX_OGLSHADERPROGRAM_H
|
||||
|
||||
#include "GLContext.h" // for fast inlines of glUniform*
|
||||
#include "gfxTypes.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Pair.h" // for Pair
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
|
||||
#include "mozilla/gfx/Rect.h" // for Rect
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Layer;
|
||||
|
||||
enum ShaderFeatures {
|
||||
ENABLE_RENDER_COLOR=0x01,
|
||||
ENABLE_TEXTURE_RECT=0x02,
|
||||
ENABLE_TEXTURE_EXTERNAL=0x04,
|
||||
ENABLE_TEXTURE_YCBCR=0x08,
|
||||
ENABLE_TEXTURE_NV12=0x10,
|
||||
ENABLE_TEXTURE_COMPONENT_ALPHA=0x20,
|
||||
ENABLE_TEXTURE_NO_ALPHA=0x40,
|
||||
ENABLE_TEXTURE_RB_SWAP=0x80,
|
||||
ENABLE_OPACITY=0x100,
|
||||
ENABLE_BLUR=0x200,
|
||||
ENABLE_COLOR_MATRIX=0x400,
|
||||
ENABLE_MASK=0x800,
|
||||
ENABLE_NO_PREMUL_ALPHA=0x1000,
|
||||
ENABLE_DEAA=0x2000,
|
||||
ENABLE_DYNAMIC_GEOMETRY=0x4000
|
||||
};
|
||||
|
||||
class KnownUniform {
|
||||
public:
|
||||
// this needs to be kept in sync with strings in 'AddUniforms'
|
||||
enum KnownUniformName {
|
||||
NotAKnownUniform = -1,
|
||||
|
||||
LayerTransform = 0,
|
||||
LayerTransformInverse,
|
||||
MaskTransform,
|
||||
BackdropTransform,
|
||||
LayerRects,
|
||||
MatrixProj,
|
||||
TextureTransform,
|
||||
TextureRects,
|
||||
RenderTargetOffset,
|
||||
LayerOpacity,
|
||||
Texture,
|
||||
YTexture,
|
||||
CbTexture,
|
||||
CrTexture,
|
||||
BlackTexture,
|
||||
WhiteTexture,
|
||||
MaskTexture,
|
||||
BackdropTexture,
|
||||
RenderColor,
|
||||
TexCoordMultiplier,
|
||||
CbCrTexCoordMultiplier,
|
||||
TexturePass2,
|
||||
ColorMatrix,
|
||||
ColorMatrixVector,
|
||||
BlurRadius,
|
||||
BlurOffset,
|
||||
BlurAlpha,
|
||||
BlurGaussianKernel,
|
||||
SSEdges,
|
||||
ViewportSize,
|
||||
VisibleCenter,
|
||||
YuvColorMatrix,
|
||||
|
||||
KnownUniformCount
|
||||
};
|
||||
|
||||
KnownUniform()
|
||||
{
|
||||
mName = NotAKnownUniform;
|
||||
mNameString = nullptr;
|
||||
mLocation = -1;
|
||||
memset(&mValue, 0, sizeof(mValue));
|
||||
}
|
||||
|
||||
bool UpdateUniform(int32_t i1) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.i1 != i1) {
|
||||
mValue.i1 = i1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f1 != f1) {
|
||||
mValue.f1 = f1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1, float f2) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f16v[0] != f1 ||
|
||||
mValue.f16v[1] != f2)
|
||||
{
|
||||
mValue.f16v[0] = f1;
|
||||
mValue.f16v[1] = f2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(float f1, float f2, float f3, float f4) {
|
||||
if (mLocation == -1) return false;
|
||||
if (mValue.f16v[0] != f1 ||
|
||||
mValue.f16v[1] != f2 ||
|
||||
mValue.f16v[2] != f3 ||
|
||||
mValue.f16v[3] != f4)
|
||||
{
|
||||
mValue.f16v[0] = f1;
|
||||
mValue.f16v[1] = f2;
|
||||
mValue.f16v[2] = f3;
|
||||
mValue.f16v[3] = f4;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateUniform(int cnt, const float *fp) {
|
||||
if (mLocation == -1) return false;
|
||||
switch (cnt) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 9:
|
||||
case 16:
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_NOTREACHED("cnt must be 1 2 3 4 9 or 16");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateArrayUniform(int cnt, const float *fp) {
|
||||
if (mLocation == -1) return false;
|
||||
if (cnt > 16) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpdateArrayUniform(int cnt, const gfx::Point3D* points) {
|
||||
if (mLocation == -1) return false;
|
||||
if (cnt > 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float fp[12];
|
||||
float *d = fp;
|
||||
for(int i=0; i < cnt; i++) {
|
||||
// Note: Do not want to make assumptions about .x, .y, .z member packing.
|
||||
// If gfx::Point3D is updated to make this guarantee, SIMD optimizations
|
||||
// may be possible
|
||||
*d++ = points[i].x;
|
||||
*d++ = points[i].y;
|
||||
*d++ = points[i].z;
|
||||
}
|
||||
|
||||
if (memcmp(mValue.f16v, fp, sizeof(float) * cnt * 3) != 0) {
|
||||
memcpy(mValue.f16v, fp, sizeof(float) * cnt * 3);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
KnownUniformName mName;
|
||||
const char *mNameString;
|
||||
int32_t mLocation;
|
||||
|
||||
union {
|
||||
int i1;
|
||||
float f1;
|
||||
float f16v[16];
|
||||
} mValue;
|
||||
};
|
||||
|
||||
class ShaderConfigOGL
|
||||
{
|
||||
public:
|
||||
ShaderConfigOGL() :
|
||||
mFeatures(0),
|
||||
mCompositionOp(gfx::CompositionOp::OP_OVER)
|
||||
{}
|
||||
|
||||
void SetRenderColor(bool aEnabled);
|
||||
void SetTextureTarget(GLenum aTarget);
|
||||
void SetRBSwap(bool aEnabled);
|
||||
void SetNoAlpha(bool aEnabled);
|
||||
void SetOpacity(bool aEnabled);
|
||||
void SetYCbCr(bool aEnabled);
|
||||
void SetNV12(bool aEnabled);
|
||||
void SetComponentAlpha(bool aEnabled);
|
||||
void SetColorMatrix(bool aEnabled);
|
||||
void SetBlur(bool aEnabled);
|
||||
void SetMask(bool aEnabled);
|
||||
void SetDEAA(bool aEnabled);
|
||||
void SetCompositionOp(gfx::CompositionOp aOp);
|
||||
void SetNoPremultipliedAlpha();
|
||||
void SetDynamicGeometry(bool aEnabled);
|
||||
|
||||
bool operator< (const ShaderConfigOGL& other) const {
|
||||
return mFeatures < other.mFeatures ||
|
||||
(mFeatures == other.mFeatures &&
|
||||
(int)mCompositionOp < (int)other.mCompositionOp);
|
||||
}
|
||||
|
||||
public:
|
||||
void SetFeature(int aBitmask, bool aState) {
|
||||
if (aState)
|
||||
mFeatures |= aBitmask;
|
||||
else
|
||||
mFeatures &= (~aBitmask);
|
||||
}
|
||||
|
||||
int mFeatures;
|
||||
gfx::CompositionOp mCompositionOp;
|
||||
};
|
||||
|
||||
static inline ShaderConfigOGL
|
||||
ShaderConfigFromTargetAndFormat(GLenum aTarget,
|
||||
gfx::SurfaceFormat aFormat)
|
||||
{
|
||||
ShaderConfigOGL config;
|
||||
config.SetTextureTarget(aTarget);
|
||||
config.SetRBSwap(aFormat == gfx::SurfaceFormat::B8G8R8A8 ||
|
||||
aFormat == gfx::SurfaceFormat::B8G8R8X8);
|
||||
config.SetNoAlpha(aFormat == gfx::SurfaceFormat::B8G8R8X8 ||
|
||||
aFormat == gfx::SurfaceFormat::R8G8B8X8 ||
|
||||
aFormat == gfx::SurfaceFormat::R5G6B5_UINT16);
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* This struct represents the shaders that make up a program and the uniform
|
||||
* and attribute parmeters that those shaders take.
|
||||
* It is used by ShaderProgramOGL.
|
||||
* Use the factory method GetProfileFor to create instances.
|
||||
*/
|
||||
struct ProgramProfileOGL
|
||||
{
|
||||
/**
|
||||
* Factory method; creates an instance of this class for the given
|
||||
* ShaderConfigOGL
|
||||
*/
|
||||
static ProgramProfileOGL GetProfileFor(ShaderConfigOGL aConfig);
|
||||
|
||||
// the source code for the program's shaders
|
||||
std::string mVertexShaderString;
|
||||
std::string mFragmentShaderString;
|
||||
|
||||
// the vertex attributes
|
||||
nsTArray<Pair<nsCString, GLuint>> mAttributes;
|
||||
|
||||
KnownUniform mUniforms[KnownUniform::KnownUniformCount];
|
||||
nsTArray<const char *> mDefines;
|
||||
size_t mTextureCount;
|
||||
|
||||
ProgramProfileOGL() :
|
||||
mTextureCount(0)
|
||||
{}
|
||||
|
||||
private:
|
||||
static void BuildMixBlender(const ShaderConfigOGL& aConfig, std::ostringstream& fs);
|
||||
};
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
#define CHECK_CURRENT_PROGRAM 1
|
||||
#define ASSERT_THIS_PROGRAM \
|
||||
do { \
|
||||
GLuint currentProgram; \
|
||||
mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, ¤tProgram); \
|
||||
MOZ_ASSERT(currentProgram == mProgram, \
|
||||
"SetUniform with wrong program active!"); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ASSERT_THIS_PROGRAM \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Represents an OGL shader program. The details of a program are represented
|
||||
* by a ProgramProfileOGL
|
||||
*/
|
||||
class ShaderProgramOGL
|
||||
{
|
||||
public:
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile);
|
||||
|
||||
~ShaderProgramOGL();
|
||||
|
||||
bool HasInitialized() {
|
||||
NS_ASSERTION(mProgramState != STATE_OK || mProgram > 0, "Inconsistent program state");
|
||||
return mProgramState == STATE_OK;
|
||||
}
|
||||
|
||||
GLuint GetProgram();
|
||||
|
||||
bool Initialize();
|
||||
|
||||
GLint CreateShader(GLenum aShaderType, const char *aShaderSource);
|
||||
|
||||
/**
|
||||
* Creates a program and stores its id.
|
||||
*/
|
||||
bool CreateProgram(const char *aVertexShaderString,
|
||||
const char *aFragmentShaderString);
|
||||
|
||||
/**
|
||||
* The following set of methods set a uniform argument to the shader program.
|
||||
* Not all uniforms may be set for all programs, and such uses will throw
|
||||
* an assertion.
|
||||
*/
|
||||
void SetLayerTransform(const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(KnownUniform::LayerTransform, aMatrix);
|
||||
}
|
||||
|
||||
void SetLayerTransformInverse(const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(KnownUniform::LayerTransformInverse, aMatrix);
|
||||
}
|
||||
|
||||
void SetMaskLayerTransform(const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(KnownUniform::MaskTransform, aMatrix);
|
||||
}
|
||||
|
||||
void SetBackdropTransform(const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(KnownUniform::BackdropTransform, aMatrix);
|
||||
}
|
||||
|
||||
void SetDEAAEdges(const gfx::Point3D* aEdges) {
|
||||
SetArrayUniform(KnownUniform::SSEdges, 4, aEdges);
|
||||
}
|
||||
|
||||
void SetViewportSize(const gfx::IntSize& aSize) {
|
||||
float vals[2] = { (float)aSize.width, (float)aSize.height };
|
||||
SetUniform(KnownUniform::ViewportSize, 2, vals);
|
||||
}
|
||||
|
||||
void SetVisibleCenter(const gfx::Point& aVisibleCenter) {
|
||||
float vals[2] = { aVisibleCenter.x, aVisibleCenter.y };
|
||||
SetUniform(KnownUniform::VisibleCenter, 2, vals);
|
||||
}
|
||||
|
||||
void SetLayerRects(const gfx::Rect* aRects) {
|
||||
float vals[16] = { aRects[0].x, aRects[0].y, aRects[0].width, aRects[0].height,
|
||||
aRects[1].x, aRects[1].y, aRects[1].width, aRects[1].height,
|
||||
aRects[2].x, aRects[2].y, aRects[2].width, aRects[2].height,
|
||||
aRects[3].x, aRects[3].y, aRects[3].width, aRects[3].height };
|
||||
SetUniform(KnownUniform::LayerRects, 16, vals);
|
||||
}
|
||||
|
||||
void SetProjectionMatrix(const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(KnownUniform::MatrixProj, aMatrix);
|
||||
}
|
||||
|
||||
// sets this program's texture transform, if it uses one
|
||||
void SetTextureTransform(const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(KnownUniform::TextureTransform, aMatrix);
|
||||
}
|
||||
|
||||
void SetTextureRects(const gfx::Rect* aRects) {
|
||||
float vals[16] = { aRects[0].x, aRects[0].y, aRects[0].width, aRects[0].height,
|
||||
aRects[1].x, aRects[1].y, aRects[1].width, aRects[1].height,
|
||||
aRects[2].x, aRects[2].y, aRects[2].width, aRects[2].height,
|
||||
aRects[3].x, aRects[3].y, aRects[3].width, aRects[3].height };
|
||||
SetUniform(KnownUniform::TextureRects, 16, vals);
|
||||
}
|
||||
|
||||
void SetRenderOffset(const nsIntPoint& aOffset) {
|
||||
float vals[4] = { float(aOffset.x), float(aOffset.y) };
|
||||
SetUniform(KnownUniform::RenderTargetOffset, 2, vals);
|
||||
}
|
||||
|
||||
void SetRenderOffset(float aX, float aY) {
|
||||
float vals[2] = { aX, aY };
|
||||
SetUniform(KnownUniform::RenderTargetOffset, 2, vals);
|
||||
}
|
||||
|
||||
void SetLayerOpacity(float aOpacity) {
|
||||
SetUniform(KnownUniform::LayerOpacity, aOpacity);
|
||||
}
|
||||
|
||||
void SetTextureUnit(GLint aUnit) {
|
||||
SetUniform(KnownUniform::Texture, aUnit);
|
||||
}
|
||||
void SetYTextureUnit(GLint aUnit) {
|
||||
SetUniform(KnownUniform::YTexture, aUnit);
|
||||
}
|
||||
|
||||
void SetCbTextureUnit(GLint aUnit) {
|
||||
SetUniform(KnownUniform::CbTexture, aUnit);
|
||||
}
|
||||
|
||||
void SetCrTextureUnit(GLint aUnit) {
|
||||
SetUniform(KnownUniform::CrTexture, aUnit);
|
||||
}
|
||||
|
||||
void SetYCbCrTextureUnits(GLint aYUnit, GLint aCbUnit, GLint aCrUnit) {
|
||||
SetUniform(KnownUniform::YTexture, aYUnit);
|
||||
SetUniform(KnownUniform::CbTexture, aCbUnit);
|
||||
SetUniform(KnownUniform::CrTexture, aCrUnit);
|
||||
}
|
||||
|
||||
void SetNV12TextureUnits(GLint aYUnit, GLint aCbCrUnit) {
|
||||
SetUniform(KnownUniform::YTexture, aYUnit);
|
||||
SetUniform(KnownUniform::CbTexture, aCbCrUnit);
|
||||
}
|
||||
|
||||
void SetBlackTextureUnit(GLint aUnit) {
|
||||
SetUniform(KnownUniform::BlackTexture, aUnit);
|
||||
}
|
||||
|
||||
void SetWhiteTextureUnit(GLint aUnit) {
|
||||
SetUniform(KnownUniform::WhiteTexture, aUnit);
|
||||
}
|
||||
|
||||
void SetMaskTextureUnit(GLint aUnit) {
|
||||
SetUniform(KnownUniform::MaskTexture, aUnit);
|
||||
}
|
||||
|
||||
void SetBackdropTextureUnit(GLint aUnit) {
|
||||
SetUniform(KnownUniform::BackdropTexture, aUnit);
|
||||
}
|
||||
|
||||
void SetRenderColor(const gfx::Color& aColor) {
|
||||
SetUniform(KnownUniform::RenderColor, aColor);
|
||||
}
|
||||
|
||||
void SetColorMatrix(const gfx::Matrix5x4& aColorMatrix)
|
||||
{
|
||||
SetMatrixUniform(KnownUniform::ColorMatrix, &aColorMatrix._11);
|
||||
SetUniform(KnownUniform::ColorMatrixVector, 4, &aColorMatrix._51);
|
||||
}
|
||||
|
||||
void SetTexCoordMultiplier(float aWidth, float aHeight) {
|
||||
float f[] = {aWidth, aHeight};
|
||||
SetUniform(KnownUniform::TexCoordMultiplier, 2, f);
|
||||
}
|
||||
|
||||
void SetCbCrTexCoordMultiplier(float aWidth, float aHeight) {
|
||||
float f[] = {aWidth, aHeight};
|
||||
SetUniform(KnownUniform::CbCrTexCoordMultiplier, 2, f);
|
||||
}
|
||||
|
||||
void SetYUVColorSpace(YUVColorSpace aYUVColorSpace);
|
||||
|
||||
// Set whether we want the component alpha shader to return the color
|
||||
// vector (pass 1, false) or the alpha vector (pass2, true). With support
|
||||
// for multiple render targets we wouldn't need two passes here.
|
||||
void SetTexturePass2(bool aFlag) {
|
||||
SetUniform(KnownUniform::TexturePass2, aFlag ? 1 : 0);
|
||||
}
|
||||
|
||||
void SetBlurRadius(float aRX, float aRY);
|
||||
|
||||
void SetBlurAlpha(float aAlpha) {
|
||||
SetUniform(KnownUniform::BlurAlpha, aAlpha);
|
||||
}
|
||||
|
||||
void SetBlurOffset(float aOffsetX, float aOffsetY) {
|
||||
float f[] = {aOffsetX, aOffsetY};
|
||||
SetUniform(KnownUniform::BlurOffset, 2, f);
|
||||
}
|
||||
|
||||
size_t GetTextureCount() const {
|
||||
return mProfile.mTextureCount;
|
||||
}
|
||||
|
||||
protected:
|
||||
RefPtr<GLContext> mGL;
|
||||
// the OpenGL id of the program
|
||||
GLuint mProgram;
|
||||
ProgramProfileOGL mProfile;
|
||||
enum {
|
||||
STATE_NEW,
|
||||
STATE_OK,
|
||||
STATE_ERROR
|
||||
} mProgramState;
|
||||
|
||||
#ifdef CHECK_CURRENT_PROGRAM
|
||||
static int sCurrentProgramKey;
|
||||
#endif
|
||||
|
||||
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, float aFloatValue)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateUniform(aFloatValue)) {
|
||||
mGL->fUniform1f(ku.mLocation, aFloatValue);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, const gfx::Color& aColor) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateUniform(aColor.r, aColor.g, aColor.b, aColor.a)) {
|
||||
mGL->fUniform4fv(ku.mLocation, 1, ku.mValue.f16v);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, int aLength, const float *aFloatValues)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateUniform(aLength, aFloatValues)) {
|
||||
switch (aLength) {
|
||||
case 1: mGL->fUniform1fv(ku.mLocation, 1, ku.mValue.f16v); break;
|
||||
case 2: mGL->fUniform2fv(ku.mLocation, 1, ku.mValue.f16v); break;
|
||||
case 3: mGL->fUniform3fv(ku.mLocation, 1, ku.mValue.f16v); break;
|
||||
case 4: mGL->fUniform4fv(ku.mLocation, 1, ku.mValue.f16v); break;
|
||||
case 16: mGL->fUniform4fv(ku.mLocation, 4, ku.mValue.f16v); break;
|
||||
default:
|
||||
NS_NOTREACHED("Bogus aLength param");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetArrayUniform(KnownUniform::KnownUniformName aKnownUniform, int aLength, float *aFloatValues)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateArrayUniform(aLength, aFloatValues)) {
|
||||
mGL->fUniform1fv(ku.mLocation, aLength, ku.mValue.f16v);
|
||||
}
|
||||
}
|
||||
|
||||
void SetArrayUniform(KnownUniform::KnownUniformName aKnownUniform, int aLength, const gfx::Point3D *aPointValues)
|
||||
{
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateArrayUniform(aLength, aPointValues)) {
|
||||
mGL->fUniform3fv(ku.mLocation, aLength, ku.mValue.f16v);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, GLint aIntValue) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateUniform(aIntValue)) {
|
||||
mGL->fUniform1i(ku.mLocation, aIntValue);
|
||||
}
|
||||
}
|
||||
|
||||
void SetMatrixUniform(KnownUniform::KnownUniformName aKnownUniform, const float *aFloatValues) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateUniform(16, aFloatValues)) {
|
||||
mGL->fUniformMatrix4fv(ku.mLocation, 1, false, ku.mValue.f16v);
|
||||
}
|
||||
}
|
||||
|
||||
void SetMatrix3fvUniform(KnownUniform::KnownUniformName aKnownUniform, const float *aFloatValues) {
|
||||
ASSERT_THIS_PROGRAM;
|
||||
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");
|
||||
|
||||
KnownUniform& ku(mProfile.mUniforms[aKnownUniform]);
|
||||
if (ku.UpdateUniform(9, aFloatValues)) {
|
||||
mGL->fUniformMatrix3fv(ku.mLocation, 1, false, ku.mValue.f16v);
|
||||
}
|
||||
}
|
||||
|
||||
void SetMatrixUniform(KnownUniform::KnownUniformName aKnownUniform, const gfx::Matrix4x4& aMatrix) {
|
||||
SetMatrixUniform(aKnownUniform, &aMatrix._11);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_OGLSHADERPROGRAM_H */
|
||||
136
gfx/layers/opengl/TextureClientOGL.cpp
Normal file
136
gfx/layers/opengl/TextureClientOGL.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GLContext.h" // for GLContext, etc
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "mozilla/layers/TextureClientOGL.h"
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "GLLibraryEGL.h"
|
||||
|
||||
using namespace mozilla::gl;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class CompositableForwarder;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// EGLImage
|
||||
|
||||
EGLImageTextureData::EGLImageTextureData(EGLImageImage* aImage, gfx::IntSize aSize)
|
||||
: mImage(aImage)
|
||||
, mSize(aSize)
|
||||
{
|
||||
MOZ_ASSERT(aImage);
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
EGLImageTextureData::CreateTextureClient(EGLImageImage* aImage, gfx::IntSize aSize,
|
||||
LayersIPCChannel* aAllocator, TextureFlags aFlags)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Can't pass an `EGLImage` between processes.");
|
||||
|
||||
if (!aImage || !XRE_IsParentProcess()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// XXX - This is quite sad and slow.
|
||||
aFlags |= TextureFlags::DEALLOCATE_CLIENT;
|
||||
|
||||
if (aImage->GetOriginPos() == gl::OriginPos::BottomLeft) {
|
||||
aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
|
||||
}
|
||||
|
||||
return TextureClient::CreateWithData(
|
||||
new EGLImageTextureData(aImage, aSize),
|
||||
aFlags, aAllocator
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
EGLImageTextureData::FillInfo(TextureData::Info& aInfo) const
|
||||
{
|
||||
aInfo.size = mSize;
|
||||
aInfo.format = gfx::SurfaceFormat::UNKNOWN;
|
||||
aInfo.hasIntermediateBuffer = false;
|
||||
aInfo.hasSynchronization = false;
|
||||
aInfo.supportsMoz2D = false;
|
||||
aInfo.canExposeMappedData = false;
|
||||
}
|
||||
|
||||
bool
|
||||
EGLImageTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
const bool hasAlpha = true;
|
||||
aOutDescriptor =
|
||||
EGLImageDescriptor((uintptr_t)mImage->GetImage(),
|
||||
(uintptr_t)mImage->GetSync(),
|
||||
mImage->GetSize(), hasAlpha);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// AndroidSurface
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTexture* aSurfTex,
|
||||
gfx::IntSize aSize,
|
||||
gl::OriginPos aOriginPos,
|
||||
LayersIPCChannel* aAllocator,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Can't pass an android surfaces between processes.");
|
||||
|
||||
if (!aSurfTex || !XRE_IsParentProcess()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aOriginPos == gl::OriginPos::BottomLeft) {
|
||||
aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
|
||||
}
|
||||
|
||||
return TextureClient::CreateWithData(
|
||||
new AndroidSurfaceTextureData(aSurfTex, aSize),
|
||||
aFlags, aAllocator
|
||||
);
|
||||
}
|
||||
|
||||
AndroidSurfaceTextureData::AndroidSurfaceTextureData(AndroidSurfaceTexture* aSurfTex,
|
||||
gfx::IntSize aSize)
|
||||
: mSurfTex(aSurfTex)
|
||||
, mSize(aSize)
|
||||
{}
|
||||
|
||||
AndroidSurfaceTextureData::~AndroidSurfaceTextureData()
|
||||
{}
|
||||
|
||||
void
|
||||
AndroidSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const
|
||||
{
|
||||
aInfo.size = mSize;
|
||||
aInfo.format = gfx::SurfaceFormat::UNKNOWN;
|
||||
aInfo.hasIntermediateBuffer = false;
|
||||
aInfo.hasSynchronization = false;
|
||||
aInfo.supportsMoz2D = false;
|
||||
aInfo.canExposeMappedData = false;
|
||||
}
|
||||
|
||||
bool
|
||||
AndroidSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
aOutDescriptor = SurfaceTextureDescriptor((uintptr_t)mSurfTex.get(),
|
||||
mSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
89
gfx/layers/opengl/TextureClientOGL.h
Normal file
89
gfx/layers/opengl/TextureClientOGL.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
// * This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_TEXTURECLIENTOGL_H
|
||||
#define MOZILLA_GFX_TEXTURECLIENTOGL_H
|
||||
|
||||
#include "GLContextTypes.h" // for SharedTextureHandle, etc
|
||||
#include "GLImages.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
|
||||
#include "AndroidSurfaceTexture.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
|
||||
class EGLImageTextureData : public TextureData
|
||||
{
|
||||
public:
|
||||
|
||||
static already_AddRefed<TextureClient>
|
||||
CreateTextureClient(EGLImageImage* aImage, gfx::IntSize aSize,
|
||||
LayersIPCChannel* aAllocator, TextureFlags aFlags);
|
||||
|
||||
virtual void FillInfo(TextureData::Info& aInfo) const override;
|
||||
|
||||
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
|
||||
|
||||
virtual void Deallocate(LayersIPCChannel*) override { mImage = nullptr; }
|
||||
|
||||
virtual void Forget(LayersIPCChannel*) override { mImage = nullptr; }
|
||||
|
||||
// Unused functions.
|
||||
virtual bool Lock(OpenMode) override { return true; }
|
||||
|
||||
virtual void Unlock() override {}
|
||||
|
||||
protected:
|
||||
EGLImageTextureData(EGLImageImage* aImage, gfx::IntSize aSize);
|
||||
|
||||
RefPtr<EGLImageImage> mImage;
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
class AndroidSurfaceTextureData : public TextureData
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<TextureClient>
|
||||
CreateTextureClient(gl::AndroidSurfaceTexture* aSurfTex,
|
||||
gfx::IntSize aSize,
|
||||
gl::OriginPos aOriginPos,
|
||||
LayersIPCChannel* aAllocator,
|
||||
TextureFlags aFlags);
|
||||
|
||||
~AndroidSurfaceTextureData();
|
||||
|
||||
virtual void FillInfo(TextureData::Info& aInfo) const override;
|
||||
|
||||
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
|
||||
|
||||
// Useless functions.
|
||||
virtual bool Lock(OpenMode) override { return true; }
|
||||
|
||||
virtual void Unlock() override {}
|
||||
|
||||
// Our data is always owned externally.
|
||||
virtual void Deallocate(LayersIPCChannel*) override {}
|
||||
|
||||
protected:
|
||||
AndroidSurfaceTextureData(gl::AndroidSurfaceTexture* aSurfTex, gfx::IntSize aSize);
|
||||
|
||||
const RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
771
gfx/layers/opengl/TextureHostOGL.cpp
Normal file
771
gfx/layers/opengl/TextureHostOGL.cpp
Normal file
|
|
@ -0,0 +1,771 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TextureHostOGL.h"
|
||||
|
||||
#include "EGLUtils.h"
|
||||
#include "GLContext.h" // for GLContext, etc
|
||||
#include "GLLibraryEGL.h" // for GLLibraryEGL
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "GLReadTexImageHelper.h"
|
||||
#include "gfx2DGlue.h" // for ContentForFormat, etc
|
||||
#include "mozilla/gfx/2D.h" // for DataSourceSurface
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Logging.h" // for gfxCriticalError
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "AndroidSurfaceTexture.h"
|
||||
#include "GfxTexturesReporter.h" // for GfxTexturesReporter
|
||||
#include "GLBlitTextureImageHelper.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include "mozilla/layers/MacIOSurfaceTextureHostOGL.h"
|
||||
#endif
|
||||
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
#include "mozilla/layers/X11TextureHost.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Compositor;
|
||||
|
||||
already_AddRefed<TextureHost>
|
||||
CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
result = CreateBackendIndependentTextureHost(aDesc,
|
||||
aDeallocator, aFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
case SurfaceDescriptor::TSurfaceTextureDescriptor: {
|
||||
const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
|
||||
result = new SurfaceTextureHost(aFlags,
|
||||
(AndroidSurfaceTexture*)desc.surfTex(),
|
||||
desc.size());
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case SurfaceDescriptor::TEGLImageDescriptor: {
|
||||
const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor();
|
||||
result = new EGLImageTextureHost(aFlags,
|
||||
(EGLImage)desc.image(),
|
||||
(EGLSync)desc.fence(),
|
||||
desc.size(),
|
||||
desc.hasAlpha());
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
|
||||
const SurfaceDescriptorMacIOSurface& desc =
|
||||
aDesc.get_SurfaceDescriptorMacIOSurface();
|
||||
result = new MacIOSurfaceTextureHostOGL(aFlags, desc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
case SurfaceDescriptor::TSurfaceDescriptorX11: {
|
||||
const auto& desc = aDesc.get_SurfaceDescriptorX11();
|
||||
result = new X11TextureHost(aFlags, desc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: {
|
||||
const auto& desc = aDesc.get_SurfaceDescriptorSharedGLTexture();
|
||||
result = new GLTextureHost(aFlags, desc.texture(),
|
||||
desc.target(),
|
||||
(GLsync)desc.fence(),
|
||||
desc.size(),
|
||||
desc.hasAlpha());
|
||||
break;
|
||||
}
|
||||
default: return nullptr;
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
static gl::TextureImage::Flags
|
||||
FlagsToGLFlags(TextureFlags aFlags)
|
||||
{
|
||||
uint32_t result = TextureImage::NoFlags;
|
||||
|
||||
if (aFlags & TextureFlags::USE_NEAREST_FILTER)
|
||||
result |= TextureImage::UseNearestFilter;
|
||||
if (aFlags & TextureFlags::ORIGIN_BOTTOM_LEFT)
|
||||
result |= TextureImage::OriginBottomLeft;
|
||||
if (aFlags & TextureFlags::DISALLOW_BIGIMAGE)
|
||||
result |= TextureImage::DisallowBigImage;
|
||||
|
||||
return static_cast<gl::TextureImage::Flags>(result);
|
||||
}
|
||||
|
||||
bool
|
||||
TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
|
||||
nsIntRegion* aDestRegion,
|
||||
gfx::IntPoint* aSrcOffset)
|
||||
{
|
||||
GLContext *gl = mCompositor->gl();
|
||||
MOZ_ASSERT(gl);
|
||||
if (!gl || !gl->MakeCurrent()) {
|
||||
NS_WARNING("trying to update TextureImageTextureSourceOGL without a GLContext");
|
||||
return false;
|
||||
}
|
||||
if (!aSurface) {
|
||||
gfxCriticalError() << "Invalid surface for OGL update";
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(aSurface);
|
||||
|
||||
IntSize size = aSurface->GetSize();
|
||||
if (!mTexImage ||
|
||||
(mTexImage->GetSize() != size && !aSrcOffset) ||
|
||||
mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) {
|
||||
if (mFlags & TextureFlags::DISALLOW_BIGIMAGE) {
|
||||
GLint maxTextureSize;
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
||||
if (size.width > maxTextureSize || size.height > maxTextureSize) {
|
||||
NS_WARNING("Texture exceeds maximum texture size, refusing upload");
|
||||
return false;
|
||||
}
|
||||
// Explicitly use CreateBasicTextureImage instead of CreateTextureImage,
|
||||
// because CreateTextureImage might still choose to create a tiled
|
||||
// texture image.
|
||||
mTexImage = CreateBasicTextureImage(gl, size,
|
||||
gfx::ContentForFormat(aSurface->GetFormat()),
|
||||
LOCAL_GL_CLAMP_TO_EDGE,
|
||||
FlagsToGLFlags(mFlags));
|
||||
} else {
|
||||
// XXX - clarify which size we want to use. IncrementalContentHost will
|
||||
// require the size of the destination surface to be different from
|
||||
// the size of aSurface.
|
||||
// See bug 893300 (tracks the implementation of ContentHost for new textures).
|
||||
mTexImage = CreateTextureImage(gl,
|
||||
size,
|
||||
gfx::ContentForFormat(aSurface->GetFormat()),
|
||||
LOCAL_GL_CLAMP_TO_EDGE,
|
||||
FlagsToGLFlags(mFlags),
|
||||
SurfaceFormatToImageFormat(aSurface->GetFormat()));
|
||||
}
|
||||
ClearCachedFilter();
|
||||
|
||||
if (aDestRegion &&
|
||||
!aSrcOffset &&
|
||||
!aDestRegion->IsEqual(gfx::IntRect(0, 0, size.width, size.height))) {
|
||||
// UpdateFromDataSource will ignore our specified aDestRegion since the texture
|
||||
// hasn't been allocated with glTexImage2D yet. Call Resize() to force the
|
||||
// allocation (full size, but no upload), and then we'll only upload the pixels
|
||||
// we care about below.
|
||||
mTexImage->Resize(size);
|
||||
}
|
||||
}
|
||||
|
||||
mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageTextureSourceOGL::EnsureBuffer(const IntSize& aSize,
|
||||
gfxContentType aContentType)
|
||||
{
|
||||
if (!mTexImage ||
|
||||
mTexImage->GetSize() != aSize ||
|
||||
mTexImage->GetContentType() != aContentType) {
|
||||
mTexImage = CreateTextureImage(mCompositor->gl(),
|
||||
aSize,
|
||||
aContentType,
|
||||
LOCAL_GL_CLAMP_TO_EDGE,
|
||||
FlagsToGLFlags(mFlags));
|
||||
}
|
||||
mTexImage->Resize(aSize);
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageTextureSourceOGL::CopyTo(const gfx::IntRect& aSourceRect,
|
||||
DataTextureSource *aDest,
|
||||
const gfx::IntRect& aDestRect)
|
||||
{
|
||||
MOZ_ASSERT(aDest->AsSourceOGL(), "Incompatible destination type!");
|
||||
TextureImageTextureSourceOGL *dest =
|
||||
aDest->AsSourceOGL()->AsTextureImageTextureSource();
|
||||
MOZ_ASSERT(dest, "Incompatible destination type!");
|
||||
|
||||
mCompositor->BlitTextureImageHelper()->BlitTextureImage(mTexImage, aSourceRect,
|
||||
dest->mTexImage, aDestRect);
|
||||
dest->mTexImage->MarkValid();
|
||||
}
|
||||
|
||||
CompositorOGL* AssertGLCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* compositor = aCompositor ? aCompositor->AsCompositorOGL()
|
||||
: nullptr;
|
||||
MOZ_ASSERT(!!compositor);
|
||||
return compositor;
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageTextureSourceOGL::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* glCompositor = AssertGLCompositor(aCompositor);
|
||||
if (!glCompositor) {
|
||||
DeallocateDeviceData();
|
||||
return;
|
||||
}
|
||||
if (mCompositor != glCompositor) {
|
||||
DeallocateDeviceData();
|
||||
mCompositor = glCompositor;
|
||||
}
|
||||
}
|
||||
|
||||
gfx::IntSize
|
||||
TextureImageTextureSourceOGL::GetSize() const
|
||||
{
|
||||
if (mTexImage) {
|
||||
if (mIterating) {
|
||||
return mTexImage->GetTileRect().Size();
|
||||
}
|
||||
return mTexImage->GetSize();
|
||||
}
|
||||
NS_WARNING("Trying to query the size of an empty TextureSource.");
|
||||
return gfx::IntSize(0, 0);
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
TextureImageTextureSourceOGL::GetFormat() const
|
||||
{
|
||||
if (mTexImage) {
|
||||
return mTexImage->GetTextureFormat();
|
||||
}
|
||||
NS_WARNING("Trying to query the format of an empty TextureSource.");
|
||||
return gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
|
||||
gfx::IntRect TextureImageTextureSourceOGL::GetTileRect()
|
||||
{
|
||||
return mTexImage->GetTileRect();
|
||||
}
|
||||
|
||||
void
|
||||
TextureImageTextureSourceOGL::BindTexture(GLenum aTextureUnit,
|
||||
gfx::SamplingFilter aSamplingFilter)
|
||||
{
|
||||
MOZ_ASSERT(mTexImage,
|
||||
"Trying to bind a TextureSource that does not have an underlying GL texture.");
|
||||
mTexImage->BindTexture(aTextureUnit);
|
||||
SetSamplingFilter(mCompositor->gl(), aSamplingFilter);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// GLTextureSource
|
||||
|
||||
GLTextureSource::GLTextureSource(CompositorOGL* aCompositor,
|
||||
GLuint aTextureHandle,
|
||||
GLenum aTarget,
|
||||
gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
bool aExternallyOwned)
|
||||
: mCompositor(aCompositor)
|
||||
, mTextureHandle(aTextureHandle)
|
||||
, mTextureTarget(aTarget)
|
||||
, mSize(aSize)
|
||||
, mFormat(aFormat)
|
||||
, mExternallyOwned(aExternallyOwned)
|
||||
{
|
||||
MOZ_COUNT_CTOR(GLTextureSource);
|
||||
}
|
||||
|
||||
GLTextureSource::~GLTextureSource()
|
||||
{
|
||||
MOZ_COUNT_DTOR(GLTextureSource);
|
||||
if (!mExternallyOwned) {
|
||||
DeleteTextureHandle();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLTextureSource::DeallocateDeviceData()
|
||||
{
|
||||
if (!mExternallyOwned) {
|
||||
DeleteTextureHandle();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLTextureSource::DeleteTextureHandle()
|
||||
{
|
||||
GLContext* gl = this->gl();
|
||||
if (mTextureHandle != 0 && gl && gl->MakeCurrent()) {
|
||||
gl->fDeleteTextures(1, &mTextureHandle);
|
||||
}
|
||||
mTextureHandle = 0;
|
||||
}
|
||||
|
||||
void
|
||||
GLTextureSource::BindTexture(GLenum aTextureUnit,
|
||||
gfx::SamplingFilter aSamplingFilter)
|
||||
{
|
||||
MOZ_ASSERT(mTextureHandle != 0);
|
||||
GLContext* gl = this->gl();
|
||||
if (!gl || !gl->MakeCurrent()) {
|
||||
return;
|
||||
}
|
||||
gl->fActiveTexture(aTextureUnit);
|
||||
gl->fBindTexture(mTextureTarget, mTextureHandle);
|
||||
ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
|
||||
}
|
||||
|
||||
void
|
||||
GLTextureSource::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* glCompositor = AssertGLCompositor(aCompositor);
|
||||
if (!glCompositor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCompositor && mCompositor != glCompositor) {
|
||||
gfxCriticalError() << "GLTextureSource does not support changing compositors";
|
||||
}
|
||||
mCompositor = glCompositor;
|
||||
|
||||
if (mNextSibling) {
|
||||
mNextSibling->SetCompositor(aCompositor);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLTextureSource::IsValid() const
|
||||
{
|
||||
return !!gl() && mTextureHandle != 0;
|
||||
}
|
||||
|
||||
gl::GLContext*
|
||||
GLTextureSource::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// SurfaceTextureHost
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
SurfaceTextureSource::SurfaceTextureSource(CompositorOGL* aCompositor,
|
||||
AndroidSurfaceTexture* aSurfTex,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
GLenum aTarget,
|
||||
GLenum aWrapMode,
|
||||
gfx::IntSize aSize)
|
||||
: mCompositor(aCompositor)
|
||||
, mSurfTex(aSurfTex)
|
||||
, mFormat(aFormat)
|
||||
, mTextureTarget(aTarget)
|
||||
, mWrapMode(aWrapMode)
|
||||
, mSize(aSize)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceTextureSource::BindTexture(GLenum aTextureUnit,
|
||||
gfx::SamplingFilter aSamplingFilter)
|
||||
{
|
||||
MOZ_ASSERT(mSurfTex);
|
||||
GLContext* gl = this->gl();
|
||||
if (!gl || !gl->MakeCurrent()) {
|
||||
NS_WARNING("Trying to bind a texture without a GLContext");
|
||||
return;
|
||||
}
|
||||
|
||||
gl->fActiveTexture(aTextureUnit);
|
||||
|
||||
// SurfaceTexture spams us if there are any existing GL errors, so
|
||||
// we'll clear them here in order to avoid that.
|
||||
gl->FlushErrors();
|
||||
|
||||
mSurfTex->UpdateTexImage();
|
||||
|
||||
ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceTextureSource::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* glCompositor = AssertGLCompositor(aCompositor);
|
||||
if (!glCompositor) {
|
||||
DeallocateDeviceData();
|
||||
return;
|
||||
}
|
||||
if (mCompositor != glCompositor) {
|
||||
DeallocateDeviceData();
|
||||
}
|
||||
|
||||
mCompositor = glCompositor;
|
||||
}
|
||||
|
||||
bool
|
||||
SurfaceTextureSource::IsValid() const
|
||||
{
|
||||
return !!gl();
|
||||
}
|
||||
|
||||
gl::GLContext*
|
||||
SurfaceTextureSource::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
gfx::Matrix4x4
|
||||
SurfaceTextureSource::GetTextureTransform()
|
||||
{
|
||||
MOZ_ASSERT(mSurfTex);
|
||||
|
||||
gfx::Matrix4x4 ret;
|
||||
mSurfTex->GetTransformMatrix(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceTextureSource::DeallocateDeviceData()
|
||||
{
|
||||
mSurfTex = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
|
||||
AndroidSurfaceTexture* aSurfTex,
|
||||
gfx::IntSize aSize)
|
||||
: TextureHost(aFlags)
|
||||
, mSurfTex(aSurfTex)
|
||||
, mSize(aSize)
|
||||
, mCompositor(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
SurfaceTextureHost::~SurfaceTextureHost()
|
||||
{
|
||||
}
|
||||
|
||||
gl::GLContext*
|
||||
SurfaceTextureHost::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
SurfaceTextureHost::Lock()
|
||||
{
|
||||
MOZ_ASSERT(mSurfTex);
|
||||
GLContext* gl = this->gl();
|
||||
if (!gl || !gl->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mTextureSource) {
|
||||
gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
|
||||
GLenum target = LOCAL_GL_TEXTURE_EXTERNAL;
|
||||
GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
|
||||
mTextureSource = new SurfaceTextureSource(mCompositor,
|
||||
mSurfTex,
|
||||
format,
|
||||
target,
|
||||
wrapMode,
|
||||
mSize);
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(mSurfTex->Attach(gl));
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceTextureHost::Unlock()
|
||||
{
|
||||
MOZ_ASSERT(mSurfTex);
|
||||
mSurfTex->Detach();
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceTextureHost::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* glCompositor = AssertGLCompositor(aCompositor);
|
||||
if (!glCompositor) {
|
||||
DeallocateDeviceData();
|
||||
return;
|
||||
}
|
||||
mCompositor = glCompositor;
|
||||
if (mTextureSource) {
|
||||
mTextureSource->SetCompositor(glCompositor);
|
||||
}
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
SurfaceTextureHost::GetFormat() const
|
||||
{
|
||||
return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
|
||||
void
|
||||
SurfaceTextureHost::DeallocateDeviceData()
|
||||
{
|
||||
if (mTextureSource) {
|
||||
mTextureSource->DeallocateDeviceData();
|
||||
}
|
||||
mSurfTex = nullptr;
|
||||
}
|
||||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// EGLImage
|
||||
|
||||
EGLImageTextureSource::EGLImageTextureSource(CompositorOGL* aCompositor,
|
||||
EGLImage aImage,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
GLenum aTarget,
|
||||
GLenum aWrapMode,
|
||||
gfx::IntSize aSize)
|
||||
: mCompositor(aCompositor)
|
||||
, mImage(aImage)
|
||||
, mFormat(aFormat)
|
||||
, mTextureTarget(aTarget)
|
||||
, mWrapMode(aWrapMode)
|
||||
, mSize(aSize)
|
||||
{
|
||||
MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D ||
|
||||
mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL);
|
||||
}
|
||||
|
||||
void
|
||||
EGLImageTextureSource::BindTexture(GLenum aTextureUnit,
|
||||
gfx::SamplingFilter aSamplingFilter)
|
||||
{
|
||||
GLContext* gl = this->gl();
|
||||
if (!gl || !gl->MakeCurrent()) {
|
||||
NS_WARNING("Trying to bind a texture without a GLContext");
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl),
|
||||
"EGLImage not supported or disabled in runtime");
|
||||
|
||||
GLuint tex = mCompositor->GetTemporaryTexture(mTextureTarget, aTextureUnit);
|
||||
|
||||
gl->fActiveTexture(aTextureUnit);
|
||||
gl->fBindTexture(mTextureTarget, tex);
|
||||
|
||||
gl->fEGLImageTargetTexture2D(mTextureTarget, mImage);
|
||||
|
||||
ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
|
||||
}
|
||||
|
||||
void
|
||||
EGLImageTextureSource::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
mCompositor = AssertGLCompositor(aCompositor);
|
||||
}
|
||||
|
||||
bool
|
||||
EGLImageTextureSource::IsValid() const
|
||||
{
|
||||
return !!gl();
|
||||
}
|
||||
|
||||
gl::GLContext*
|
||||
EGLImageTextureSource::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
gfx::Matrix4x4
|
||||
EGLImageTextureSource::GetTextureTransform()
|
||||
{
|
||||
gfx::Matrix4x4 ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EGLImageTextureHost::EGLImageTextureHost(TextureFlags aFlags,
|
||||
EGLImage aImage,
|
||||
EGLSync aSync,
|
||||
gfx::IntSize aSize,
|
||||
bool hasAlpha)
|
||||
: TextureHost(aFlags)
|
||||
, mImage(aImage)
|
||||
, mSync(aSync)
|
||||
, mSize(aSize)
|
||||
, mHasAlpha(hasAlpha)
|
||||
, mCompositor(nullptr)
|
||||
{}
|
||||
|
||||
EGLImageTextureHost::~EGLImageTextureHost()
|
||||
{}
|
||||
|
||||
gl::GLContext*
|
||||
EGLImageTextureHost::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
EGLImageTextureHost::Lock()
|
||||
{
|
||||
GLContext* gl = this->gl();
|
||||
if (!gl || !gl->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLint status = LOCAL_EGL_CONDITION_SATISFIED;
|
||||
|
||||
if (mSync) {
|
||||
MOZ_ASSERT(sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync));
|
||||
status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSync, 0, LOCAL_EGL_FOREVER);
|
||||
}
|
||||
|
||||
if (status != LOCAL_EGL_CONDITION_SATISFIED) {
|
||||
MOZ_ASSERT(status != 0,
|
||||
"ClientWaitSync generated an error. Has mSync already been destroyed?");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mTextureSource) {
|
||||
gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
|
||||
: gfx::SurfaceFormat::R8G8B8X8;
|
||||
GLenum target = gl->GetPreferredEGLImageTextureTarget();
|
||||
GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
|
||||
mTextureSource = new EGLImageTextureSource(mCompositor,
|
||||
mImage,
|
||||
format,
|
||||
target,
|
||||
wrapMode,
|
||||
mSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
EGLImageTextureHost::Unlock()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
EGLImageTextureHost::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* glCompositor = AssertGLCompositor(aCompositor);
|
||||
if (!glCompositor) {
|
||||
mCompositor = nullptr;
|
||||
mTextureSource = nullptr;
|
||||
return;
|
||||
}
|
||||
mCompositor = glCompositor;
|
||||
if (mTextureSource) {
|
||||
mTextureSource->SetCompositor(glCompositor);
|
||||
}
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
EGLImageTextureHost::GetFormat() const
|
||||
{
|
||||
MOZ_ASSERT(mTextureSource);
|
||||
return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GLTextureHost::GLTextureHost(TextureFlags aFlags,
|
||||
GLuint aTextureHandle,
|
||||
GLenum aTarget,
|
||||
GLsync aSync,
|
||||
gfx::IntSize aSize,
|
||||
bool aHasAlpha)
|
||||
: TextureHost(aFlags)
|
||||
, mTexture(aTextureHandle)
|
||||
, mTarget(aTarget)
|
||||
, mSync(aSync)
|
||||
, mSize(aSize)
|
||||
, mHasAlpha(aHasAlpha)
|
||||
, mCompositor(nullptr)
|
||||
{}
|
||||
|
||||
GLTextureHost::~GLTextureHost()
|
||||
{}
|
||||
|
||||
gl::GLContext*
|
||||
GLTextureHost::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
GLTextureHost::Lock()
|
||||
{
|
||||
GLContext* gl = this->gl();
|
||||
if (!gl || !gl->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mSync) {
|
||||
if (!gl->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
gl->fWaitSync(mSync, 0, LOCAL_GL_TIMEOUT_IGNORED);
|
||||
gl->fDeleteSync(mSync);
|
||||
mSync = 0;
|
||||
}
|
||||
|
||||
if (!mTextureSource) {
|
||||
gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
|
||||
: gfx::SurfaceFormat::R8G8B8X8;
|
||||
mTextureSource = new GLTextureSource(mCompositor,
|
||||
mTexture,
|
||||
mTarget,
|
||||
mSize,
|
||||
format,
|
||||
false /* owned by the client */);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
void
|
||||
GLTextureHost::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* glCompositor = AssertGLCompositor(aCompositor);
|
||||
if (!glCompositor) {
|
||||
mCompositor = nullptr;
|
||||
mTextureSource = nullptr;
|
||||
return;
|
||||
}
|
||||
mCompositor = glCompositor;
|
||||
if (mTextureSource) {
|
||||
mTextureSource->SetCompositor(glCompositor);
|
||||
}
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
GLTextureHost::GetFormat() const
|
||||
{
|
||||
MOZ_ASSERT(mTextureSource);
|
||||
return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
539
gfx/layers/opengl/TextureHostOGL.h
Normal file
539
gfx/layers/opengl/TextureHostOGL.h
Normal file
|
|
@ -0,0 +1,539 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_TEXTUREOGL_H
|
||||
#define MOZILLA_GFX_TEXTUREOGL_H
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint64_t
|
||||
#include "CompositableHost.h"
|
||||
#include "GLContextTypes.h" // for GLContext
|
||||
#include "GLDefs.h" // for GLenum, LOCAL_GL_CLAMP_TO_EDGE, etc
|
||||
#include "GLTextureImage.h" // for TextureImage
|
||||
#include "gfxTypes.h"
|
||||
#include "mozilla/GfxMessageUtils.h" // for gfxContentType
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
|
||||
#include "mozilla/gfx/Point.h" // for IntSize, IntPoint
|
||||
#include "mozilla/gfx/Types.h" // for SurfaceFormat, etc
|
||||
#include "mozilla/layers/CompositorOGL.h" // for CompositorOGL
|
||||
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||
#include "mozilla/layers/TextureHost.h" // for TextureHost, etc
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#include "nsISupportsImpl.h" // for TextureImage::Release, etc
|
||||
#include "nsRegionFwd.h" // for nsIntRegion
|
||||
#include "OGLShaderProgram.h" // for ShaderProgramType, etc
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class DataSourceSurface;
|
||||
} // namespace gfx
|
||||
|
||||
namespace gl {
|
||||
class AndroidSurfaceTexture;
|
||||
} // namespace gl
|
||||
|
||||
namespace layers {
|
||||
|
||||
class Compositor;
|
||||
class CompositorOGL;
|
||||
class TextureImageTextureSourceOGL;
|
||||
class GLTextureSource;
|
||||
|
||||
inline void ApplySamplingFilterToBoundTexture(gl::GLContext* aGL,
|
||||
gfx::SamplingFilter aSamplingFilter,
|
||||
GLuint aTarget = LOCAL_GL_TEXTURE_2D)
|
||||
{
|
||||
GLenum filter =
|
||||
(aSamplingFilter == gfx::SamplingFilter::POINT ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR);
|
||||
|
||||
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, filter);
|
||||
aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, filter);
|
||||
}
|
||||
|
||||
/*
|
||||
* TextureHost implementations for the OpenGL backend.
|
||||
*
|
||||
* Note that it is important to be careful about the ownership model with
|
||||
* the OpenGL backend, due to some widget limitation on Linux: before
|
||||
* the nsBaseWidget associated with our OpenGL context has been completely
|
||||
* deleted, every resource belonging to the OpenGL context MUST have been
|
||||
* released. At the moment the teardown sequence happens in the middle of
|
||||
* the nsBaseWidget's destructor, meaning that at a given moment we must be
|
||||
* able to easily find and release all the GL resources.
|
||||
* The point is: be careful about the ownership model and limit the number
|
||||
* of objects sharing references to GL resources to make the tear down
|
||||
* sequence as simple as possible.
|
||||
*/
|
||||
|
||||
/**
|
||||
* TextureSourceOGL provides the necessary API for CompositorOGL to composite
|
||||
* a TextureSource.
|
||||
*/
|
||||
class TextureSourceOGL
|
||||
{
|
||||
public:
|
||||
TextureSourceOGL()
|
||||
: mHasCachedSamplingFilter(false)
|
||||
{}
|
||||
|
||||
virtual bool IsValid() const = 0;
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit,
|
||||
gfx::SamplingFilter aSamplingFilter) = 0;
|
||||
|
||||
virtual gfx::IntSize GetSize() const = 0;
|
||||
|
||||
virtual GLenum GetTextureTarget() const { return LOCAL_GL_TEXTURE_2D; }
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const = 0;
|
||||
|
||||
virtual GLenum GetWrapMode() const = 0;
|
||||
|
||||
virtual gfx::Matrix4x4 GetTextureTransform() { return gfx::Matrix4x4(); }
|
||||
|
||||
virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() { return nullptr; }
|
||||
|
||||
virtual GLTextureSource* AsGLTextureSource() { return nullptr; }
|
||||
|
||||
void SetSamplingFilter(gl::GLContext* aGL, gfx::SamplingFilter aSamplingFilter)
|
||||
{
|
||||
if (mHasCachedSamplingFilter &&
|
||||
mCachedSamplingFilter == aSamplingFilter) {
|
||||
return;
|
||||
}
|
||||
mHasCachedSamplingFilter = true;
|
||||
mCachedSamplingFilter = aSamplingFilter;
|
||||
ApplySamplingFilterToBoundTexture(aGL, aSamplingFilter, GetTextureTarget());
|
||||
}
|
||||
|
||||
void ClearCachedFilter() { mHasCachedSamplingFilter = false; }
|
||||
|
||||
private:
|
||||
gfx::SamplingFilter mCachedSamplingFilter;
|
||||
bool mHasCachedSamplingFilter;
|
||||
};
|
||||
|
||||
/**
|
||||
* A TextureSource backed by a TextureImage.
|
||||
*
|
||||
* Depending on the underlying TextureImage, may support texture tiling, so
|
||||
* make sure to check AsBigImageIterator() and use the texture accordingly.
|
||||
*
|
||||
* This TextureSource can be used without a TextureHost and manage it's own
|
||||
* GL texture(s).
|
||||
*/
|
||||
class TextureImageTextureSourceOGL final : public DataTextureSource
|
||||
, public TextureSourceOGL
|
||||
, public BigImageIterator
|
||||
{
|
||||
public:
|
||||
explicit TextureImageTextureSourceOGL(CompositorOGL *aCompositor,
|
||||
TextureFlags aFlags = TextureFlags::DEFAULT)
|
||||
: mCompositor(aCompositor)
|
||||
, mFlags(aFlags)
|
||||
, mIterating(false)
|
||||
{}
|
||||
|
||||
virtual const char* Name() const override { return "TextureImageTextureSourceOGL"; }
|
||||
// DataTextureSource
|
||||
|
||||
virtual bool Update(gfx::DataSourceSurface* aSurface,
|
||||
nsIntRegion* aDestRegion = nullptr,
|
||||
gfx::IntPoint* aSrcOffset = nullptr) override;
|
||||
|
||||
void EnsureBuffer(const gfx::IntSize& aSize,
|
||||
gfxContentType aContentType);
|
||||
|
||||
void CopyTo(const gfx::IntRect& aSourceRect,
|
||||
DataTextureSource* aDest,
|
||||
const gfx::IntRect& aDestRect);
|
||||
|
||||
virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() override { return this; }
|
||||
|
||||
// TextureSource
|
||||
|
||||
virtual void DeallocateDeviceData() override
|
||||
{
|
||||
mTexImage = nullptr;
|
||||
SetUpdateSerial(0);
|
||||
}
|
||||
|
||||
virtual TextureSourceOGL* AsSourceOGL() override { return this; }
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit,
|
||||
gfx::SamplingFilter aSamplingFilter) override;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual bool IsValid() const override { return !!mTexImage; }
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
virtual GLenum GetWrapMode() const override
|
||||
{
|
||||
return mTexImage->GetWrapMode();
|
||||
}
|
||||
|
||||
// BigImageIterator
|
||||
|
||||
virtual BigImageIterator* AsBigImageIterator() override { return this; }
|
||||
|
||||
virtual void BeginBigImageIteration() override
|
||||
{
|
||||
mTexImage->BeginBigImageIteration();
|
||||
mIterating = true;
|
||||
}
|
||||
|
||||
virtual void EndBigImageIteration() override
|
||||
{
|
||||
mIterating = false;
|
||||
}
|
||||
|
||||
virtual gfx::IntRect GetTileRect() override;
|
||||
|
||||
virtual size_t GetTileCount() override
|
||||
{
|
||||
return mTexImage->GetTileCount();
|
||||
}
|
||||
|
||||
virtual bool NextTile() override
|
||||
{
|
||||
return mTexImage->NextTile();
|
||||
}
|
||||
|
||||
protected:
|
||||
RefPtr<gl::TextureImage> mTexImage;
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
TextureFlags mFlags;
|
||||
bool mIterating;
|
||||
};
|
||||
|
||||
/**
|
||||
* A texture source for GL textures.
|
||||
*
|
||||
* It does not own any GL texture, and attaches its shared handle to one of
|
||||
* the compositor's temporary textures when binding.
|
||||
*
|
||||
* The shared texture handle is owned by the TextureHost.
|
||||
*/
|
||||
class GLTextureSource : public TextureSource
|
||||
, public TextureSourceOGL
|
||||
{
|
||||
public:
|
||||
GLTextureSource(CompositorOGL* aCompositor,
|
||||
GLuint aTextureHandle,
|
||||
GLenum aTarget,
|
||||
gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
bool aExternallyOwned = false);
|
||||
|
||||
~GLTextureSource();
|
||||
|
||||
virtual const char* Name() const override { return "GLTextureSource"; }
|
||||
|
||||
virtual GLTextureSource* AsGLTextureSource() override { return this; }
|
||||
|
||||
virtual TextureSourceOGL* AsSourceOGL() override { return this; }
|
||||
|
||||
virtual void BindTexture(GLenum activetex,
|
||||
gfx::SamplingFilter aSamplingFilter) override;
|
||||
|
||||
virtual bool IsValid() const override;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
|
||||
|
||||
virtual GLenum GetTextureTarget() const override { return mTextureTarget; }
|
||||
|
||||
virtual GLenum GetWrapMode() const override { return LOCAL_GL_CLAMP_TO_EDGE; }
|
||||
|
||||
virtual void DeallocateDeviceData() override;
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
void SetSize(gfx::IntSize aSize) { mSize = aSize; }
|
||||
|
||||
void SetFormat(gfx::SurfaceFormat aFormat) { mFormat = aFormat; }
|
||||
|
||||
GLuint GetTextureHandle() const { return mTextureHandle; }
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
protected:
|
||||
void DeleteTextureHandle();
|
||||
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
GLuint mTextureHandle;
|
||||
GLenum mTextureTarget;
|
||||
gfx::IntSize mSize;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
// If the texture is externally owned, the gl handle will not be deleted
|
||||
// in the destructor.
|
||||
bool mExternallyOwned;
|
||||
};
|
||||
|
||||
class GLTextureHost : public TextureHost
|
||||
{
|
||||
public:
|
||||
GLTextureHost(TextureFlags aFlags,
|
||||
GLuint aTextureHandle,
|
||||
GLenum aTarget,
|
||||
GLsync aSync,
|
||||
gfx::IntSize aSize,
|
||||
bool aHasAlpha);
|
||||
|
||||
virtual ~GLTextureHost();
|
||||
|
||||
// We don't own anything.
|
||||
virtual void DeallocateDeviceData() override {}
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
virtual Compositor* GetCompositor() override { return mCompositor; }
|
||||
|
||||
virtual bool Lock() override;
|
||||
|
||||
virtual void Unlock() override {}
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override
|
||||
{
|
||||
aTexture = mTextureSource;
|
||||
return !!aTexture;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
|
||||
{
|
||||
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
|
||||
}
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual const char* Name() override { return "GLTextureHost"; }
|
||||
|
||||
protected:
|
||||
const GLuint mTexture;
|
||||
const GLenum mTarget;
|
||||
GLsync mSync;
|
||||
const gfx::IntSize mSize;
|
||||
const bool mHasAlpha;
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<GLTextureSource> mTextureSource;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// SurfaceTexture
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
class SurfaceTextureSource : public TextureSource
|
||||
, public TextureSourceOGL
|
||||
{
|
||||
public:
|
||||
SurfaceTextureSource(CompositorOGL* aCompositor,
|
||||
mozilla::gl::AndroidSurfaceTexture* aSurfTex,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
GLenum aTarget,
|
||||
GLenum aWrapMode,
|
||||
gfx::IntSize aSize);
|
||||
|
||||
virtual const char* Name() const override { return "SurfaceTextureSource"; }
|
||||
|
||||
virtual TextureSourceOGL* AsSourceOGL() override { return this; }
|
||||
|
||||
virtual void BindTexture(GLenum activetex,
|
||||
gfx::SamplingFilter aSamplingFilter) override;
|
||||
|
||||
virtual bool IsValid() const override;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
|
||||
|
||||
virtual gfx::Matrix4x4 GetTextureTransform() override;
|
||||
|
||||
virtual GLenum GetTextureTarget() const override { return mTextureTarget; }
|
||||
|
||||
virtual GLenum GetWrapMode() const override { return mWrapMode; }
|
||||
|
||||
virtual void DeallocateDeviceData() override;
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
protected:
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
|
||||
const gfx::SurfaceFormat mFormat;
|
||||
const GLenum mTextureTarget;
|
||||
const GLenum mWrapMode;
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
class SurfaceTextureHost : public TextureHost
|
||||
{
|
||||
public:
|
||||
SurfaceTextureHost(TextureFlags aFlags,
|
||||
mozilla::gl::AndroidSurfaceTexture* aSurfTex,
|
||||
gfx::IntSize aSize);
|
||||
|
||||
virtual ~SurfaceTextureHost();
|
||||
|
||||
virtual void DeallocateDeviceData() override;
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
virtual Compositor* GetCompositor() override { return mCompositor; }
|
||||
|
||||
virtual bool Lock() override;
|
||||
|
||||
virtual void Unlock() override;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override
|
||||
{
|
||||
aTexture = mTextureSource;
|
||||
return !!aTexture;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
|
||||
{
|
||||
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
|
||||
}
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual const char* Name() override { return "SurfaceTextureHost"; }
|
||||
|
||||
protected:
|
||||
RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
|
||||
const gfx::IntSize mSize;
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<SurfaceTextureSource> mTextureSource;
|
||||
};
|
||||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// EGLImage
|
||||
|
||||
class EGLImageTextureSource : public TextureSource
|
||||
, public TextureSourceOGL
|
||||
{
|
||||
public:
|
||||
EGLImageTextureSource(CompositorOGL* aCompositor,
|
||||
EGLImage aImage,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
GLenum aTarget,
|
||||
GLenum aWrapMode,
|
||||
gfx::IntSize aSize);
|
||||
|
||||
virtual const char* Name() const override { return "EGLImageTextureSource"; }
|
||||
|
||||
virtual TextureSourceOGL* AsSourceOGL() override { return this; }
|
||||
|
||||
virtual void BindTexture(GLenum activetex,
|
||||
gfx::SamplingFilter aSamplingFilter) override;
|
||||
|
||||
virtual bool IsValid() const override;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
|
||||
|
||||
virtual gfx::Matrix4x4 GetTextureTransform() override;
|
||||
|
||||
virtual GLenum GetTextureTarget() const override { return mTextureTarget; }
|
||||
|
||||
virtual GLenum GetWrapMode() const override { return mWrapMode; }
|
||||
|
||||
// We don't own anything.
|
||||
virtual void DeallocateDeviceData() override {}
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
protected:
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
const EGLImage mImage;
|
||||
const gfx::SurfaceFormat mFormat;
|
||||
const GLenum mTextureTarget;
|
||||
const GLenum mWrapMode;
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
class EGLImageTextureHost : public TextureHost
|
||||
{
|
||||
public:
|
||||
EGLImageTextureHost(TextureFlags aFlags,
|
||||
EGLImage aImage,
|
||||
EGLSync aSync,
|
||||
gfx::IntSize aSize,
|
||||
bool hasAlpha);
|
||||
|
||||
virtual ~EGLImageTextureHost();
|
||||
|
||||
// We don't own anything.
|
||||
virtual void DeallocateDeviceData() override {}
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
virtual Compositor* GetCompositor() override { return mCompositor; }
|
||||
|
||||
virtual bool Lock() override;
|
||||
|
||||
virtual void Unlock() override;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override
|
||||
{
|
||||
aTexture = mTextureSource;
|
||||
return !!aTexture;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
|
||||
{
|
||||
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
|
||||
}
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual const char* Name() override { return "EGLImageTextureHost"; }
|
||||
|
||||
protected:
|
||||
const EGLImage mImage;
|
||||
const EGLSync mSync;
|
||||
const gfx::IntSize mSize;
|
||||
const bool mHasAlpha;
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<EGLImageTextureSource> mTextureSource;
|
||||
};
|
||||
|
||||
CompositorOGL* AssertGLCompositor(Compositor* aCompositor);
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* MOZILLA_GFX_TEXTUREOGL_H */
|
||||
123
gfx/layers/opengl/TexturePoolOGL.cpp
Normal file
123
gfx/layers/opengl/TexturePoolOGL.cpp
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "TexturePoolOGL.h"
|
||||
#include <stdlib.h> // for malloc
|
||||
#include "GLContext.h" // for GLContext
|
||||
#include "mozilla/Monitor.h" // for Monitor, MonitorAutoLock
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
#include "nsDebug.h" // for NS_ASSERTION, NS_ERROR, etc
|
||||
#include "nsDeque.h" // for nsDeque
|
||||
|
||||
#define TEXTURE_POOL_SIZE 10
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
static GLContext* sActiveContext = nullptr;
|
||||
|
||||
static Monitor* sMonitor = nullptr;
|
||||
static nsDeque* sTextures = nullptr;
|
||||
|
||||
GLuint TexturePoolOGL::AcquireTexture()
|
||||
{
|
||||
NS_ASSERTION(sMonitor, "not initialized");
|
||||
|
||||
MonitorAutoLock lock(*sMonitor);
|
||||
|
||||
if (!sActiveContext) {
|
||||
// Wait for a context
|
||||
sMonitor->Wait();
|
||||
|
||||
if (!sActiveContext)
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint texture = 0;
|
||||
if (sActiveContext->IsOwningThreadCurrent()) {
|
||||
sActiveContext->MakeCurrent();
|
||||
|
||||
sActiveContext->fGenTextures(1, &texture);
|
||||
} else {
|
||||
while (sTextures->GetSize() == 0) {
|
||||
NS_WARNING("Waiting for texture");
|
||||
sMonitor->Wait();
|
||||
}
|
||||
|
||||
GLuint* popped = (GLuint*) sTextures->Pop();
|
||||
if (!popped) {
|
||||
NS_ERROR("Failed to pop texture pool item");
|
||||
return 0;
|
||||
}
|
||||
|
||||
texture = *popped;
|
||||
delete popped;
|
||||
|
||||
NS_ASSERTION(texture, "Failed to retrieve texture from pool");
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static void Clear()
|
||||
{
|
||||
if (!sActiveContext)
|
||||
return;
|
||||
|
||||
sActiveContext->MakeCurrent();
|
||||
|
||||
GLuint* item;
|
||||
while (sTextures->GetSize()) {
|
||||
item = (GLuint*)sTextures->Pop();
|
||||
sActiveContext->fDeleteTextures(1, item);
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void TexturePoolOGL::Fill(GLContext* aContext)
|
||||
{
|
||||
NS_ASSERTION(aContext, "NULL GLContext");
|
||||
NS_ASSERTION(sMonitor, "not initialized");
|
||||
|
||||
MonitorAutoLock lock(*sMonitor);
|
||||
|
||||
if (sActiveContext != aContext) {
|
||||
Clear();
|
||||
sActiveContext = aContext;
|
||||
}
|
||||
|
||||
if (sTextures->GetSize() == TEXTURE_POOL_SIZE)
|
||||
return;
|
||||
|
||||
sActiveContext->MakeCurrent();
|
||||
|
||||
GLuint* texture = nullptr;
|
||||
while (sTextures->GetSize() < TEXTURE_POOL_SIZE) {
|
||||
texture = (GLuint*)malloc(sizeof(GLuint));
|
||||
sActiveContext->fGenTextures(1, texture);
|
||||
sTextures->Push((void*) texture);
|
||||
}
|
||||
|
||||
sMonitor->NotifyAll();
|
||||
}
|
||||
|
||||
GLContext* TexturePoolOGL::GetGLContext()
|
||||
{
|
||||
return sActiveContext;
|
||||
}
|
||||
|
||||
void TexturePoolOGL::Init()
|
||||
{
|
||||
sMonitor = new Monitor("TexturePoolOGL.sMonitor");
|
||||
sTextures = new nsDeque();
|
||||
}
|
||||
|
||||
void TexturePoolOGL::Shutdown()
|
||||
{
|
||||
delete sMonitor;
|
||||
delete sTextures;
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
||||
40
gfx/layers/opengl/TexturePoolOGL.h
Normal file
40
gfx/layers/opengl/TexturePoolOGL.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_TEXTUREPOOLOGL_H
|
||||
#define GFX_TEXTUREPOOLOGL_H
|
||||
|
||||
#include "GLContextTypes.h" // for GLContext, GLuint
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
// A texture pool for for the on-screen GLContext. The main purpose of this class
|
||||
// is to provide the ability to easily allocate an on-screen texture from the
|
||||
// content thread. The unfortunate nature of the SurfaceTexture API (see AndroidSurfaceTexture)
|
||||
// necessitates this.
|
||||
class TexturePoolOGL
|
||||
{
|
||||
public:
|
||||
// Get a new texture from the pool. Will block
|
||||
// and wait for one to be created if necessary
|
||||
static GLuint AcquireTexture();
|
||||
|
||||
// Called by the active LayerManagerOGL to fill
|
||||
// the pool
|
||||
static void Fill(GLContext* aContext);
|
||||
|
||||
static GLContext* GetGLContext();
|
||||
|
||||
// Initializes the pool, but does not fill it. Called by gfxPlatform init.
|
||||
static void Init();
|
||||
|
||||
// Clears all internal data structures in preparation for shutdown
|
||||
static void Shutdown();
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GFX_TEXTUREPOOLOGL_H
|
||||
114
gfx/layers/opengl/X11TextureSourceOGL.cpp
Normal file
114
gfx/layers/opengl/X11TextureSourceOGL.cpp
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
|
||||
#include "X11TextureSourceOGL.h"
|
||||
#include "gfxXlibSurface.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
X11TextureSourceOGL::X11TextureSourceOGL(CompositorOGL* aCompositor, gfxXlibSurface* aSurface)
|
||||
: mCompositor(aCompositor)
|
||||
, mSurface(aSurface)
|
||||
, mTexture(0)
|
||||
, mUpdated(false)
|
||||
{
|
||||
}
|
||||
|
||||
X11TextureSourceOGL::~X11TextureSourceOGL()
|
||||
{
|
||||
DeallocateDeviceData();
|
||||
}
|
||||
|
||||
void
|
||||
X11TextureSourceOGL::DeallocateDeviceData()
|
||||
{
|
||||
if (mTexture) {
|
||||
if (gl() && gl()->MakeCurrent()) {
|
||||
gl::sGLXLibrary.ReleaseTexImage(mSurface->XDisplay(), mSurface->GetGLXPixmap());
|
||||
gl()->fDeleteTextures(1, &mTexture);
|
||||
mTexture = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
X11TextureSourceOGL::BindTexture(GLenum aTextureUnit,
|
||||
gfx::SamplingFilter aSamplingFilter)
|
||||
{
|
||||
gl()->fActiveTexture(aTextureUnit);
|
||||
|
||||
if (!mTexture) {
|
||||
gl()->fGenTextures(1, &mTexture);
|
||||
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
|
||||
gl::sGLXLibrary.BindTexImage(mSurface->XDisplay(), mSurface->GetGLXPixmap());
|
||||
} else {
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
if (mUpdated) {
|
||||
gl::sGLXLibrary.UpdateTexImage(mSurface->XDisplay(), mSurface->GetGLXPixmap());
|
||||
mUpdated = false;
|
||||
}
|
||||
}
|
||||
|
||||
ApplySamplingFilterToBoundTexture(gl(), aSamplingFilter, LOCAL_GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
IntSize
|
||||
X11TextureSourceOGL::GetSize() const
|
||||
{
|
||||
return mSurface->GetSize();
|
||||
}
|
||||
|
||||
SurfaceFormat
|
||||
X11TextureSourceOGL::GetFormat() const {
|
||||
gfxContentType type = mSurface->GetContentType();
|
||||
return X11TextureSourceOGL::ContentTypeToSurfaceFormat(type);
|
||||
}
|
||||
|
||||
void
|
||||
X11TextureSourceOGL::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorOGL* glCompositor = AssertGLCompositor(aCompositor);
|
||||
if (mCompositor == glCompositor) {
|
||||
return;
|
||||
}
|
||||
DeallocateDeviceData();
|
||||
if (glCompositor) {
|
||||
mCompositor = glCompositor;
|
||||
}
|
||||
}
|
||||
|
||||
gl::GLContext*
|
||||
X11TextureSourceOGL::gl() const
|
||||
{
|
||||
return mCompositor ? mCompositor->gl() : nullptr;
|
||||
}
|
||||
|
||||
SurfaceFormat
|
||||
X11TextureSourceOGL::ContentTypeToSurfaceFormat(gfxContentType aType)
|
||||
{
|
||||
// X11 uses a switched format and the OGL compositor
|
||||
// doesn't support ALPHA / A8.
|
||||
switch (aType) {
|
||||
case gfxContentType::COLOR:
|
||||
return SurfaceFormat::R8G8B8X8;
|
||||
case gfxContentType::COLOR_ALPHA:
|
||||
return SurfaceFormat::R8G8B8A8;
|
||||
default:
|
||||
return SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
65
gfx/layers/opengl/X11TextureSourceOGL.h
Normal file
65
gfx/layers/opengl/X11TextureSourceOGL.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_X11TEXTURESOURCEOGL__H
|
||||
#define MOZILLA_GFX_X11TEXTURESOURCEOGL__H
|
||||
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
|
||||
#include "mozilla/layers/CompositorOGL.h"
|
||||
#include "mozilla/layers/TextureHostOGL.h"
|
||||
#include "mozilla/layers/X11TextureHost.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
// TextureSource for Xlib-backed surfaces.
|
||||
class X11TextureSourceOGL
|
||||
: public TextureSourceOGL
|
||||
, public X11TextureSource
|
||||
{
|
||||
public:
|
||||
X11TextureSourceOGL(CompositorOGL* aCompositor, gfxXlibSurface* aSurface);
|
||||
~X11TextureSourceOGL();
|
||||
|
||||
virtual X11TextureSourceOGL* AsSourceOGL() override { return this; }
|
||||
|
||||
virtual bool IsValid() const override { return !!gl(); } ;
|
||||
|
||||
virtual void BindTexture(GLenum aTextureUnit, gfx::SamplingFilter aSamplingFilter) override;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override;
|
||||
|
||||
virtual GLenum GetTextureTarget() const override { return LOCAL_GL_TEXTURE_2D; }
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual GLenum GetWrapMode() const override { return LOCAL_GL_CLAMP_TO_EDGE; }
|
||||
|
||||
virtual void DeallocateDeviceData() override;
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) override;
|
||||
|
||||
virtual void Updated() override { mUpdated = true; }
|
||||
|
||||
gl::GLContext* gl() const;
|
||||
|
||||
static gfx::SurfaceFormat ContentTypeToSurfaceFormat(gfxContentType aType);
|
||||
|
||||
protected:
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<gfxXlibSurface> mSurface;
|
||||
RefPtr<gfx::SourceSurface> mSourceSurface;
|
||||
GLuint mTexture;
|
||||
bool mUpdated;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
#endif // MOZILLA_GFX_X11TEXTURESOURCEOGL__H
|
||||
Loading…
Add table
Add a link
Reference in a new issue