Skip to content

Commit

Permalink
[xulrunner] Fix embeded offscreen surfaces not being painted. Contrib…
Browse files Browse the repository at this point in the history
…utes to JB#48494

Instead of trying to intercept composite task to redraw to an embedded
surface which stopped working when a scheduling was moved to a distinct
object override the actual composite call. Then only swap the front and
back buffers if a composite task succeeds and do this before notifying
the front end that compositing was done. And finally add a version of
GetPlatformImage which takes a callback to invoke to pass the image so
a lock can be held preventing buffers being swapped while an image
pointer belonging to one of those buffers is being referenced.
  • Loading branch information
denexter committed Feb 28, 2020
1 parent 96f0088 commit ba21a86
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 73 deletions.
5 changes: 5 additions & 0 deletions embedding/embedlite/EmbedLiteWindow.cpp
Expand Up @@ -93,6 +93,11 @@ void* EmbedLiteWindow::GetPlatformImage(int* width, int* height)
return mWindowParent->GetPlatformImage(width, height);
}

void EmbedLiteWindow::GetPlatformImage(const Function<void(void *image, int width, int height)> &callback)
{
mWindowParent->GetPlatformImage(callback);
}

} // nemsapace embedlite
} // namespace mozilla

2 changes: 2 additions & 0 deletions embedding/embedlite/EmbedLiteWindow.h
Expand Up @@ -9,6 +9,7 @@
#include <stdint.h>

#include "nsRect.h"
#include "mozilla/Function.h"

namespace mozilla {
namespace embedlite {
Expand Down Expand Up @@ -83,6 +84,7 @@ class EmbedLiteWindow {
virtual void SuspendRendering();
virtual void ResumeRendering();
virtual void* GetPlatformImage(int* width, int* height);
virtual void GetPlatformImage(const Function<void(void *image, int width, int height)> &callback);

protected:
friend class EmbedLiteApp;
Expand Down
5 changes: 5 additions & 0 deletions embedding/embedlite/embedshared/EmbedLitePuppetWidget.cpp
Expand Up @@ -846,6 +846,11 @@ EmbedLitePuppetWidget::PostRender(LayerManagerComposite *aManager)
{
MOZ_ASSERT(mWindow);
Unused << aManager;

if (mCompositorParent) {
static_cast<EmbedLiteCompositorParent*>(mCompositorParent.get())->PresentOffscreenSurface();
}

EmbedLiteWindow* window = EmbedLiteApp::GetInstance()->GetWindowByID(mWindow->GetUniqueID());
if (window) {
window->GetListener()->CompositingFinished();
Expand Down
7 changes: 7 additions & 0 deletions embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.cpp
Expand Up @@ -97,6 +97,13 @@ void* EmbedLiteWindowBaseParent::GetPlatformImage(int* width, int* height)
return nullptr;
}

void EmbedLiteWindowBaseParent::GetPlatformImage(const Function<void(void *image, int width, int height)> &callback)
{
if (mCompositor) {
mCompositor->GetPlatformImage(callback);
}
}

void EmbedLiteWindowBaseParent::SetEmbedAPIWindow(EmbedLiteWindow* window)
{
mWindow = window;
Expand Down
2 changes: 2 additions & 0 deletions embedding/embedlite/embedshared/EmbedLiteWindowBaseParent.h
Expand Up @@ -7,6 +7,7 @@
#define MOZ_WINDOW_EMBED_BASE_PARENT_H

#include "mozilla/embedlite/PEmbedLiteWindowParent.h"
#include "mozilla/Function.h"
#include "mozilla/WidgetUtils.h"

namespace mozilla {
Expand Down Expand Up @@ -40,6 +41,7 @@ class EmbedLiteWindowBaseParent : public PEmbedLiteWindowParent
void SuspendRendering();
void ResumeRendering();
void* GetPlatformImage(int* width, int* height);
void GetPlatformImage(const Function<void(void *image, int width, int height)> &callback);

protected:
friend class EmbedLiteCompositorParent;
Expand Down
123 changes: 54 additions & 69 deletions embedding/embedlite/embedthread/EmbedLiteCompositorParent.cpp
Expand Up @@ -122,105 +122,90 @@ EmbedLiteCompositorParent::PrepareOffscreen()
}
}

void
EmbedLiteCompositorParent::UpdateTransformState()
void EmbedLiteCompositorParent::CompositeToDefaultTarget()
{
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(RootLayerTreeId());
NS_ENSURE_TRUE(state && state->mLayerManager, );

CompositorOGL *compositor = static_cast<CompositorOGL*>(state->mLayerManager->GetCompositor());
NS_ENSURE_TRUE(compositor, );

GLContext* context = compositor->gl();
GLContext* context = static_cast<CompositorOGL*>(state->mLayerManager->GetCompositor())->gl();
NS_ENSURE_TRUE(context, );

if (context->IsOffscreen() && context->OffscreenSize() != mSurfaceSize && context->ResizeOffscreen(mSurfaceSize)) {
ScheduleRenderOnCompositorThread();
if (!context->IsCurrent()) {
context->MakeCurrent(true);
}
}
NS_ENSURE_TRUE(context->IsCurrent(), );

void
EmbedLiteCompositorParent::ScheduleTask(CancelableTask* task, int time)
{
if (Invalidate()) {
task->Cancel();
CancelCurrentCompositeTask();
} else {
CompositorParent::ScheduleTask(task, time);
if (context->IsOffscreen()) {
MutexAutoLock lock(mRenderMutex);
if (context->OffscreenSize() != mSurfaceSize && !context->ResizeOffscreen(mSurfaceSize)) {
return;
}
}
}

bool
EmbedLiteCompositorParent::Invalidate()
{
if (!mUseExternalGLContext) {
UpdateTransformState();
mCurrentCompositeTask = NewRunnableMethod(this, &EmbedLiteCompositorParent::RenderGL, TimeStamp::Now());
MessageLoop::current()->PostDelayedTask(FROM_HERE, mCurrentCompositeTask, sDefaultPaintInterval);
return true;
{
ScopedScissorRect autoScissor(context);
GLenum oldTexUnit;
context->GetUIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &oldTexUnit);
CompositeToTarget(nullptr);
context->fActiveTexture(oldTexUnit);
}

return false;
}

bool EmbedLiteCompositorParent::RenderGL(TimeStamp aScheduleTime)
void EmbedLiteCompositorParent::PresentOffscreenSurface()
{
// mLastCompose = aScheduleTime;
if (mCurrentCompositeTask) {
mCurrentCompositeTask->Cancel();
mCurrentCompositeTask = nullptr;
}

const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(RootLayerTreeId());
NS_ENSURE_TRUE(state && state->mLayerManager, false);
NS_ENSURE_TRUE(state && state->mLayerManager, );

GLContext* context = static_cast<CompositorOGL*>(state->mLayerManager->GetCompositor())->gl();
NS_ENSURE_TRUE(context, false);
if (!context->IsCurrent()) {
context->MakeCurrent(true);
}
NS_ENSURE_TRUE(context->IsCurrent(), false);
NS_ENSURE_TRUE(context, );
NS_ENSURE_TRUE(context->IsOffscreen(), );

{
ScopedScissorRect autoScissor(context);
GLenum oldTexUnit;
context->GetUIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &oldTexUnit);
CompositeToTarget(nullptr);
context->fActiveTexture(oldTexUnit);
}
// RenderGL is called always from Gecko compositor thread.
// GLScreenBuffer::PublishFrame does swap buffers and that
// cannot happen while reading previous frame on EmbedLiteCompositorParent::GetPlatformImage
// (potentially from another thread).
MutexAutoLock lock(mRenderMutex);

if (context->IsOffscreen()) {
// RenderGL is called always from Gecko compositor thread.
// GLScreenBuffer::PublishFrame does swap buffers and that
// cannot happen while reading previous frame on EmbedLiteCompositorParent::GetPlatformImage
// (potentially from another thread).
MutexAutoLock lock(mRenderMutex);
GLScreenBuffer* screen = context->Screen();
MOZ_ASSERT(screen);
GLScreenBuffer* screen = context->Screen();
MOZ_ASSERT(screen);

if (screen->Size().IsEmpty() || !screen->PublishFrame(screen->Size())) {
NS_ERROR("Failed to publish context frame");
return false;
}
// Temporary hack, we need two extra paints in order to get initial picture
static int sInitialPaintCount = 0;
if (sInitialPaintCount < 2) {
ScheduleRenderOnCompositorThread();
sInitialPaintCount++;
}
if (screen->Size().IsEmpty() || !screen->PublishFrame(screen->Size())) {
NS_ERROR("Failed to publish context frame");
}

return false;
}

void EmbedLiteCompositorParent::SetSurfaceSize(int width, int height)
{
if (width > 0 && height > 0 && (mSurfaceSize.width != width || mSurfaceSize.height != height)) {
SetEGLSurfaceSize(width, height);

MutexAutoLock lock(mRenderMutex);
mSurfaceSize = gfx::IntSize(width, height);
}
}

void EmbedLiteCompositorParent::GetPlatformImage(const Function<void(void *image, int width, int height)> &callback)
{
MutexAutoLock lock(mRenderMutex);
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(RootLayerTreeId());
NS_ENSURE_TRUE(state && state->mLayerManager, );

GLContext* context = static_cast<CompositorOGL*>(state->mLayerManager->GetCompositor())->gl();
NS_ENSURE_TRUE(context, );
NS_ENSURE_TRUE(context->IsOffscreen(), );

GLScreenBuffer* screen = context->Screen();
MOZ_ASSERT(screen);
NS_ENSURE_TRUE(screen->Front(),);
SharedSurface* sharedSurf = screen->Front()->Surf();
NS_ENSURE_TRUE(sharedSurf, );
sharedSurf->WaitSync();

if (sharedSurf->mType == SharedSurfaceType::EGLImageShare) {
SharedSurface_EGLImage* eglImageSurf = SharedSurface_EGLImage::Cast(sharedSurf);
callback(eglImageSurf->mImage, sharedSurf->mSize.width, sharedSurf->mSize.height);
}
}

void*
EmbedLiteCompositorParent::GetPlatformImage(int* width, int* height)
{
Expand Down
11 changes: 7 additions & 4 deletions embedding/embedlite/embedthread/EmbedLiteCompositorParent.h
Expand Up @@ -9,6 +9,7 @@
#define COMPOSITOR_PERFORMANCE_WARNING

#include "Layers.h"
#include "mozilla/Function.h"
#include "mozilla/Mutex.h"
#include "mozilla/WidgetUtils.h"
#include "mozilla/layers/CompositorChild.h"
Expand All @@ -22,6 +23,8 @@ class LayerManagerComposite;

namespace embedlite {

class EmbedLiteWindowListener;

class EmbedLiteCompositorParent : public mozilla::layers::CompositorParent
{
public:
Expand All @@ -31,9 +34,12 @@ class EmbedLiteCompositorParent : public mozilla::layers::CompositorParent

void SetSurfaceSize(int width, int height);
void* GetPlatformImage(int* width, int* height);
void GetPlatformImage(const Function<void(void *image, int width, int height)> &callback);
void SuspendRendering();
void ResumeRendering();

void PresentOffscreenSurface();

protected:
friend class EmbedLitePuppetWidget;

Expand All @@ -43,13 +49,10 @@ class EmbedLiteCompositorParent : public mozilla::layers::CompositorParent
const uint64_t& aId,
TextureFactoryIdentifier* aTextureFactoryIdentifier,
bool* aSuccess) override;
virtual void ScheduleTask(CancelableTask*, int) override;
virtual void CompositeToDefaultTarget() override;

private:
void PrepareOffscreen();
bool Invalidate();
void UpdateTransformState();
bool RenderGL(TimeStamp aScheduleTime);

uint32_t mWindowId;
CancelableTask* mCurrentCompositeTask;
Expand Down
@@ -0,0 +1,74 @@
From f2e8fe315400e9df42d1e89a7d7bacf4fe6038c1 Mon Sep 17 00:00:00 2001
From: Andrew den Exter <andrew.den.exter@qinetic.com.au>
Date: Mon, 9 Dec 2019 01:29:16 +0000
Subject: [PATCH] Allow compositor specializations to override the composite
command.

---
gfx/layers/ipc/CompositorParent.cpp | 16 +++++++++++++---
gfx/layers/ipc/CompositorParent.h | 1 +
2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp
index be0f067..c3cc99b 100644
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -437,7 +437,7 @@ CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp)
if (mNeedsComposite || mAsapScheduling) {
mNeedsComposite = 0;
mLastCompose = aVsyncTimestamp;
- ComposeToTarget(nullptr);
+ mCompositorParent->CompositeToDefaultTarget();
mVsyncNotificationsSkipped = 0;

TimeDuration compositeFrameTotal = TimeStamp::Now() - aVsyncTimestamp;
@@ -548,7 +548,7 @@ CompositorVsyncScheduler::ResumeComposition()
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
mLastCompose = TimeStamp::Now();
- ComposeToTarget(nullptr);
+ mCompositorParent->CompositeToDefaultTarget();
}

void
@@ -556,7 +556,11 @@ CompositorVsyncScheduler::ComposeToTarget(gfx::DrawTarget* aTarget, const IntRec
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
MOZ_ASSERT(mCompositorParent);
- mCompositorParent->CompositeToTarget(aTarget, aRect);
+ if (aTarget) {
+ mCompositorParent->CompositeToTarget(aTarget, aRect);
+ } else {
+ mCompositorParent->CompositeToDefaultTarget();
+ }
}

CompositorParent::CompositorParent(nsIWidget* aWidget,
@@ -1044,6 +1048,12 @@ CompositorParent::SetShadowProperties(Layer* aLayer)
}

void
+CompositorParent::CompositeToDefaultTarget()
+{
+ CompositeToTarget(nullptr);
+}
+
+void
CompositorParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRect)
{
profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h
index bc9a319..7ca9053 100644
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -422,6 +422,7 @@ protected:
virtual void ScheduleTask(CancelableTask*, int);
void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
+ virtual void CompositeToDefaultTarget();

void SetEGLSurfaceSize(int width, int height);

--
1.8.3-rc3

2 changes: 2 additions & 0 deletions rpm/xulrunner-qt5.spec
Expand Up @@ -61,6 +61,7 @@ Patch15: 0015-Disable-SiteSpecificUserAgent.js-from-the-build.-Con.patch
Patch16: 0016-Cleanup-build-configuration.-Fixes-JB-44612.patch
Patch17: 0017-Make-gc-stats-work-with-gcc8.patch
Patch18: 0018-Use-libcontentaction-for-custom-schem.patch
Patch19: 0019-Allow-compositor-specializations-to-override-the-com.patch

BuildRequires: pkgconfig(Qt5Quick)
BuildRequires: pkgconfig(Qt5Network)
Expand Down Expand Up @@ -168,6 +169,7 @@ Tests and misc files for xulrunner.
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1

mkdir -p "%BUILD_DIR"
cp -rf "%BASE_CONFIG" "%BUILD_DIR"/mozconfig
Expand Down

0 comments on commit ba21a86

Please sign in to comment.