From 3e94e67a5bcd88c8b40efd0caa6ebeaeb2233906 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Wed, 13 Jan 2016 20:37:56 -0800 Subject: [PATCH] Bug 1238876 - Move StartRemoteDrawing() implementation from nsWindow to nsScreenGonk r=mwu --- widget/gonk/nsScreenManagerGonk.cpp | 123 ++++++++++++++++++++++++++++ widget/gonk/nsScreenManagerGonk.h | 27 +++++- widget/gonk/nsWindow.cpp | 106 +----------------------- widget/gonk/nsWindow.h | 19 ----- 4 files changed, 150 insertions(+), 125 deletions(-) diff --git a/widget/gonk/nsScreenManagerGonk.cpp b/widget/gonk/nsScreenManagerGonk.cpp index e95610d4dfb..afaf0f18c75 100644 --- a/widget/gonk/nsScreenManagerGonk.cpp +++ b/widget/gonk/nsScreenManagerGonk.cpp @@ -16,6 +16,7 @@ #include "android/log.h" #include "GLContext.h" #include "gfxPrefs.h" +#include "gfxUtils.h" #include "mozilla/MouseEvents.h" #include "mozilla/TouchEvents.h" #include "mozilla/Hal.h" @@ -129,6 +130,8 @@ nsScreenGonk::nsScreenGonk(uint32_t aId, , mEGLDisplay(EGL_NO_DISPLAY) , mEGLSurface(EGL_NO_SURFACE) , mGLContext(nullptr) + , mFramebuffer(nullptr) + , mMappedBuffer(nullptr) { if (mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &mVirtualBounds.width) || mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &mVirtualBounds.height) || @@ -368,6 +371,126 @@ nsScreenGonk::BringToTop(nsWindow* aWindow) mTopWindows.InsertElementAt(0, aWindow); } +static gralloc_module_t const* +gralloc_module() +{ + hw_module_t const *module; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)) { + return nullptr; + } + return reinterpret_cast(module); +} + +static SurfaceFormat +HalFormatToSurfaceFormat(int aHalFormat) +{ + switch (aHalFormat) { + case HAL_PIXEL_FORMAT_RGBA_8888: + // Needs RB swap + return SurfaceFormat::B8G8R8A8; + case HAL_PIXEL_FORMAT_RGBX_8888: + // Needs RB swap + return SurfaceFormat::B8G8R8X8; + case HAL_PIXEL_FORMAT_BGRA_8888: + return SurfaceFormat::B8G8R8A8; + case HAL_PIXEL_FORMAT_RGB_565: + return SurfaceFormat::R5G6B5_UINT16; + default: + MOZ_CRASH("Unhandled HAL pixel format"); + return SurfaceFormat::UNKNOWN; // not reached + } +} + +static bool +NeedsRBSwap(int aHalFormat) +{ + switch (aHalFormat) { + case HAL_PIXEL_FORMAT_RGBA_8888: + return true; + case HAL_PIXEL_FORMAT_RGBX_8888: + return true; + case HAL_PIXEL_FORMAT_BGRA_8888: + return false; + case HAL_PIXEL_FORMAT_RGB_565: + return false; + default: + MOZ_CRASH("Unhandled HAL pixel format"); + return false; // not reached + } +} + +already_AddRefed +nsScreenGonk::StartRemoteDrawing() +{ + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + MOZ_ASSERT(!mFramebuffer); + MOZ_ASSERT(!mMappedBuffer); + + mFramebuffer = DequeueBuffer(); + int width = mFramebuffer->width, height = mFramebuffer->height; + if (gralloc_module()->lock(gralloc_module(), mFramebuffer->handle, + GRALLOC_USAGE_SW_READ_NEVER | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_FB, + 0, 0, width, height, + reinterpret_cast(&mMappedBuffer))) { + EndRemoteDrawing(); + return nullptr; + } + SurfaceFormat format = HalFormatToSurfaceFormat(GetSurfaceFormat()); + mFramebufferTarget = Factory::CreateDrawTargetForData( + BackendType::CAIRO, + mMappedBuffer, + IntSize(width, height), + mFramebuffer->stride * gfx::BytesPerPixel(format), + format); + if (!mFramebufferTarget) { + MOZ_CRASH("nsWindow::StartRemoteDrawing failed in CreateDrawTargetForData"); + } + if (!mBackBuffer || + mBackBuffer->GetSize() != mFramebufferTarget->GetSize() || + mBackBuffer->GetFormat() != mFramebufferTarget->GetFormat()) { + mBackBuffer = mFramebufferTarget->CreateSimilarDrawTarget( + mFramebufferTarget->GetSize(), mFramebufferTarget->GetFormat()); + } + RefPtr buffer(mBackBuffer); + return buffer.forget(); +} + +void +nsScreenGonk::EndRemoteDrawing() +{ + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + + if (mFramebufferTarget && mFramebuffer) { + IntSize size = mFramebufferTarget->GetSize(); + Rect rect(0, 0, size.width, size.height); + RefPtr source = mBackBuffer->Snapshot(); + mFramebufferTarget->DrawSurface(source, rect, rect); + + // Convert from BGR to RGB + // XXX this is a temporary solution. It consumes extra cpu cycles, + // it should not be used on product device. + if (NeedsRBSwap(GetSurfaceFormat())) { + LOGE("Very slow composition path, it should not be used on product!!!"); + SurfaceFormat format = HalFormatToSurfaceFormat(GetSurfaceFormat()); + gfxUtils::ConvertBGRAtoRGBA( + mMappedBuffer, + mFramebuffer->stride * mFramebuffer->height * gfx::BytesPerPixel(format)); + } + } + if (mMappedBuffer) { + MOZ_ASSERT(mFramebuffer); + gralloc_module()->unlock(gralloc_module(), mFramebuffer->handle); + mMappedBuffer = nullptr; + } + if (mFramebuffer) { + QueueBuffer(mFramebuffer); + } + mFramebuffer = nullptr; + mFramebufferTarget = nullptr; +} + ANativeWindowBuffer* nsScreenGonk::DequeueBuffer() { diff --git a/widget/gonk/nsScreenManagerGonk.h b/widget/gonk/nsScreenManagerGonk.h index 625df8a8a63..4c9fdc33bf4 100644 --- a/widget/gonk/nsScreenManagerGonk.h +++ b/widget/gonk/nsScreenManagerGonk.h @@ -82,8 +82,8 @@ public: ScreenConfiguration GetConfiguration(); bool IsPrimaryScreen(); - ANativeWindowBuffer* DequeueBuffer(); - bool QueueBuffer(ANativeWindowBuffer* buf); + already_AddRefed StartRemoteDrawing(); + void EndRemoteDrawing(); #if ANDROID_VERSION >= 17 android::DisplaySurface* GetDisplaySurface(); @@ -122,6 +122,9 @@ public: nsWindow* GetMirroringWidget(); // Primary screen only protected: + ANativeWindowBuffer* DequeueBuffer(); + bool QueueBuffer(ANativeWindowBuffer* buf); + uint32_t mId; NotifyDisplayChangedEvent mEventVisibility; int32_t mColorDepth; @@ -145,6 +148,26 @@ protected: hwc_surface_t mEGLSurface; RefPtr mGLContext; RefPtr mMirroringWidget; // Primary screen only + + // If we're using a BasicCompositor, these fields are temporarily + // set during frame composition. They wrap the hardware + // framebuffer. + RefPtr mFramebufferTarget; + ANativeWindowBuffer* mFramebuffer; + /** + * Points to a mapped gralloc buffer between calls to lock and unlock. + * Should be null outside of the lock-unlock pair. + */ + uint8_t* mMappedBuffer; + // If we're using a BasicCompositor, this is our window back + // buffer. The gralloc framebuffer driver expects us to draw the + // entire framebuffer on every frame, but gecko expects the + // windowing system to be tracking buffer updates for invalidated + // regions. We get stuck holding that bag. + // + // Only accessed on the compositor thread, except during + // destruction. + RefPtr mBackBuffer; }; class nsScreenManagerGonk final : public nsIScreenManager diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index a4f4f557bed..2d57c981b41 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -25,7 +25,6 @@ #include "mozilla/ClearOnShutdown.h" #include "gfxContext.h" #include "gfxPlatform.h" -#include "gfxUtils.h" #include "GLContextProvider.h" #include "GLContext.h" #include "GLContextEGL.h" @@ -66,8 +65,6 @@ static nsWindow *gFocusedWindow = nullptr; NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget) nsWindow::nsWindow() - : mFramebuffer(nullptr) - , mMappedBuffer(nullptr) { RefPtr screenManager = nsScreenManagerGonk::GetInstance(); screenManager->Initialize(); @@ -623,116 +620,17 @@ nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*) return NS_OK; } -static gralloc_module_t const* -gralloc_module() -{ - hw_module_t const *module; - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)) { - return nullptr; - } - return reinterpret_cast(module); -} - -static SurfaceFormat -HalFormatToSurfaceFormat(int aHalFormat) -{ - switch (aHalFormat) { - case HAL_PIXEL_FORMAT_RGBA_8888: - // Needs RB swap - return SurfaceFormat::B8G8R8A8; - case HAL_PIXEL_FORMAT_RGBX_8888: - // Needs RB swap - return SurfaceFormat::B8G8R8X8; - case HAL_PIXEL_FORMAT_BGRA_8888: - return SurfaceFormat::B8G8R8A8; - case HAL_PIXEL_FORMAT_RGB_565: - return SurfaceFormat::R5G6B5_UINT16; - default: - MOZ_CRASH("Unhandled HAL pixel format"); - return SurfaceFormat::UNKNOWN; // not reached - } -} - -static bool -NeedsRBSwap(int aHalFormat) -{ - switch (aHalFormat) { - case HAL_PIXEL_FORMAT_RGBA_8888: - return true; - case HAL_PIXEL_FORMAT_RGBX_8888: - return true; - case HAL_PIXEL_FORMAT_BGRA_8888: - return false; - case HAL_PIXEL_FORMAT_RGB_565: - return false; - default: - MOZ_CRASH("Unhandled HAL pixel format"); - return false; // not reached - } -} - - already_AddRefed nsWindow::StartRemoteDrawing() { - mFramebuffer = mScreen->DequeueBuffer(); - int width = mFramebuffer->width, height = mFramebuffer->height; - if (gralloc_module()->lock(gralloc_module(), mFramebuffer->handle, - GRALLOC_USAGE_SW_READ_NEVER | - GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_FB, - 0, 0, width, height, - reinterpret_cast(&mMappedBuffer))) { - EndRemoteDrawing(); - return nullptr; - } - SurfaceFormat format = HalFormatToSurfaceFormat(mScreen->GetSurfaceFormat()); - mFramebufferTarget = Factory::CreateDrawTargetForData( - BackendType::CAIRO, - mMappedBuffer, - IntSize(width, height), - mFramebuffer->stride * gfx::BytesPerPixel(format), - format); - if (!mFramebufferTarget) { - MOZ_CRASH("nsWindow::StartRemoteDrawing failed in CreateDrawTargetForData"); - } - if (!mBackBuffer || - mBackBuffer->GetSize() != mFramebufferTarget->GetSize() || - mBackBuffer->GetFormat() != mFramebufferTarget->GetFormat()) { - mBackBuffer = mFramebufferTarget->CreateSimilarDrawTarget( - mFramebufferTarget->GetSize(), mFramebufferTarget->GetFormat()); - } - RefPtr buffer(mBackBuffer); + RefPtr buffer = mScreen->StartRemoteDrawing(); return buffer.forget(); } void nsWindow::EndRemoteDrawing() { - if (mFramebufferTarget && mFramebuffer) { - IntSize size = mFramebufferTarget->GetSize(); - Rect rect(0, 0, size.width, size.height); - RefPtr source = mBackBuffer->Snapshot(); - mFramebufferTarget->DrawSurface(source, rect, rect); - - // Convert from BGR to RGB - // XXX this is a temporary solution. It consumes extra cpu cycles, - // it should not be used on product device. - if (NeedsRBSwap(mScreen->GetSurfaceFormat())) { - LOGE("Very slow composition path, it should not be used on product!!!"); - SurfaceFormat format = HalFormatToSurfaceFormat(mScreen->GetSurfaceFormat()); - gfxUtils::ConvertBGRAtoRGBA( - mMappedBuffer, - mFramebuffer->stride * mFramebuffer->height * gfx::BytesPerPixel(format)); - mMappedBuffer = nullptr; - gralloc_module()->unlock(gralloc_module(), mFramebuffer->handle); - } - } - if (mFramebuffer) { - mScreen->QueueBuffer(mFramebuffer); - } - mFramebuffer = nullptr; - mFramebufferTarget = nullptr; + mScreen->EndRemoteDrawing(); } float diff --git a/widget/gonk/nsWindow.h b/widget/gonk/nsWindow.h index 8ac865eba3b..e27a50cc4c3 100644 --- a/widget/gonk/nsWindow.h +++ b/widget/gonk/nsWindow.h @@ -138,25 +138,6 @@ protected: bool mVisible; InputContext mInputContext; nsCOMPtr mIdleService; - // If we're using a BasicCompositor, these fields are temporarily - // set during frame composition. They wrap the hardware - // framebuffer. - RefPtr mFramebufferTarget; - ANativeWindowBuffer* mFramebuffer; - /** - * Points to a mapped gralloc buffer between calls to lock and unlock. - * Should be null outside of the lock-unlock pair. - */ - uint8_t* mMappedBuffer; - // If we're using a BasicCompositor, this is our window back - // buffer. The gralloc framebuffer driver expects us to draw the - // entire framebuffer on every frame, but gecko expects the - // windowing system to be tracking buffer updates for invalidated - // regions. We get stuck holding that bag. - // - // Only accessed on the compositor thread, except during - // destruction. - RefPtr mBackBuffer; virtual ~nsWindow();