Skip to content

Commit

Permalink
[Skia] Use a different GL context on every thread
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=274454

Reviewed by Miguel Gomez.

This will allow to have accelerated ImageBitmap and offscreen canvas.

* Source/WebCore/platform/graphics/PlatformDisplay.cpp:
(WebCore::PlatformDisplay::clearSharingGLContext):
* Source/WebCore/platform/graphics/PlatformDisplay.h:
(WebCore::PlatformDisplay::skiaGrContext): Deleted.
* Source/WebCore/platform/graphics/skia/PlatformDisplaySkia.cpp:
(WebCore::skiaGLInterface):
(WebCore::SkiaGLContext::create):
(WebCore::SkiaGLContext::invalidate):
(WebCore::SkiaGLContext::skiaGLContext const):
(WebCore::SkiaGLContext::skiaGrContext const):
(WebCore::SkiaGLContext::SkiaGLContext):
(WebCore::PlatformDisplay::skiaGLContext):
(WebCore::PlatformDisplay::skiaGrContext):
(WebCore::PlatformDisplay::invalidateSkiaGLContexts):

Canonical link: https://commits.webkit.org/279119@main
  • Loading branch information
carlosgcampos committed May 22, 2024
1 parent be4cdc9 commit 685354b
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 23 deletions.
3 changes: 3 additions & 0 deletions Source/WebCore/platform/graphics/PlatformDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ GLContext* PlatformDisplay::sharingGLContext()

void PlatformDisplay::clearSharingGLContext()
{
#if USE(SKIA)
invalidateSkiaGLContexts();
#endif
#if ENABLE(VIDEO) && USE(GSTREAMER_GL)
m_gstGLContext = nullptr;
#endif
Expand Down
13 changes: 10 additions & 3 deletions Source/WebCore/platform/graphics/PlatformDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,15 @@ typedef struct _GstGLDisplay GstGLDisplay;

#if USE(SKIA)
#include <skia/gpu/GrDirectContext.h>
#include <wtf/ThreadSafeWeakHashSet.h>
#endif

namespace WebCore {

class GLContext;
#if USE(SKIA)
class SkiaGLContext;
#endif

class PlatformDisplay {
WTF_MAKE_NONCOPYABLE(PlatformDisplay); WTF_MAKE_FAST_ALLOCATED;
Expand Down Expand Up @@ -141,7 +145,7 @@ class PlatformDisplay {

#if USE(SKIA)
GLContext* skiaGLContext();
GrDirectContext* skiaGrContext() { RELEASE_ASSERT(m_skiaGLContext); return m_skiaGrContext.get(); }
GrDirectContext* skiaGrContext();
#endif

#if USE(LCMS)
Expand Down Expand Up @@ -199,6 +203,10 @@ class PlatformDisplay {
private:
static std::unique_ptr<PlatformDisplay> createPlatformDisplay();

#if USE(SKIA)
void invalidateSkiaGLContexts();
#endif

#if ENABLE(WEBGL) && !PLATFORM(WIN)
void clearANGLESharingGLContext();
#endif
Expand Down Expand Up @@ -226,8 +234,7 @@ class PlatformDisplay {
#endif

#if USE(SKIA)
std::unique_ptr<GLContext> m_skiaGLContext;
sk_sp<GrDirectContext> m_skiaGrContext;
ThreadSafeWeakHashSet<SkiaGLContext> m_skiaGLContexts;
#endif

#if PLATFORM(WPE)
Expand Down
114 changes: 94 additions & 20 deletions Source/WebCore/platform/graphics/skia/PlatformDisplaySkia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,18 @@
#if USE(SKIA)
#include "GLContext.h"
#include <skia/gpu/GrBackendSurface.h>

IGNORE_CLANG_WARNINGS_BEGIN("cast-align")
#include <skia/gpu/ganesh/SkSurfaceGanesh.h>
IGNORE_CLANG_WARNINGS_END

#include <skia/gpu/ganesh/gl/GrGLBackendSurface.h>
#include <skia/gpu/ganesh/gl/GrGLDirectContext.h>
#include <skia/gpu/gl/GrGLInterface.h>
#include <skia/gpu/gl/GrGLTypes.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/RunLoop.h>
#include <wtf/ThreadSafeWeakPtr.h>
#include <wtf/threads/BinarySemaphore.h>

IGNORE_CLANG_WARNINGS_BEGIN("cast-align")
#include <skia/gpu/ganesh/SkSurfaceGanesh.h>
IGNORE_CLANG_WARNINGS_END

#if USE(LIBEPOXY)
#include <skia/gpu/gl/epoxy/GrGLMakeEpoxyEGLInterface.h>
Expand All @@ -61,29 +63,101 @@ static sk_sp<const GrGLInterface> skiaGLInterface()

return interface.get();
}
#endif

GLContext* PlatformDisplay::skiaGLContext()
{
static std::once_flag onceFlag;
std::call_once(onceFlag, [this] {
// The PlayStation OpenGL implementation does not dispatch to the context bound to
// the current thread so Skia cannot use OpenGL with coordinated graphics
#if !(PLATFORM(PLAYSTATION) && USE(COORDINATED_GRAPHICS))
auto skiaGLContext = GLContext::createOffscreen(*this);
if (!skiaGLContext || !skiaGLContext->makeContextCurrent())
static thread_local RefPtr<SkiaGLContext> s_skiaGLContext;

class SkiaGLContext : public ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr<SkiaGLContext> {
public:
static Ref<SkiaGLContext> create(PlatformDisplay& display)
{
return adoptRef(*new SkiaGLContext(display));
}

~SkiaGLContext() = default;

void invalidate()
{
if (&RunLoop::current() == m_runLoop) {
invalidateOnCurrentThread();
return;
}

BinarySemaphore semaphore;
m_runLoop->dispatch([&semaphore, this] {
invalidateOnCurrentThread();
semaphore.signal();
});
semaphore.wait();
}

GLContext* skiaGLContext() const
{
Locker locker { m_lock };
return m_skiaGLContext.get();
}

GrDirectContext* skiaGrContext() const
{
Locker locker { m_lock };
return m_skiaGrContext.get();
}

private:
explicit SkiaGLContext(PlatformDisplay& display)
: m_runLoop(&RunLoop::current())
{
auto glContext = GLContext::createOffscreen(display);
if (!glContext || !glContext->makeContextCurrent())
return;

// FIXME: add GrContextOptions, shader cache, etc.
if (auto skiaGrContext = GrDirectContexts::MakeGL(skiaGLInterface())) {
m_skiaGLContext = WTFMove(skiaGLContext);
m_skiaGrContext = WTFMove(skiaGrContext);
if (auto grContext = GrDirectContexts::MakeGL(skiaGLInterface())) {
m_skiaGLContext = WTFMove(glContext);
m_skiaGrContext = WTFMove(grContext);
}
}

void invalidateOnCurrentThread()
{
Locker locker { m_lock };
m_skiaGrContext = nullptr;
m_skiaGLContext = nullptr;
}

RunLoop* m_runLoop { nullptr };
std::unique_ptr<GLContext> m_skiaGLContext WTF_GUARDED_BY_LOCK(m_lock);
sk_sp<GrDirectContext> m_skiaGrContext WTF_GUARDED_BY_LOCK(m_lock);
mutable Lock m_lock;
};
#endif

GLContext* PlatformDisplay::skiaGLContext()
{
#if !(PLATFORM(PLAYSTATION) && USE(COORDINATED_GRAPHICS))
if (!s_skiaGLContext) {
s_skiaGLContext = SkiaGLContext::create(*this);
m_skiaGLContexts.add(*s_skiaGLContext);
}
return s_skiaGLContext->skiaGLContext();
#else
UNUSED_PARAM(this);
// The PlayStation OpenGL implementation does not dispatch to the context bound to
// the current thread so Skia cannot use OpenGL with coordinated graphics.
return nullptr;
#endif
}

GrDirectContext* PlatformDisplay::skiaGrContext()
{
RELEASE_ASSERT(s_skiaGLContext);
return s_skiaGLContext->skiaGrContext();
}

void PlatformDisplay::invalidateSkiaGLContexts()
{
auto contexts = WTFMove(m_skiaGLContexts);
contexts.forEach([](auto& context) {
context.invalidate();
});
return m_skiaGLContext.get();
}

} // namespace WebCore
Expand Down

0 comments on commit 685354b

Please sign in to comment.