Bug 1152135 - Split EGLSurface buffer swap and HWC buffer swap r=mwu,nical,jgilbert
☠☠ backed out by a75dd40cf3fc ☠ ☠
authorSotaro Ikeda <sikeda@mozilla.com>
Thu, 16 Apr 2015 18:15:26 -0700
changeset 239680 abe6234be8a3dc97ac5136041b6c462c3430790a
parent 239679 62b47badf9f9557385658eb42cf2a025fa70ea5e
child 239681 f3cc197b263238106855111dcbd1fe966e398a35
push id12444
push userryanvm@gmail.com
push dateFri, 17 Apr 2015 20:04:42 +0000
treeherderfx-team@560a202db924 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwu, nical, jgilbert
bugs1152135
milestone40.0a1
Bug 1152135 - Split EGLSurface buffer swap and HWC buffer swap r=mwu,nical,jgilbert
gfx/gl/GLContextEGL.h
gfx/gl/GLContextProviderEGL.cpp
gfx/layers/composite/LayerManagerComposite.cpp
gfx/layers/opengl/Composer2D.h
gfx/layers/opengl/CompositorOGL.cpp
widget/gonk/HwcComposer2D.cpp
widget/gonk/HwcComposer2D.h
widget/gonk/libdisplay/GonkDisplay.h
widget/gonk/libdisplay/GonkDisplayICS.cpp
widget/gonk/libdisplay/GonkDisplayJB.cpp
widget/gonk/nsWindow.cpp
widget/gonk/nsWindow.h
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -91,16 +91,24 @@ public:
     // hold a reference to the given surface
     // for the lifetime of this context.
     void HoldSurface(gfxASurface *aSurf);
 
     EGLContext GetEGLContext() {
         return mContext;
     }
 
+    EGLSurface GetEGLSurface() {
+        return mSurface;
+    }
+
+    EGLDisplay GetEGLDisplay() {
+        return EGL_DISPLAY();
+    }
+
     bool BindTex2DOffscreen(GLContext *aOffscreen);
     void UnbindTex2DOffscreen(GLContext *aOffscreen);
     void BindOffscreenFramebuffer();
 
     static already_AddRefed<GLContextEGL>
     CreateEGLPixmapOffscreenContext(const gfxIntSize& size);
 
     static already_AddRefed<GLContextEGL>
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -225,27 +225,16 @@ GLContextEGL::GLContextEGL(
     , mOwnsContext(true)
 {
     // any EGL contexts will always be GLESv2
     SetProfileVersion(ContextProfile::OpenGLES, 200);
 
 #ifdef DEBUG
     printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
 #endif
-#if defined(MOZ_WIDGET_GONK)
-    if (!mIsOffscreen) {
-        mHwc = HwcComposer2D::GetInstance();
-        MOZ_ASSERT(!mHwc->Initialized());
-
-        if (mHwc->Init(EGL_DISPLAY(), mSurface, this)) {
-            NS_WARNING("HWComposer initialization failed!");
-            mHwc = nullptr;
-        }
-    }
-#endif
 }
 
 GLContextEGL::~GLContextEGL()
 {
     MarkDestroyed();
 
     // Wrapped context should not destroy eglContext/Surface
     if (!mOwnsContext) {
@@ -461,26 +450,23 @@ GLContextEGL::SetupLookupFunction()
 
 bool
 GLContextEGL::SwapBuffers()
 {
     EGLSurface surface = mSurfaceOverride != EGL_NO_SURFACE
                           ? mSurfaceOverride
                           : mSurface;
     if (surface) {
-#ifdef MOZ_WIDGET_GONK
+#if ANDROID_VERSION < 17
         if (!mIsOffscreen) {
-            if (mHwc) {
-                return mHwc->Render(EGL_DISPLAY(), surface);
-            } else {
-                return GetGonkDisplay()->SwapBuffers(EGL_DISPLAY(), surface);
-            }
-        } else
+            // eglSwapBuffers() is called by hwcomposer.
+            return true;
+        }
 #endif
-            return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), surface);
+        return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), surface);
     } else {
         return false;
     }
 }
 
 // hold a reference to the given surface
 // for the lifetime of this context.
 void
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -656,40 +656,36 @@ LayerManagerComposite::Render()
     auto packet = MakeUnique<layerscope::Packet>();
     layerscope::LayersPacket* layersPacket = packet->mutable_layers();
     this->Dump(layersPacket);
     LayerScope::SendLayerDump(Move(packet));
   }
 
   /** Our more efficient but less powerful alter ego, if one is available. */
   nsRefPtr<Composer2D> composer2D;
+  composer2D = mCompositor->GetWidget()->GetComposer2D();
 
-  // We can't use composert2D if we have layer effects, so only get it
-  // when we don't have any effects.
-  if (!haveLayerEffects) {
-    composer2D = mCompositor->GetWidget()->GetComposer2D();
-  }
-
-  if (!mTarget &&
+  // We can't use composert2D if we have layer effects
+  if (!mTarget && !haveLayerEffects &&
       gfxPrefs::Composer2DCompositionEnabled() &&
-      composer2D && composer2D->TryRender(mRoot, mGeometryChanged))
+      composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot, mGeometryChanged))
   {
     LayerScope::SetHWComposed();
     if (mFPS) {
       double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
       if (gfxPrefs::LayersDrawFPS()) {
         printf_stderr("HWComposer: FPS is %g\n", fps);
       }
     }
     mCompositor->EndFrameForExternalComposition(Matrix());
     // Reset the invalid region as compositing is done
     mInvalidRegion.SetEmpty();
     mLastFrameMissedHWC = false;
     return;
-  } else if (!mTarget) {
+  } else if (!mTarget && !haveLayerEffects) {
     mLastFrameMissedHWC = !!composer2D;
   }
 
   {
     PROFILER_LABEL("LayerManagerComposite", "PreRender",
       js::ProfileEntry::Category::GRAPHICS);
 
     if (!mCompositor->GetWidget()->PreRender(this)) {
@@ -770,16 +766,20 @@ LayerManagerComposite::Render()
   {
     PROFILER_LABEL("LayerManagerComposite", "EndFrame",
       js::ProfileEntry::Category::GRAPHICS);
 
     mCompositor->EndFrame();
     mCompositor->SetFBAcquireFence(mRoot);
   }
 
+  if (composer2D) {
+    composer2D->Render();
+  }
+
   mCompositor->GetWidget()->PostRender(this);
 
   RecordFrame();
 }
 
 #ifdef MOZ_WIDGET_ANDROID
 class ScopedCompositorProjMatrix {
 public:
--- a/gfx/layers/opengl/Composer2D.h
+++ b/gfx/layers/opengl/Composer2D.h
@@ -47,15 +47,27 @@ public:
   /**
    * Return true if |aRoot| met the implementation's criteria for fast
    * composition and the render was successful.  Return false to fall
    * back on the GPU.
    *
    * Currently, when TryRender() returns true, the entire framebuffer
    * must have been rendered.
    */
-  virtual bool TryRender(Layer* aRoot, bool aGeometryChanged) = 0;
+  virtual bool TryRenderWithHwc(Layer* aRoot, bool aGeometryChanged) = 0;
+
+  /**
+   * Return true if Composer2D does composition. Return false if Composer2D
+   * failed the composition.
+   */
+  virtual bool Render() = 0;
+
+  /**
+   * Return true if Composer2D has a fast composition hardware.
+   * Return false if Composer2D does not have a fast composition hardware.
+   */
+  virtual bool HasHwc() = 0;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_Composer2D_h
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -126,23 +126,29 @@ CompositorOGL::CreateContext()
     caps.bpp16 = gfxPlatform::GetPlatform()->GetOffscreenFormat() == gfxImageFormat::RGB16_565;
 
     bool requireCompatProfile = true;
     context = GLContextProvider::CreateOffscreen(gfxIntSize(mSurfaceSize.width,
                                                             mSurfaceSize.height),
                                                  caps, requireCompatProfile);
   }
 
-  if (!context)
+  if (!context) {
     context = gl::GLContextProvider::CreateForWindow(mWidget);
+  }
 
   if (!context) {
     NS_WARNING("Failed to create CompositorOGL context");
   }
 
+#ifdef MOZ_WIDGET_GONK
+  mWidget->SetNativeData(NS_NATIVE_OPENGL_CONTEXT,
+                         reinterpret_cast<uintptr_t>(context.get()));
+#endif
+
   return context.forget();
 }
 
 void
 CompositorOGL::Destroy()
 {
   if (mTexturePool) {
     mTexturePool->Clear();
--- a/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -106,46 +106,38 @@ static const hwc_procs_t sHWCProcs = {
 };
 #endif
 
 static StaticRefPtr<HwcComposer2D> sInstance;
 
 HwcComposer2D::HwcComposer2D()
     : mHwc(nullptr)
     , mList(nullptr)
+    , mDpy(EGL_NO_DISPLAY)
+    , mSur(EGL_NO_SURFACE)
     , mGLContext(nullptr)
     , mMaxLayerCount(0)
     , mColorFill(false)
     , mRBSwapSupport(false)
 #if ANDROID_VERSION >= 17
     , mPrevRetireFence(Fence::NO_FENCE)
     , mPrevDisplayFence(Fence::NO_FENCE)
 #endif
     , mPrepared(false)
     , mHasHWVsync(false)
     , mLock("mozilla.HwcComposer2D.mLock")
 {
 #if ANDROID_VERSION >= 17
     RegisterHwcEventCallback();
 #endif
-}
-
-HwcComposer2D::~HwcComposer2D() {
-    free(mList);
-}
-
-int
-HwcComposer2D::Init(hwc_display_t dpy, hwc_surface_t sur, gl::GLContext* aGLContext)
-{
-    MOZ_ASSERT(!Initialized());
 
     mHwc = (HwcDevice*)GetGonkDisplay()->GetHWCDevice();
     if (!mHwc) {
-        LOGE("Failed to initialize hwc");
-        return -1;
+        LOGD("no hwc support");
+        return;
     }
 
     nsIntSize screenSize;
 
     ANativeWindow *win = GetGonkDisplay()->GetNativeWindow();
     win->query(win, NATIVE_WINDOW_WIDTH, &screenSize.width);
     win->query(win, NATIVE_WINDOW_HEIGHT, &screenSize.height);
     mScreenRect = nsIntRect(nsIntPoint(0, 0), screenSize);
@@ -165,22 +157,20 @@ HwcComposer2D::Init(hwc_display_t dpy, h
         mRBSwapSupport = false;
     }
 #else
     char propValue[PROPERTY_VALUE_MAX];
     property_get("ro.display.colorfill", propValue, "0");
     mColorFill = (atoi(propValue) == 1) ? true : false;
     mRBSwapSupport = true;
 #endif
+}
 
-    mDpy = dpy;
-    mSur = sur;
-    mGLContext = aGLContext;
-
-    return 0;
+HwcComposer2D::~HwcComposer2D() {
+    free(mList);
 }
 
 HwcComposer2D*
 HwcComposer2D::GetInstance()
 {
     if (!sInstance) {
         LOGI("Creating new instance");
         sInstance = new HwcComposer2D();
@@ -238,17 +228,17 @@ HwcComposer2D::Vsync(int aDisplay, nsecs
     TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(aVsyncTimestamp);
     gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().NotifyVsync(vsyncTime);
 }
 
 // Called on the "invalidator" thread (run from HAL).
 void
 HwcComposer2D::Invalidate()
 {
-    if (!Initialized()) {
+    if (!mHwc) {
         LOGE("HwcComposer2D::Invalidate failed!");
         return;
     }
 
     MutexAutoLock lock(mLock);
     if (mCompositorParent) {
         mCompositorParent->ScheduleRenderOnCompositorThread();
     }
@@ -257,16 +247,24 @@ HwcComposer2D::Invalidate()
 
 void
 HwcComposer2D::SetCompositorParent(CompositorParent* aCompositorParent)
 {
     MutexAutoLock lock(mLock);
     mCompositorParent = aCompositorParent;
 }
 
+void
+HwcComposer2D::SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, gl::GLContext* aGLContext)
+{
+    mDpy = aDisplay;
+    mSur = aSurface;
+    mGLContext = aGLContext;
+}
+
 bool
 HwcComposer2D::ReallocLayerList()
 {
     int size = sizeof(HwcList) +
         ((mMaxLayerCount + LAYER_COUNT_INCREMENTS) * sizeof(HwcLayer));
 
     HwcList* listrealloc = (HwcList*)realloc(mList, size);
 
@@ -762,25 +760,23 @@ HwcComposer2D::TryHwComposition()
     Commit();
 
     GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[idx].releaseFenceFd);
     mList->hwLayers[idx].releaseFenceFd = -1;
     return true;
 }
 
 bool
-HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
+HwcComposer2D::Render()
 {
-    if (!mList) {
-        // After boot, HWC list hasn't been created yet
-        return GetGonkDisplay()->SwapBuffers(dpy, sur);
+    // HWC module does not exist or mList is not created yet.
+    if (!mHwc || !mList) {
+        return GetGonkDisplay()->SwapBuffers(mDpy, mSur);
     }
 
-    GetGonkDisplay()->UpdateFBSurface(dpy, sur);
-
     FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface());
     if (!fbsurface) {
         LOGE("H/W Composition failed. FBSurface not initialized.");
         return false;
     }
 
     if (mPrepared) {
         // No mHwc prepare, if already prepared in current draw cycle
@@ -910,33 +906,36 @@ HwcComposer2D::Reset()
 #else
 bool
 HwcComposer2D::TryHwComposition()
 {
     return !mHwc->set(mHwc, mDpy, mSur, mList);
 }
 
 bool
-HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
+HwcComposer2D::Render()
 {
-    return GetGonkDisplay()->SwapBuffers(dpy, sur);
+    return GetGonkDisplay()->SwapBuffers(mDpy, mSur);
 }
 
 void
 HwcComposer2D::Reset()
 {
     mPrepared = false;
 }
 #endif
 
 bool
-HwcComposer2D::TryRender(Layer* aRoot,
-                         bool aGeometryChanged)
+HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
+                                bool aGeometryChanged)
 {
-    MOZ_ASSERT(Initialized());
+    if (!mHwc) {
+        return false;
+    }
+
     if (mList) {
         setHwcGeometry(aGeometryChanged);
         mList->numHwLayers = 0;
         mHwcLayerMap.Clear();
     }
 
     if (mPrepared) {
         Reset();
@@ -955,17 +954,17 @@ HwcComposer2D::TryRender(Layer* aRoot,
         LOGD("Render aborted. Nothing was drawn to the screen");
         return false;
     }
 
     // Send data to LayerScope for debugging
     SendtoLayerScope();
 
     if (!TryHwComposition()) {
-        LOGD("H/W Composition failed");
+        LOGD("Full HWC Composition failed. Fallback to GPU Composition or partial OVERLAY Composition");
         LayerScope::CleanLayer();
         return false;
     }
 
     LOGD("Frame rendered");
     return true;
 }
 
--- a/widget/gonk/HwcComposer2D.h
+++ b/widget/gonk/HwcComposer2D.h
@@ -72,55 +72,57 @@ typedef hwc_layer_t HwcLayer;
  * using the GPU with OpenGL.
  *
  */
 class HwcComposer2D : public mozilla::layers::Composer2D {
 public:
     HwcComposer2D();
     virtual ~HwcComposer2D();
 
-    int Init(hwc_display_t aDisplay, hwc_surface_t aSurface, gl::GLContext* aGLContext);
-
-    bool Initialized() const { return mHwc; }
-
     static HwcComposer2D* GetInstance();
 
     // Returns TRUE if the container has been succesfully rendered
     // Returns FALSE if the container cannot be fully rendered
     // by this composer so nothing was rendered at all
-    bool TryRender(layers::Layer* aRoot,
-                   bool aGeometryChanged) override;
+    virtual bool TryRenderWithHwc(layers::Layer* aRoot,
+                                  bool aGeometryChanged) override;
 
-    bool Render(EGLDisplay dpy, EGLSurface sur);
+    virtual bool Render() override;
+
+    virtual bool HasHwc() override { return mHwc; }
 
     bool EnableVsync(bool aEnable);
 #if ANDROID_VERSION >= 17
     bool RegisterHwcEventCallback();
     void Vsync(int aDisplay, int64_t aTimestamp);
     void Invalidate();
 #endif
     void SetCompositorParent(layers::CompositorParent* aCompositorParent);
 
+    // Set EGL info of primary display. Used for BLIT Composition.
+    // XXX Add multiple displays compostion support.
+    void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, gl::GLContext* aGLContext);
+
 private:
     void Reset();
     void Prepare(buffer_handle_t fbHandle, int fence);
     bool Commit();
     bool TryHwComposition();
     bool ReallocLayerList();
     bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,
           const gfx::Matrix& aParentTransform);
     void setCrop(HwcLayer* layer, hwc_rect_t srcCrop);
     void setHwcGeometry(bool aGeometryChanged);
     void SendtoLayerScope();
 
     HwcDevice*              mHwc;
     HwcList*                mList;
-    hwc_display_t           mDpy;
-    hwc_surface_t           mSur;
-    gl::GLContext*          mGLContext;
+    hwc_display_t           mDpy; // Store for BLIT Composition and GonkDisplayICS
+    hwc_surface_t           mSur; // Store for BLIT Composition and GonkDisplayICS
+    gl::GLContext*          mGLContext; // Store for BLIT Composition
     nsIntRect               mScreenRect;
     int                     mMaxLayerCount;
     bool                    mColorFill;
     bool                    mRBSwapSupport;
     //Holds all the dynamically allocated RectVectors needed
     //to render the current frame
     std::list<RectVector>   mVisibleRegions;
 #if ANDROID_VERSION >= 17
--- a/widget/gonk/libdisplay/GonkDisplay.h
+++ b/widget/gonk/libdisplay/GonkDisplay.h
@@ -37,16 +37,19 @@ public:
     typedef void (*OnEnabledCallbackType)(bool enabled);
 
     virtual void OnEnabled(OnEnabledCallbackType callback) = 0;
 
     virtual void* GetHWCDevice() = 0;
 
     virtual void* GetFBSurface() = 0;
 
+    /**
+     * Only GonkDisplayICS uses arguments.
+     */
     virtual bool SwapBuffers(EGLDisplay dpy, EGLSurface sur) = 0;
 
     virtual ANativeWindowBuffer* DequeueBuffer() = 0;
 
     virtual bool QueueBuffer(ANativeWindowBuffer* buf) = 0;
 
     virtual void UpdateFBSurface(EGLDisplay dpy, EGLSurface sur) = 0;
 
--- a/widget/gonk/libdisplay/GonkDisplayICS.cpp
+++ b/widget/gonk/libdisplay/GonkDisplayICS.cpp
@@ -181,18 +181,19 @@ GonkDisplayICS::GetFBSurface()
 
 bool
 GonkDisplayICS::SwapBuffers(EGLDisplay dpy, EGLSurface sur)
 {
     // Should be called when composition rendering is complete for a frame.
     // Only HWC v1.0 needs this call. ICS gonk always needs the call.
     mFBSurface->compositionComplete();
 
-    if (!mHwc)
-        return eglSwapBuffers(dpy, sur);
+    if (!mHwc) {
+        return true;
+    }
 
     mHwc->prepare(mHwc, nullptr);
     return !mHwc->set(mHwc, dpy, sur, 0);
 }
 
 ANativeWindowBuffer*
 GonkDisplayICS::DequeueBuffer()
 {
--- a/widget/gonk/libdisplay/GonkDisplayJB.cpp
+++ b/widget/gonk/libdisplay/GonkDisplayJB.cpp
@@ -233,22 +233,16 @@ GonkDisplayJB::SwapBuffers(EGLDisplay dp
 {
     // Should be called when composition rendering is complete for a frame.
     // Only HWC v1.0 needs this call.
     // HWC > v1.0 case, do not call compositionComplete().
     // mFBDevice is present only when HWC is v1.0.
     if (mFBDevice && mFBDevice->compositionComplete) {
         mFBDevice->compositionComplete(mFBDevice);
     }
-
-#if ANDROID_VERSION == 17
-    mList->dpy = dpy;
-    mList->sur = sur;
-#endif
-    eglSwapBuffers(dpy, sur);
     return Post(mFBSurface->lastHandle, mFBSurface->GetPrevFBAcquireFd());
 }
 
 bool
 GonkDisplayJB::Post(buffer_handle_t buf, int fence)
 {
     if (!mHwc) {
         if (fence >= 0)
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -26,16 +26,17 @@
 #include "mozilla/Services.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "GLContextProvider.h"
 #include "GLContext.h"
+#include "GLContextEGL.h"
 #include "nsAutoPtr.h"
 #include "nsAppShell.h"
 #include "nsIdleService.h"
 #include "nsIObserverService.h"
 #include "nsScreenManagerGonk.h"
 #include "nsTArray.h"
 #include "nsWindow.h"
 #include "nsIWidgetListener.h"
@@ -595,21 +596,38 @@ nsWindow::WidgetToScreenOffset()
     return p;
 }
 
 void*
 nsWindow::GetNativeData(uint32_t aDataType)
 {
     switch (aDataType) {
     case NS_NATIVE_WINDOW:
+        // Called before primary display's EGLSurface creation.
         return GetGonkDisplay()->GetNativeWindow();
     }
     return nullptr;
 }
 
+void
+nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal)
+{
+    switch (aDataType) {
+    case NS_NATIVE_OPENGL_CONTEXT:
+        // Called after primary display's GLContextEGL creation.
+        GLContext* context = reinterpret_cast<GLContext*>(aVal);
+
+        HwcComposer2D* hwc = HwcComposer2D::GetInstance();
+        hwc->SetEGLInfo(GLContextEGL::Cast(context)->GetEGLDisplay(),
+                        GLContextEGL::Cast(context)->GetEGLSurface(),
+                        context);
+        return;
+    }
+}
+
 NS_IMETHODIMP
 nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
 {
     if (mWidgetListener)
       aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
     return NS_OK;
 }
 
@@ -852,21 +870,17 @@ nsWindow::NeedsPaint()
     return false;
   }
   return nsIWidget::NeedsPaint();
 }
 
 Composer2D*
 nsWindow::GetComposer2D()
 {
-    if (HwcComposer2D* hwc = HwcComposer2D::GetInstance()) {
-        return hwc->Initialized() ? hwc : nullptr;
-    }
-
-    return nullptr;
+    return HwcComposer2D::GetInstance();
 }
 
 // nsScreenGonk.cpp
 
 nsScreenGonk::nsScreenGonk(void *nativeScreen)
 {
 }
 
--- a/widget/gonk/nsWindow.h
+++ b/widget/gonk/nsWindow.h
@@ -77,16 +77,17 @@ public:
                       double aHeight,
                       bool aRepaint);
     NS_IMETHOD Enable(bool aState);
     virtual bool IsEnabled() const;
     NS_IMETHOD SetFocus(bool aRaise = false);
     NS_IMETHOD ConfigureChildren(const nsTArray<nsIWidget::Configuration>&);
     NS_IMETHOD Invalidate(const nsIntRect &aRect);
     virtual void* GetNativeData(uint32_t aDataType);
+    virtual void SetNativeData(uint32_t aDataType, uintptr_t aVal);
     NS_IMETHOD SetTitle(const nsAString& aTitle)
     {
         return NS_OK;
     }
     virtual mozilla::LayoutDeviceIntPoint WidgetToScreenOffset();
     void DispatchTouchInputViaAPZ(mozilla::MultiTouchInput& aInput);
     void DispatchTouchEventForAPZ(const mozilla::MultiTouchInput& aInput,
                                   const ScrollableLayerGuid& aGuid,