Bug 1097116 - Fix readback for EGLImageImage r=jgilbert

This commit is contained in:
James Willcox 2014-11-21 09:28:21 -06:00
parent 072c94925b
commit f72db720a8
4 changed files with 84 additions and 35 deletions

View File

@ -305,6 +305,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
GLuint *fragShaderPtr;
const char* fragShaderSource;
switch (target) {
case ConvertEGLImage:
case BlitTex2D:
programPtr = &mTex2DBlit_Program;
fragShaderPtr = &mTex2DBlit_FragShader;
@ -451,6 +452,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
switch (target) {
case BlitTex2D:
case BlitTexRect:
case ConvertEGLImage:
case ConvertSurfaceTexture:
case ConvertGralloc: {
#ifdef ANDROID
@ -666,25 +668,26 @@ GLBlitHelper::BindAndUploadYUVTexture(Channel which,
}
}
#ifdef MOZ_WIDGET_GONK
void
GLBlitHelper::BindAndUploadExternalTexture(EGLImage image)
GLBlitHelper::BindAndUploadEGLImage(EGLImage image, GLuint target)
{
MOZ_ASSERT(image != EGL_NO_IMAGE, "Bad EGLImage");
if (!mSrcTexEGL) {
mGL->fGenTextures(1, &mSrcTexEGL);
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mSrcTexEGL);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
mGL->fBindTexture(target, mSrcTexEGL);
mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
} else {
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mSrcTexEGL);
mGL->fBindTexture(target, mSrcTexEGL);
}
mGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL_OES, image);
mGL->fEGLImageTargetTexture2D(target, image);
}
#ifdef MOZ_WIDGET_GONK
bool
GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip)
{
@ -705,7 +708,7 @@ GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip)
int oldBinding = 0;
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL_OES, &oldBinding);
BindAndUploadExternalTexture(image);
BindAndUploadEGLImage(image, LOCAL_GL_TEXTURE_EXTERNAL_OES);
mGL->fUniform1f(mYFlipLoc, yFlip ? (float)1.0f : (float)0.0f);
@ -720,13 +723,14 @@ GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip)
#ifdef MOZ_WIDGET_ANDROID
bool
GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage)
GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool yFlip)
{
AndroidSurfaceTexture* surfaceTexture = stImage->GetData()->mSurfTex;
bool yFlip = stImage->GetData()->mInverted;
if (stImage->GetData()->mInverted) {
yFlip = !yFlip;
}
ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
if (NS_FAILED(surfaceTexture->Attach(mGL))) {
return false;
@ -751,6 +755,39 @@ GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage)
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, oldBinding);
return true;
}
bool
GLBlitHelper::BlitEGLImageImage(layers::EGLImageImage* image, bool yFlip)
{
EGLImage eglImage = image->GetData()->mImage;
EGLSync eglSync = image->GetData()->mSync;
if (image->GetData()->mInverted) {
yFlip = !yFlip;
}
if (eglSync) {
EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), eglSync, 0, LOCAL_EGL_FOREVER);
if (status != LOCAL_EGL_CONDITION_SATISFIED) {
return false;
}
}
ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
int oldBinding = 0;
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldBinding);
BindAndUploadEGLImage(eglImage, LOCAL_GL_TEXTURE_2D);
mGL->fUniform1f(mYFlipLoc, yFlip ? 1.0f : 0.0f);
mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, oldBinding);
return true;
}
#endif
bool
@ -816,6 +853,9 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
case ImageFormat::SURFACE_TEXTURE:
type = ConvertSurfaceTexture;
break;
case ImageFormat::EGLIMAGE:
type = ConvertEGLImage;
break;
#endif
default:
return false;
@ -848,7 +888,11 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
#ifdef MOZ_WIDGET_ANDROID
if (type == ConvertSurfaceTexture) {
layers::SurfaceTextureImage* stImage = static_cast<layers::SurfaceTextureImage*>(srcImage);
return BlitSurfaceTextureImage(stImage);
return BlitSurfaceTextureImage(stImage, yFlip);
}
if (type == ConvertEGLImage) {
layers::EGLImageImage* eglImage = static_cast<layers::EGLImageImage*>(srcImage);
return BlitEGLImageImage(eglImage, yFlip);
}
#endif

View File

@ -20,6 +20,7 @@ class Image;
class PlanarYCbCrImage;
class GrallocImage;
class SurfaceTextureImage;
class EGLImageImage;
}
namespace gl {
@ -98,7 +99,8 @@ class GLBlitHelper MOZ_FINAL
BlitTexRect,
ConvertGralloc,
ConvertPlanarYCbCr,
ConvertSurfaceTexture
ConvertSurfaceTexture,
ConvertEGLImage
};
// The GLContext is the sole owner of the GLBlitHelper.
GLContext* mGL;
@ -140,14 +142,15 @@ class GLBlitHelper MOZ_FINAL
bool InitTexQuadProgram(BlitType target = BlitTex2D);
void DeleteTexBlitProgram();
void BindAndUploadYUVTexture(Channel which, uint32_t width, uint32_t height, void* data, bool allocation);
void BindAndUploadEGLImage(EGLImage image, GLuint target);
#ifdef MOZ_WIDGET_GONK
void BindAndUploadExternalTexture(EGLImage image);
bool BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip = false);
#endif
bool BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFlip = false);
#ifdef MOZ_WIDGET_ANDROID
bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage);
bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool yFlip = false);
bool BlitEGLImageImage(layers::EGLImageImage* eglImage, bool yFlip = false);
#endif
public:

View File

@ -35,16 +35,16 @@ EGLImageImage::~EGLImageImage()
}
}
TemporaryRef<gfx::SourceSurface>
SurfaceTextureImage::GetAsSourceSurface()
TemporaryRef<SourceSurface>
GLImage::GetAsSourceSurface()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread");
if (!sSnapshotContext) {
SurfaceCaps caps = SurfaceCaps::ForRGBA();
sSnapshotContext = GLContextProvider::CreateOffscreen(gfxIntSize(16, 16), caps);
sSnapshotContext = GLContextProvider::CreateHeadless();
if (!sSnapshotContext) {
NS_WARNING("Failed to create snapshot GLContext");
return nullptr;
}
}
@ -52,8 +52,10 @@ SurfaceTextureImage::GetAsSourceSurface()
sSnapshotContext->MakeCurrent();
ScopedTexture scopedTex(sSnapshotContext);
ScopedBindTexture boundTex(sSnapshotContext, scopedTex.Texture());
gfx::IntSize size = GetSize();
sSnapshotContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA,
mData.mSize.width, mData.mSize.height, 0,
size.width, size.height, 0,
LOCAL_GL_RGBA,
LOCAL_GL_UNSIGNED_BYTE,
nullptr);
@ -62,11 +64,11 @@ SurfaceTextureImage::GetAsSourceSurface()
GLBlitHelper helper(sSnapshotContext);
helper.BlitImageToFramebuffer(this, mData.mSize, fb.FB(), false);
helper.BlitImageToFramebuffer(this, size, fb.FB(), false);
ScopedBindFramebuffer bind(sSnapshotContext, fb.FB());
RefPtr<gfx::DataSourceSurface> source =
gfx::Factory::CreateDataSourceSurface(mData.mSize, gfx::SurfaceFormat::B8G8R8A8);
gfx::Factory::CreateDataSourceSurface(size, gfx::SurfaceFormat::B8G8R8A8);
if (NS_WARN_IF(!source)) {
return nullptr;
}

View File

@ -18,7 +18,14 @@ class AndroidSurfaceTexture;
}
namespace layers {
class EGLImageImage : public Image {
class GLImage : public Image {
public:
GLImage(ImageFormat aFormat) : Image(nullptr, aFormat){}
virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
};
class EGLImageImage : public GLImage {
public:
struct Data {
EGLImage mImage;
@ -37,12 +44,7 @@ public:
gfx::IntSize GetSize() { return mData.mSize; }
virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE
{
return nullptr;
}
EGLImageImage() : Image(nullptr, ImageFormat::EGLIMAGE) {}
EGLImageImage() : GLImage(ImageFormat::EGLIMAGE) {}
protected:
virtual ~EGLImageImage();
@ -53,7 +55,7 @@ private:
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureImage : public Image {
class SurfaceTextureImage : public GLImage {
public:
struct Data {
mozilla::gl::AndroidSurfaceTexture* mSurfTex;
@ -66,9 +68,7 @@ public:
gfx::IntSize GetSize() { return mData.mSize; }
virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
SurfaceTextureImage() : Image(nullptr, ImageFormat::SURFACE_TEXTURE) {}
SurfaceTextureImage() : GLImage(ImageFormat::SURFACE_TEXTURE) {}
private:
Data mData;