Bug 1506747 - Add GeckoView API for drawing transparent border around the content window r=snorp,droeh,kats

Differential Revision: https://phabricator.services.mozilla.com/D11717

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Randall Barker 2018-11-15 01:54:18 +00:00
Родитель 1d2422df54
Коммит 69a08335b4
16 изменённых файлов: 144 добавлений и 41 удалений

Просмотреть файл

@ -816,19 +816,22 @@ CompositorBridgeParent::CancelCurrentCompositeTask()
}
void
CompositorBridgeParent::SetEGLSurfaceSize(int width, int height)
CompositorBridgeParent::SetEGLSurfaceRect(int x, int y, int width, int height)
{
NS_ASSERTION(mUseExternalSurfaceSize, "Compositor created without UseExternalSurfaceSize provided");
mEGLSurfaceSize.SizeTo(width, height);
if (mCompositor) {
mCompositor->SetDestinationSurfaceSize(gfx::IntSize(mEGLSurfaceSize.width, mEGLSurfaceSize.height));
if (mCompositor->AsCompositorOGL()) {
mCompositor->AsCompositorOGL()->SetSurfaceOrigin(ScreenIntPoint(x, y));
}
}
}
void
CompositorBridgeParent::ResumeCompositionAndResize(int width, int height)
CompositorBridgeParent::ResumeCompositionAndResize(int x, int y, int width, int height)
{
SetEGLSurfaceSize(width, height);
SetEGLSurfaceRect(x, y, width, height);
ResumeComposition();
}
@ -869,15 +872,16 @@ CompositorBridgeParent::ScheduleResumeOnCompositorThread()
}
bool
CompositorBridgeParent::ScheduleResumeOnCompositorThread(int width, int height)
CompositorBridgeParent::ScheduleResumeOnCompositorThread(int x, int y, int width, int height)
{
MonitorAutoLock lock(mResumeCompositionMonitor);
MOZ_ASSERT(CompositorLoop());
CompositorLoop()->PostTask(NewRunnableMethod<int, int>(
CompositorLoop()->PostTask(NewRunnableMethod<int, int, int, int>(
"layers::CompositorBridgeParent::ResumeCompositionAndResize",
this,
&CompositorBridgeParent::ResumeCompositionAndResize,
x, y,
width,
height));

Просмотреть файл

@ -316,7 +316,7 @@ public:
* otherwise.
*/
bool ScheduleResumeOnCompositorThread();
bool ScheduleResumeOnCompositorThread(int width, int height);
bool ScheduleResumeOnCompositorThread(int x, int y, int width, int height);
void ScheduleComposition();
void NotifyShadowTreeTransaction(LayersId aId, bool aIsFirstPaint,
@ -538,14 +538,14 @@ protected:
bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) override;
virtual void ScheduleTask(already_AddRefed<CancelableRunnable>, int);
void SetEGLSurfaceSize(int width, int height);
void SetEGLSurfaceRect(int x, int y, int width, int height);
void InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints);
public:
void PauseComposition();
void ResumeComposition();
void ResumeCompositionAndResize(int width, int height);
void ResumeCompositionAndResize(int x, int y, int width, int height);
void Invalidate();
protected:

Просмотреть файл

@ -28,7 +28,7 @@ parent:
// the compositor needs to pause/resume in lockstep with the application.
sync Pause();
sync Resume();
sync ResumeAndResize(int32_t aWidth, int32_t aHeight);
sync ResumeAndResize(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight);
async InvalidateAndRender();
async MaxToolbarHeight(int32_t aHeight);

Просмотреть файл

@ -92,14 +92,14 @@ UiCompositorControllerChild::Resume()
}
bool
UiCompositorControllerChild::ResumeAndResize(const int32_t& aWidth, const int32_t& aHeight)
UiCompositorControllerChild::ResumeAndResize(const int32_t& aX, const int32_t& aY, const int32_t& aWidth, const int32_t& aHeight)
{
if (!mIsOpen) {
mResize = Some(gfx::IntSize(aWidth, aHeight));
mResize = Some(gfx::IntRect(aX, aY, aWidth, aHeight));
// Since we are caching these values, pretend the call succeeded.
return true;
}
return SendResumeAndResize(aWidth, aHeight);
return SendResumeAndResize(aX, aY, aWidth, aHeight);
}
bool
@ -358,7 +358,7 @@ UiCompositorControllerChild::SendCachedValues()
{
MOZ_ASSERT(mIsOpen);
if (mResize) {
SendResumeAndResize(mResize.ref().width, mResize.ref().height);
SendResumeAndResize(mResize.ref().x, mResize.ref().y, mResize.ref().width, mResize.ref().height);
mResize.reset();
}
if (mMaxToolbarHeight) {

Просмотреть файл

@ -31,7 +31,7 @@ public:
bool Pause();
bool Resume();
bool ResumeAndResize(const int32_t& aHeight, const int32_t& aWidth);
bool ResumeAndResize(const int32_t& aX, const int32_t& aY, const int32_t& aHeight, const int32_t& aWidth);
bool InvalidateAndRender();
bool SetMaxToolbarHeight(const int32_t& aHeight);
bool SetPinned(const bool& aPinned, const int32_t& aReason);
@ -64,7 +64,7 @@ private:
bool mIsOpen;
uint64_t mProcessToken;
Maybe<gfx::IntSize> mResize;
Maybe<gfx::IntRect> mResize;
Maybe<int32_t> mMaxToolbarHeight;
Maybe<uint32_t> mDefaultClearColor;
Maybe<bool> mLayerUpdateEnabled;

Просмотреть файл

@ -69,14 +69,15 @@ UiCompositorControllerParent::RecvResume()
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvResumeAndResize(const int32_t& aWidth,
UiCompositorControllerParent::RecvResumeAndResize(const int32_t& aX, const int32_t& aY,
const int32_t& aWidth,
const int32_t& aHeight)
{
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
if (parent) {
// Front-end expects a first paint callback upon resume/resize.
parent->ForceIsFirstPaint();
parent->ResumeCompositionAndResize(aWidth, aHeight);
parent->ResumeCompositionAndResize(aX, aY, aWidth, aHeight);
}
return IPC_OK();
}

Просмотреть файл

@ -29,7 +29,9 @@ public:
// PUiCompositorControllerParent functions
mozilla::ipc::IPCResult RecvPause() override;
mozilla::ipc::IPCResult RecvResume() override;
mozilla::ipc::IPCResult RecvResumeAndResize(const int32_t& aHeight,
mozilla::ipc::IPCResult RecvResumeAndResize(const int32_t& aX,
const int32_t& aY,
const int32_t& aHeight,
const int32_t& aWidth) override;
mozilla::ipc::IPCResult RecvInvalidateAndRender() override;
mozilla::ipc::IPCResult RecvMaxToolbarHeight(const int32_t& aHeight) override;

Просмотреть файл

@ -576,7 +576,7 @@ CompositorOGL::PrepareViewport(CompositingRenderTargetOGL* aRenderTarget)
const gfx::IntSize& phySize = aRenderTarget->mInitParams.mPhySize;
// Set the viewport correctly.
mGLContext->fViewport(0, 0, phySize.width, phySize.height);
mGLContext->fViewport(mSurfaceOrigin.x, mSurfaceOrigin.y, phySize.width, phySize.height);
mViewportSize = size;
@ -848,7 +848,18 @@ CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
aClipRectOut->SetRect(0, 0, width, height);
}
#if defined(MOZ_WIDGET_ANDROID)
if ((mSurfaceOrigin.x > 0) || (mSurfaceOrigin.y > 0)) {
mGLContext->fClearColor(gfxPrefs::CompositorOverrideClearColorR(),
gfxPrefs::CompositorOverrideClearColorG(),
gfxPrefs::CompositorOverrideClearColorB(),
gfxPrefs::CompositorOverrideClearColorA());
} else {
mGLContext->fClearColor(mClearColor.r, mClearColor.g, mClearColor.b, mClearColor.a);
}
#else
mGLContext->fClearColor(mClearColor.r, mClearColor.g, mClearColor.b, mClearColor.a);
#endif // defined(MOZ_WIDGET_ANDROID)
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
}
@ -1246,7 +1257,7 @@ CompositorOGL::DrawGeometry(const Geometry& aGeometry,
// drawing is going to be shifted by mRenderOffset then we need
// to shift the clip rect by the same amount.
if (!mTarget && mCurrentRenderTarget->IsWindow()) {
clipRect.MoveBy(mRenderOffset.x, mRenderOffset.y);
clipRect.MoveBy(mRenderOffset.x + mSurfaceOrigin.x, mRenderOffset.y - mSurfaceOrigin.y);
}
ScopedGLState scopedScissorTestState(mGLContext, LOCAL_GL_SCISSOR_TEST, true);

Просмотреть файл

@ -275,6 +275,14 @@ public:
return mRenderOffset;
}
/**
* Allow the origin of the surface to be offset so that content does not
* start at (0, 0) on the surface.
*/
void SetSurfaceOrigin(const ScreenIntPoint& aOrigin) {
mSurfaceOrigin = aOrigin;
}
private:
template<typename Geometry>
void DrawGeometry(const Geometry& aGeometry,
@ -304,6 +312,9 @@ private:
ScreenPoint mRenderOffset;
/** The origin of the content on the surface */
ScreenIntPoint mSurfaceOrigin;
already_AddRefed<mozilla::gl::GLContext> CreateContext();
/** Texture target to use for FBOs */

Просмотреть файл

@ -454,6 +454,14 @@ private:
#else
DECL_GFX_PREF(Once, "gfx.blocklist.all", BlocklistAll, int32_t, 0);
#endif
#if defined(MOZ_WIDGET_ANDROID)
// Overrides the glClear color used when the surface origin is not (0, 0)
// Used for drawing a border around the content.
DECL_GFX_PREF(Live, "gfx.compositor.override.clear-color.r", CompositorOverrideClearColorR, float, 0.0f);
DECL_GFX_PREF(Live, "gfx.compositor.override.clear-color.g", CompositorOverrideClearColorG, float, 0.0f);
DECL_GFX_PREF(Live, "gfx.compositor.override.clear-color.b", CompositorOverrideClearColorB, float, 0.0f);
DECL_GFX_PREF(Live, "gfx.compositor.override.clear-color.a", CompositorOverrideClearColorA, float, 0.0f);
#endif // defined(MOZ_WIDGET_ANDROID)
DECL_GFX_PREF(Live, "gfx.compositor.clearstate", CompositorClearState, bool, false);
DECL_GFX_PREF(Live, "gfx.compositor.glcontext.opaque", CompositorGLContextOpaque, bool, false);
DECL_GFX_PREF(Live, "gfx.canvas.auto_accelerate.min_calls", CanvasAutoAccelerateMinCalls, int32_t, 4);

Просмотреть файл

@ -206,6 +206,7 @@ public class GeckoAppShell
static private int sDensityDpi;
static private Float sDensity;
static private int sScreenDepth;
static private boolean sUseMaxScreenDepth;
/* Is the value in sVibrationEndTime valid? */
private static boolean sVibrationMaybePlaying;
@ -1045,9 +1046,13 @@ public class GeckoAppShell
return HardwareUtils.getMemSize() > HIGH_MEMORY_DEVICE_THRESHOLD_MB;
}
public static synchronized void useMaxScreenDepth(final boolean enable) {
sUseMaxScreenDepth = enable;
}
/**
* Returns the colour depth of the default screen. This will either be
* 24 or 16.
* 32, 24 or 16.
*/
@WrapForJNI(calledFrom = "gecko")
public static synchronized int getScreenDepth() {
@ -1058,7 +1063,7 @@ public class GeckoAppShell
getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
PixelFormat.getPixelFormatInfo(wm.getDefaultDisplay().getPixelFormat(), info);
if (info.bitsPerPixel >= 24 && isHighMemoryDevice()) {
sScreenDepth = 24;
sScreenDepth = sUseMaxScreenDepth ? info.bitsPerPixel : 24;
}
}

Просмотреть файл

@ -14,8 +14,8 @@ import org.mozilla.gecko.util.ThreadUtils;
/**
* Applications use a GeckoDisplay instance to provide {@link GeckoSession} with a {@link Surface} for
* displaying content. To ensure drawing only happens on a valid {@link Surface}, {@link GeckoSession}
* will only use the provided {@link Surface} after {@link #surfaceChanged(Surface, int, int)} is
* called and before {@link #surfaceDestroyed()} returns.
* will only use the provided {@link Surface} after {@link #surfaceChanged(Surface, int, int)} or
* {@link #surfaceChanged(Surface, int, int, int, int)} is called and before {@link #surfaceDestroyed()} returns.
*/
public class GeckoDisplay {
private final GeckoSession session;
@ -25,25 +25,53 @@ public class GeckoDisplay {
}
/**
* Required callback. The display's Surface has been created or changed. Must be
* Sets a surface for the compositor render a surface.
*
* Required call. The display's Surface has been created or changed. Must be
* called on the application main thread. GeckoSession may block this call to ensure
* the Surface is valid while resuming drawing.
*
* @param surface The new Surface.
* @param width New width of the Surface.
* @param height New height of the Surface.
* @param width New width of the Surface. Can not be negative.
* @param height New height of the Surface. Can not be negative.
*/
@UiThread
public void surfaceChanged(Surface surface, int width, int height) {
surfaceChanged(surface, 0, 0, width, height);
}
/**
* Sets a surface for the compositor render a surface.
*
* Required call. The display's Surface has been created or changed. Must be
* called on the application main thread. GeckoSession may block this call to ensure
* the Surface is valid while resuming drawing. The origin of the content window
* (0, 0) is the top left corner of the screen.
*
* @param surface The new Surface.
* @param left The compositor origin offset in the X axis. Can not be negative.
* @param top The compositor origin offset in the Y axis. Can not be negative.
* @param width New width of the Surface. Can not be negative.
* @param height New height of the Surface. Can not be negative.
* @throws IllegalArgumentException if left or top are negative.
*/
@UiThread
public void surfaceChanged(Surface surface, int left, int top, int width, int height) {
ThreadUtils.assertOnUiThread();
if ((left < 0) || (top < 0)) {
throw new IllegalArgumentException("Parameters can not be negative.");
}
if (session.getDisplay() == this) {
session.onSurfaceChanged(surface, width, height);
session.onSurfaceChanged(surface, left, top, width, height);
}
}
/**
* Required callback. The display's Surface has been destroyed. Must be called on the
* Removes the current surface registered with the compositor.
*
* Required call. The display's Surface has been destroyed. Must be called on the
* application main thread. GeckoSession may block this call to ensure the Surface is
* valid while pausing drawing.
*/
@ -57,7 +85,9 @@ public class GeckoDisplay {
}
/**
* Optional callback. The display's coordinates on the screen has changed. Must be
* Update the position of the surface on the screen.
*
* Optional call. The display's coordinates on the screen has changed. Must be
* called on the application main thread.
*
* @param left The X coordinate of the display on the screen, in screen pixels.
@ -73,10 +103,11 @@ public class GeckoDisplay {
}
/**
* Return whether the display should be pinned on the screen. When pinned, the display
* should not be moved on the screen due to animation, scrolling, etc. A common reason
* for the display being pinned is when the user is dragging a selection caret inside
* the display; normal user interaction would be disrupted in that case if the display
* Return whether the display should be pinned on the screen.
*
* When pinned, the display should not be moved on the screen due to animation, scrolling, etc.
* A common reason for the display being pinned is when the user is dragging a selection caret
* inside the display; normal user interaction would be disrupted in that case if the display
* was moved on screen.
*
* @return True if display should be pinned on the screen.

Просмотреть файл

@ -200,6 +200,7 @@ public final class GeckoRuntime implements Parcelable {
}
}
GeckoAppShell.useMaxScreenDepth(settings.getUseMaxScreenDepth());
GeckoAppShell.setDisplayDensityOverride(settings.getDisplayDensityOverride());
GeckoAppShell.setDisplayDpiOverride(settings.getDisplayDpiOverride());
GeckoAppShell.setScreenSizeOverride(settings.getScreenSizeOverride());

Просмотреть файл

@ -138,6 +138,20 @@ public final class GeckoRuntimeSettings implements Parcelable {
mSettings.mDebugPause = enabled;
return this;
}
/**
* Set whether the to report the full bit depth of the device.
*
* By default, 24 bits are reported for high memory devices and 16 bits
* for low memory devices. If set to true, the device's maximum bit depth is
* reported. On most modern devices this will be 32 bit screen depth.
*
* @param enable A flag determining whether maximum screen depth should be used.
* @return This Builder.
*/
public @NonNull Builder useMaxScreenDepth(boolean enable) {
mSettings.mUseMaxScreenDepth = enable;
return this;
}
/**
* Set cookie storage behavior.
@ -389,6 +403,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
"browser.safebrowsing.phishing.enabled", true);
/* package */ boolean mDebugPause;
/* package */ boolean mUseMaxScreenDepth;
/* package */ float mDisplayDensityOverride = -1.0f;
/* package */ int mDisplayDpiOverride;
/* package */ int mScreenWidthOverride;
@ -432,6 +447,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
}
mDebugPause = settings.mDebugPause;
mUseMaxScreenDepth = settings.mUseMaxScreenDepth;
mDisplayDensityOverride = settings.mDisplayDensityOverride;
mDisplayDpiOverride = settings.mDisplayDpiOverride;
mScreenWidthOverride = settings.mScreenWidthOverride;
@ -562,6 +578,13 @@ public final class GeckoRuntimeSettings implements Parcelable {
*/
public boolean getPauseForDebuggerEnabled() { return mDebugPause; }
/**
* Gets whether the compositor should use the maximum screen depth when rendering.
*
* @return True if the maximum screen depth should be used.
*/
public boolean getUseMaxScreenDepth() { return mUseMaxScreenDepth; }
/**
* Gets the display density override value.
*
@ -836,6 +859,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
}
ParcelableUtils.writeBoolean(out, mDebugPause);
ParcelableUtils.writeBoolean(out, mUseMaxScreenDepth);
out.writeFloat(mDisplayDensityOverride);
out.writeInt(mDisplayDpiOverride);
out.writeInt(mScreenWidthOverride);
@ -858,6 +882,7 @@ public final class GeckoRuntimeSettings implements Parcelable {
}
mDebugPause = ParcelableUtils.readBoolean(source);
mUseMaxScreenDepth = ParcelableUtils.readBoolean(source);
mDisplayDensityOverride = source.readFloat();
mDisplayDpiOverride = source.readInt();
mScreenWidthOverride = source.readInt();

Просмотреть файл

@ -121,6 +121,8 @@ public class GeckoSession implements Parcelable {
private int mLeft;
private int mTop; // Top of the surface (including toolbar);
private int mClientTop; // Top of the client area (i.e. excluding toolbar);
private int mOffsetX;
private int mOffsetY;
private int mWidth;
private int mHeight; // Height of the surface (including toolbar);
private int mClientHeight; // Height of the client area (i.e. excluding toolbar);
@ -195,7 +197,7 @@ public class GeckoSession implements Parcelable {
// UI thread resumes compositor and notifies Gecko thread; does not block UI thread.
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void syncResumeResizeCompositor(int width, int height, Object surface);
public native void syncResumeResizeCompositor(int x, int y, int width, int height, Object surface);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void setMaxToolbarHeight(int height);
@ -3924,15 +3926,17 @@ public class GeckoSession implements Parcelable {
int virtualId);
}
/* package */ void onSurfaceChanged(final Surface surface, final int width,
/* package */ void onSurfaceChanged(final Surface surface, final int x, final int y, final int width,
final int height) {
ThreadUtils.assertOnUiThread();
mOffsetX = x;
mOffsetY = y;
mWidth = width;
mHeight = height;
if (mCompositorReady) {
mCompositor.syncResumeResizeCompositor(width, height, surface);
mCompositor.syncResumeResizeCompositor(x, y, width, height, surface);
onWindowBoundsChanged();
return;
}
@ -3984,7 +3988,7 @@ public class GeckoSession implements Parcelable {
if (mSurface != null) {
// If we have a valid surface, create the compositor now that we're attached.
// Leave mSurface alone because we'll need it later for onCompositorReady.
onSurfaceChanged(mSurface, mWidth, mHeight);
onSurfaceChanged(mSurface, mOffsetX, mOffsetY, mWidth, mHeight);
}
mCompositor.sendToolbarAnimatorMessage(IS_COMPOSITOR_CONTROLLER_OPEN);
@ -4084,7 +4088,7 @@ public class GeckoSession implements Parcelable {
if (mSurface != null) {
// If we have a valid surface, resume the
// compositor now that the compositor is ready.
onSurfaceChanged(mSurface, mWidth, mHeight);
onSurfaceChanged(mSurface, mOffsetX, mOffsetY, mWidth, mHeight);
mSurface = null;
}

Просмотреть файл

@ -1005,7 +1005,7 @@ public:
}
void SyncResumeResizeCompositor(const GeckoSession::Compositor::LocalRef& aObj,
int32_t aWidth, int32_t aHeight,
int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
jni::Object::Param aSurface)
{
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
@ -1013,7 +1013,7 @@ public:
mSurface = aSurface;
if (RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild()) {
child->ResumeAndResize(aWidth, aHeight);
child->ResumeAndResize(aX, aY, aWidth, aHeight);
}
mCompositorPaused = false;