Bug 1265824 - Add a new texture source type "DirectMapTextureSource" r?mattwoodrow
The DirectMapTextureSource could let the compositor to read the buffer directly.
That could get rid of some memory copy operations during texture uploading.
MozReview-Commit-ID: CHhoR96P7VG
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -76,16 +76,17 @@ static const char* const sExtensionNames
"GL_ANGLE_depth_texture",
"GL_ANGLE_framebuffer_blit",
"GL_ANGLE_framebuffer_multisample",
"GL_ANGLE_instanced_arrays",
"GL_ANGLE_texture_compression_dxt3",
"GL_ANGLE_texture_compression_dxt5",
"GL_ANGLE_timer_query",
"GL_APPLE_client_storage",
+ "GL_APPLE_fence",
"GL_APPLE_framebuffer_multisample",
"GL_APPLE_sync",
"GL_APPLE_texture_range",
"GL_APPLE_vertex_array_object",
"GL_ARB_ES2_compatibility",
"GL_ARB_ES3_compatibility",
"GL_ARB_color_buffer_float",
"GL_ARB_compatibility",
@@ -1075,16 +1076,25 @@ GLContext::LoadMoreSymbols(const char* p
if (IsExtensionSupported(APPLE_texture_range)) {
const SymLoadStruct symbols[] = {
{ (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
END_SYMBOLS
};
fnLoadForExt(symbols, APPLE_texture_range);
}
+ if (IsExtensionSupported(APPLE_fence)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fFinishObjectAPPLE, { "FinishObjectAPPLE", nullptr } },
+ { (PRFuncPtr*) &mSymbols.fTestObjectAPPLE, { "TestObjectAPPLE", nullptr } },
+ END_SYMBOLS
+ };
+ fnLoadForExt(symbols, APPLE_fence);
+ }
+
if (IsSupported(GLFeature::vertex_array_object)) {
const SymLoadStruct coreSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", nullptr } },
END_SYMBOLS
};
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -375,16 +375,17 @@ public:
ANGLE_depth_texture,
ANGLE_framebuffer_blit,
ANGLE_framebuffer_multisample,
ANGLE_instanced_arrays,
ANGLE_texture_compression_dxt3,
ANGLE_texture_compression_dxt5,
ANGLE_timer_query,
APPLE_client_storage,
+ APPLE_fence,
APPLE_framebuffer_multisample,
APPLE_sync,
APPLE_texture_range,
APPLE_vertex_array_object,
ARB_ES2_compatibility,
ARB_ES3_compatibility,
ARB_color_buffer_float,
ARB_compatibility,
@@ -3298,16 +3299,35 @@ public:
void fResolveMultisampleFramebufferAPPLE() {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fResolveMultisampleFramebufferAPPLE);
mSymbols.fResolveMultisampleFramebufferAPPLE();
AFTER_GL_CALL;
}
// -----------------------------------------------------------------------------
+// APPLE_fence
+
+ void fFinishObjectAPPLE(GLenum object, GLint name) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fFinishObjectAPPLE);
+ mSymbols.fFinishObjectAPPLE(object, name);
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fTestObjectAPPLE(GLenum object, GLint name) {
+ realGLboolean ret = false;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fTestObjectAPPLE);
+ ret = mSymbols.fTestObjectAPPLE(object, name);
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
// prim_restart
void fPrimitiveRestartIndex(GLuint index) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fPrimitiveRestartIndex);
mSymbols.fPrimitiveRestartIndex(index);
AFTER_GL_CALL;
}
--- a/gfx/gl/GLContextSymbols.h
+++ b/gfx/gl/GLContextSymbols.h
@@ -132,16 +132,18 @@ struct GLContextSymbols final
void (GLAPIENTRY * fStencilMaskSeparate)(GLenum, GLuint);
void (GLAPIENTRY * fStencilOp)(GLenum, GLenum, GLenum);
void (GLAPIENTRY * fStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum);
void (GLAPIENTRY * fTexImage2D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint,
GLenum, GLenum, const GLvoid*);
void (GLAPIENTRY * fTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei,
GLsizei, GLenum, GLenum, const void*);
void (GLAPIENTRY * fTextureRangeAPPLE)(GLenum, GLsizei, GLvoid*);
+ void (GLAPIENTRY * fFinishObjectAPPLE)(GLenum, GLint);
+ realGLboolean (GLAPIENTRY * fTestObjectAPPLE)(GLenum, GLint);
void (GLAPIENTRY * fUniform1f)(GLint, GLfloat);
void (GLAPIENTRY * fUniform1fv)(GLint, GLsizei, const GLfloat*);
void (GLAPIENTRY * fUniform1i)(GLint, GLint);
void (GLAPIENTRY * fUniform1iv)(GLint, GLsizei, const GLint*);
void (GLAPIENTRY * fUniform2f)(GLint, GLfloat, GLfloat);
void (GLAPIENTRY * fUniform2fv)(GLint, GLsizei, const GLfloat*);
void (GLAPIENTRY * fUniform2i)(GLint, GLint, GLint);
void (GLAPIENTRY * fUniform2iv)(GLint, GLsizei, const GLint*);
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -178,16 +178,24 @@ public:
// individual tiles.
virtual RefPtr<TextureSource> ExtractCurrentTile() {
NS_WARNING("Implementation does not expose tile sources");
return nullptr;
}
int NumCompositableRefs() const { return mCompositableCount; }
+ // Some texture sources could wrap the cpu buffer to gpu directly. Then,
+ // we could get better performance of texture uploading.
+ virtual bool IsDirectMap() { return false; }
+ // The direct-map cpu buffer should be alive when gpu uses it. And it
+ // should not be updated while gpu reads it. This Sync() function
+ // implements this synchronized behavior.
+ virtual void Sync() { }
+
protected:
RefPtr<TextureSource> mNextSibling;
int mCompositableCount;
};
/// Equivalent of a RefPtr<TextureSource>, that calls AddCompositableRef and
/// ReleaseCompositableRef in addition to the usual AddRef and Release.
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -305,16 +305,103 @@ GLTextureSource::SetTextureSourceProvide
bool
GLTextureSource::IsValid() const
{
return !!gl() && mTextureHandle != 0;
}
////////////////////////////////////////////////////////////////////////
+// DirectMapTextureSource
+
+DirectMapTextureSource::DirectMapTextureSource(TextureSourceProvider* aProvider,
+ gfx::DataSourceSurface* aSurface)
+ : GLTextureSource(aProvider,
+ 0,
+ LOCAL_GL_TEXTURE_2D,
+ aSurface->GetSize(),
+ aSurface->GetFormat())
+{
+ MOZ_ASSERT(aSurface);
+
+ UpdateInternal(aSurface, nullptr, nullptr, true);
+}
+
+bool
+DirectMapTextureSource::Update(gfx::DataSourceSurface* aSurface,
+ nsIntRegion* aDestRegion,
+ gfx::IntPoint* aSrcOffset)
+{
+ if (!aSurface) {
+ return false;
+ }
+
+ return UpdateInternal(aSurface, aDestRegion, aSrcOffset, false);
+}
+
+void
+DirectMapTextureSource::Sync()
+{
+ gl()->MakeCurrent();
+ if (!gl()->IsDestroyed()) {
+ gl()->fFinishObjectAPPLE(LOCAL_GL_TEXTURE, mTextureHandle);
+ }
+}
+
+bool
+DirectMapTextureSource::UpdateInternal(gfx::DataSourceSurface* aSurface,
+ nsIntRegion* aDestRegion,
+ gfx::IntPoint* aSrcOffset,
+ bool aInit)
+{
+ gl()->MakeCurrent();
+
+ if (aInit) {
+ gl()->fGenTextures(1, &mTextureHandle);
+ gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextureHandle);
+
+ gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D,
+ LOCAL_GL_TEXTURE_STORAGE_HINT_APPLE,
+ LOCAL_GL_STORAGE_CACHED_APPLE);
+
+ gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D,
+ LOCAL_GL_TEXTURE_WRAP_S,
+ LOCAL_GL_CLAMP_TO_EDGE);
+ gl()->fTexParameteri(LOCAL_GL_TEXTURE_2D,
+ LOCAL_GL_TEXTURE_WRAP_T,
+ LOCAL_GL_CLAMP_TO_EDGE);
+ }
+
+ MOZ_ASSERT(mTextureHandle);
+
+ // APPLE_client_storage
+ gl()->fPixelStorei(LOCAL_GL_UNPACK_CLIENT_STORAGE_APPLE, LOCAL_GL_TRUE);
+
+ nsIntRegion destRegion = aDestRegion ? *aDestRegion
+ : IntRect(0, 0,
+ aSurface->GetSize().width,
+ aSurface->GetSize().height);
+ gfx::IntPoint srcPoint = aSrcOffset ? *aSrcOffset
+ : gfx::IntPoint(0, 0);
+ mFormat = gl::UploadSurfaceToTexture(gl(),
+ aSurface,
+ destRegion,
+ mTextureHandle,
+ aSurface->GetSize(),
+ nullptr,
+ aInit,
+ srcPoint,
+ LOCAL_GL_TEXTURE0,
+ LOCAL_GL_TEXTURE_2D);
+
+ gl()->fPixelStorei(LOCAL_GL_UNPACK_CLIENT_STORAGE_APPLE, LOCAL_GL_FALSE);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// SurfaceTextureHost
#ifdef MOZ_WIDGET_ANDROID
SurfaceTextureSource::SurfaceTextureSource(TextureSourceProvider* aProvider,
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::SurfaceFormat aFormat,
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -219,27 +219,27 @@ protected:
/**
* 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
+class GLTextureSource : public DataTextureSource
, public TextureSourceOGL
{
public:
GLTextureSource(TextureSourceProvider* aProvider,
GLuint aTextureHandle,
GLenum aTarget,
gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
- ~GLTextureSource();
+ virtual ~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,
@@ -264,27 +264,61 @@ public:
void SetFormat(gfx::SurfaceFormat aFormat) { mFormat = aFormat; }
GLuint GetTextureHandle() const { return mTextureHandle; }
gl::GLContext* gl() const {
return mGL;
}
+ virtual bool Update(gfx::DataSourceSurface* aSurface,
+ nsIntRegion* aDestRegion = nullptr,
+ gfx::IntPoint* aSrcOffset = nullptr) override
+ {
+ return false;
+ }
+
protected:
void DeleteTextureHandle();
RefPtr<gl::GLContext> mGL;
RefPtr<CompositorOGL> mCompositor;
GLuint mTextureHandle;
GLenum mTextureTarget;
gfx::IntSize mSize;
gfx::SurfaceFormat mFormat;
};
+// This texture source try to wrap "aSurface" in ctor for compositor direct
+// access. Since we can't know the timing for gpu buffer access, the surface
+// should be alive until the ~ClientStorageTextureSource(). And if we try to
+// update the surface we mapped before, we need to call Sync() to make sure
+// the surface is not used by compositor.
+class DirectMapTextureSource : public GLTextureSource
+{
+public:
+ DirectMapTextureSource(TextureSourceProvider* aProvider,
+ gfx::DataSourceSurface* aSurface);
+
+ virtual bool Update(gfx::DataSourceSurface* aSurface,
+ nsIntRegion* aDestRegion = nullptr,
+ gfx::IntPoint* aSrcOffset = nullptr) override;
+
+ virtual bool IsDirectMap() override { return true; }
+
+ // Wait until this texture source is not used by the compositor.
+ virtual void Sync() override;
+
+private:
+ bool UpdateInternal(gfx::DataSourceSurface* aSurface,
+ nsIntRegion* aDestRegion,
+ gfx::IntPoint* aSrcOffset,
+ bool aInit);
+};
+
class GLTextureHost : public TextureHost
{
public:
GLTextureHost(TextureFlags aFlags,
GLuint aTextureHandle,
GLenum aTarget,
GLsync aSync,
gfx::IntSize aSize,