Bug 1014614 - Add GLBlitHelper::BlitImageToFramebuffer and support SurfaceTexture images r=jgilbert

--HG--
extra : rebase_source : e823897f3ff6593af7286432903618dc483877dd
This commit is contained in:
James Willcox 2014-10-21 08:53:02 -05:00
parent e6fdc3e284
commit 9a5423d8f0
2 changed files with 122 additions and 31 deletions

View File

@ -10,12 +10,18 @@
#include "mozilla/Preferences.h"
#include "ImageContainer.h"
#include "HeapCopyOfStackArray.h"
#include "mozilla/gfx/Matrix.h"
#ifdef MOZ_WIDGET_GONK
#include "GrallocImages.h"
#include "GLLibraryEGL.h"
#endif
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidSurfaceTexture.h"
#include "GLImages.h"
#endif
using mozilla::layers::PlanarYCbCrImage;
using mozilla::layers::PlanarYCbCrData;
@ -144,6 +150,7 @@ GLBlitHelper::GLBlitHelper(GLContext* gl)
, mTex2DBlit_Program(0)
, mTex2DRectBlit_Program(0)
, mYFlipLoc(-1)
, mTextureTransformLoc(-1)
, mTexExternalBlit_FragShader(0)
, mTexYUVPlanarBlit_FragShader(0)
, mTexExternalBlit_Program(0)
@ -238,21 +245,23 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
vTexCoord * uTexCoordMult); \n\
} \n\
";
#ifdef MOZ_WIDGET_GONK
#ifdef ANDROID /* MOZ_WIDGET_ANDROID || MOZ_WIDGET_GONK */
const char kTexExternalBlit_FragShaderSource[] = "\
#extension GL_OES_EGL_image_external : require \n\
#ifdef GL_FRAGMENT_PRECISION_HIGH \n\
precision highp float; \n\
#else \n\
precision mediump float; \n\
#endif \n\
varying vec2 vTexCoord; \n\
uniform samplerExternalOES uTexUnit; \n\
\n\
void main() \n\
{ \n\
gl_FragColor = texture2D(uTexUnit, vTexCoord); \n\
} \n\
#extension GL_OES_EGL_image_external : require \n\
#ifdef GL_FRAGMENT_PRECISION_HIGH \n\
precision highp float; \n\
#else \n\
precision mediump float; \n\
#endif \n\
varying vec2 vTexCoord; \n\
uniform mat4 uTextureTransform; \n\
uniform samplerExternalOES uTexUnit; \n\
\n\
void main() \n\
{ \n\
gl_FragColor = texture2D(uTexUnit, \n\
(uTextureTransform * vec4(vTexCoord, 0.0, 1.0)).xy); \n\
} \n\
";
#endif
/* From Rec601:
@ -306,7 +315,8 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
fragShaderPtr = &mTex2DRectBlit_FragShader;
fragShaderSource = kTex2DRectBlit_FragShaderSource;
break;
#ifdef MOZ_WIDGET_GONK
#ifdef ANDROID
case ConvertSurfaceTexture:
case ConvertGralloc:
programPtr = &mTexExternalBlit_Program;
fragShaderPtr = &mTexExternalBlit_FragShader;
@ -441,8 +451,9 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
switch (target) {
case BlitTex2D:
case BlitTexRect:
case ConvertSurfaceTexture:
case ConvertGralloc: {
#ifdef MOZ_WIDGET_GONK
#ifdef ANDROID
GLint texUnitLoc = mGL->fGetUniformLocation(program, "uTexUnit");
MOZ_ASSERT(texUnitLoc != -1, "uniform uTexUnit not found");
mGL->fUniform1i(texUnitLoc, 0);
@ -472,6 +483,12 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
MOZ_ASSERT(mGL->fGetAttribLocation(program, "aPosition") == 0);
mYFlipLoc = mGL->fGetUniformLocation(program, "uYflip");
MOZ_ASSERT(mYFlipLoc != -1, "uniform: uYflip not found");
mTextureTransformLoc = mGL->fGetUniformLocation(program, "uTextureTransform");
if (mTextureTransformLoc >= 0) {
// Set identity matrix as default
gfx::Matrix4x4 identity;
mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &identity._11);
}
success = true;
} while (false);
@ -700,6 +717,42 @@ GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip)
}
#endif
#ifdef MOZ_WIDGET_ANDROID
bool
GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage)
{
AndroidSurfaceTexture* surfaceTexture = stImage->GetData()->mSurfTex;
bool yFlip = stImage->GetData()->mInverted;
ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
if (!surfaceTexture->Attach(mGL)) {
return false;
}
// UpdateTexImage() changes the EXTERNAL binding, so save it here
// so we can restore it after.
int oldBinding = 0;
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &oldBinding);
surfaceTexture->UpdateTexImage();
gfx::Matrix4x4 transform;
surfaceTexture->GetTransformMatrix(transform);
mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &transform._11);
mGL->fUniform1f(mYFlipLoc, yFlip ? 1.0f : 0.0f);
mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
surfaceTexture->Detach();
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, oldBinding);
return true;
}
#endif
bool
GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFlip)
{
@ -738,15 +791,14 @@ GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFli
}
bool
GLBlitHelper::BlitImageToTexture(layers::Image* srcImage,
const gfx::IntSize& destSize,
GLuint destTex,
GLenum destTarget,
bool yFlip,
GLuint xoffset,
GLuint yoffset,
GLuint cropWidth,
GLuint cropHeight)
GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
const gfx::IntSize& destSize,
GLuint destFB,
bool yFlip,
GLuint xoffset,
GLuint yoffset,
GLuint cropWidth,
GLuint cropHeight)
{
ScopedGLDrawState autoStates(mGL);
@ -759,6 +811,11 @@ GLBlitHelper::BlitImageToTexture(layers::Image* srcImage,
#ifdef MOZ_WIDGET_GONK
type = ConvertGralloc;
break;
#endif
#ifdef MOZ_WIDGET_ANDROID
case ImageFormat::SURFACE_TEXTURE:
type = ConvertSurfaceTexture;
break;
#endif
default:
return false;
@ -769,12 +826,7 @@ GLBlitHelper::BlitImageToTexture(layers::Image* srcImage,
return false;
}
if (!mFBO) {
mGL->fGenFramebuffers(1, &mFBO);
}
ScopedBindFramebuffer boundFB(mGL, mFBO);
mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, destTarget, destTex, 0);
ScopedBindFramebuffer boundFB(mGL, destFB);
mGL->fColorMask(LOCAL_GL_TRUE, LOCAL_GL_TRUE, LOCAL_GL_TRUE, LOCAL_GL_TRUE);
mGL->fViewport(0, 0, destSize.width, destSize.height);
if (xoffset != 0 && yoffset != 0 && cropWidth != 0 && cropHeight != 0) {
@ -793,10 +845,39 @@ GLBlitHelper::BlitImageToTexture(layers::Image* srcImage,
PlanarYCbCrImage* yuvImage = static_cast<PlanarYCbCrImage*>(srcImage);
return BlitPlanarYCbCrImage(yuvImage, yFlip);
}
#ifdef MOZ_WIDGET_ANDROID
if (type == ConvertSurfaceTexture) {
layers::SurfaceTextureImage* stImage = static_cast<layers::SurfaceTextureImage*>(srcImage);
return BlitSurfaceTextureImage(stImage);
}
#endif
return false;
}
bool
GLBlitHelper::BlitImageToTexture(layers::Image* srcImage,
const gfx::IntSize& destSize,
GLuint destTex,
GLenum destTarget,
bool yFlip,
GLuint xoffset,
GLuint yoffset,
GLuint cropWidth,
GLuint cropHeight)
{
ScopedGLDrawState autoStates(mGL);
if (!mFBO) {
mGL->fGenFramebuffers(1, &mFBO);
}
ScopedBindFramebuffer boundFB(mGL, mFBO);
mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, destTarget, destTex, 0);
return BlitImageToFramebuffer(srcImage, destSize, mFBO, yFlip, xoffset, yoffset,
cropWidth, cropHeight);
}
void
GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
const gfx::IntSize& srcSize,

View File

@ -19,6 +19,7 @@ namespace layers {
class Image;
class PlanarYCbCrImage;
class GrallocImage;
class SurfaceTextureImage;
}
namespace gl {
@ -97,6 +98,7 @@ class GLBlitHelper MOZ_FINAL
BlitTexRect,
ConvertGralloc,
ConvertPlanarYCbCr,
ConvertSurfaceTexture
};
// The GLContext is the sole owner of the GLBlitHelper.
GLContext* mGL;
@ -110,6 +112,8 @@ class GLBlitHelper MOZ_FINAL
GLint mYFlipLoc;
GLint mTextureTransformLoc;
// Data for image blit path
GLuint mTexExternalBlit_FragShader;
GLuint mTexYUVPlanarBlit_FragShader;
@ -142,6 +146,9 @@ class GLBlitHelper MOZ_FINAL
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);
#endif
public:
@ -175,6 +182,9 @@ public:
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
GLenum destTarget = LOCAL_GL_TEXTURE_2D);
bool BlitImageToFramebuffer(layers::Image* srcImage, const gfx::IntSize& destSize,
GLuint destFB, bool yFlip = false, GLuint xoffset = 0,
GLuint yoffset = 0, GLuint width = 0, GLuint height = 0);
bool BlitImageToTexture(layers::Image* srcImage, const gfx::IntSize& destSize,
GLuint destTex, GLenum destTarget, bool yFlip = false, GLuint xoffset = 0,
GLuint yoffset = 0, GLuint width = 0, GLuint height = 0);