Bug 1168015 - Dump source image from graphic buffer directly on B2G. r=kamidphish, r=hshih

This commit is contained in:
CJKu 2015-05-28 02:30:00 -04:00
parent 21de128d37
commit 747011926e
5 changed files with 201 additions and 43 deletions

View File

@ -74,6 +74,7 @@ struct TexturedEffect : public Effect
TextureSource* mTexture;
bool mPremultiplied;
gfx::Filter mFilter;
LayerRenderState mState;
};
// Support an alpha mask.
@ -248,7 +249,8 @@ inline TemporaryRef<TexturedEffect>
CreateTexturedEffect(gfx::SurfaceFormat aFormat,
TextureSource* aSource,
const gfx::Filter& aFilter,
bool isAlphaPremultiplied)
bool isAlphaPremultiplied,
const LayerRenderState &state = LayerRenderState())
{
MOZ_ASSERT(aSource);
RefPtr<TexturedEffect> result;
@ -268,6 +270,8 @@ CreateTexturedEffect(gfx::SurfaceFormat aFormat,
break;
}
result->mState = state;
return result.forget();
}
@ -281,7 +285,8 @@ inline TemporaryRef<TexturedEffect>
CreateTexturedEffect(TextureSource* aSource,
TextureSource* aSourceOnWhite,
const gfx::Filter& aFilter,
bool isAlphaPremultiplied)
bool isAlphaPremultiplied,
const LayerRenderState &state = LayerRenderState())
{
MOZ_ASSERT(aSource);
if (aSourceOnWhite) {
@ -294,7 +299,8 @@ CreateTexturedEffect(TextureSource* aSource,
return CreateTexturedEffect(aSource->GetFormat(),
aSource,
aFilter,
isAlphaPremultiplied);
isAlphaPremultiplied,
state);
}
/**
@ -304,9 +310,10 @@ CreateTexturedEffect(TextureSource* aSource,
*/
inline TemporaryRef<TexturedEffect>
CreateTexturedEffect(TextureSource *aTexture,
const gfx::Filter& aFilter)
const gfx::Filter& aFilter,
const LayerRenderState &state = LayerRenderState())
{
return CreateTexturedEffect(aTexture, nullptr, aFilter, true);
return CreateTexturedEffect(aTexture, nullptr, aFilter, true, state);
}

View File

@ -270,6 +270,87 @@ protected:
int64_t mFrameStamp;
};
#ifdef MOZ_WIDGET_GONK
// B2G optimization.
class DebugGLGraphicBuffer final: public DebugGLData {
public:
DebugGLGraphicBuffer(void *layerRef,
GLenum target,
GLuint name,
const LayerRenderState &aState)
: DebugGLData(Packet::TEXTURE),
mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
mTarget(target),
mName(name),
mState(aState)
{
}
virtual bool Write() override {
return WriteToStream(mPacket);
}
bool TryPack() {
android::sp<android::GraphicBuffer> buffer = mState.mSurface;
MOZ_ASSERT(buffer.get());
mPacket.set_type(mDataType);
TexturePacket* tp = mPacket.mutable_texture();
tp->set_layerref(mLayerRef);
tp->set_name(mName);
tp->set_target(mTarget);
int format = buffer->getPixelFormat();
if (HAL_PIXEL_FORMAT_RGBA_8888 != format &&
HAL_PIXEL_FORMAT_RGBX_8888 != format) {
return false;
}
uint8_t* grallocData;
if (BAD_VALUE == buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN |
GRALLOC_USAGE_SW_WRITE_NEVER,
reinterpret_cast<void**>(&grallocData))) {
return false;
}
int32_t stride = buffer->getStride() * 4;
int32_t height = buffer->getHeight();
int32_t width = buffer->getWidth();
int32_t sourceSize = stride * height;
bool ret = false;
if (sourceSize > 0) {
auto compressedData = MakeUnique<char[]>(LZ4::maxCompressedSize(sourceSize));
int compressedSize = LZ4::compress((char*)grallocData,
sourceSize,
compressedData.get());
if (compressedSize > 0) {
uint32_t format = mState.FormatRBSwapped() ?
LOCAL_GL_BGRA : LOCAL_GL_RGBA;
tp->set_dataformat(format);
tp->set_dataformat((1 << 16 | tp->dataformat()));
tp->set_width(width);
tp->set_height(height);
tp->set_stride(stride);
tp->set_data(compressedData.get(), compressedSize);
ret = true;
}
}
buffer->unlock();
return ret;
}
private:
uint64_t mLayerRef;
GLenum mTarget;
GLuint mName;
const LayerRenderState &mState;
Packet mPacket;
};
#endif
class DebugGLTextureData final: public DebugGLData {
public:
DebugGLTextureData(GLContext* cx,
@ -608,7 +689,6 @@ public:
static void ClearTextureIdList();
static bool IsTextureIdContainsInList(GLuint aTextureId);
// Sender private functions
private:
@ -619,14 +699,23 @@ private:
static void SendTextureSource(GLContext* aGLContext,
void* aLayerRef,
TextureSourceOGL* aSource,
GLuint aTexID,
bool aFlipY);
#ifdef MOZ_WIDGET_GONK
static bool SendGraphicBuffer(void* aLayerRef,
TextureSourceOGL* aSource,
GLuint aTexID,
const TexturedEffect* aEffect);
#endif
static void SendTexturedEffect(GLContext* aGLContext,
void* aLayerRef,
const TexturedEffect* aEffect);
static void SendYCbCrEffect(GLContext* aGLContext,
void* aLayerRef,
const EffectYCbCr* aEffect);
static GLuint GetTextureID(GLContext* aGLContext,
TextureSourceOGL* aSource);
static bool IsTextureIdContainsInList(GLuint aTextureId);
// Data fields
private:
static bool sLayersTreeSendable;
@ -714,10 +803,31 @@ SenderHelper::SendColor(void* aLayerRef,
new DebugGLColorData(aLayerRef, aColor, aWidth, aHeight));
}
GLuint
SenderHelper::GetTextureID(GLContext* aGLContext,
TextureSourceOGL* aSource) {
GLenum textureTarget = aSource->GetTextureTarget();
aSource->BindTexture(LOCAL_GL_TEXTURE0, gfx::Filter::LINEAR);
GLuint texID = 0;
// This is horrid hack. It assumes that aGLContext matches the context
// aSource has bound to.
if (textureTarget == LOCAL_GL_TEXTURE_2D) {
aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &texID);
} else if (textureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &texID);
} else if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &texID);
}
return texID;
}
void
SenderHelper::SendTextureSource(GLContext* aGLContext,
void* aLayerRef,
TextureSourceOGL* aSource,
GLuint aTexID,
bool aFlipY)
{
MOZ_ASSERT(aGLContext);
@ -730,46 +840,68 @@ SenderHelper::SendTextureSource(GLContext* aGLContext,
aSource->GetFormat());
int shaderConfig = config.mFeatures;
aSource->BindTexture(LOCAL_GL_TEXTURE0, gfx::Filter::LINEAR);
gfx::IntSize size = aSource->GetSize();
GLuint textureId = 0;
// This is horrid hack. It assumes that aGLContext matches the context
// aSource has bound to.
if (textureTarget == LOCAL_GL_TEXTURE_2D) {
aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &textureId);
} else if (textureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &textureId);
} else if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
aGLContext->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &textureId);
}
if (!IsTextureIdContainsInList(textureId)) {
gfx::IntSize size = aSource->GetSize();
// By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
// texture correctly. textureId is used for tracking in DebugGLTextureData.
RefPtr<DataSourceSurface> img =
aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
// By sending 0 to ReadTextureImage rely upon aSource->BindTexture binding
// texture correctly. texID is used for tracking in DebugGLTextureData.
RefPtr<DataSourceSurface> img =
aGLContext->ReadTexImageHelper()->ReadTexImage(0, textureTarget,
size,
shaderConfig, aFlipY);
sTextureIdList.push_back(textureId);
WebSocketHelper::GetSocketManager()->AppendDebugData(
new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
textureId, img));
}
WebSocketHelper::GetSocketManager()->AppendDebugData(
new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
aTexID, img));
sTextureIdList.push_back(aTexID);
}
#ifdef MOZ_WIDGET_GONK
bool
SenderHelper::SendGraphicBuffer(void* aLayerRef,
TextureSourceOGL* aSource,
GLuint aTexID,
const TexturedEffect* aEffect) {
if (!aEffect->mState.mSurface.get()) {
return false;
}
GLenum target = aSource->GetTextureTarget();
mozilla::UniquePtr<DebugGLGraphicBuffer> package =
MakeUnique<DebugGLGraphicBuffer>(aLayerRef, target, aTexID, aEffect->mState);
if (!package->TryPack()) {
return false;
}
// Transfer ownership to SocketManager.
WebSocketHelper::GetSocketManager()->AppendDebugData(package.release());
sTextureIdList.push_back(aTexID);
return true;
}
#endif
void
SenderHelper::SendTexturedEffect(GLContext* aGLContext,
void* aLayerRef,
const TexturedEffect* aEffect)
{
TextureSourceOGL* source = aEffect->mTexture->AsSourceOGL();
if (!source)
if (!source) {
return;
}
bool flipY = false;
SendTextureSource(aGLContext, aLayerRef, source, flipY);
GLuint texID = GetTextureID(aGLContext, source);
if (IsTextureIdContainsInList(texID)) {
return;
}
#ifdef MOZ_WIDGET_GONK
if (SendGraphicBuffer(aLayerRef, source, texID, aEffect)) {
return;
}
#endif
// Render to texture and read pixels back.
SendTextureSource(aGLContext, aLayerRef, source, texID, false);
}
void
@ -786,10 +918,20 @@ SenderHelper::SendYCbCrEffect(GLContext* aGLContext,
TextureSourceOGL* sourceCb = sourceYCbCr->GetSubSource(Cb)->AsSourceOGL();
TextureSourceOGL* sourceCr = sourceYCbCr->GetSubSource(Cr)->AsSourceOGL();
bool flipY = false;
SendTextureSource(aGLContext, aLayerRef, sourceY, flipY);
SendTextureSource(aGLContext, aLayerRef, sourceCb, flipY);
SendTextureSource(aGLContext, aLayerRef, sourceCr, flipY);
GLuint texID = GetTextureID(aGLContext, sourceY);
if (!IsTextureIdContainsInList(texID)) {
SendTextureSource(aGLContext, aLayerRef, sourceY, texID, false);
}
texID = GetTextureID(aGLContext, sourceCb);
if (!IsTextureIdContainsInList(texID)) {
SendTextureSource(aGLContext, aLayerRef, sourceCb, texID, false);
}
texID = GetTextureID(aGLContext, sourceCr);
if (!IsTextureIdContainsInList(texID)) {
SendTextureSource(aGLContext, aLayerRef, sourceCr, texID, false);
}
}
void

View File

@ -63,7 +63,8 @@ ContentHostTexture::Composite(EffectChain& aEffectChain,
RefPtr<TexturedEffect> effect = CreateTexturedEffect(mTextureSource.get(),
mTextureSourceOnWhite.get(),
aFilter, true);
aFilter, true,
GetRenderState());
if (!effect) {
return;
}
@ -460,7 +461,8 @@ ContentHostTexture::GenEffect(const gfx::Filter& aFilter)
}
return CreateTexturedEffect(mTextureSource.get(),
mTextureSourceOnWhite.get(),
aFilter, true);
aFilter, true,
GetRenderState());
}
TemporaryRef<gfx::DataSourceSurface>

View File

@ -106,7 +106,8 @@ ImageHost::Composite(EffectChain& aEffectChain,
RefPtr<TexturedEffect> effect = CreateTexturedEffect(mFrontBuffer->GetFormat(),
mTextureSource.get(),
aFilter,
isAlphaPremultiplied);
isAlphaPremultiplied,
GetRenderState());
if (!effect) {
return;
}
@ -298,7 +299,8 @@ ImageHost::GenEffect(const gfx::Filter& aFilter)
return CreateTexturedEffect(mFrontBuffer->GetFormat(),
mTextureSource,
aFilter,
isAlphaPremultiplied);
isAlphaPremultiplied,
GetRenderState());
}
#ifdef MOZ_WIDGET_GONK

View File

@ -468,7 +468,12 @@ TiledContentHost::RenderTile(TileHost& aTile,
return;
}
RefPtr<TexturedEffect> effect = CreateTexturedEffect(aTile.mTextureSource, aTile.mTextureSourceOnWhite, aFilter, true);
RefPtr<TexturedEffect> effect =
CreateTexturedEffect(aTile.mTextureSource,
aTile.mTextureSourceOnWhite,
aFilter,
true,
aTile.mTextureHost->GetRenderState());
if (!effect) {
return;
}