Add method to sk_gpu_test::TestContext to automatically restore the previous context.
The motivation for this is to allow a GM to create a GL context, do some some work in it, and then return to the context that was set when it was invoked. Change-Id: Ie8496072a10f8f3ff36a08889e593a6ca961b61a Reviewed-on: https://skia-review.googlesource.com/70720 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
47f6029d3d
commit
5627d65146
@ -272,6 +272,7 @@ skia_core_sources = [
|
||||
"$_src/core/SkScan_Antihair.cpp",
|
||||
"$_src/core/SkScan_Hairline.cpp",
|
||||
"$_src/core/SkScan_Path.cpp",
|
||||
"$_src/core/SkScopeExit.h",
|
||||
"$_src/core/SkSemaphore.cpp",
|
||||
"$_src/core/SkSharedMutex.cpp",
|
||||
"$_src/core/SkSharedMutex.h",
|
||||
|
@ -46,5 +46,4 @@ skia_pdf_sources = [
|
||||
"$_src/pdf/SkPDFTypes.h",
|
||||
"$_src/pdf/SkPDFUtils.cpp",
|
||||
"$_src/pdf/SkPDFUtils.h",
|
||||
"$_src/pdf/SkScopeExit.h",
|
||||
]
|
||||
|
@ -10,6 +10,30 @@
|
||||
|
||||
#include "SkTypes.h"
|
||||
|
||||
/** SkScopeExit calls a std:::function<void()> in its destructor. */
|
||||
class SkScopeExit {
|
||||
public:
|
||||
SkScopeExit(std::function<void()> f) : fFn(std::move(f)) {}
|
||||
SkScopeExit(SkScopeExit&& that) : fFn(std::move(that.fFn)) {}
|
||||
|
||||
~SkScopeExit() {
|
||||
if (fFn) {
|
||||
fFn();
|
||||
}
|
||||
}
|
||||
|
||||
SkScopeExit& operator=(SkScopeExit&& that) {
|
||||
fFn = std::move(that.fFn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void()> fFn;
|
||||
|
||||
SkScopeExit( const SkScopeExit& ) = delete;
|
||||
SkScopeExit& operator=(const SkScopeExit& ) = delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* SK_AT_SCOPE_EXIT(stmt) evaluates stmt when the current scope ends.
|
||||
*
|
||||
@ -23,28 +47,7 @@
|
||||
* SkASSERT(x == 4);
|
||||
* }
|
||||
*/
|
||||
template <typename Fn>
|
||||
class SkScopeExit {
|
||||
public:
|
||||
SkScopeExit(Fn f) : fFn(std::move(f)) {}
|
||||
~SkScopeExit() { fFn(); }
|
||||
|
||||
private:
|
||||
Fn fFn;
|
||||
|
||||
SkScopeExit( const SkScopeExit& ) = delete;
|
||||
SkScopeExit& operator=(const SkScopeExit& ) = delete;
|
||||
SkScopeExit( SkScopeExit&&) = delete;
|
||||
SkScopeExit& operator=( SkScopeExit&&) = delete;
|
||||
};
|
||||
|
||||
template <typename Fn>
|
||||
inline SkScopeExit<Fn> SkMakeScopeExit(Fn&& fn) {
|
||||
return {std::move(fn)};
|
||||
}
|
||||
|
||||
#define SK_AT_SCOPE_EXIT(stmt) \
|
||||
SK_UNUSED auto&& SK_MACRO_APPEND_LINE(at_scope_exit_) = \
|
||||
SkMakeScopeExit([&]() { stmt; });
|
||||
SkScopeExit SK_MACRO_APPEND_LINE(at_scope_exit_)([&]() { stmt; })
|
||||
|
||||
#endif // SkScopeExit_DEFINED
|
@ -436,10 +436,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeTextureImage, reporter, contextIn
|
||||
// Create a texture image.
|
||||
[context] { return create_gpu_image(context); },
|
||||
// Create a texture image in a another GrContext.
|
||||
[testContext, otherContextInfo] {
|
||||
otherContextInfo.testContext()->makeCurrent();
|
||||
[otherContextInfo] {
|
||||
auto restore = otherContextInfo.testContext()->makeCurrentAndAutoRestore();
|
||||
sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.grContext());
|
||||
testContext->makeCurrent();
|
||||
otherContextInfo.grContext()->flush();
|
||||
return otherContextImage;
|
||||
}
|
||||
};
|
||||
@ -487,7 +487,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkImage_makeTextureImage, reporter, contextIn
|
||||
}
|
||||
}
|
||||
|
||||
testContext->makeCurrent();
|
||||
context->flush();
|
||||
}
|
||||
}
|
||||
@ -1197,10 +1196,10 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(makeBackendTexture, reporter, ctxInfo) {
|
||||
{ create_picture_image, true, false },
|
||||
{ [context] { return create_gpu_image(context); }, true, true },
|
||||
// Create a texture image in a another GrContext.
|
||||
{ [testContext, otherContextInfo] {
|
||||
otherContextInfo.testContext()->makeCurrent();
|
||||
{ [otherContextInfo] {
|
||||
auto restore = otherContextInfo.testContext()->makeCurrentAndAutoRestore();
|
||||
sk_sp<SkImage> otherContextImage = create_gpu_image(otherContextInfo.grContext());
|
||||
testContext->makeCurrent();
|
||||
otherContextInfo.grContext()->flush();
|
||||
return otherContextImage;
|
||||
}, false, false },
|
||||
// Create an image that is too large to be texture backed.
|
||||
@ -1232,7 +1231,6 @@ DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(makeBackendTexture, reporter, ctxInfo) {
|
||||
kExpectedState[testCase.fCanTakeDirectly]);
|
||||
}
|
||||
|
||||
testContext->makeCurrent();
|
||||
context->flush();
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +52,9 @@ GrContextFactory::~GrContextFactory() {
|
||||
|
||||
void GrContextFactory::destroyContexts() {
|
||||
for (Context& context : fContexts) {
|
||||
SkScopeExit restore(nullptr);
|
||||
if (context.fTestContext) {
|
||||
context.fTestContext->makeCurrent();
|
||||
restore = context.fTestContext->makeCurrentAndAutoRestore();
|
||||
}
|
||||
if (!context.fGrContext->unique()) {
|
||||
context.fGrContext->releaseResourcesAndAbandonContext();
|
||||
@ -69,7 +70,7 @@ void GrContextFactory::abandonContexts() {
|
||||
for (Context& context : fContexts) {
|
||||
if (!context.fAbandoned) {
|
||||
if (context.fTestContext) {
|
||||
context.fTestContext->makeCurrent();
|
||||
auto restore = context.fTestContext->makeCurrentAndAutoRestore();
|
||||
context.fTestContext->testAbandon();
|
||||
delete(context.fTestContext);
|
||||
context.fTestContext = nullptr;
|
||||
@ -82,9 +83,10 @@ void GrContextFactory::abandonContexts() {
|
||||
|
||||
void GrContextFactory::releaseResourcesAndAbandonContexts() {
|
||||
for (Context& context : fContexts) {
|
||||
SkScopeExit restore(nullptr);
|
||||
if (!context.fAbandoned) {
|
||||
if (context.fTestContext) {
|
||||
context.fTestContext->makeCurrent();
|
||||
restore = context.fTestContext->makeCurrentAndAutoRestore();
|
||||
}
|
||||
context.fGrContext->releaseResourcesAndAbandonContext();
|
||||
context.fAbandoned = true;
|
||||
@ -237,7 +239,7 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
|
||||
default:
|
||||
return ContextInfo();
|
||||
}
|
||||
testCtx->makeCurrent();
|
||||
|
||||
SkASSERT(testCtx && testCtx->backend() == backend);
|
||||
GrContextOptions grOptions = fGlobalOptions;
|
||||
if (ContextOverrides::kDisableNVPR & overrides) {
|
||||
@ -252,7 +254,11 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
|
||||
if (ContextOverrides::kAvoidStencilBuffers & overrides) {
|
||||
grOptions.fAvoidStencilBuffers = true;
|
||||
}
|
||||
sk_sp<GrContext> grCtx = testCtx->makeGrContext(grOptions);
|
||||
sk_sp<GrContext> grCtx;
|
||||
{
|
||||
auto restore = testCtx->makeCurrentAndAutoRestore();
|
||||
grCtx = testCtx->makeGrContext(grOptions);
|
||||
}
|
||||
if (!grCtx.get()) {
|
||||
return ContextInfo();
|
||||
}
|
||||
@ -282,6 +288,7 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
|
||||
context.fShareContext = shareContext;
|
||||
context.fShareIndex = shareIndex;
|
||||
context.fOptions = grOptions;
|
||||
context.fTestContext->makeCurrent();
|
||||
return ContextInfo(context.fType, context.fTestContext, context.fGrContext, context.fOptions);
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,15 @@ sk_sp<GrContext> TestContext::makeGrContext(const GrContextOptions&) {
|
||||
|
||||
void TestContext::makeCurrent() const { this->onPlatformMakeCurrent(); }
|
||||
|
||||
SkScopeExit TestContext::makeCurrentAndAutoRestore() const {
|
||||
auto asr = SkScopeExit(this->onPlatformGetAutoContextRestore());
|
||||
this->makeCurrent();
|
||||
return asr;
|
||||
}
|
||||
|
||||
void TestContext::swapBuffers() { this->onPlatformSwapBuffers(); }
|
||||
|
||||
|
||||
void TestContext::waitOnSyncOrSwap() {
|
||||
if (!fFenceSync) {
|
||||
// Fallback on the platform SwapBuffers method for synchronization. This may have no effect.
|
||||
|
@ -9,10 +9,11 @@
|
||||
#ifndef TestContext_DEFINED
|
||||
#define TestContext_DEFINED
|
||||
|
||||
#include "../private/SkTemplates.h"
|
||||
#include "FenceSync.h"
|
||||
#include "GrTypes.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "../private/SkTemplates.h"
|
||||
#include "SkScopeExit.h"
|
||||
|
||||
class GrContext;
|
||||
struct GrContextOptions;
|
||||
@ -45,6 +46,18 @@ public:
|
||||
|
||||
void makeCurrent() const;
|
||||
|
||||
/**
|
||||
* Like makeCurrent() but this returns an object that will restore the previous current
|
||||
* context in its destructor. Useful to undo the effect making this current before returning to
|
||||
* a caller that doesn't expect the current context to be changed underneath it.
|
||||
*
|
||||
* The returned object restores the current context of the same type (e.g. egl, glx, ...) in its
|
||||
* destructor. It is undefined behavior if that context is destroyed before the destructor
|
||||
* executes. If the concept of a current context doesn't make sense for this context type then
|
||||
* the returned object's destructor is a no-op.
|
||||
*/
|
||||
SkScopeExit SK_WARN_UNUSED_RESULT makeCurrentAndAutoRestore() const;
|
||||
|
||||
virtual GrBackend backend() = 0;
|
||||
virtual GrBackendContext backendContext() = 0;
|
||||
|
||||
@ -94,6 +107,14 @@ protected:
|
||||
virtual void teardown();
|
||||
|
||||
virtual void onPlatformMakeCurrent() const = 0;
|
||||
/**
|
||||
* Subclasses should implement such that the returned function will cause the current context
|
||||
* of this type to be made current again when it is called. It should additionally be the
|
||||
* case that if "this" is already current when this is called, then "this" is destroyed (thereby
|
||||
* setting the null context as current), and then the std::function is called the null context
|
||||
* should remain current.
|
||||
*/
|
||||
virtual std::function<void()> onPlatformGetAutoContextRestore() const = 0;
|
||||
virtual void onPlatformSwapBuffers() const = 0;
|
||||
|
||||
private:
|
||||
|
@ -34,6 +34,16 @@ struct Libs {
|
||||
void* fEGLLib;
|
||||
};
|
||||
|
||||
std::function<void()> context_restorer() {
|
||||
auto display = eglGetCurrentDisplay();
|
||||
auto dsurface = eglGetCurrentSurface(EGL_DRAW);
|
||||
auto rsurface = eglGetCurrentSurface(EGL_READ);
|
||||
auto context = eglGetCurrentContext();
|
||||
return [display, dsurface, rsurface, context] {
|
||||
eglMakeCurrent(display, dsurface, rsurface, context);
|
||||
};
|
||||
}
|
||||
|
||||
static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
|
||||
const Libs* libs = reinterpret_cast<const Libs*>(ctx);
|
||||
GrGLFuncPtr proc = (GrGLFuncPtr) GetProcedureAddress(libs->fGLLib, name);
|
||||
@ -87,6 +97,7 @@ private:
|
||||
void destroyGLContext();
|
||||
|
||||
void onPlatformMakeCurrent() const override;
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override;
|
||||
void onPlatformSwapBuffers() const override;
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
|
||||
|
||||
@ -214,6 +225,7 @@ ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
|
||||
|
||||
fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
|
||||
|
||||
SkScopeExit restorer(context_restorer());
|
||||
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
|
||||
SkDebugf("Could not set the context.");
|
||||
this->destroyGLContext();
|
||||
@ -320,7 +332,10 @@ std::unique_ptr<sk_gpu_test::GLTestContext> ANGLEGLContext::makeNew() const {
|
||||
|
||||
void ANGLEGLContext::destroyGLContext() {
|
||||
if (EGL_NO_DISPLAY != fDisplay) {
|
||||
eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (eglGetCurrentContext() == fContext) {
|
||||
// This will ensure that the context is immediately deleted.
|
||||
eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
if (EGL_NO_CONTEXT != fContext) {
|
||||
eglDestroyContext(fDisplay, fContext);
|
||||
@ -355,6 +370,13 @@ void ANGLEGLContext::onPlatformMakeCurrent() const {
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void()> ANGLEGLContext::onPlatformGetAutoContextRestore() const {
|
||||
if (eglGetCurrentContext() == fContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return context_restorer();
|
||||
}
|
||||
|
||||
void ANGLEGLContext::onPlatformSwapBuffers() const {
|
||||
if (!eglSwapBuffers(fDisplay, fSurface)) {
|
||||
SkDebugf("Could not complete eglSwapBuffers.\n");
|
||||
|
@ -25,6 +25,7 @@ typedef void* EGLNativeDisplayType;
|
||||
typedef void* EGLNativeWindowType;
|
||||
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
|
||||
#define EGL_FALSE 0
|
||||
#define EGL_TRUE 1
|
||||
#define EGL_OPENGL_ES2_BIT 0x0004
|
||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||
#define EGL_NO_SURFACE ((EGLSurface)0)
|
||||
@ -45,6 +46,8 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void);
|
||||
#define EGL_NONE 0x3038
|
||||
#define EGL_WIDTH 0x3057
|
||||
#define EGL_HEIGHT 0x3056
|
||||
#define EGL_DRAW 0x3059
|
||||
#define EGL_READ 0x305A
|
||||
|
||||
typedef EGLDisplay (*GetDisplayProc)(EGLNativeDisplayType display_id);
|
||||
typedef EGLBoolean (*InitializeProc)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
@ -77,6 +80,37 @@ static GetProcAddressProc gfGetProcAddress = nullptr;
|
||||
static void* gLibrary = nullptr;
|
||||
static bool gfFunctionsLoadedSuccessfully = false;
|
||||
|
||||
// The command buffer does not correctly implement eglGetCurrent. It always returns EGL_NO_<foo>.
|
||||
// So we implement them ourselves and hook eglMakeCurrent to store the current values in TLS.
|
||||
thread_local EGLDisplay gCurrDisplay = EGL_NO_DISPLAY;
|
||||
thread_local EGLSurface gCurrReadSurface = EGL_NO_SURFACE;
|
||||
thread_local EGLSurface gCurrDrawSurface = EGL_NO_SURFACE;
|
||||
thread_local EGLContext gCurrContext = EGL_NO_CONTEXT;
|
||||
|
||||
EGLDisplay fakeGetCurrentDisplay() { return gCurrDisplay; }
|
||||
EGLSurface fakeGetCurrentSurface(EGLint readdraw) {
|
||||
switch (readdraw) {
|
||||
case EGL_DRAW:
|
||||
return gCurrDrawSurface;
|
||||
case EGL_READ:
|
||||
return gCurrReadSurface;
|
||||
default:
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
}
|
||||
EGLContext fakeGetCurrentContext() { return gCurrContext; }
|
||||
|
||||
EGLBoolean hookedMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext ctx) {
|
||||
if (gfFunctionsLoadedSuccessfully && EGL_TRUE == gfMakeCurrent(display, draw, read, ctx)) {
|
||||
gCurrDisplay = display;
|
||||
gCurrDrawSurface = draw;
|
||||
gCurrReadSurface = read;
|
||||
gCurrContext = ctx;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
namespace {
|
||||
static void load_command_buffer_functions() {
|
||||
if (!gLibrary) {
|
||||
@ -104,12 +138,11 @@ static void load_command_buffer_functions() {
|
||||
gfSwapBuffers = (SwapBuffersProc)GetProcedureAddress(gLibrary, "eglSwapBuffers");
|
||||
gfGetProcAddress = (GetProcAddressProc)GetProcedureAddress(gLibrary, "eglGetProcAddress");
|
||||
|
||||
gfFunctionsLoadedSuccessfully = gfGetDisplay && gfInitialize && gfTerminate &&
|
||||
gfChooseConfig && gfCreateWindowSurface &&
|
||||
gfCreatePbufferSurface && gfDestroySurface &&
|
||||
gfCreateContext && gfDestroyContext && gfMakeCurrent &&
|
||||
gfSwapBuffers && gfGetProcAddress;
|
||||
|
||||
gfFunctionsLoadedSuccessfully =
|
||||
gfGetDisplay && gfInitialize && gfTerminate && gfChooseConfig &&
|
||||
gfCreateWindowSurface && gfCreatePbufferSurface && gfDestroySurface &&
|
||||
gfCreateContext && gfDestroyContext && gfMakeCurrent && gfSwapBuffers &&
|
||||
gfGetProcAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,6 +167,19 @@ static const GrGLInterface* create_command_buffer_interface() {
|
||||
return GrGLAssembleGLESInterface(gLibrary, command_buffer_get_gl_proc);
|
||||
}
|
||||
|
||||
std::function<void()> context_restorer() {
|
||||
if (!gfFunctionsLoadedSuccessfully) {
|
||||
return nullptr;
|
||||
}
|
||||
auto display = fakeGetCurrentDisplay();
|
||||
auto dsurface = fakeGetCurrentSurface(EGL_DRAW);
|
||||
auto rsurface = fakeGetCurrentSurface(EGL_READ);
|
||||
auto context = fakeGetCurrentContext();
|
||||
return [display, dsurface, rsurface, context] {
|
||||
hookedMakeCurrent(display, dsurface, rsurface, context);
|
||||
};
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace sk_gpu_test {
|
||||
@ -204,7 +250,8 @@ CommandBufferGLTestContext::CommandBufferGLTestContext(CommandBufferGLTestContex
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
|
||||
SkScopeExit restorer(context_restorer());
|
||||
if (!hookedMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
|
||||
SkDebugf("Command Buffer: Could not make EGL context current.\n");
|
||||
this->destroyGLContext();
|
||||
return;
|
||||
@ -237,15 +284,19 @@ void CommandBufferGLTestContext::destroyGLContext() {
|
||||
if (EGL_NO_DISPLAY == fDisplay) {
|
||||
return;
|
||||
}
|
||||
bool wasCurrent = false;
|
||||
if (EGL_NO_CONTEXT != fContext) {
|
||||
wasCurrent = fakeGetCurrentContext() == fContext;
|
||||
gfDestroyContext(fDisplay, fContext);
|
||||
fContext = EGL_NO_CONTEXT;
|
||||
}
|
||||
// Call MakeCurrent after destroying the context, so that the EGL implementation knows that
|
||||
// the context is not used anymore after it is released from being current. This way
|
||||
// command buffer does not need to abandon the context before destruction, and no
|
||||
// client-side errors are printed.
|
||||
gfMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (wasCurrent) {
|
||||
// Call MakeCurrent after destroying the context, so that the EGL implementation knows that
|
||||
// the context is not used anymore after it is released from being current.This way the
|
||||
// command buffer does not need to abandon the context before destruction, and no
|
||||
// client-side errors are printed.
|
||||
hookedMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
if (EGL_NO_SURFACE != fSurface) {
|
||||
gfDestroySurface(fDisplay, fSurface);
|
||||
@ -258,11 +309,18 @@ void CommandBufferGLTestContext::onPlatformMakeCurrent() const {
|
||||
if (!gfFunctionsLoadedSuccessfully) {
|
||||
return;
|
||||
}
|
||||
if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
|
||||
if (!hookedMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
|
||||
SkDebugf("Command Buffer: Could not make EGL context current.\n");
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void()> CommandBufferGLTestContext::onPlatformGetAutoContextRestore() const {
|
||||
if (!gfFunctionsLoadedSuccessfully || fakeGetCurrentContext() == fContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return context_restorer();
|
||||
}
|
||||
|
||||
void CommandBufferGLTestContext::onPlatformSwapBuffers() const {
|
||||
if (!gfFunctionsLoadedSuccessfully) {
|
||||
return;
|
||||
@ -288,7 +346,7 @@ void CommandBufferGLTestContext::presentCommandBuffer() {
|
||||
}
|
||||
|
||||
bool CommandBufferGLTestContext::makeCurrent() {
|
||||
return gfMakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE;
|
||||
return hookedMakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE;
|
||||
}
|
||||
|
||||
int CommandBufferGLTestContext::getStencilBits() {
|
||||
|
@ -42,6 +42,8 @@ private:
|
||||
|
||||
void onPlatformMakeCurrent() const override;
|
||||
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override;
|
||||
|
||||
void onPlatformSwapBuffers() const override;
|
||||
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char *name) const override;
|
||||
|
@ -1203,6 +1203,7 @@ public:
|
||||
|
||||
private:
|
||||
void onPlatformMakeCurrent() const override {}
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
|
||||
void onPlatformSwapBuffers() const override {}
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; }
|
||||
};
|
||||
|
@ -39,6 +39,16 @@ private:
|
||||
typedef sk_gpu_test::FenceSync INHERITED;
|
||||
};
|
||||
|
||||
std::function<void()> context_restorer() {
|
||||
auto display = eglGetCurrentDisplay();
|
||||
auto dsurface = eglGetCurrentSurface(EGL_DRAW);
|
||||
auto rsurface = eglGetCurrentSurface(EGL_READ);
|
||||
auto context = eglGetCurrentContext();
|
||||
return [display, dsurface, rsurface, context] {
|
||||
eglMakeCurrent(display, dsurface, rsurface, context);
|
||||
};
|
||||
}
|
||||
|
||||
class EGLGLTestContext : public sk_gpu_test::GLTestContext {
|
||||
public:
|
||||
EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext);
|
||||
@ -53,6 +63,7 @@ private:
|
||||
void destroyGLContext();
|
||||
|
||||
void onPlatformMakeCurrent() const override;
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override;
|
||||
void onPlatformSwapBuffers() const override;
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
|
||||
|
||||
@ -168,6 +179,7 @@ EGLGLTestContext::EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext*
|
||||
continue;
|
||||
}
|
||||
|
||||
SkScopeExit restorer(context_restorer());
|
||||
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
|
||||
SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError());
|
||||
this->destroyGLContext();
|
||||
@ -199,9 +211,11 @@ EGLGLTestContext::~EGLGLTestContext() {
|
||||
|
||||
void EGLGLTestContext::destroyGLContext() {
|
||||
if (fDisplay) {
|
||||
eglMakeCurrent(fDisplay, 0, 0, 0);
|
||||
|
||||
if (fContext) {
|
||||
if (eglGetCurrentContext() == fContext) {
|
||||
// This will ensure that the context is immediately deleted.
|
||||
eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
eglDestroyContext(fDisplay, fContext);
|
||||
fContext = EGL_NO_CONTEXT;
|
||||
}
|
||||
@ -284,6 +298,13 @@ void EGLGLTestContext::onPlatformMakeCurrent() const {
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void()> EGLGLTestContext::onPlatformGetAutoContextRestore() const {
|
||||
if (eglGetCurrentContext() == fContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return context_restorer();
|
||||
}
|
||||
|
||||
void EGLGLTestContext::onPlatformSwapBuffers() const {
|
||||
if (!eglSwapBuffers(fDisplay, fSurface)) {
|
||||
SkDebugf("Could not complete eglSwapBuffers.\n");
|
||||
|
@ -51,6 +51,13 @@ static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::function<void()> context_restorer() {
|
||||
auto display = glXGetCurrentDisplay();
|
||||
auto drawable = glXGetCurrentDrawable();
|
||||
auto context = glXGetCurrentContext();
|
||||
return [display, drawable, context] { glXMakeCurrent(display, drawable, context); };
|
||||
}
|
||||
|
||||
class GLXGLTestContext : public sk_gpu_test::GLTestContext {
|
||||
public:
|
||||
GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext* shareList);
|
||||
@ -62,6 +69,7 @@ private:
|
||||
GLXContext glxSharedContext);
|
||||
|
||||
void onPlatformMakeCurrent() const override;
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override;
|
||||
void onPlatformSwapBuffers() const override;
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
|
||||
|
||||
@ -214,6 +222,7 @@ GLXGLTestContext::GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext*
|
||||
//SkDebugf("Direct GLX rendering context obtained.\n");
|
||||
}
|
||||
|
||||
SkScopeExit restorer(context_restorer());
|
||||
//SkDebugf("Making context current.\n");
|
||||
if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
|
||||
SkDebugf("Could not set the context.\n");
|
||||
@ -245,9 +254,11 @@ GLXGLTestContext::~GLXGLTestContext() {
|
||||
|
||||
void GLXGLTestContext::destroyGLContext() {
|
||||
if (fDisplay) {
|
||||
glXMakeCurrent(fDisplay, 0, 0);
|
||||
|
||||
if (fContext) {
|
||||
if (glXGetCurrentContext() == fContext) {
|
||||
// This will ensure that the context is immediately deleted.
|
||||
glXMakeContextCurrent(fDisplay, None, None, nullptr);
|
||||
}
|
||||
glXDestroyContext(fDisplay, fContext);
|
||||
fContext = nullptr;
|
||||
}
|
||||
@ -334,6 +345,13 @@ void GLXGLTestContext::onPlatformMakeCurrent() const {
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void()> GLXGLTestContext::onPlatformGetAutoContextRestore() const {
|
||||
if (glXGetCurrentContext() == fContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return context_restorer();
|
||||
}
|
||||
|
||||
void GLXGLTestContext::onPlatformSwapBuffers() const {
|
||||
glXSwapBuffers(fDisplay, fGlxPixmap);
|
||||
}
|
||||
|
@ -14,6 +14,11 @@
|
||||
|
||||
namespace {
|
||||
|
||||
std::function<void()> context_restorer() {
|
||||
EAGLContext* context = [EAGLContext currentContext];
|
||||
return [context] { [EAGLContext setCurrentContext:context]; };
|
||||
}
|
||||
|
||||
class IOSGLTestContext : public sk_gpu_test::GLTestContext {
|
||||
public:
|
||||
IOSGLTestContext(IOSGLTestContext* shareContext);
|
||||
@ -23,6 +28,7 @@ private:
|
||||
void destroyGLContext();
|
||||
|
||||
void onPlatformMakeCurrent() const override;
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override;
|
||||
void onPlatformSwapBuffers() const override;
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
|
||||
|
||||
@ -41,6 +47,7 @@ IOSGLTestContext::IOSGLTestContext(IOSGLTestContext* shareContext)
|
||||
} else {
|
||||
fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
}
|
||||
SkScopeExit restorer(context_restorer());
|
||||
[EAGLContext setCurrentContext:fEAGLContext];
|
||||
|
||||
sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
|
||||
@ -70,6 +77,7 @@ IOSGLTestContext::~IOSGLTestContext() {
|
||||
void IOSGLTestContext::destroyGLContext() {
|
||||
if (fEAGLContext) {
|
||||
if ([EAGLContext currentContext] == fEAGLContext) {
|
||||
// This will ensure that the context is immediately deleted.
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
fEAGLContext = nil;
|
||||
@ -86,6 +94,13 @@ void IOSGLTestContext::onPlatformMakeCurrent() const {
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void()> IOSGLTestContext::onPlatformGetAutoContextRestore() const {
|
||||
if ([EAGLContext currentContext] == fEAGLContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return context_restorer();
|
||||
}
|
||||
|
||||
void IOSGLTestContext::onPlatformSwapBuffers() const { }
|
||||
|
||||
GrGLFuncPtr IOSGLTestContext::onPlatformGetProcAddress(const char* procName) const {
|
||||
|
@ -14,6 +14,12 @@
|
||||
#include <dlfcn.h>
|
||||
|
||||
namespace {
|
||||
|
||||
std::function<void()> context_restorer() {
|
||||
auto context = CGLGetCurrentContext();
|
||||
return [context] { CGLSetCurrentContext(context); };
|
||||
}
|
||||
|
||||
class MacGLTestContext : public sk_gpu_test::GLTestContext {
|
||||
public:
|
||||
MacGLTestContext(MacGLTestContext* shareContext);
|
||||
@ -23,6 +29,7 @@ private:
|
||||
void destroyGLContext();
|
||||
|
||||
void onPlatformMakeCurrent() const override;
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override;
|
||||
void onPlatformSwapBuffers() const override;
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
|
||||
|
||||
@ -58,6 +65,7 @@ MacGLTestContext::MacGLTestContext(MacGLTestContext* shareContext)
|
||||
return;
|
||||
}
|
||||
|
||||
SkScopeExit restorer(context_restorer());
|
||||
CGLSetCurrentContext(fContext);
|
||||
|
||||
sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
|
||||
@ -86,6 +94,10 @@ MacGLTestContext::~MacGLTestContext() {
|
||||
|
||||
void MacGLTestContext::destroyGLContext() {
|
||||
if (fContext) {
|
||||
if (CGLGetCurrentContext() == fContext) {
|
||||
// This will ensure that the context is immediately deleted.
|
||||
CGLSetCurrentContext(nullptr);
|
||||
}
|
||||
CGLReleaseContext(fContext);
|
||||
fContext = nullptr;
|
||||
}
|
||||
@ -98,6 +110,13 @@ void MacGLTestContext::onPlatformMakeCurrent() const {
|
||||
CGLSetCurrentContext(fContext);
|
||||
}
|
||||
|
||||
std::function<void()> MacGLTestContext::onPlatformGetAutoContextRestore() const {
|
||||
if (CGLGetCurrentContext() == fContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return context_restorer();
|
||||
}
|
||||
|
||||
void MacGLTestContext::onPlatformSwapBuffers() const {
|
||||
CGLFlushDrawable(fContext);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
|
||||
private:
|
||||
void onPlatformMakeCurrent() const override {}
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
|
||||
void onPlatformSwapBuffers() const override {}
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; }
|
||||
};
|
||||
|
@ -16,6 +16,12 @@
|
||||
|
||||
namespace {
|
||||
|
||||
std::function<void()> context_restorer() {
|
||||
auto glrc = wglGetCurrentContext();
|
||||
auto dc = wglGetCurrentDC();
|
||||
return [glrc, dc] { wglMakeCurrent(dc, glrc); };
|
||||
}
|
||||
|
||||
class WinGLTestContext : public sk_gpu_test::GLTestContext {
|
||||
public:
|
||||
WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext);
|
||||
@ -25,6 +31,7 @@ private:
|
||||
void destroyGLContext();
|
||||
|
||||
void onPlatformMakeCurrent() const override;
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override;
|
||||
void onPlatformSwapBuffers() const override;
|
||||
GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
|
||||
|
||||
@ -113,6 +120,7 @@ WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext*
|
||||
glrc = fPbufferContext->getGLRC();
|
||||
}
|
||||
|
||||
SkScopeExit restorer(context_restorer());
|
||||
if (!(wglMakeCurrent(dc, glrc))) {
|
||||
SkDebugf("Could not set the context.\n");
|
||||
this->destroyGLContext();
|
||||
@ -142,6 +150,7 @@ WinGLTestContext::~WinGLTestContext() {
|
||||
void WinGLTestContext::destroyGLContext() {
|
||||
SkSafeSetNull(fPbufferContext);
|
||||
if (fGlRenderContext) {
|
||||
// This deletes the context immediately even if it is current.
|
||||
wglDeleteContext(fGlRenderContext);
|
||||
fGlRenderContext = 0;
|
||||
}
|
||||
@ -172,6 +181,13 @@ void WinGLTestContext::onPlatformMakeCurrent() const {
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const {
|
||||
if (wglGetCurrentContext() == fGlRenderContext) {
|
||||
return nullptr;
|
||||
}
|
||||
return context_restorer();
|
||||
}
|
||||
|
||||
void WinGLTestContext::onPlatformSwapBuffers() const {
|
||||
HDC dc;
|
||||
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
protected:
|
||||
void teardown() override {}
|
||||
void onPlatformMakeCurrent() const override {}
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
|
||||
void onPlatformSwapBuffers() const override {}
|
||||
|
||||
private:
|
||||
|
@ -144,6 +144,7 @@ private:
|
||||
}
|
||||
|
||||
void onPlatformMakeCurrent() const override {}
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
|
||||
void onPlatformSwapBuffers() const override {}
|
||||
|
||||
id<MTLDevice> fDevice;
|
||||
|
@ -154,6 +154,7 @@ private:
|
||||
}
|
||||
|
||||
void onPlatformMakeCurrent() const override {}
|
||||
std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
|
||||
void onPlatformSwapBuffers() const override {}
|
||||
|
||||
typedef sk_gpu_test::VkTestContext INHERITED;
|
||||
|
Loading…
Reference in New Issue
Block a user