diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 43a5e027bbc..24710d7b6dc 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -42,6 +42,7 @@ #include "ShadowLayersParent.h" #include "LayerManagerOGL.h" #include "nsIWidget.h" +#include "nsGkAtoms.h" #if defined(MOZ_WIDGET_ANDROID) #include "AndroidBridge.h" @@ -181,6 +182,14 @@ CompositorParent::Composite() #endif layer->AsShadowLayer()->SetShadowTransform(worldTransform); +#ifdef MOZ_WIDGET_ANDROID + // Hang the transform of the root layer off the layer manager. + gfx3DMatrix transform = layer->GetTransform(); + transform *= worldTransform; + TransformLayerUserData* transformUserData = new TransformLayerUserData(transform); + mLayerManager->SetUserData(nsGkAtoms::transform, transformUserData); +#endif + mLayerManager->EndEmptyTransaction(); mLastCompose = mozilla::TimeStamp::Now(); } @@ -195,7 +204,7 @@ CompositorParent::GetPrimaryScrollableLayer() nsTArray queue; queue.AppendElement(root); - for (int i = 0; i < queue.Length(); i++) { + for (unsigned i = 0; i < queue.Length(); i++) { ContainerLayer* containerLayer = queue[i]->AsContainerLayer(); if (!containerLayer) { continue; diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index c81e079b8d3..b41f41ab2e1 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -785,10 +785,14 @@ LayerManagerOGL::Render() mGLContext->fClearColor(1.0, 1.0, 1.0, 0.0); mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT); + // Allow widget to render a custom background. + mWidget->DrawWindowUnderlay(this, rect); + // Render our layers. RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO, nsIntPoint(0, 0)); + // Allow widget to render a custom foreground too. mWidget->DrawWindowOverlay(this, rect); if (mTarget) { @@ -801,8 +805,6 @@ LayerManagerOGL::Render() mFPS.DrawFPS(mGLContext, GetCopy2DProgram()); } - PerformPostRenderHook(); - if (mGLContext->IsDoubleBuffered()) { mGLContext->SwapBuffers(); LayerManager::PostPresent(); @@ -894,22 +896,6 @@ LayerManagerOGL::Render() mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); } -void -LayerManagerOGL::PerformPreRenderHook() -{ -#ifdef MOZ_WIDGET_ANDROID - // TODO: AndroidBridge::PerformPreRenderHook(); -#endif -} - -void -LayerManagerOGL::PerformPostRenderHook() -{ -#ifdef MOZ_WIDGET_ANDROID - // TODO: AndroidBridge::PerformPostRenderHook(); -#endif -} - void LayerManagerOGL::SetWorldTransform(const gfxMatrix& aMatrix) { diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h index 3f584bec292..849f17e9881 100644 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -387,9 +387,6 @@ public: * to a window of the given dimensions. */ void SetupPipeline(int aWidth, int aHeight, WorldTransforPolicy aTransformPolicy); - - void PerformPreRenderHook(); - void PerformPostRenderHook(); /** * Setup World transform matrix. diff --git a/mobile/android/base/gfx/GeckoGLLayerClient.java b/mobile/android/base/gfx/GeckoGLLayerClient.java index fcc8714b790..570005e4e0a 100644 --- a/mobile/android/base/gfx/GeckoGLLayerClient.java +++ b/mobile/android/base/gfx/GeckoGLLayerClient.java @@ -44,6 +44,7 @@ import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; +import android.graphics.RectF; import android.util.Log; import android.view.View; @@ -51,6 +52,9 @@ public class GeckoGLLayerClient extends GeckoLayerClient implements FlexibleGLSurfaceView.Listener, VirtualLayer.Listener { private static final String LOGTAG = "GeckoGLLayerClient"; + private LayerRenderer mLayerRenderer; + private boolean mLayerRendererInitialized; + public GeckoGLLayerClient(Context context) { super(context); } @@ -95,7 +99,10 @@ public class GeckoGLLayerClient extends GeckoLayerClient public void setLayerController(LayerController layerController) { super.setLayerController(layerController); - ((FlexibleGLSurfaceView)layerController.getView()).setListener(this); + LayerView view = layerController.getView(); + view.setListener(this); + + mLayerRenderer = new LayerRenderer(view); } @Override @@ -211,5 +218,25 @@ public class GeckoGLLayerClient extends GeckoLayerClient compositionResumeRequested(); renderRequested(); } + + /** For Gecko to use. */ + public LayerRenderer.Frame createFrame(float offsetX, float offsetY, float zoomFactor) { + // Create the shaders and textures if necessary. + if (!mLayerRendererInitialized) { + mLayerRenderer.onSurfaceCreated(null, null); + } + + // FIXME: This geometry is surely wrong. + ViewportMetrics metrics = getLayerController().getViewportMetrics(); + FloatSize pageSize = metrics.getPageSize(), screenSize = metrics.getSize(); + RectF viewport = new RectF(offsetX, offsetY, offsetX + screenSize.width, + offsetY + screenSize.height); + + // Build the contexts and create the frame. + Layer.RenderContext pageContext = mLayerRenderer.createContext(viewport, pageSize, + zoomFactor); + Layer.RenderContext screenContext = mLayerRenderer.createScreenContext(); + return mLayerRenderer.createFrame(false, pageContext, screenContext); + } } diff --git a/mobile/android/base/gfx/LayerRenderer.java b/mobile/android/base/gfx/LayerRenderer.java index 1f89e3c03fd..d3cd4ad464f 100644 --- a/mobile/android/base/gfx/LayerRenderer.java +++ b/mobile/android/base/gfx/LayerRenderer.java @@ -255,7 +255,8 @@ public class LayerRenderer implements GLSurfaceView.Renderer { * Called whenever a new frame is about to be drawn. */ public void onDrawFrame(GL10 gl) { - Frame frame = new Frame(true); + RenderContext pageContext = createPageContext(), screenContext = createScreenContext(); + Frame frame = createFrame(true, pageContext, screenContext); synchronized (mView.getController()) { frame.beginDrawing(); frame.drawBackground(); @@ -286,13 +287,12 @@ public class LayerRenderer implements GLSurfaceView.Renderer { return pixelBuffer; } - private RenderContext createScreenContext() { + public RenderContext createScreenContext() { LayerController layerController = mView.getController(); IntSize viewportSize = new IntSize(layerController.getViewportSize()); RectF viewport = new RectF(0.0f, 0.0f, viewportSize.width, viewportSize.height); FloatSize pageSize = new FloatSize(layerController.getPageSize()); - return new RenderContext(viewport, pageSize, 1.0f, mPositionHandle, mTextureHandle, - mCoordBuffer); + return createContext(viewport, pageSize, 1.0f); } private RenderContext createPageContext() { @@ -303,8 +303,12 @@ public class LayerRenderer implements GLSurfaceView.Renderer { FloatSize pageSize = new FloatSize(layerController.getPageSize()); float zoomFactor = layerController.getZoomFactor(); - return new RenderContext(new RectF(viewport), pageSize, zoomFactor, mPositionHandle, - mTextureHandle, mCoordBuffer); + return createContext(new RectF(viewport), pageSize, zoomFactor); + } + + public RenderContext createContext(RectF viewport, FloatSize pageSize, float zoomFactor) { + return new RenderContext(viewport, pageSize, zoomFactor, mPositionHandle, mTextureHandle, + mCoordBuffer); } private Rect getPageRect() { @@ -423,6 +427,11 @@ public class LayerRenderer implements GLSurfaceView.Renderer { return shader; } + public Frame createFrame(boolean scissor, RenderContext pageContext, + RenderContext screenContext) { + return new Frame(scissor, pageContext, screenContext); + } + class FadeRunnable implements Runnable { private boolean mStarted; private long mRunAt; @@ -469,8 +478,10 @@ public class LayerRenderer implements GLSurfaceView.Renderer { // Whether a layer was updated. private boolean mUpdated; - public Frame(boolean scissor) { + public Frame(boolean scissor, RenderContext pageContext, RenderContext screenContext) { mScissor = scissor; + mPageContext = pageContext; + mScreenContext = screenContext; } public void beginDrawing() { @@ -479,13 +490,10 @@ public class LayerRenderer implements GLSurfaceView.Renderer { TextureReaper.get().reap(); TextureGenerator.get().fill(); - LayerController controller = mView.getController(); - mScreenContext = createScreenContext(); - mUpdated = true; + LayerController controller = mView.getController(); Layer rootLayer = controller.getRoot(); - mPageContext = createPageContext(); if (!mPageContext.fuzzyEquals(mLastPageContext)) { // the viewport or page changed, so show the scrollbars again @@ -558,7 +566,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer { } // Draws the layer the client added to us. - public void drawRootLayer() { + void drawRootLayer() { Layer rootLayer = mView.getController().getRoot(); if (rootLayer != null) rootLayer.draw(mPageContext); diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 76aada2edc1..9504bcbb5a5 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -120,6 +120,13 @@ jmethodID AndroidGeckoSoftwareLayerClient::jGetRenderOffsetMethod = 0; jclass AndroidGeckoGLLayerClient::jGeckoGLLayerClientClass = 0; jmethodID AndroidGeckoGLLayerClient::jGetViewTransformMethod = 0; +jmethodID AndroidGeckoGLLayerClient::jCreateFrameMethod = 0; + +jclass AndroidLayerRendererFrame::jLayerRendererFrameClass = 0; +jmethodID AndroidLayerRendererFrame::jBeginDrawingMethod = 0; +jmethodID AndroidLayerRendererFrame::jDrawBackgroundMethod = 0; +jmethodID AndroidLayerRendererFrame::jDrawForegroundMethod = 0; +jmethodID AndroidLayerRendererFrame::jEndDrawingMethod = 0; jclass AndroidViewTransform::jViewTransformClass = 0; jfieldID AndroidViewTransform::jXField = 0; @@ -162,6 +169,7 @@ mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) AndroidGeckoLayerClient::InitGeckoLayerClientClass(jEnv); AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(jEnv); AndroidGeckoGLLayerClient::InitGeckoGLLayerClientClass(jEnv); + AndroidLayerRendererFrame::InitLayerRendererFrameClass(jEnv); AndroidViewTransform::InitViewTransformClass(jEnv); AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(jEnv); } @@ -377,6 +385,23 @@ AndroidGeckoGLLayerClient::InitGeckoGLLayerClientClass(JNIEnv *jEnv) jGetViewTransformMethod = getMethod("getViewTransform", "()Lorg/mozilla/gecko/gfx/ViewTransform;"); + jCreateFrameMethod = getMethod("createFrame", + "(FFF)Lorg/mozilla/gecko/gfx/LayerRenderer$Frame;"); +#endif +} + +void +AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv) +{ +#ifdef MOZ_JAVA_COMPOSITOR + initInit(); + + jLayerRendererFrameClass = getClassGlobalRef("org/mozilla/gecko/gfx/LayerRenderer$Frame"); + + jBeginDrawingMethod = getMethod("beginDrawing", "()V"); + jDrawBackgroundMethod = getMethod("drawBackground", "()V"); + jDrawForegroundMethod = getMethod("drawForeground", "()V"); + jEndDrawingMethod = getMethod("endDrawing", "()V"); #endif } @@ -666,6 +691,27 @@ AndroidGeckoGLLayerClient::Init(jobject jobj) AndroidBridge::Bridge()->SetViewTransformGetter(mViewTransformGetter); } +void +AndroidLayerRendererFrame::Init(jobject jobj) +{ + if (!isNull()) { + Dispose(); + } + + wrapped_obj = GetJNIForThread()->NewGlobalRef(jobj); +} + +void +AndroidLayerRendererFrame::Dispose() +{ + if (isNull()) { + return; + } + + GetJNIForThread()->DeleteGlobalRef(wrapped_obj); + wrapped_obj = 0; +} + void AndroidViewTransform::Init(jobject jobj) { @@ -880,6 +926,70 @@ AndroidGeckoGLLayerClient::GetViewTransform(AndroidViewTransform& aViewTransform aViewTransform.Init(viewTransformJObj); } +void +AndroidGeckoGLLayerClient::CreateFrame(AndroidLayerRendererFrame& aFrame, + float aXOffset, float aYOffset, float aZoomFactor) +{ + JNIEnv *env = GetJNIForThread(); + NS_ABORT_IF_FALSE(env, "No JNI environment at CreateFrame()!"); + if (!env) { + return; + } + + jobject frameJObj = env->CallObjectMethod(wrapped_obj, jCreateFrameMethod, aXOffset, aYOffset, + aZoomFactor); + NS_ABORT_IF_FALSE(frameJObj, "No frame object!"); + aFrame.Init(frameJObj); +} + +void +AndroidLayerRendererFrame::BeginDrawing() +{ + JNIEnv *env = GetJNIForThread(); + NS_ABORT_IF_FALSE(env, "No JNI environment at BeginDrawing()!"); + if (!env) { + return; + } + + env->CallVoidMethod(wrapped_obj, jBeginDrawingMethod); +} + +void +AndroidLayerRendererFrame::DrawBackground() +{ + JNIEnv *env = GetJNIForThread(); + NS_ABORT_IF_FALSE(env, "No JNI environment at DrawBackground()!"); + if (!env) { + return; + } + + env->CallVoidMethod(wrapped_obj, jDrawBackgroundMethod); +} + +void +AndroidLayerRendererFrame::DrawForeground() +{ + JNIEnv *env = GetJNIForThread(); + NS_ABORT_IF_FALSE(env, "No JNI environment at DrawForeground()!"); + if (!env) { + return; + } + + env->CallVoidMethod(wrapped_obj, jDrawForegroundMethod); +} + +void +AndroidLayerRendererFrame::EndDrawing() +{ + JNIEnv *env = GetJNIForThread(); + NS_ABORT_IF_FALSE(env, "No JNI environment at EndDrawing()!"); + if (!env) { + return; + } + + env->CallVoidMethod(wrapped_obj, jEndDrawingMethod); +} + float AndroidViewTransform::GetX() { diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 499731e2fa4..9cb1578a242 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -237,6 +237,26 @@ private: static jfieldID jScaleField; }; +class AndroidLayerRendererFrame : public WrappedJavaObject { +public: + static void InitLayerRendererFrameClass(JNIEnv *jEnv); + + void Init(jobject jobj); + void Dispose(); + + void BeginDrawing(); + void DrawBackground(); + void DrawForeground(); + void EndDrawing(); + +private: + static jclass jLayerRendererFrameClass; + static jmethodID jBeginDrawingMethod; + static jmethodID jDrawBackgroundMethod; + static jmethodID jDrawForegroundMethod; + static jmethodID jEndDrawingMethod; +}; + class AndroidGeckoGLLayerClient : public AndroidGeckoLayerClient { public: static void InitGeckoGLLayerClientClass(JNIEnv *jEnv); @@ -250,10 +270,13 @@ public: : mViewTransformGetter(*this) { Init(jobj); } void GetViewTransform(AndroidViewTransform& aViewTransform); + void CreateFrame(AndroidLayerRendererFrame& aFrame, float aXOffset, float aYOffset, + float aZoomFactor); private: static jclass jGeckoGLLayerClientClass; static jmethodID jGetViewTransformMethod; + static jmethodID jCreateFrameMethod; AndroidGeckoGLLayerClientViewTransformGetter mViewTransformGetter; }; diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 8b0ed5240a4..89126a036e2 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2385,3 +2385,33 @@ nsWindow::GetIMEUpdatePreference() return nsIMEUpdatePreference(true, true); } +#ifdef MOZ_JAVA_COMPOSITOR +void +nsWindow::DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) { +#if 0 + TransformLayerUserData* userData = + static_cast(aManager->GetUserData(nsGkAtoms::transform)); + NS_ABORT_IF_FALSE(userData, "No transform user data!"); + + // Transform the unit square to figure out the offset and scale we need. + gfxRect rect(0, 0, 1, 1); + userData->matrix.TransformBounds(rect); + + AndroidGeckoLayerClient& client = AndroidBridge::Bridge()->GetLayerClient(); + AndroidGeckoGLLayerClient& glClient = static_cast(client); + glClient.CreateFrame(mLayerRendererFrame, rect.x, rect.y, rect.width); + mLayerRendererFrame.DrawBackground(); +#endif +} + +void +nsWindow::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) { +#if 0 + NS_ABORT_IF_FALSE(!mLayerRendererFrame.isNull(), + "Frame should have been created in DrawWindowUnderlay()!"); + mLayerRendererFrame.DrawForeground(); + mLayerRendererFrame.Dispose(); +#endif +} +#endif + diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index cb2fe287963..7d41138a247 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -47,6 +47,11 @@ #include "nsAccessible.h" #endif +#ifdef MOZ_JAVA_COMPOSITOR +#include "AndroidJavaWrappers.h" +#include "Layers.h" +#endif + class gfxASurface; class nsIdleService; @@ -179,6 +184,9 @@ public: #ifdef MOZ_JAVA_COMPOSITOR static void BindToTexture(); static bool HasDirectTexture(); + + virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect); + virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect); #endif protected: @@ -246,6 +254,18 @@ private: */ nsAccessible *DispatchAccessibleEvent(); #endif // ACCESSIBILITY + +#ifdef MOZ_JAVA_COMPOSITOR + mozilla::AndroidLayerRendererFrame mLayerRendererFrame; +#endif +}; + +class TransformLayerUserData : public mozilla::layers::LayerUserData { +public: + gfx3DMatrix matrix; + + TransformLayerUserData(gfx3DMatrix& aMatrix) : matrix(aMatrix) {} + virtual ~TransformLayerUserData() {} }; #endif /* NSWINDOW_H_ */ diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index eb5e2879581..394a81ac1f8 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1071,6 +1071,14 @@ class nsIWidget : public nsISupports { LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT, bool* aAllowRetaining = nsnull) = 0; + /** + * Called before the LayerManager draws the layer tree. + * + * @param aManager The drawing LayerManager. + * @param aWidgetRect The current widget rect that is being drawn. + */ + virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) = 0; + /** * Called after the LayerManager draws the layer tree * diff --git a/widget/xpwidgets/nsBaseWidget.h b/widget/xpwidgets/nsBaseWidget.h index 4f9647134d7..8455e0cebb3 100644 --- a/widget/xpwidgets/nsBaseWidget.h +++ b/widget/xpwidgets/nsBaseWidget.h @@ -132,6 +132,7 @@ public: bool* aAllowRetaining = nsnull); virtual void CreateCompositor(); + virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {} virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {} virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) {} virtual gfxASurface* GetThebesSurface();