13724e574a744491b7cfb8187ac865a70ef3d4528bsalomon
258629291bc145edca8fb303e465c8537bed65314djsollen@google.com/*
358629291bc145edca8fb303e465c8537bed65314djsollen@google.com * Copyright 2011 Google Inc.
458629291bc145edca8fb303e465c8537bed65314djsollen@google.com *
558629291bc145edca8fb303e465c8537bed65314djsollen@google.com * Use of this source code is governed by a BSD-style license that can be
658629291bc145edca8fb303e465c8537bed65314djsollen@google.com * found in the LICENSE file.
758629291bc145edca8fb303e465c8537bed65314djsollen@google.com */
8273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomon#include "gl/GLTestContext.h"
958629291bc145edca8fb303e465c8537bed65314djsollen@google.com
10273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomon#define GL_GLEXT_PROTOTYPES
119e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen#include <GLES2/gl2.h>
12d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
13d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton#define EGL_EGLEXT_PROTOTYPES
149e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen#include <EGL/egl.h>
15d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton#include <EGL/eglext.h>
1658629291bc145edca8fb303e465c8537bed65314djsollen@google.com
177ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon#include "gl/GrGLDefines.h"
187ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon#include "gl/GrGLUtil.h"
197ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon
209e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunennamespace {
21a90ed4e83897b45d6331ee4c54e1edd4054de9a8kkinnunen
22d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton// TODO: Share this class with ANGLE if/when it gets support for EGL_KHR_fence_sync.
23421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdaltonclass EGLFenceSync : public sk_gpu_test::FenceSync {
24d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdaltonpublic:
25145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner    static std::unique_ptr<EGLFenceSync> MakeIfSupported(EGLDisplay);
26d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
27421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdalton    sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override;
28421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdalton    bool waitFence(sk_gpu_test::PlatformFence fence) const override;
29421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdalton    void deleteFence(sk_gpu_test::PlatformFence fence) const override;
30d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
31d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdaltonprivate:
32273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomon    EGLFenceSync(EGLDisplay display) : fDisplay(display) {}
33d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
34d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    EGLDisplay                    fDisplay;
35d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
36421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdalton    typedef sk_gpu_test::FenceSync INHERITED;
37d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton};
38d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
39273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonclass EGLGLTestContext : public sk_gpu_test::GLTestContext {
409e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunenpublic:
4160c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman    EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext);
42273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomon    ~EGLGLTestContext() override;
4358629291bc145edca8fb303e465c8537bed65314djsollen@google.com
447ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GrEGLImage texture2DToEGLImage(GrGLuint texID) const override;
457ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    void destroyEGLImage(GrEGLImage) const override;
467ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GrGLuint eglImageToExternalTexture(GrEGLImage) const override;
47145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner    std::unique_ptr<sk_gpu_test::GLTestContext> makeNew() const override;
487ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon
499e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunenprivate:
5030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    void destroyGLContext();
5130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
52d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    void onPlatformMakeCurrent() const override;
53d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    void onPlatformSwapBuffers() const override;
54d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
55d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
569e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen    EGLContext fContext;
579e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen    EGLDisplay fDisplay;
589e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen    EGLSurface fSurface;
599e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen};
6058629291bc145edca8fb303e465c8537bed65314djsollen@google.com
6160c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian OsmanEGLGLTestContext::EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext)
6258629291bc145edca8fb303e465c8537bed65314djsollen@google.com    : fContext(EGL_NO_CONTEXT)
6358629291bc145edca8fb303e465c8537bed65314djsollen@google.com    , fDisplay(EGL_NO_DISPLAY)
6458629291bc145edca8fb303e465c8537bed65314djsollen@google.com    , fSurface(EGL_NO_SURFACE) {
6560c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman
6660c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman    EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
6760c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman
68f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org    static const EGLint kEGLContextAttribsForOpenGL[] = {
69f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org        EGL_NONE
70f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org    };
71f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org
72f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org    static const EGLint kEGLContextAttribsForOpenGLES[] = {
73f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org        EGL_CONTEXT_CLIENT_VERSION, 2,
74f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org        EGL_NONE
75f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org    };
76f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org
771e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org    static const struct {
781e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        const EGLint* fContextAttribs;
791e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        EGLenum fAPI;
801e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        EGLint  fRenderableTypeBit;
819e90aed5de82732cc9921f01388d3063a41a053bcommit-bot@chromium.org        GrGLStandard fStandard;
821e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org    } kAPIs[] = {
831e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        {   // OpenGL
841e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            kEGLContextAttribsForOpenGL,
851e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_OPENGL_API,
861e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_OPENGL_BIT,
879e90aed5de82732cc9921f01388d3063a41a053bcommit-bot@chromium.org            kGL_GrGLStandard
881e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        },
891e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        {   // OpenGL ES. This seems to work for both ES2 and 3 (when available).
901e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            kEGLContextAttribsForOpenGLES,
911e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_OPENGL_ES_API,
921e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_OPENGL_ES2_BIT,
939e90aed5de82732cc9921f01388d3063a41a053bcommit-bot@chromium.org            kGLES_GrGLStandard
941e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        },
951e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org    };
96f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org
9780549fcdd50269d7e069d6db02b395fca128056ckkinnunen    size_t apiLimit = SK_ARRAY_COUNT(kAPIs);
9880549fcdd50269d7e069d6db02b395fca128056ckkinnunen    size_t api = 0;
9980549fcdd50269d7e069d6db02b395fca128056ckkinnunen    if (forcedGpuAPI == kGL_GrGLStandard) {
10080549fcdd50269d7e069d6db02b395fca128056ckkinnunen        apiLimit = 1;
10180549fcdd50269d7e069d6db02b395fca128056ckkinnunen    } else if (forcedGpuAPI == kGLES_GrGLStandard) {
10280549fcdd50269d7e069d6db02b395fca128056ckkinnunen        api = 1;
10380549fcdd50269d7e069d6db02b395fca128056ckkinnunen    }
10480549fcdd50269d7e069d6db02b395fca128056ckkinnunen    SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI);
10580549fcdd50269d7e069d6db02b395fca128056ckkinnunen
1061b612a89fba2275e3effe12bdc9b6cdc2f4d9eeeHal Canary    sk_sp<const GrGLInterface> gl;
107d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
10896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    for (; nullptr == gl.get() && api < apiLimit; ++api) {
1091e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
11058629291bc145edca8fb303e465c8537bed65314djsollen@google.com
1111e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        EGLint majorVersion;
1121e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        EGLint minorVersion;
1131e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        eglInitialize(fDisplay, &majorVersion, &minorVersion);
114dabdd9e71df4619db0260b9091c9bcc0d57b0a34borenet@google.com
1151e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org#if 0
1161e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR));
1171e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS));
1181e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION));
1191e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS));
1201e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org#endif
12158629291bc145edca8fb303e465c8537bed65314djsollen@google.com
1221e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        if (!eglBindAPI(kAPIs[api].fAPI)) {
1231e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            continue;
1241e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        }
12558629291bc145edca8fb303e465c8537bed65314djsollen@google.com
126bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg        EGLint numConfigs = 0;
1271e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        const EGLint configAttribs[] = {
1281e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
1291e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit,
1301e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_RED_SIZE, 8,
1311e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_GREEN_SIZE, 8,
1321e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_BLUE_SIZE, 8,
1331e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_ALPHA_SIZE, 8,
1341e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_NONE
1351e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        };
1361e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org
1371e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        EGLConfig surfaceConfig;
1381e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
1391e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError());
1401e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            continue;
1411e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        }
14258629291bc145edca8fb303e465c8537bed65314djsollen@google.com
143bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg        if (0 == numConfigs) {
144bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg            SkDebugf("No suitable EGL config found.\n");
145bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg            continue;
146bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg        }
147bb25e44593ff9c318d9fe1dbb5cf30bc2b89eb76joakim.landberg
14860c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman        fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext,
14960c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman                                    kAPIs[api].fContextAttribs);
1501e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        if (EGL_NO_CONTEXT == fContext) {
1511e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            SkDebugf("eglCreateContext failed.  EGL Error: 0x%08x\n", eglGetError());
1521e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            continue;
1531e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        }
15458629291bc145edca8fb303e465c8537bed65314djsollen@google.com
1551e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        static const EGLint kSurfaceAttribs[] = {
1561e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_WIDTH, 1,
1571e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_HEIGHT, 1,
1581e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            EGL_NONE
1591e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        };
1601e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org
1611e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs);
1621e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        if (EGL_NO_SURFACE == fSurface) {
1631e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError());
1641e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            this->destroyGLContext();
1651e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            continue;
1661e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        }
16758629291bc145edca8fb303e465c8537bed65314djsollen@google.com
1681e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
1691e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            SkDebugf("eglMakeCurrent failed.  EGL Error: 0x%08x\n", eglGetError());
1701e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            this->destroyGLContext();
1711e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            continue;
1721e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        }
17358629291bc145edca8fb303e465c8537bed65314djsollen@google.com
174d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        gl.reset(GrGLCreateNativeInterface());
17596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == gl.get()) {
1761e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            SkDebugf("Failed to create gl interface.\n");
1771e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            this->destroyGLContext();
1781e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            continue;
1791e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        }
1801e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org
181d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        if (!gl->validate()) {
18230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            SkDebugf("Failed to validate gl interface.\n");
1831e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org            this->destroyGLContext();
18430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            continue;
1851e627276c55f1627bef3afa0051685d99443ab1fcommit-bot@chromium.org        }
186d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
187145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner        this->init(gl.release(), EGLFenceSync::MakeIfSupported(fDisplay));
188d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        break;
18958629291bc145edca8fb303e465c8537bed65314djsollen@google.com    }
19030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen}
191f5897f83e65f18a85f71f2d3357df13c5443e89fcommit-bot@chromium.org
192273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonEGLGLTestContext::~EGLGLTestContext() {
193d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    this->teardown();
19430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    this->destroyGLContext();
19558629291bc145edca8fb303e465c8537bed65314djsollen@google.com}
19658629291bc145edca8fb303e465c8537bed65314djsollen@google.com
197273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonvoid EGLGLTestContext::destroyGLContext() {
19830bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    if (fDisplay) {
19930bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        eglMakeCurrent(fDisplay, 0, 0, 0);
20030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
20130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        if (fContext) {
20230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            eglDestroyContext(fDisplay, fContext);
20330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            fContext = EGL_NO_CONTEXT;
20430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        }
20530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
20630bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        if (fSurface) {
20730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            eglDestroySurface(fDisplay, fSurface);
20830bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            fSurface = EGL_NO_SURFACE;
20930bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        }
21030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
21130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        //TODO should we close the display?
21230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        fDisplay = EGL_NO_DISPLAY;
21330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    }
21430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen}
21530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
216273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonGrEGLImage EGLGLTestContext::texture2DToEGLImage(GrGLuint texID) const {
2177ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
2187ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        return GR_EGL_NO_IMAGE;
2197ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    }
2207ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GrEGLImage img;
2217ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GrEGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0, GR_EGL_NONE };
2227ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>(texID);
2237ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GR_GL_CALL_RET(this->gl(), img,
2247ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon                   EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer, attribs));
2257ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    return img;
2267ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon}
2277ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon
228273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonvoid EGLGLTestContext::destroyEGLImage(GrEGLImage image) const {
2297ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
2307ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon}
2317ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon
232273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonGrGLuint EGLGLTestContext::eglImageToExternalTexture(GrEGLImage image) const {
2337ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GrGLClearErr(this->gl());
2347ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
2357ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        return 0;
2367ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    }
237b5a94e3e24ef16f96ecfbe4ee427f7a0c69d7290bsalomon    typedef GrGLvoid (*EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
238b5a94e3e24ef16f96ecfbe4ee427f7a0c69d7290bsalomon
239b5a94e3e24ef16f96ecfbe4ee427f7a0c69d7290bsalomon    EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
240b5a94e3e24ef16f96ecfbe4ee427f7a0c69d7290bsalomon        (EGLImageTargetTexture2DProc) eglGetProcAddress("glEGLImageTargetTexture2DOES");
2417ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    if (!glEGLImageTargetTexture2D) {
2427ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        return 0;
2437ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    }
2447ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    GrGLuint texID;
2457ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    glGenTextures(1, &texID);
2467ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    if (!texID) {
2477ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        return 0;
2487ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    }
2497ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    glBindTexture(GR_GL_TEXTURE_EXTERNAL, texID);
2507ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    if (glGetError() != GR_GL_NO_ERROR) {
2517ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        glDeleteTextures(1, &texID);
2527ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        return 0;
2537ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    }
2547ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
2557ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    if (glGetError() != GR_GL_NO_ERROR) {
2567ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        glDeleteTextures(1, &texID);
2577ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        return 0;
2587ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    }
2597ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    return texID;
2607ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon}
2617ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon
262145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagnerstd::unique_ptr<sk_gpu_test::GLTestContext> EGLGLTestContext::makeNew() const {
26360c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman    std::unique_ptr<sk_gpu_test::GLTestContext> ctx(new EGLGLTestContext(this->gl()->fStandard,
26460c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman                                                                         nullptr));
2657ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    if (ctx) {
2667ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon        ctx->makeCurrent();
2677ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    }
2687ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon    return ctx;
2697ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103bsalomon}
27030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
271273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonvoid EGLGLTestContext::onPlatformMakeCurrent() const {
27258629291bc145edca8fb303e465c8537bed65314djsollen@google.com    if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
27358629291bc145edca8fb303e465c8537bed65314djsollen@google.com        SkDebugf("Could not set the context.\n");
27458629291bc145edca8fb303e465c8537bed65314djsollen@google.com    }
27558629291bc145edca8fb303e465c8537bed65314djsollen@google.com}
276c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com
277273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonvoid EGLGLTestContext::onPlatformSwapBuffers() const {
278c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com    if (!eglSwapBuffers(fDisplay, fSurface)) {
279c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com        SkDebugf("Could not complete eglSwapBuffers.\n");
280c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com    }
281c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com}
2829e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen
283273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonGrGLFuncPtr EGLGLTestContext::onPlatformGetProcAddress(const char* procName) const {
284d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    return eglGetProcAddress(procName);
285d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton}
286d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
287d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdaltonstatic bool supports_egl_extension(EGLDisplay display, const char* extension) {
2889fba90979243501d2348d1539ad2bb0bdf411b5bscroggo    size_t extensionLength = strlen(extension);
289d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    const char* extensionsStr = eglQueryString(display, EGL_EXTENSIONS);
290d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    while (const char* match = strstr(extensionsStr, extension)) {
291d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        // Ensure the string we found is its own extension, not a substring of a larger extension
292d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        // (e.g. GL_ARB_occlusion_query / GL_ARB_occlusion_query2).
293d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        if ((match == extensionsStr || match[-1] == ' ') &&
294d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            (match[extensionLength] == ' ' || match[extensionLength] == '\0')) {
295d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton            return true;
296d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        }
297d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton        extensionsStr = match + extensionLength;
298d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    }
299d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    return false;
300d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton}
301d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
302145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagnerstd::unique_ptr<EGLFenceSync> EGLFenceSync::MakeIfSupported(EGLDisplay display) {
303d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    if (!display || !supports_egl_extension(display, "EGL_KHR_fence_sync")) {
30496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
305d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    }
306145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner    return std::unique_ptr<EGLFenceSync>(new EGLFenceSync(display));
307d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton}
308d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
309421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdaltonsk_gpu_test::PlatformFence EGLFenceSync::insertFence() const {
310421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdalton    EGLSyncKHR eglsync = eglCreateSyncKHR(fDisplay, EGL_SYNC_FENCE_KHR, nullptr);
311421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdalton    return reinterpret_cast<sk_gpu_test::PlatformFence>(eglsync);
312d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton}
313d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
314421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdaltonbool EGLFenceSync::waitFence(sk_gpu_test::PlatformFence platformFence) const {
315421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdalton    EGLSyncKHR eglsync = reinterpret_cast<EGLSyncKHR>(platformFence);
3164e8f567fa3229133670864a06fe4df26f437d14ejoshualitt    return EGL_CONDITION_SATISFIED_KHR ==
3174e8f567fa3229133670864a06fe4df26f437d14ejoshualitt            eglClientWaitSyncKHR(fDisplay,
3184e8f567fa3229133670864a06fe4df26f437d14ejoshualitt                                 eglsync,
319edea94c356dddd339d776e1f0d906f44427222b9bsalomon                                 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
3204e8f567fa3229133670864a06fe4df26f437d14ejoshualitt                                 EGL_FOREVER_KHR);
321d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton}
322d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
323421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdaltonvoid EGLFenceSync::deleteFence(sk_gpu_test::PlatformFence platformFence) const {
324421a3c1cc1b227084c7c84618d0b6a6804faabefcsmartdalton    EGLSyncKHR eglsync = reinterpret_cast<EGLSyncKHR>(platformFence);
325d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton    eglDestroySyncKHR(fDisplay, eglsync);
326d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton}
327d416a5b10ff9e6d4f55a1f5b0419722132d68ff3cdalton
328024229a38d86fc53801092e149d8599b2b2bc9fbcsmartdaltonGR_STATIC_ASSERT(sizeof(EGLSyncKHR) <= sizeof(sk_gpu_test::PlatformFence));
329024229a38d86fc53801092e149d8599b2b2bc9fbcsmartdalton
3303724e574a744491b7cfb8187ac865a70ef3d4528bsalomon}  // anonymous namespace
3319e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen
3323724e574a744491b7cfb8187ac865a70ef3d4528bsalomonnamespace sk_gpu_test {
333273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomonGLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
334273c0f5e87397c40d22bb7e3ee078bb46a3f6860bsalomon                                           GLTestContext *shareContext) {
33560c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman    EGLGLTestContext* eglShareContext = reinterpret_cast<EGLGLTestContext*>(shareContext);
33660c774db3ec46f3eb85f6390ba31e38c8d29e2d4Brian Osman    EGLGLTestContext *ctx = new EGLGLTestContext(forcedGpuAPI, eglShareContext);
33730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    if (!ctx->isValid()) {
338385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete ctx;
33996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
34030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    }
34130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    return ctx;
3429e61bb7815b133bc40ea7b00fccc853f4b728e3ckkinnunen}
3433724e574a744491b7cfb8187ac865a70ef3d4528bsalomon}  // namespace sk_gpu_test
344