author | Kan-Ru Chen <kanru@kanru.info> |
Tue, 17 Jul 2012 10:12:58 +0800 | |
changeset 99509 | 2bf404e6e7e207a3632e21c8c3c47883dc356027 |
parent 99508 | dd08c10193c62abf525b3be5a3ecffbc6012c152 |
child 99510 | ba8463beab132c2c6be9a576d7d25d094671844a |
push id | 23135 |
push user | emorley@mozilla.com |
push date | Tue, 17 Jul 2012 09:04:49 +0000 |
treeherder | mozilla-central@ba8463beab13 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc, BenWa |
bugs | 774552 |
milestone | 17.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -50,16 +50,17 @@ class GLContext; typedef uintptr_t SharedTextureHandle; enum ShaderProgramType { RGBALayerProgramType, BGRALayerProgramType, RGBXLayerProgramType, BGRXLayerProgramType, RGBARectLayerProgramType, + RGBAExternalLayerProgramType, ColorLayerProgramType, YCbCrLayerProgramType, ComponentAlphaPass1ProgramType, ComponentAlphaPass2ProgramType, Copy2DProgramType, Copy2DRectProgramType, NumProgramTypes }; @@ -735,16 +736,17 @@ public: */ virtual bool ReleaseTexImage() { return false; } /** * Applies aFilter to the texture currently bound to GL_TEXTURE_2D. */ void ApplyFilterToBoundTexture(gfxPattern::GraphicsFilter aFilter); + virtual bool BindExternalBuffer(GLuint texture, void* buffer) { return false; } /* * Offscreen support API */ /* * Bind aOffscreen's color buffer as a texture to the TEXTURE_2D * target. Returns TRUE on success, otherwise FALSE. If
--- a/gfx/gl/GLContextProviderEGL.cpp +++ b/gfx/gl/GLContextProviderEGL.cpp @@ -39,16 +39,17 @@ # if defined(MOZ_WIDGET_GONK) # include "cutils/properties.h" # include <ui/GraphicBuffer.h> using namespace android; # define EGL_NATIVE_BUFFER_ANDROID 0x3140 # define EGL_IMAGE_PRESERVED_KHR 0x30D2 +# define GL_TEXTURE_EXTERNAL_OES 0x8D65 # endif #endif #define GLES2_LIB "libGLESv2.so" #define GLES2_LIB2 "libGLESv2.so.2" @@ -398,16 +399,36 @@ public: LOCAL_EGL_BACK_BUFFER); if (success == LOCAL_EGL_FALSE) return false; mBound = false; 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; // Assume that EGL has the same problem as WGL does, // where MakeCurrent with an already-current context is // still expensive. #ifndef MOZ_WIDGET_QT if (!mSurface) {
--- a/gfx/layers/ImageLayers.cpp +++ b/gfx/layers/ImageLayers.cpp @@ -42,16 +42,20 @@ ImageFactory::CreateImage(const Image::F if (FormatInList(aFormats, aNumFormats, Image::PLANAR_YCBCR)) { img = new PlanarYCbCrImage(aRecycleBin); } else if (FormatInList(aFormats, aNumFormats, Image::CAIRO_SURFACE)) { img = new CairoImage(); #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(); } BufferRecycleBin::BufferRecycleBin() : mLock("mozilla.layers.BufferRecycleBin.mLock") { }
--- a/gfx/layers/ImageLayers.h +++ b/gfx/layers/ImageLayers.h @@ -22,16 +22,19 @@ #endif #ifdef XP_WIN struct ID3D10Texture2D; struct ID3D10Device; struct ID3D10ShaderResourceView; typedef void* HANDLE; #endif +#ifdef MOZ_WIDGET_GONK +# include <ui/GraphicBuffer.h> +#endif namespace mozilla { class CrossProcessMutex; namespace ipc { class Shmem; } @@ -102,16 +105,23 @@ public: /** * The MAC_IO_SURFACE format creates a MacIOSurfaceImage. * * It wraps an IOSurface object and binds it directly to a GL texture. */ 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. */ REMOTE_IMAGE_BITMAP, /** * An DXGI shared surface handle that can be shared with a remote process. */ REMOTE_IMAGE_DXGI_TEXTURE @@ -919,16 +929,92 @@ private: gfxIntSize mSize; nsRefPtr<nsIOSurface> mIOSurface; void* mPluginInstanceOwner; UpdateSurfaceCallback mUpdateCallback; DestroyCallback mDestroyCallback; }; #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) {} already_AddRefed<gfxASurface> GetAsSurface(); gfxIntSize GetSize() { return mSize; }
--- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -171,16 +171,33 @@ AllocateTextureIOSurface(MacIOSurfaceIma LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV, 0); aGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0); aIOImage->SetBackendData(LayerManager::LAYERS_OPENGL, backendData.forget()); } #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() { return this; } void ImageLayerOGL::RenderLayer(int, @@ -292,18 +309,16 @@ ImageLayerOGL::RenderLayer(int, } if (!data || data->mTexture.GetGLContext() != gl()) { // XXX - Can this ever happen? If so I need to fix this! return; } 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()); #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO) GLXPixmap pixmap; if (cairoImage->mSurface) { @@ -316,61 +331,31 @@ ImageLayerOGL::RenderLayer(int, #endif ShaderProgramOGL *program = mOGLManager->GetProgram(data->mLayerProgram, GetMaskLayer()); 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(); - - 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?"); + mOGLManager->BindAndDrawQuadWithTextureRect(program, + GetVisibleRegion().GetBounds(), + nsIntSize(cairoImage->GetSize().width, + cairoImage->GetSize().height)); - 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); sGLXLibrary.DestroyPixmap(pixmap); } #endif #ifdef XP_MACOSX } else if (image->GetFormat() == Image::MAC_IO_SURFACE) { @@ -423,16 +408,55 @@ ImageLayerOGL::RenderLayer(int, program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); program->LoadMask(GetMaskLayer()); 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); } static void SetClamping(GLContext* aGL, GLuint aTexture) { aGL->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
--- a/gfx/layers/opengl/LayerManagerOGLProgram.cpp +++ b/gfx/layers/opengl/LayerManagerOGLProgram.cpp @@ -99,16 +99,31 @@ ProgramProfileOGL::GetProfileFor(gl::Sha } else { result.mVertexShaderString = sLayerVS; result.mFragmentShaderString = sRGBARectTextureLayerFS; } AddCommonArgs(result); 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; result.mFragmentShaderString = sSolidColorLayerMaskFS; } else { result.mVertexShaderString = sLayerVS; result.mFragmentShaderString = sSolidColorLayerFS; } @@ -322,17 +337,17 @@ ShaderProgramOGL::CreateProgram(const ch if (!success) { mGL->fDeleteProgram(result); return false; } mProgram = result; return true; } - + bool ShaderProgramOGL::LoadMask(Layer* aMaskLayer) { if (!aMaskLayer) { return false; } gfxIntSize size;
--- a/gfx/layers/opengl/LayerManagerOGLShaders.h +++ b/gfx/layers/opengl/LayerManagerOGLShaders.h @@ -336,16 +336,98 @@ gl_FragColor = texture2DRect(uTexture, v #else\n\ void main()\n\ {\n\ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n\ }\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\ precision lowp float;\n\ #endif\n\ \n\ #ifndef NO_LAYER_OPACITY\n\ uniform float uLayerOpacity;\n\
--- a/gfx/layers/opengl/LayerManagerOGLShaders.txt +++ b/gfx/layers/opengl/LayerManagerOGLShaders.txt @@ -231,16 +231,35 @@ void main() #else void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } #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>$ uniform sampler2D uTexture; void main() { $FRAGMENT_CALC_MASK<mask>$