widget/gonk/nsWindow.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* Copyright 2012 Mozilla Foundation and Mozilla contributors
     2  *
     3  * Licensed under the Apache License, Version 2.0 (the "License");
     4  * you may not use this file except in compliance with the License.
     5  * You may obtain a copy of the License at
     6  *
     7  *     http://www.apache.org/licenses/LICENSE-2.0
     8  *
     9  * Unless required by applicable law or agreed to in writing, software
    10  * distributed under the License is distributed on an "AS IS" BASIS,
    11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  * See the License for the specific language governing permissions and
    13  * limitations under the License.
    14  */
    16 #include "mozilla/DebugOnly.h"
    18 #include <fcntl.h>
    20 #include "android/log.h"
    22 #include "mozilla/dom/TabParent.h"
    23 #include "mozilla/Hal.h"
    24 #include "mozilla/Preferences.h"
    25 #include "mozilla/FileUtils.h"
    26 #include "mozilla/ClearOnShutdown.h"
    27 #include "Framebuffer.h"
    28 #include "gfxContext.h"
    29 #include "gfxPlatform.h"
    30 #include "gfxUtils.h"
    31 #include "GLContextProvider.h"
    32 #include "GLContext.h"
    33 #include "nsAutoPtr.h"
    34 #include "nsAppShell.h"
    35 #include "nsIdleService.h"
    36 #include "nsScreenManagerGonk.h"
    37 #include "nsTArray.h"
    38 #include "nsWindow.h"
    39 #include "nsIWidgetListener.h"
    40 #include "cutils/properties.h"
    41 #include "ClientLayerManager.h"
    42 #include "BasicLayers.h"
    43 #include "libdisplay/GonkDisplay.h"
    44 #include "pixelflinger/format.h"
    45 #include "mozilla/BasicEvents.h"
    46 #include "mozilla/layers/APZCTreeManager.h"
    47 #include "mozilla/layers/CompositorParent.h"
    48 #include "ParentProcessController.h"
    49 #include "nsThreadUtils.h"
    50 #include "HwcComposer2D.h"
    52 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
    53 #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
    54 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
    56 #define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)
    58 using namespace mozilla;
    59 using namespace mozilla::dom;
    60 using namespace mozilla::hal;
    61 using namespace mozilla::gl;
    62 using namespace mozilla::layers;
    63 using namespace mozilla::widget;
    65 nsIntRect gScreenBounds;
    66 static uint32_t sScreenRotation;
    67 static uint32_t sPhysicalScreenRotation;
    68 static nsIntRect sVirtualBounds;
    70 static nsRefPtr<GLContext> sGLContext;
    71 static nsTArray<nsWindow *> sTopWindows;
    72 static nsWindow *gFocusedWindow = nullptr;
    73 static bool sFramebufferOpen;
    74 static bool sUsingOMTC;
    75 static bool sUsingHwc;
    76 static bool sScreenInitialized;
    77 static nsRefPtr<gfxASurface> sOMTCSurface;
    79 namespace {
    81 static uint32_t
    82 EffectiveScreenRotation()
    83 {
    84     return (sScreenRotation + sPhysicalScreenRotation) % (360 / 90);
    85 }
    87 class ScreenOnOffEvent : public nsRunnable {
    88 public:
    89     ScreenOnOffEvent(bool on)
    90         : mIsOn(on)
    91     {}
    93     NS_IMETHOD Run() {
    94         for (uint32_t i = 0; i < sTopWindows.Length(); i++) {
    95             nsWindow *win = sTopWindows[i];
    97             if (nsIWidgetListener* listener = win->GetWidgetListener()) {
    98                 listener->SizeModeChanged(mIsOn ? nsSizeMode_Fullscreen : nsSizeMode_Minimized);
    99             }
   100         }
   102         // Notify observers that the screen state has just changed.
   103         nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
   104         if (observerService) {
   105           observerService->NotifyObservers(
   106             nullptr, "screen-state-changed",
   107             mIsOn ? MOZ_UTF16("on") : MOZ_UTF16("off")
   108           );
   109         }
   111         return NS_OK;
   112     }
   114 private:
   115     bool mIsOn;
   116 };
   118 static StaticRefPtr<ScreenOnOffEvent> sScreenOnEvent;
   119 static StaticRefPtr<ScreenOnOffEvent> sScreenOffEvent;
   121 static void
   122 displayEnabledCallback(bool enabled)
   123 {
   124     NS_DispatchToMainThread(enabled ? sScreenOnEvent : sScreenOffEvent);
   125 }
   127 } // anonymous namespace
   129 nsWindow::nsWindow()
   130 {
   131     if (!sScreenInitialized) {
   132         sScreenOnEvent = new ScreenOnOffEvent(true);
   133         ClearOnShutdown(&sScreenOnEvent);
   134         sScreenOffEvent = new ScreenOnOffEvent(false);
   135         ClearOnShutdown(&sScreenOffEvent);
   136         GetGonkDisplay()->OnEnabled(displayEnabledCallback);
   138         nsIntSize screenSize;
   139         bool gotFB = Framebuffer::GetSize(&screenSize);
   140         if (!gotFB) {
   141             NS_RUNTIMEABORT("Failed to get size from framebuffer, aborting...");
   142         }
   143         gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize);
   145         char propValue[PROPERTY_VALUE_MAX];
   146         property_get("ro.sf.hwrotation", propValue, "0");
   147         sPhysicalScreenRotation = atoi(propValue) / 90;
   149         sVirtualBounds = gScreenBounds;
   151         sScreenInitialized = true;
   153         nsAppShell::NotifyScreenInitialized();
   155         // This is a hack to force initialization of the compositor
   156         // resources, if we're going to use omtc.
   157         //
   158         // NB: GetPlatform() will create the gfxPlatform, which wants
   159         // to know the color depth, which asks our native window.
   160         // This has to happen after other init has finished.
   161         gfxPlatform::GetPlatform();
   162         sUsingOMTC = ShouldUseOffMainThreadCompositing();
   164         property_get("ro.display.colorfill", propValue, "0");
   166         //Update sUsingHwc whenever layers.composer2d.enabled changes
   167         Preferences::AddBoolVarCache(&sUsingHwc, "layers.composer2d.enabled");
   169         if (sUsingOMTC) {
   170           sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1),
   171                                              gfxImageFormat::RGB24);
   172         }
   173     }
   174 }
   176 nsWindow::~nsWindow()
   177 {
   178 }
   180 void
   181 nsWindow::DoDraw(void)
   182 {
   183     if (!hal::GetScreenEnabled()) {
   184         gDrawRequest = true;
   185         return;
   186     }
   188     if (sTopWindows.IsEmpty()) {
   189         LOG("  no window to draw, bailing");
   190         return;
   191     }
   193     nsWindow *targetWindow = (nsWindow *)sTopWindows[0];
   194     while (targetWindow->GetLastChild())
   195         targetWindow = (nsWindow *)targetWindow->GetLastChild();
   197     nsIWidgetListener* listener = targetWindow->GetWidgetListener();
   198     if (listener) {
   199         listener->WillPaintWindow(targetWindow);
   200     }
   202     LayerManager* lm = targetWindow->GetLayerManager();
   203     if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) {
   204       // No need to do anything, the compositor will handle drawing
   205     } else if (mozilla::layers::LayersBackend::LAYERS_BASIC == lm->GetBackendType()) {
   206         MOZ_ASSERT(sFramebufferOpen || sUsingOMTC);
   207         nsRefPtr<gfxASurface> targetSurface;
   209         if(sUsingOMTC)
   210             targetSurface = sOMTCSurface;
   211         else
   212             targetSurface = Framebuffer::BackBuffer();
   214         {
   215             nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
   216             gfxUtils::PathFromRegion(ctx, sVirtualBounds);
   217             ctx->Clip();
   219             // No double-buffering needed.
   220             AutoLayerManagerSetup setupLayerManager(
   221                 targetWindow, ctx, mozilla::layers::BufferMode::BUFFER_NONE,
   222                 ScreenRotation(EffectiveScreenRotation()));
   224             listener = targetWindow->GetWidgetListener();
   225             if (listener) {
   226                 listener->PaintWindow(targetWindow, sVirtualBounds);
   227             }
   228         }
   230         if (!sUsingOMTC) {
   231             targetSurface->Flush();
   232             Framebuffer::Present(sVirtualBounds);
   233         }
   234     } else {
   235         NS_RUNTIMEABORT("Unexpected layer manager type");
   236     }
   238     listener = targetWindow->GetWidgetListener();
   239     if (listener) {
   240         listener->DidPaintWindow();
   241     }
   242 }
   244 nsEventStatus
   245 nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent, bool* aWasCaptured)
   246 {
   247     if (aWasCaptured) {
   248         *aWasCaptured = false;
   249     }
   250     if (!gFocusedWindow) {
   251         return nsEventStatus_eIgnore;
   252     }
   254     gFocusedWindow->UserActivity();
   256     aEvent.widget = gFocusedWindow;
   258     if (TabParent* capturer = TabParent::GetEventCapturer()) {
   259         bool captured = capturer->TryCapture(aEvent);
   260         if (aWasCaptured) {
   261             *aWasCaptured = captured;
   262         }
   263         if (captured) {
   264             return nsEventStatus_eConsumeNoDefault;
   265         }
   266     }
   268     nsEventStatus status;
   269     gFocusedWindow->DispatchEvent(&aEvent, status);
   270     return status;
   271 }
   273 NS_IMETHODIMP
   274 nsWindow::Create(nsIWidget *aParent,
   275                  void *aNativeParent,
   276                  const nsIntRect &aRect,
   277                  nsDeviceContext *aContext,
   278                  nsWidgetInitData *aInitData)
   279 {
   280     BaseCreate(aParent, IS_TOPLEVEL() ? sVirtualBounds : aRect,
   281                aContext, aInitData);
   283     mBounds = aRect;
   285     mParent = (nsWindow *)aParent;
   286     mVisible = false;
   288     if (!aParent) {
   289         mBounds = sVirtualBounds;
   290     }
   292     if (!IS_TOPLEVEL())
   293         return NS_OK;
   295     sTopWindows.AppendElement(this);
   297     Resize(0, 0, sVirtualBounds.width, sVirtualBounds.height, false);
   298     return NS_OK;
   299 }
   301 NS_IMETHODIMP
   302 nsWindow::Destroy(void)
   303 {
   304     mOnDestroyCalled = true;
   305     sTopWindows.RemoveElement(this);
   306     if (this == gFocusedWindow)
   307         gFocusedWindow = nullptr;
   308     nsBaseWidget::OnDestroy();
   309     return NS_OK;
   310 }
   312 NS_IMETHODIMP
   313 nsWindow::Show(bool aState)
   314 {
   315     if (mWindowType == eWindowType_invisible)
   316         return NS_OK;
   318     if (mVisible == aState)
   319         return NS_OK;
   321     mVisible = aState;
   322     if (!IS_TOPLEVEL())
   323         return mParent ? mParent->Show(aState) : NS_OK;
   325     if (aState) {
   326         BringToTop();
   327     } else {
   328         for (unsigned int i = 0; i < sTopWindows.Length(); i++) {
   329             nsWindow *win = sTopWindows[i];
   330             if (!win->mVisible)
   331                 continue;
   333             win->BringToTop();
   334             break;
   335         }
   336     }
   338     return NS_OK;
   339 }
   341 bool
   342 nsWindow::IsVisible() const
   343 {
   344     return mVisible;
   345 }
   347 NS_IMETHODIMP
   348 nsWindow::ConstrainPosition(bool aAllowSlop,
   349                             int32_t *aX,
   350                             int32_t *aY)
   351 {
   352     return NS_OK;
   353 }
   355 NS_IMETHODIMP
   356 nsWindow::Move(double aX,
   357                double aY)
   358 {
   359     return NS_OK;
   360 }
   362 NS_IMETHODIMP
   363 nsWindow::Resize(double aWidth,
   364                  double aHeight,
   365                  bool   aRepaint)
   366 {
   367     return Resize(0, 0, aWidth, aHeight, aRepaint);
   368 }
   370 NS_IMETHODIMP
   371 nsWindow::Resize(double aX,
   372                  double aY,
   373                  double aWidth,
   374                  double aHeight,
   375                  bool   aRepaint)
   376 {
   377     mBounds = nsIntRect(NSToIntRound(aX), NSToIntRound(aY),
   378                         NSToIntRound(aWidth), NSToIntRound(aHeight));
   379     if (mWidgetListener)
   380         mWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
   382     if (aRepaint)
   383         Invalidate(sVirtualBounds);
   385     return NS_OK;
   386 }
   388 NS_IMETHODIMP
   389 nsWindow::Enable(bool aState)
   390 {
   391     return NS_OK;
   392 }
   394 bool
   395 nsWindow::IsEnabled() const
   396 {
   397     return true;
   398 }
   400 NS_IMETHODIMP
   401 nsWindow::SetFocus(bool aRaise)
   402 {
   403     if (aRaise)
   404         BringToTop();
   406     gFocusedWindow = this;
   407     return NS_OK;
   408 }
   410 NS_IMETHODIMP
   411 nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>&)
   412 {
   413     return NS_OK;
   414 }
   416 NS_IMETHODIMP
   417 nsWindow::Invalidate(const nsIntRect &aRect)
   418 {
   419     nsWindow *top = mParent;
   420     while (top && top->mParent)
   421         top = top->mParent;
   422     if (top != sTopWindows[0] && this != sTopWindows[0])
   423         return NS_OK;
   425     gDrawRequest = true;
   426     mozilla::NotifyEvent();
   427     return NS_OK;
   428 }
   430 nsIntPoint
   431 nsWindow::WidgetToScreenOffset()
   432 {
   433     nsIntPoint p(0, 0);
   434     nsWindow *w = this;
   436     while (w && w->mParent) {
   437         p.x += w->mBounds.x;
   438         p.y += w->mBounds.y;
   440         w = w->mParent;
   441     }
   443     return p;
   444 }
   446 void*
   447 nsWindow::GetNativeData(uint32_t aDataType)
   448 {
   449     switch (aDataType) {
   450     case NS_NATIVE_WINDOW:
   451         return GetGonkDisplay()->GetNativeWindow();
   452     }
   453     return nullptr;
   454 }
   456 NS_IMETHODIMP
   457 nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
   458 {
   459     if (mWidgetListener)
   460       aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
   461     return NS_OK;
   462 }
   464 NS_IMETHODIMP_(void)
   465 nsWindow::SetInputContext(const InputContext& aContext,
   466                           const InputContextAction& aAction)
   467 {
   468     mInputContext = aContext;
   469 }
   471 NS_IMETHODIMP_(InputContext)
   472 nsWindow::GetInputContext()
   473 {
   474     // There is only one IME context on Gonk.
   475     mInputContext.mNativeIMEContext = nullptr;
   476     return mInputContext;
   477 }
   479 NS_IMETHODIMP
   480 nsWindow::ReparentNativeWidget(nsIWidget* aNewParent)
   481 {
   482     return NS_OK;
   483 }
   485 NS_IMETHODIMP
   486 nsWindow::MakeFullScreen(bool aFullScreen)
   487 {
   488     if (mWindowType != eWindowType_toplevel) {
   489         // Ignore fullscreen request for non-toplevel windows.
   490         NS_WARNING("MakeFullScreen() on a dialog or child widget?");
   491         return nsBaseWidget::MakeFullScreen(aFullScreen);
   492     }
   494     if (aFullScreen) {
   495         // Fullscreen is "sticky" for toplevel widgets on gonk: we
   496         // must paint the entire screen, and should only have one
   497         // toplevel widget, so it doesn't make sense to ever "exit"
   498         // fullscreen.  If we do, we can leave parts of the screen
   499         // unpainted.
   500         Resize(sVirtualBounds.x, sVirtualBounds.y,
   501                sVirtualBounds.width, sVirtualBounds.height,
   502                /*repaint*/true);
   503     }
   504     return NS_OK;
   505 }
   507 float
   508 nsWindow::GetDPI()
   509 {
   510     return GetGonkDisplay()->xdpi;
   511 }
   513 double
   514 nsWindow::GetDefaultScaleInternal()
   515 {
   516     float dpi = GetDPI();
   517     // The mean pixel density for mdpi devices is 160dpi, 240dpi for hdpi,
   518     // and 320dpi for xhdpi, respectively.
   519     // We'll take the mid-value between these three numbers as the boundary.
   520     if (dpi < 200.0) {
   521         return 1.0; // mdpi devices.
   522     }
   523     if (dpi < 300.0) {
   524         return 1.5; // hdpi devices.
   525     }
   526     // xhdpi devices and beyond.
   527     return floor(dpi / 150.0 + 0.5);
   528 }
   530 LayerManager *
   531 nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
   532                           LayersBackend aBackendHint,
   533                           LayerManagerPersistence aPersistence,
   534                           bool* aAllowRetaining)
   535 {
   536     if (aAllowRetaining)
   537         *aAllowRetaining = true;
   538     if (mLayerManager) {
   539         // This layer manager might be used for painting outside of DoDraw(), so we need
   540         // to set the correct rotation on it.
   541         if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) {
   542             BasicLayerManager* manager =
   543                 static_cast<BasicLayerManager*>(mLayerManager.get());
   544             manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE,
   545                                                    ScreenRotation(EffectiveScreenRotation()));
   546         } else if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
   547             ClientLayerManager* manager =
   548                 static_cast<ClientLayerManager*>(mLayerManager.get());
   549             manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE,
   550                                                    ScreenRotation(EffectiveScreenRotation()));
   551         }
   552         return mLayerManager;
   553     }
   555     // Set mUseLayersAcceleration here to make it consistent with
   556     // nsBaseWidget::GetLayerManager
   557     mUseLayersAcceleration = ComputeShouldAccelerate(mUseLayersAcceleration);
   558     nsWindow *topWindow = sTopWindows[0];
   560     if (!topWindow) {
   561         LOGW(" -- no topwindow\n");
   562         return nullptr;
   563     }
   565     if (sUsingOMTC) {
   566         CreateCompositor();
   567         if (mCompositorParent) {
   568             uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId();
   569             CompositorParent::SetControllerForLayerTree(rootLayerTreeId, new ParentProcessController());
   570             CompositorParent::GetAPZCTreeManager(rootLayerTreeId)->SetDPI(GetDPI());
   571         }
   572         if (mLayerManager)
   573             return mLayerManager;
   574     }
   576     if (mUseLayersAcceleration) {
   577         DebugOnly<nsIntRect> fbBounds = gScreenBounds;
   578         if (!sGLContext) {
   579             sGLContext = GLContextProvider::CreateForWindow(this);
   580         }
   582         MOZ_ASSERT(fbBounds.value == gScreenBounds);
   583     }
   585     // Fall back to software rendering.
   586     sFramebufferOpen = Framebuffer::Open();
   587     if (sFramebufferOpen) {
   588         LOG("Falling back to framebuffer software rendering");
   589     } else {
   590         LOGE("Failed to mmap fb(?!?), aborting ...");
   591         NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
   592     }
   594     mLayerManager = new ClientLayerManager(this);
   595     mUseLayersAcceleration = false;
   597     return mLayerManager;
   598 }
   600 gfxASurface *
   601 nsWindow::GetThebesSurface()
   602 {
   603     /* This is really a dummy surface; this is only used when doing reflow, because
   604      * we need a RenderingContext to measure text against.
   605      */
   607     // XXX this really wants to return already_AddRefed, but this only really gets used
   608     // on direct assignment to a gfxASurface
   609     return new gfxImageSurface(gfxIntSize(5,5), gfxImageFormat::RGB24);
   610 }
   612 void
   613 nsWindow::BringToTop()
   614 {
   615     if (!sTopWindows.IsEmpty()) {
   616         if (nsIWidgetListener* listener = sTopWindows[0]->GetWidgetListener())
   617             listener->WindowDeactivated();
   618     }
   620     sTopWindows.RemoveElement(this);
   621     sTopWindows.InsertElementAt(0, this);
   623     if (mWidgetListener)
   624         mWidgetListener->WindowActivated();
   625     Invalidate(sVirtualBounds);
   626 }
   628 void
   629 nsWindow::UserActivity()
   630 {
   631     if (!mIdleService) {
   632         mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
   633     }
   635     if (mIdleService) {
   636         mIdleService->ResetIdleTimeOut(0);
   637     }
   638 }
   640 uint32_t
   641 nsWindow::GetGLFrameBufferFormat()
   642 {
   643     if (mLayerManager &&
   644         mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) {
   645         // We directly map the hardware fb on Gonk.  The hardware fb
   646         // has RGB format.
   647         return LOCAL_GL_RGB;
   648     }
   649     return LOCAL_GL_NONE;
   650 }
   652 nsIntRect
   653 nsWindow::GetNaturalBounds()
   654 {
   655     return gScreenBounds;
   656 }
   658 bool
   659 nsWindow::NeedsPaint()
   660 {
   661   if (!mLayerManager) {
   662     return false;
   663   }
   664   return nsIWidget::NeedsPaint();
   665 }
   667 Composer2D*
   668 nsWindow::GetComposer2D()
   669 {
   670     if (!sUsingHwc) {
   671         return nullptr;
   672     }
   674     if (HwcComposer2D* hwc = HwcComposer2D::GetInstance()) {
   675         return hwc->Initialized() ? hwc : nullptr;
   676     }
   678     return nullptr;
   679 }
   681 // nsScreenGonk.cpp
   683 nsScreenGonk::nsScreenGonk(void *nativeScreen)
   684 {
   685 }
   687 nsScreenGonk::~nsScreenGonk()
   688 {
   689 }
   691 NS_IMETHODIMP
   692 nsScreenGonk::GetRect(int32_t *outLeft,  int32_t *outTop,
   693                       int32_t *outWidth, int32_t *outHeight)
   694 {
   695     *outLeft = sVirtualBounds.x;
   696     *outTop = sVirtualBounds.y;
   698     *outWidth = sVirtualBounds.width;
   699     *outHeight = sVirtualBounds.height;
   701     return NS_OK;
   702 }
   704 NS_IMETHODIMP
   705 nsScreenGonk::GetAvailRect(int32_t *outLeft,  int32_t *outTop,
   706                            int32_t *outWidth, int32_t *outHeight)
   707 {
   708     return GetRect(outLeft, outTop, outWidth, outHeight);
   709 }
   711 static uint32_t
   712 ColorDepth()
   713 {
   714     switch (GetGonkDisplay()->surfaceformat) {
   715     case GGL_PIXEL_FORMAT_RGB_565:
   716         return 16;
   717     case GGL_PIXEL_FORMAT_RGBA_8888:
   718         return 32;
   719     }
   720     return 24; // GGL_PIXEL_FORMAT_RGBX_8888
   721 }
   723 NS_IMETHODIMP
   724 nsScreenGonk::GetPixelDepth(int32_t *aPixelDepth)
   725 {
   726     // XXX: this should actually return 32 when we're using 24-bit
   727     // color, because we use RGBX.
   728     *aPixelDepth = ColorDepth();
   729     return NS_OK;
   730 }
   732 NS_IMETHODIMP
   733 nsScreenGonk::GetColorDepth(int32_t *aColorDepth)
   734 {
   735     return GetPixelDepth(aColorDepth);
   736 }
   738 NS_IMETHODIMP
   739 nsScreenGonk::GetRotation(uint32_t* aRotation)
   740 {
   741     *aRotation = sScreenRotation;
   742     return NS_OK;
   743 }
   745 NS_IMETHODIMP
   746 nsScreenGonk::SetRotation(uint32_t aRotation)
   747 {
   748     if (!(aRotation <= ROTATION_270_DEG))
   749         return NS_ERROR_ILLEGAL_VALUE;
   751     if (sScreenRotation == aRotation)
   752         return NS_OK;
   754     sScreenRotation = aRotation;
   755     uint32_t rotation = EffectiveScreenRotation();
   756     if (rotation == nsIScreen::ROTATION_90_DEG ||
   757         rotation == nsIScreen::ROTATION_270_DEG) {
   758         sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height,
   759                                    gScreenBounds.width);
   760     } else {
   761         sVirtualBounds = gScreenBounds;
   762     }
   764     nsAppShell::NotifyScreenRotation();
   766     for (unsigned int i = 0; i < sTopWindows.Length(); i++)
   767         sTopWindows[i]->Resize(sVirtualBounds.width,
   768                                sVirtualBounds.height,
   769                                true);
   771     return NS_OK;
   772 }
   774 // NB: This isn't gonk-specific, but gonk is the only widget backend
   775 // that does this calculation itself, currently.
   776 static ScreenOrientation
   777 ComputeOrientation(uint32_t aRotation, const nsIntSize& aScreenSize)
   778 {
   779     bool naturallyPortrait = (aScreenSize.height > aScreenSize.width);
   780     switch (aRotation) {
   781     case nsIScreen::ROTATION_0_DEG:
   782         return (naturallyPortrait ? eScreenOrientation_PortraitPrimary : 
   783                 eScreenOrientation_LandscapePrimary);
   784     case nsIScreen::ROTATION_90_DEG:
   785         // Arbitrarily choosing 90deg to be primary "unnatural"
   786         // rotation.
   787         return (naturallyPortrait ? eScreenOrientation_LandscapePrimary : 
   788                 eScreenOrientation_PortraitPrimary);
   789     case nsIScreen::ROTATION_180_DEG:
   790         return (naturallyPortrait ? eScreenOrientation_PortraitSecondary : 
   791                 eScreenOrientation_LandscapeSecondary);
   792     case nsIScreen::ROTATION_270_DEG:
   793         return (naturallyPortrait ? eScreenOrientation_LandscapeSecondary : 
   794                 eScreenOrientation_PortraitSecondary);
   795     default:
   796         MOZ_CRASH("Gonk screen must always have a known rotation");
   797     }
   798 }
   800 /*static*/ uint32_t
   801 nsScreenGonk::GetRotation()
   802 {
   803     return sScreenRotation;
   804 }
   806 /*static*/ ScreenConfiguration
   807 nsScreenGonk::GetConfiguration()
   808 {
   809     ScreenOrientation orientation = ComputeOrientation(sScreenRotation,
   810                                                        gScreenBounds.Size());
   811     uint32_t colorDepth = ColorDepth();
   812     // NB: perpetuating colorDepth == pixelDepth illusion here, for
   813     // consistency.
   814     return ScreenConfiguration(sVirtualBounds, orientation,
   815                                colorDepth, colorDepth);
   816 }
   818 NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager)
   820 nsScreenManagerGonk::nsScreenManagerGonk()
   821 {
   822     mOneScreen = new nsScreenGonk(nullptr);
   823 }
   825 nsScreenManagerGonk::~nsScreenManagerGonk()
   826 {
   827 }
   829 NS_IMETHODIMP
   830 nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen)
   831 {
   832     NS_IF_ADDREF(*outScreen = mOneScreen.get());
   833     return NS_OK;
   834 }
   836 NS_IMETHODIMP
   837 nsScreenManagerGonk::ScreenForRect(int32_t inLeft,
   838                                    int32_t inTop,
   839                                    int32_t inWidth,
   840                                    int32_t inHeight,
   841                                    nsIScreen **outScreen)
   842 {
   843     return GetPrimaryScreen(outScreen);
   844 }
   846 NS_IMETHODIMP
   847 nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen)
   848 {
   849     return GetPrimaryScreen(outScreen);
   850 }
   852 NS_IMETHODIMP
   853 nsScreenManagerGonk::GetNumberOfScreens(uint32_t *aNumberOfScreens)
   854 {
   855     *aNumberOfScreens = 1;
   856     return NS_OK;
   857 }
   859 NS_IMETHODIMP
   860 nsScreenManagerGonk::GetSystemDefaultScale(float *aDefaultScale)
   861 {
   862     *aDefaultScale = 1.0f;
   863     return NS_OK;
   864 }

mercurial