-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fall back on Skia when PLS isn't supported on Android
Adds a check to make sure PLS is supported, and falls back on Skia if not. Also keeps the PLS worker alive when the external ref count reaches zero, and instead frees its GPU resources. This has a similar effect, without having to pay the hefty price of destroying and re-creating the entire GL context Diffs= c4bdda67c Fall back on Skia when PLS isn't supported on Android (#6080) Co-authored-by: Chris Dalton <[email protected]>
- Loading branch information
1 parent
f57aac2
commit 0c5c1a5
Showing
8 changed files
with
161 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
22077bedae4c277e5e8a81c732167ab5d559917c | ||
c4bdda67cc0767e7910c53c30f97c172611b5e76 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,143 @@ | ||
#include "helpers/egl_worker.hpp" | ||
|
||
#include "helpers/general.hpp" | ||
#include "helpers/thread_state_pls.hpp" | ||
#include <thread> | ||
|
||
using namespace rive; | ||
|
||
namespace rive_android | ||
{ | ||
static std::mutex s_eglWorkerMutex; | ||
static EGLWorker* s_currentWorkers[2] = {nullptr, nullptr}; | ||
|
||
rcp<EGLWorker> EGLWorker::Current(const RendererType rendererType) | ||
rcp<EGLWorker> EGLWorker::RiveWorker() | ||
{ | ||
static enum class RiveRendererSupport { unknown, no, yes } s_isSupported; | ||
static std::unique_ptr<EGLWorker> s_riveWorker; | ||
|
||
std::lock_guard lock(s_eglWorkerMutex); | ||
int workerIdx = static_cast<int>(rendererType); | ||
if (s_currentWorkers[workerIdx] == nullptr) | ||
|
||
if (s_isSupported == RiveRendererSupport::unknown) | ||
{ | ||
LOGI("Created a new EGLWorker with type %s", | ||
rendererType == RendererType::Skia ? "Skia" : "Rive"); | ||
s_currentWorkers[workerIdx] = new EGLWorker(rendererType); | ||
assert(s_riveWorker == nullptr); | ||
LOGI("Creating a new EGLWorker with Rive"); | ||
std::unique_ptr<EGLWorker> candidateWorker(new EGLWorker(RendererType::Rive)); | ||
// Check if PLS is supported. | ||
candidateWorker->runAndWait([](rive_android::EGLThreadState* threadState) { | ||
PLSThreadState* plsThreadState = static_cast<PLSThreadState*>(threadState); | ||
s_isSupported = plsThreadState->plsContext() != nullptr ? RiveRendererSupport::yes | ||
: RiveRendererSupport::no; | ||
}); | ||
assert(s_isSupported != RiveRendererSupport::unknown); | ||
if (s_isSupported == RiveRendererSupport::yes) | ||
{ | ||
// The Rive renderer is supported! | ||
s_riveWorker = std::move(candidateWorker); | ||
} | ||
else | ||
{ | ||
LOGI("Rive renderer is not supported. Falling back on Skia."); | ||
} | ||
} | ||
else | ||
|
||
if (s_riveWorker != nullptr) | ||
{ | ||
LOGI("Referenced an existing EGLWorker."); | ||
s_currentWorkers[workerIdx]->ref(); | ||
++s_riveWorker->m_externalRefCount; // Increment the external ref count. | ||
} | ||
return rcp(s_currentWorkers[workerIdx]); | ||
return rcp(s_riveWorker.get()); | ||
} | ||
|
||
EGLWorker::~EGLWorker() | ||
static std::unique_ptr<EGLWorker> s_skiaWorker; | ||
|
||
rcp<EGLWorker> EGLWorker::SkiaWorker() | ||
{ | ||
std::lock_guard lock(s_eglWorkerMutex); | ||
LOGI("Deleting the current %s EGLWorker.", | ||
m_RendererType == RendererType::Skia ? "Skia" : "Rive"); | ||
int workerIdx = static_cast<int>(m_RendererType); | ||
assert(s_currentWorkers[workerIdx] == this); | ||
if (s_skiaWorker == nullptr) | ||
{ | ||
LOGI("Creating a new EGLWorker with Skia"); | ||
s_skiaWorker = std::unique_ptr<EGLWorker>(new EGLWorker(RendererType::Skia)); | ||
} | ||
++s_skiaWorker->m_externalRefCount; // Increment the external ref count. | ||
return rcp(s_skiaWorker.get()); | ||
} | ||
|
||
rcp<EGLWorker> EGLWorker::CurrentOrSkia(RendererType rendererType) | ||
{ | ||
rcp<EGLWorker> currentOrSkia; | ||
switch (rendererType) | ||
{ | ||
case RendererType::Rive: | ||
currentOrSkia = RiveWorker(); | ||
break; | ||
case RendererType::Skia: | ||
currentOrSkia = SkiaWorker(); | ||
break; | ||
} | ||
if (currentOrSkia == nullptr) | ||
{ | ||
currentOrSkia = SkiaWorker(); | ||
} | ||
return currentOrSkia; | ||
} | ||
|
||
static const char* renderer_name(RendererType rendererType) | ||
{ | ||
switch (rendererType) | ||
{ | ||
case RendererType::Rive: | ||
return "Rive"; | ||
case RendererType::Skia: | ||
return "Skia"; | ||
} | ||
} | ||
|
||
EGLWorker::~EGLWorker() | ||
{ | ||
LOGI("Deleting the EGLWorker with %s", renderer_name(rendererType())); | ||
terminateThread(); | ||
s_currentWorkers[workerIdx] = nullptr; | ||
} | ||
|
||
void EGLWorker::ref() | ||
{ | ||
std::lock_guard lock(s_eglWorkerMutex); | ||
++m_externalRefCount; | ||
} | ||
|
||
void EGLWorker::unref() | ||
{ | ||
std::lock_guard lock(s_eglWorkerMutex); | ||
assert(m_externalRefCount > 0); | ||
if (--m_externalRefCount == 0) | ||
{ | ||
externalRefCountDidReachZero(); | ||
} | ||
} | ||
|
||
void EGLWorker::externalRefCountDidReachZero() | ||
{ | ||
switch (rendererType()) | ||
{ | ||
case RendererType::Rive: | ||
// Release the Rive worker's GPU resources, but keep the GL context alive. We have | ||
// simple way to release GPU resources here instead, without having to pay the hefty | ||
// price of destroying and re-creating the entire GL context. | ||
run([](rive_android::EGLThreadState* threadState) { | ||
PLSThreadState* plsThreadState = static_cast<PLSThreadState*>(threadState); | ||
rive::pls::PLSRenderContext* plsContext = plsThreadState->plsContext(); | ||
if (plsContext != nullptr) | ||
{ | ||
LOGI("Releasing GPU resources on the Rive renderer"); | ||
plsContext->resetGPUResources(); | ||
} | ||
}); | ||
break; | ||
case RendererType::Skia: | ||
{ | ||
// Delete the entire Skia context. | ||
assert(s_skiaWorker.get() == this); | ||
s_skiaWorker = nullptr; | ||
break; | ||
} | ||
} | ||
} | ||
} // namespace rive_android |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters