Bug 774552 - Draw GraphicBuffer directly. r=roc,BenWa
This commit is contained in:
@@ -55,6 +55,7 @@ enum ShaderProgramType {
|
||||
RGBXLayerProgramType,
|
||||
BGRXLayerProgramType,
|
||||
RGBARectLayerProgramType,
|
||||
RGBAExternalLayerProgramType,
|
||||
ColorLayerProgramType,
|
||||
YCbCrLayerProgramType,
|
||||
ComponentAlphaPass1ProgramType,
|
||||
@@ -740,6 +741,7 @@ public:
|
||||
*/
|
||||
void ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter);
|
||||
|
||||
virtual bool BindExternalBuffer(GLuint texture, void* buffer) { return false; }
|
||||
|
||||
/*
|
||||
* Offscreen support API
|
||||
|
||||
@@ -44,6 +44,7 @@ using namespace android;
|
||||
|
||||
# define EGL_NATIVE_BUFFER_ANDROID 0x3140
|
||||
# define EGL_IMAGE_PRESERVED_KHR 0x30D2
|
||||
# define GL_TEXTURE_EXTERNAL_OES 0x8D65
|
||||
|
||||
# endif
|
||||
|
||||
@@ -403,6 +404,26 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BindExternalBuffer(GLuint texture, void* buffer)
|
||||
{
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
EGLint attrs[] = {
|
||||
EGL_IMAGE_PRESERVED_KHR, LOCAL_EGL_TRUE,
|
||||
LOCAL_EGL_NONE, LOCAL_EGL_NONE
|
||||
};
|
||||
EGLImage image = sEGLLibrary.fCreateImage(EGL_DISPLAY(),
|
||||
EGL_NO_CONTEXT,
|
||||
EGL_NATIVE_BUFFER_ANDROID,
|
||||
buffer, attrs);
|
||||
sEGLLibrary.fImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
|
||||
fBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
|
||||
sEGLLibrary.fDestroyImage(EGL_DISPLAY(), image);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MakeCurrentImpl(bool aForce = false) {
|
||||
bool succeeded = true;
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@ ImageFactory::CreateImage(const Image::Format *aFormats,
|
||||
#ifdef XP_MACOSX
|
||||
} else if (FormatInList(aFormats, aNumFormats, Image::MAC_IO_SURFACE)) {
|
||||
img = new MacIOSurfaceImage();
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
} else if (FormatInList(aFormats, aNumFormats, Image::GONK_IO_SURFACE)) {
|
||||
img = new GonkIOSurfaceImage();
|
||||
#endif
|
||||
}
|
||||
return img.forget();
|
||||
|
||||
@@ -27,6 +27,9 @@ struct ID3D10ShaderResourceView;
|
||||
|
||||
typedef void* HANDLE;
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
# include <ui/GraphicBuffer.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -106,6 +109,13 @@ public:
|
||||
*/
|
||||
MAC_IO_SURFACE,
|
||||
|
||||
/**
|
||||
* The GONK_IO_SURFACE format creates a GonkIOSurfaceImage.
|
||||
*
|
||||
* It wraps an GraphicBuffer object and binds it directly to a GL texture.
|
||||
*/
|
||||
GONK_IO_SURFACE,
|
||||
|
||||
/**
|
||||
* An bitmap image that can be shared with a remote process.
|
||||
*/
|
||||
@@ -924,6 +934,82 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
/**
|
||||
* The gralloc buffer maintained by android GraphicBuffer can be
|
||||
* shared between the compositor thread and the producer thread. The
|
||||
* mGraphicBuffer is owned by the producer thread, but when it is
|
||||
* wrapped by GraphicBufferLocked and passed to the compositor, the
|
||||
* buffer content is guaranteed to not change until Unlock() is
|
||||
* called. Each producer must maintain their own buffer queue and
|
||||
* implement the GraphicBufferLocked::Unlock() interface.
|
||||
*/
|
||||
class GraphicBufferLocked {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GraphicBufferLocked)
|
||||
|
||||
public:
|
||||
GraphicBufferLocked(android::GraphicBuffer* aGraphicBuffer)
|
||||
: mGraphicBuffer(aGraphicBuffer)
|
||||
{}
|
||||
|
||||
virtual ~GraphicBufferLocked() {}
|
||||
|
||||
virtual void Unlock() {}
|
||||
|
||||
virtual void* GetNativeBuffer()
|
||||
{
|
||||
return mGraphicBuffer->getNativeBuffer();
|
||||
}
|
||||
|
||||
protected:
|
||||
android::GraphicBuffer* mGraphicBuffer;
|
||||
};
|
||||
|
||||
class THEBES_API GonkIOSurfaceImage : public Image {
|
||||
public:
|
||||
struct Data {
|
||||
nsRefPtr<GraphicBufferLocked> mGraphicBuffer;
|
||||
gfxIntSize mPicSize;
|
||||
};
|
||||
|
||||
GonkIOSurfaceImage()
|
||||
: Image(NULL, GONK_IO_SURFACE)
|
||||
, mSize(0, 0)
|
||||
{}
|
||||
|
||||
virtual ~GonkIOSurfaceImage()
|
||||
{
|
||||
mGraphicBuffer->Unlock();
|
||||
}
|
||||
|
||||
virtual void SetData(const Data& aData)
|
||||
{
|
||||
mGraphicBuffer = aData.mGraphicBuffer;
|
||||
mSize = aData.mPicSize;
|
||||
}
|
||||
|
||||
virtual gfxIntSize GetSize()
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
virtual already_AddRefed<gfxASurface> GetAsSurface()
|
||||
{
|
||||
// We need to fix this and return a ASurface at some point.
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void* GetNativeBuffer()
|
||||
{
|
||||
return mGraphicBuffer->GetNativeBuffer();
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<GraphicBufferLocked> mGraphicBuffer;
|
||||
gfxIntSize mSize;
|
||||
};
|
||||
#endif
|
||||
|
||||
class RemoteBitmapImage : public Image {
|
||||
public:
|
||||
RemoteBitmapImage() : Image(NULL, REMOTE_IMAGE_BITMAP) {}
|
||||
|
||||
@@ -176,6 +176,23 @@ AllocateTextureIOSurface(MacIOSurfaceImage *aIOImage, mozilla::gl::GLContext* aG
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
struct THEBES_API GonkIOSurfaceImageOGLBackendData : public ImageBackendData
|
||||
{
|
||||
GLTexture mTexture;
|
||||
};
|
||||
|
||||
void
|
||||
AllocateTextureIOSurface(GonkIOSurfaceImage *aIOImage, mozilla::gl::GLContext* aGL)
|
||||
{
|
||||
nsAutoPtr<GonkIOSurfaceImageOGLBackendData> backendData(
|
||||
new GonkIOSurfaceImageOGLBackendData);
|
||||
|
||||
backendData->mTexture.Allocate(aGL);
|
||||
aIOImage->SetBackendData(LayerManager::LAYERS_OPENGL, backendData.forget());
|
||||
}
|
||||
#endif
|
||||
|
||||
Layer*
|
||||
ImageLayerOGL::GetLayer()
|
||||
{
|
||||
@@ -297,8 +314,6 @@ ImageLayerOGL::RenderLayer(int,
|
||||
}
|
||||
|
||||
gl()->MakeCurrent();
|
||||
unsigned int iwidth = cairoImage->mSize.width;
|
||||
unsigned int iheight = cairoImage->mSize.height;
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTexture.GetTextureID());
|
||||
@@ -321,51 +336,21 @@ ImageLayerOGL::RenderLayer(int,
|
||||
gl()->ApplyFilterToBoundTexture(mFilter);
|
||||
|
||||
program->Activate();
|
||||
// The following uniform controls the scaling of the vertex coords.
|
||||
// Instead of setting the scale here and using coords in the range [0,1], we
|
||||
// set an identity transform and use pixel coordinates below
|
||||
program->SetLayerQuadRect(nsIntRect(0, 0, 1, 1));
|
||||
program->SetLayerQuadRect(nsIntRect(0, 0,
|
||||
cairoImage->GetSize().width,
|
||||
cairoImage->GetSize().height));
|
||||
program->SetLayerTransform(GetEffectiveTransform());
|
||||
program->SetLayerOpacity(GetEffectiveOpacity());
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetTextureUnit(0);
|
||||
program->LoadMask(GetMaskLayer());
|
||||
|
||||
nsIntRect rect = GetVisibleRegion().GetBounds();
|
||||
mOGLManager->BindAndDrawQuadWithTextureRect(program,
|
||||
GetVisibleRegion().GetBounds(),
|
||||
nsIntSize(cairoImage->GetSize().width,
|
||||
cairoImage->GetSize().height));
|
||||
|
||||
GLContext::RectTriangles triangleBuffer;
|
||||
|
||||
float tex_offset_u = float(rect.x % iwidth) / iwidth;
|
||||
float tex_offset_v = float(rect.y % iheight) / iheight;
|
||||
triangleBuffer.addRect(rect.x, rect.y,
|
||||
rect.x + rect.width, rect.y + rect.height,
|
||||
tex_offset_u, tex_offset_v,
|
||||
tex_offset_u + float(rect.width) / float(iwidth),
|
||||
tex_offset_v + float(rect.height) / float(iheight));
|
||||
|
||||
GLuint vertAttribIndex =
|
||||
program->AttribLocation(ShaderProgramOGL::VertexCoordAttrib);
|
||||
GLuint texCoordAttribIndex =
|
||||
program->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
|
||||
NS_ASSERTION(texCoordAttribIndex != GLuint(-1), "no texture coords?");
|
||||
|
||||
gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
gl()->fVertexAttribPointer(vertAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
triangleBuffer.vertexPointer());
|
||||
|
||||
gl()->fVertexAttribPointer(texCoordAttribIndex, 2,
|
||||
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
|
||||
triangleBuffer.texCoordPointer());
|
||||
{
|
||||
gl()->fEnableVertexAttribArray(texCoordAttribIndex);
|
||||
{
|
||||
gl()->fEnableVertexAttribArray(vertAttribIndex);
|
||||
gl()->fDrawArrays(LOCAL_GL_TRIANGLES, 0, triangleBuffer.elements());
|
||||
gl()->fDisableVertexAttribArray(vertAttribIndex);
|
||||
}
|
||||
gl()->fDisableVertexAttribArray(texCoordAttribIndex);
|
||||
}
|
||||
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
|
||||
if (cairoImage->mSurface && pixmap) {
|
||||
sGLXLibrary.ReleaseTexImage(pixmap);
|
||||
@@ -427,6 +412,45 @@ ImageLayerOGL::RenderLayer(int,
|
||||
|
||||
mOGLManager->BindAndDrawQuad(program);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
} else if (image->GetFormat() == Image::GONK_IO_SURFACE) {
|
||||
|
||||
GonkIOSurfaceImage *ioImage = static_cast<GonkIOSurfaceImage*>(image);
|
||||
if (!ioImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
gl()->MakeCurrent();
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
|
||||
if (!ioImage->GetBackendData(LayerManager::LAYERS_OPENGL)) {
|
||||
AllocateTextureIOSurface(ioImage, gl());
|
||||
}
|
||||
GonkIOSurfaceImageOGLBackendData *data =
|
||||
static_cast<GonkIOSurfaceImageOGLBackendData*>(ioImage->GetBackendData(LayerManager::LAYERS_OPENGL));
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->BindExternalBuffer(data->mTexture.GetTextureID(), ioImage->GetNativeBuffer());
|
||||
|
||||
ShaderProgramOGL *program = mOGLManager->GetProgram(RGBAExternalLayerProgramType, GetMaskLayer());
|
||||
|
||||
gl()->ApplyFilterToBoundTexture(mFilter);
|
||||
|
||||
program->Activate();
|
||||
program->SetLayerQuadRect(nsIntRect(0, 0,
|
||||
ioImage->GetSize().width,
|
||||
ioImage->GetSize().height));
|
||||
program->SetLayerTransform(GetEffectiveTransform());
|
||||
program->SetLayerOpacity(GetEffectiveOpacity());
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->SetTextureUnit(0);
|
||||
program->LoadMask(GetMaskLayer());
|
||||
|
||||
mOGLManager->BindAndDrawQuadWithTextureRect(program,
|
||||
GetVisibleRegion().GetBounds(),
|
||||
nsIntSize(ioImage->GetSize().width,
|
||||
ioImage->GetSize().height));
|
||||
#endif
|
||||
}
|
||||
GetContainer()->NotifyPaintedImage(image);
|
||||
|
||||
@@ -104,6 +104,21 @@ ProgramProfileOGL::GetProfileFor(gl::ShaderProgramType aType,
|
||||
AddCommonTextureArgs(result);
|
||||
result.mTextureCount = 1;
|
||||
break;
|
||||
case gl::RGBAExternalLayerProgramType:
|
||||
if (aMask == Mask3d) {
|
||||
result.mVertexShaderString = sLayerMask3DVS;
|
||||
result.mFragmentShaderString = sRGBAExternalTextureLayerMask3DFS;
|
||||
} else if (aMask == Mask2d) {
|
||||
result.mVertexShaderString = sLayerMaskVS;
|
||||
result.mFragmentShaderString = sRGBAExternalTextureLayerMaskFS;
|
||||
} else {
|
||||
result.mVertexShaderString = sLayerVS;
|
||||
result.mFragmentShaderString = sRGBAExternalTextureLayerFS;
|
||||
}
|
||||
AddCommonArgs(result);
|
||||
AddCommonTextureArgs(result);
|
||||
result.mTextureCount = 1;
|
||||
break;
|
||||
case gl::ColorLayerProgramType:
|
||||
if (aMask == Mask2d) {
|
||||
result.mVertexShaderString = sLayerMaskVS;
|
||||
@@ -327,7 +342,7 @@ ShaderProgramOGL::CreateProgram(const char *aVertexShaderString,
|
||||
mProgram = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ShaderProgramOGL::LoadMask(Layer* aMaskLayer)
|
||||
{
|
||||
|
||||
@@ -341,6 +341,88 @@ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n\
|
||||
#endif\n\
|
||||
";
|
||||
|
||||
static const char sRGBAExternalTextureLayerFS[] = "/* sRGBAExternalTextureLayerFS */\n\
|
||||
#extension GL_OES_EGL_image_external : require\n\
|
||||
/* Fragment Shader */\n\
|
||||
#ifdef GL_ES\n\
|
||||
precision lowp float;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifndef NO_LAYER_OPACITY\n\
|
||||
uniform float uLayerOpacity;\n\
|
||||
#endif\n\
|
||||
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range\n\
|
||||
varying mediump vec2 vTexCoord;\n\
|
||||
#else\n\
|
||||
varying vec2 vTexCoord;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
uniform samplerExternalOES uTexture;\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
float mask = 1.0;\n\
|
||||
\n\
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity * mask;\n\
|
||||
}\n\
|
||||
";
|
||||
|
||||
static const char sRGBAExternalTextureLayerMaskFS[] = "/* sRGBAExternalTextureLayerMaskFS */\n\
|
||||
#extension GL_OES_EGL_image_external : require\n\
|
||||
/* Fragment Shader */\n\
|
||||
#ifdef GL_ES\n\
|
||||
precision lowp float;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifndef NO_LAYER_OPACITY\n\
|
||||
uniform float uLayerOpacity;\n\
|
||||
#endif\n\
|
||||
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range\n\
|
||||
varying mediump vec2 vTexCoord;\n\
|
||||
#else\n\
|
||||
varying vec2 vTexCoord;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
varying vec2 vMaskCoord;\n\
|
||||
uniform sampler2D uMaskTexture;\n\
|
||||
\n\
|
||||
uniform samplerExternalOES uTexture;\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
float mask = texture2D(uMaskTexture, vMaskCoord).r;\n\
|
||||
\n\
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity * mask;\n\
|
||||
}\n\
|
||||
";
|
||||
|
||||
static const char sRGBAExternalTextureLayerMask3DFS[] = "/* sRGBAExternalTextureLayerMask3DFS */\n\
|
||||
#extension GL_OES_EGL_image_external : require\n\
|
||||
/* Fragment Shader */\n\
|
||||
#ifdef GL_ES\n\
|
||||
precision lowp float;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#ifndef NO_LAYER_OPACITY\n\
|
||||
uniform float uLayerOpacity;\n\
|
||||
#endif\n\
|
||||
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range\n\
|
||||
varying mediump vec2 vTexCoord;\n\
|
||||
#else\n\
|
||||
varying vec2 vTexCoord;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
varying vec3 vMaskCoord;\n\
|
||||
uniform sampler2D uMaskTexture;\n\
|
||||
\n\
|
||||
uniform samplerExternalOES uTexture;\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;\n\
|
||||
float mask = texture2D(uMaskTexture, maskCoords).r;\n\
|
||||
\n\
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity * mask;\n\
|
||||
}\n\
|
||||
";
|
||||
|
||||
static const char sBGRATextureLayerFS[] = "/* sBGRATextureLayerFS */\n\
|
||||
/* Fragment Shader */\n\
|
||||
#ifdef GL_ES\n\
|
||||
|
||||
@@ -236,6 +236,25 @@ void main()
|
||||
#endif
|
||||
@end
|
||||
|
||||
// Single texture in RGBA format, but uses external image. External
|
||||
// image is an EGLImage which have internal formats not otherwise
|
||||
// supported by OpenGL ES. It is up to the implementation exactly what
|
||||
// formats are accepted. It is specified in the OES_EGL_image_external
|
||||
// extension.
|
||||
@shader sRGBAExternalTextureLayer<mask:,Mask,Mask3D>FS
|
||||
#extension GL_OES_EGL_image_external : require
|
||||
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
uniform samplerExternalOES uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity * mask;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
// Single texture in BGRA format (via swizzle)
|
||||
@shader sBGRATextureLayer<mask:,Mask>FS
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
|
||||
Reference in New Issue
Block a user