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

--HG--
extra : rebase_source : 65c167644096a1b72fe5dfbb55837842f41377bb
This commit is contained in:
Doug Thayer 2018-05-02 18:20:10 -07:00
Родитель 14d6b57804
Коммит 40c168f2fd
6 изменённых файлов: 163 добавлений и 2 удалений

Просмотреть файл

@ -81,6 +81,7 @@ static const char* const sExtensionNames[] = {
"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",
@ -1080,6 +1081,15 @@ GLContext::LoadMoreSymbols(const char* prefix, bool trygl)
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 } },

Просмотреть файл

@ -380,6 +380,7 @@ public:
ANGLE_texture_compression_dxt5,
ANGLE_timer_query,
APPLE_client_storage,
APPLE_fence,
APPLE_framebuffer_multisample,
APPLE_sync,
APPLE_texture_range,
@ -3302,6 +3303,25 @@ public:
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

Просмотреть файл

@ -137,6 +137,8 @@ struct GLContextSymbols final
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);

Просмотреть файл

@ -183,6 +183,14 @@ public:
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;

Просмотреть файл

@ -309,6 +309,93 @@ 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

Просмотреть файл

@ -224,7 +224,7 @@ protected:
*
* The shared texture handle is owned by the TextureHost.
*/
class GLTextureSource : public TextureSource
class GLTextureSource : public DataTextureSource
, public TextureSourceOGL
{
public:
@ -234,7 +234,7 @@ public:
gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
~GLTextureSource();
virtual ~GLTextureSource();
virtual const char* Name() const override { return "GLTextureSource"; }
@ -269,6 +269,13 @@ public:
return mGL;
}
virtual bool Update(gfx::DataSourceSurface* aSurface,
nsIntRegion* aDestRegion = nullptr,
gfx::IntPoint* aSrcOffset = nullptr) override
{
return false;
}
protected:
void DeleteTextureHandle();
@ -280,6 +287,33 @@ protected:
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: