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

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

mercurial