Bug 1238876 - Move StartRemoteDrawing() implementation from nsWindow to nsScreenGonk r=mwu

This commit is contained in:
Sotaro Ikeda 2016-01-13 20:37:56 -08:00
parent bbba74ba11
commit 3e94e67a5b
4 changed files with 150 additions and 125 deletions

View File

@ -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<gralloc_module_t const*>(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<DrawTarget>
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<void**>(&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<DrawTarget> 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<SourceSurface> 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()
{

View File

@ -82,8 +82,8 @@ public:
ScreenConfiguration GetConfiguration();
bool IsPrimaryScreen();
ANativeWindowBuffer* DequeueBuffer();
bool QueueBuffer(ANativeWindowBuffer* buf);
already_AddRefed<mozilla::gfx::DrawTarget> 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<mozilla::gl::GLContext> mGLContext;
RefPtr<nsWindow> mMirroringWidget; // Primary screen only
// If we're using a BasicCompositor, these fields are temporarily
// set during frame composition. They wrap the hardware
// framebuffer.
RefPtr<mozilla::gfx::DrawTarget> 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<mozilla::gfx::DrawTarget> mBackBuffer;
};
class nsScreenManagerGonk final : public nsIScreenManager

View File

@ -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<nsScreenManagerGonk> 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<gralloc_module_t const*>(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<DrawTarget>
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<void**>(&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<DrawTarget> buffer(mBackBuffer);
RefPtr<DrawTarget> 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<SourceSurface> 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

View File

@ -138,25 +138,6 @@ protected:
bool mVisible;
InputContext mInputContext;
nsCOMPtr<nsIIdleServiceInternal> mIdleService;
// If we're using a BasicCompositor, these fields are temporarily
// set during frame composition. They wrap the hardware
// framebuffer.
RefPtr<mozilla::gfx::DrawTarget> 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<mozilla::gfx::DrawTarget> mBackBuffer;
virtual ~nsWindow();