1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "tools/gpu/gl/angle/GLTestContext_angle.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkTime.h"
11cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLAssembleInterface.h"
12cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLInterface.h"
13cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h"
14cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLDefines.h"
15cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLUtil.h"
16cb93a386Sopenharmony_ci#include "src/ports/SkOSLibrary.h"
17cb93a386Sopenharmony_ci#include "third_party/externals/angle2/include/platform/Platform.h"
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci#include <vector>
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci#define EGL_EGL_PROTOTYPES 1
22cb93a386Sopenharmony_ci#include <EGL/egl.h>
23cb93a386Sopenharmony_ci#include <EGL/eglext.h>
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci#define EGL_PLATFORM_ANGLE_ANGLE                0x3202
26cb93a386Sopenharmony_ci#define EGL_PLATFORM_ANGLE_TYPE_ANGLE           0x3203
27cb93a386Sopenharmony_ci#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE      0x3207
28cb93a386Sopenharmony_ci#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE     0x3208
29cb93a386Sopenharmony_ci#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE    0x320D
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci#define EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483
32cb93a386Sopenharmony_ci
33cb93a386Sopenharmony_ciusing sk_gpu_test::ANGLEBackend;
34cb93a386Sopenharmony_ciusing sk_gpu_test::ANGLEContextVersion;
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_cinamespace {
37cb93a386Sopenharmony_cistruct Libs {
38cb93a386Sopenharmony_ci    void* fGLLib;
39cb93a386Sopenharmony_ci    void* fEGLLib;
40cb93a386Sopenharmony_ci};
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_cistd::function<void()> context_restorer() {
43cb93a386Sopenharmony_ci    auto display = eglGetCurrentDisplay();
44cb93a386Sopenharmony_ci    auto dsurface = eglGetCurrentSurface(EGL_DRAW);
45cb93a386Sopenharmony_ci    auto rsurface = eglGetCurrentSurface(EGL_READ);
46cb93a386Sopenharmony_ci    auto context = eglGetCurrentContext();
47cb93a386Sopenharmony_ci    return [display, dsurface, rsurface, context] {
48cb93a386Sopenharmony_ci        eglMakeCurrent(display, dsurface, rsurface, context);
49cb93a386Sopenharmony_ci    };
50cb93a386Sopenharmony_ci}
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_cistatic GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
53cb93a386Sopenharmony_ci    const Libs* libs = reinterpret_cast<const Libs*>(ctx);
54cb93a386Sopenharmony_ci    GrGLFuncPtr proc = (GrGLFuncPtr) SkGetProcedureAddress(libs->fGLLib, name);
55cb93a386Sopenharmony_ci    if (proc) {
56cb93a386Sopenharmony_ci        return proc;
57cb93a386Sopenharmony_ci    }
58cb93a386Sopenharmony_ci    proc = (GrGLFuncPtr) SkGetProcedureAddress(libs->fEGLLib, name);
59cb93a386Sopenharmony_ci    if (proc) {
60cb93a386Sopenharmony_ci        return proc;
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci    return eglGetProcAddress(name);
63cb93a386Sopenharmony_ci}
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_civoid* get_angle_egl_display(void* nativeDisplay, ANGLEBackend type) {
66cb93a386Sopenharmony_ci    PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
67cb93a386Sopenharmony_ci    eglGetPlatformDisplayEXT =
68cb93a386Sopenharmony_ci        (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    // We expect ANGLE to support this extension
71cb93a386Sopenharmony_ci    if (!eglGetPlatformDisplayEXT) {
72cb93a386Sopenharmony_ci        return EGL_NO_DISPLAY;
73cb93a386Sopenharmony_ci    }
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    EGLint typeNum = 0;
76cb93a386Sopenharmony_ci    switch (type) {
77cb93a386Sopenharmony_ci        case ANGLEBackend::kD3D9:
78cb93a386Sopenharmony_ci            typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
79cb93a386Sopenharmony_ci            break;
80cb93a386Sopenharmony_ci        case ANGLEBackend::kD3D11:
81cb93a386Sopenharmony_ci            typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
82cb93a386Sopenharmony_ci            break;
83cb93a386Sopenharmony_ci        case ANGLEBackend::kOpenGL:
84cb93a386Sopenharmony_ci            typeNum = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
85cb93a386Sopenharmony_ci            break;
86cb93a386Sopenharmony_ci    }
87cb93a386Sopenharmony_ci    const EGLint attribs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, typeNum, EGL_NONE };
88cb93a386Sopenharmony_ci    return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, attribs);
89cb93a386Sopenharmony_ci}
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ciclass ANGLEGLContext : public sk_gpu_test::GLTestContext {
92cb93a386Sopenharmony_cipublic:
93cb93a386Sopenharmony_ci    ANGLEGLContext(ANGLEBackend, ANGLEContextVersion, ANGLEGLContext* shareContext, void* display);
94cb93a386Sopenharmony_ci    ~ANGLEGLContext() override;
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci    GrEGLImage texture2DToEGLImage(GrGLuint texID) const override;
97cb93a386Sopenharmony_ci    void destroyEGLImage(GrEGLImage) const override;
98cb93a386Sopenharmony_ci    GrGLuint eglImageToExternalTexture(GrEGLImage) const override;
99cb93a386Sopenharmony_ci    std::unique_ptr<sk_gpu_test::GLTestContext> makeNew() const override;
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ciprivate:
102cb93a386Sopenharmony_ci    void destroyGLContext();
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_ci    void onPlatformMakeNotCurrent() const override;
105cb93a386Sopenharmony_ci    void onPlatformMakeCurrent() const override;
106cb93a386Sopenharmony_ci    std::function<void()> onPlatformGetAutoContextRestore() const override;
107cb93a386Sopenharmony_ci    GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci    void*                       fContext;
110cb93a386Sopenharmony_ci    void*                       fDisplay;
111cb93a386Sopenharmony_ci    void*                       fSurface;
112cb93a386Sopenharmony_ci    ANGLEBackend                fType;
113cb93a386Sopenharmony_ci    ANGLEContextVersion         fVersion;
114cb93a386Sopenharmony_ci    bool                        fOwnsDisplay;
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ci    angle::ResetDisplayPlatformFunc fResetPlatform = nullptr;
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci    PFNEGLCREATEIMAGEKHRPROC    fCreateImage = nullptr;
119cb93a386Sopenharmony_ci    PFNEGLDESTROYIMAGEKHRPROC   fDestroyImage = nullptr;
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_WIN
122cb93a386Sopenharmony_ci    HWND                        fWindow;
123cb93a386Sopenharmony_ci    HDC                         fDeviceContext;
124cb93a386Sopenharmony_ci    static ATOM                 gWC;
125cb93a386Sopenharmony_ci#endif
126cb93a386Sopenharmony_ci};
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_WIN
129cb93a386Sopenharmony_ciATOM ANGLEGLContext::gWC = 0;
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_cienum class IsWine { kUnknown, kNo, kYes };
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_cistatic IsWine is_wine() {
134cb93a386Sopenharmony_ci    HMODULE ntdll = GetModuleHandle("ntdll.dll");
135cb93a386Sopenharmony_ci    if (!ntdll) {
136cb93a386Sopenharmony_ci        SkDebugf("No ntdll.dll on Windows?!\n");
137cb93a386Sopenharmony_ci        return IsWine::kUnknown;
138cb93a386Sopenharmony_ci    }
139cb93a386Sopenharmony_ci    return GetProcAddress(ntdll, "wine_get_version") == nullptr ? IsWine::kNo : IsWine::kYes;
140cb93a386Sopenharmony_ci}
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci#endif
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_cistatic const unsigned char* ANGLE_getTraceCategoryEnabledFlag(angle::PlatformMethods* platform,
145cb93a386Sopenharmony_ci                                                              const char* category_group) {
146cb93a386Sopenharmony_ci    return SkEventTracer::GetInstance()->getCategoryGroupEnabled(category_group);
147cb93a386Sopenharmony_ci}
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_cistatic angle::TraceEventHandle ANGLE_addTraceEvent(angle::PlatformMethods* platform,
150cb93a386Sopenharmony_ci                                                   char phase,
151cb93a386Sopenharmony_ci                                                   const unsigned char* category_group_enabled,
152cb93a386Sopenharmony_ci                                                   const char* name,
153cb93a386Sopenharmony_ci                                                   unsigned long long id,
154cb93a386Sopenharmony_ci                                                   double timestamp,
155cb93a386Sopenharmony_ci                                                   int num_args,
156cb93a386Sopenharmony_ci                                                   const char** arg_names,
157cb93a386Sopenharmony_ci                                                   const unsigned char* arg_types,
158cb93a386Sopenharmony_ci                                                   const unsigned long long* arg_values,
159cb93a386Sopenharmony_ci                                                   unsigned char flags) {
160cb93a386Sopenharmony_ci    static_assert(sizeof(unsigned long long) == sizeof(uint64_t), "Non-64-bit trace event args!");
161cb93a386Sopenharmony_ci    return SkEventTracer::GetInstance()->addTraceEvent(
162cb93a386Sopenharmony_ci            phase, category_group_enabled, name, id, num_args, arg_names, arg_types,
163cb93a386Sopenharmony_ci            reinterpret_cast<const uint64_t*>(arg_values), flags);
164cb93a386Sopenharmony_ci}
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_cistatic void ANGLE_updateTraceEventDuration(angle::PlatformMethods* platform,
167cb93a386Sopenharmony_ci                                           const unsigned char* category_group_enabled,
168cb93a386Sopenharmony_ci                                           const char* name,
169cb93a386Sopenharmony_ci                                           angle::TraceEventHandle handle) {
170cb93a386Sopenharmony_ci    SkEventTracer::GetInstance()->updateTraceEventDuration(category_group_enabled, name, handle);
171cb93a386Sopenharmony_ci}
172cb93a386Sopenharmony_ci
173cb93a386Sopenharmony_cistatic double ANGLE_monotonicallyIncreasingTime(angle::PlatformMethods* platform) {
174cb93a386Sopenharmony_ci    return SkTime::GetSecs();
175cb93a386Sopenharmony_ci}
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_ciANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
178cb93a386Sopenharmony_ci                               ANGLEGLContext* shareContext, void* display)
179cb93a386Sopenharmony_ci    : fContext(EGL_NO_CONTEXT)
180cb93a386Sopenharmony_ci    , fDisplay(display)
181cb93a386Sopenharmony_ci    , fSurface(EGL_NO_SURFACE)
182cb93a386Sopenharmony_ci    , fType(type)
183cb93a386Sopenharmony_ci    , fVersion(version)
184cb93a386Sopenharmony_ci    , fOwnsDisplay(false) {
185cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_WIN
186cb93a386Sopenharmony_ci    fWindow = nullptr;
187cb93a386Sopenharmony_ci    fDeviceContext = nullptr;
188cb93a386Sopenharmony_ci
189cb93a386Sopenharmony_ci    static IsWine gIsWine = is_wine();
190cb93a386Sopenharmony_ci    if (gIsWine == IsWine::kYes && type != ANGLEBackend::kOpenGL) {
191cb93a386Sopenharmony_ci        // D3D backends of ANGLE don't really work well under Wine with our tests and are likely to
192cb93a386Sopenharmony_ci        // crash. This makes it easier to test using the GL ANGLE backend under Wine on Linux
193cb93a386Sopenharmony_ci        // without lots of spurious Wine debug spew and crashes.
194cb93a386Sopenharmony_ci        return;
195cb93a386Sopenharmony_ci    }
196cb93a386Sopenharmony_ci
197cb93a386Sopenharmony_ci    if (EGL_NO_DISPLAY == fDisplay) {
198cb93a386Sopenharmony_ci        HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(nullptr);
199cb93a386Sopenharmony_ci
200cb93a386Sopenharmony_ci        if (!gWC) {
201cb93a386Sopenharmony_ci            WNDCLASS wc;
202cb93a386Sopenharmony_ci            wc.cbClsExtra = 0;
203cb93a386Sopenharmony_ci            wc.cbWndExtra = 0;
204cb93a386Sopenharmony_ci            wc.hbrBackground = nullptr;
205cb93a386Sopenharmony_ci            wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
206cb93a386Sopenharmony_ci            wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
207cb93a386Sopenharmony_ci            wc.hInstance = hInstance;
208cb93a386Sopenharmony_ci            wc.lpfnWndProc = (WNDPROC) DefWindowProc;
209cb93a386Sopenharmony_ci            wc.lpszClassName = TEXT("ANGLE-win");
210cb93a386Sopenharmony_ci            wc.lpszMenuName = nullptr;
211cb93a386Sopenharmony_ci            wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
212cb93a386Sopenharmony_ci
213cb93a386Sopenharmony_ci            gWC = RegisterClass(&wc);
214cb93a386Sopenharmony_ci            if (!gWC) {
215cb93a386Sopenharmony_ci                SkDebugf("Could not register window class.\n");
216cb93a386Sopenharmony_ci                return;
217cb93a386Sopenharmony_ci            }
218cb93a386Sopenharmony_ci        }
219cb93a386Sopenharmony_ci        if (!(fWindow = CreateWindow(TEXT("ANGLE-win"),
220cb93a386Sopenharmony_ci                                        TEXT("The Invisible Man"),
221cb93a386Sopenharmony_ci                                        WS_OVERLAPPEDWINDOW,
222cb93a386Sopenharmony_ci                                        0, 0, 1, 1,
223cb93a386Sopenharmony_ci                                        nullptr, nullptr,
224cb93a386Sopenharmony_ci                                        hInstance, nullptr))) {
225cb93a386Sopenharmony_ci            SkDebugf("Could not create window.\n");
226cb93a386Sopenharmony_ci            return;
227cb93a386Sopenharmony_ci        }
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ci        if (!(fDeviceContext = GetDC(fWindow))) {
230cb93a386Sopenharmony_ci            SkDebugf("Could not get device context.\n");
231cb93a386Sopenharmony_ci            this->destroyGLContext();
232cb93a386Sopenharmony_ci            return;
233cb93a386Sopenharmony_ci        }
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci        fDisplay = get_angle_egl_display(fDeviceContext, type);
236cb93a386Sopenharmony_ci        fOwnsDisplay = true;
237cb93a386Sopenharmony_ci    }
238cb93a386Sopenharmony_ci#else
239cb93a386Sopenharmony_ci    SkASSERT(EGL_NO_DISPLAY == fDisplay);
240cb93a386Sopenharmony_ci    fDisplay = get_angle_egl_display(EGL_DEFAULT_DISPLAY, type);
241cb93a386Sopenharmony_ci    fOwnsDisplay = true;
242cb93a386Sopenharmony_ci#endif
243cb93a386Sopenharmony_ci    if (EGL_NO_DISPLAY == fDisplay) {
244cb93a386Sopenharmony_ci        SkDebugf("Could not create EGL display!");
245cb93a386Sopenharmony_ci        return;
246cb93a386Sopenharmony_ci    }
247cb93a386Sopenharmony_ci
248cb93a386Sopenharmony_ci    // Add ANGLE platform hooks to connect to Skia's tracing implementation
249cb93a386Sopenharmony_ci    angle::GetDisplayPlatformFunc getPlatform = reinterpret_cast<angle::GetDisplayPlatformFunc>(
250cb93a386Sopenharmony_ci            eglGetProcAddress("ANGLEGetDisplayPlatform"));
251cb93a386Sopenharmony_ci    if (getPlatform) {
252cb93a386Sopenharmony_ci        fResetPlatform = reinterpret_cast<angle::ResetDisplayPlatformFunc>(
253cb93a386Sopenharmony_ci                eglGetProcAddress("ANGLEResetDisplayPlatform"));
254cb93a386Sopenharmony_ci        SkASSERT(fResetPlatform);
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_ci        angle::PlatformMethods* platformMethods = nullptr;
257cb93a386Sopenharmony_ci        if (getPlatform(fDisplay, angle::g_PlatformMethodNames, angle::g_NumPlatformMethods,
258cb93a386Sopenharmony_ci                        nullptr, &platformMethods)) {
259cb93a386Sopenharmony_ci            platformMethods->addTraceEvent               = ANGLE_addTraceEvent;
260cb93a386Sopenharmony_ci            platformMethods->getTraceCategoryEnabledFlag = ANGLE_getTraceCategoryEnabledFlag;
261cb93a386Sopenharmony_ci            platformMethods->updateTraceEventDuration    = ANGLE_updateTraceEventDuration;
262cb93a386Sopenharmony_ci            platformMethods->monotonicallyIncreasingTime = ANGLE_monotonicallyIncreasingTime;
263cb93a386Sopenharmony_ci        }
264cb93a386Sopenharmony_ci    }
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_ci    EGLint majorVersion;
267cb93a386Sopenharmony_ci    EGLint minorVersion;
268cb93a386Sopenharmony_ci    if (!eglInitialize(fDisplay, &majorVersion, &minorVersion)) {
269cb93a386Sopenharmony_ci        SkDebugf("Could not initialize display!");
270cb93a386Sopenharmony_ci        this->destroyGLContext();
271cb93a386Sopenharmony_ci        return;
272cb93a386Sopenharmony_ci    }
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_ci    EGLint numConfigs;
275cb93a386Sopenharmony_ci    static const EGLint configAttribs[] = {
276cb93a386Sopenharmony_ci        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
277cb93a386Sopenharmony_ci        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
278cb93a386Sopenharmony_ci        EGL_RED_SIZE, 8,
279cb93a386Sopenharmony_ci        EGL_GREEN_SIZE, 8,
280cb93a386Sopenharmony_ci        EGL_BLUE_SIZE, 8,
281cb93a386Sopenharmony_ci        EGL_ALPHA_SIZE, 8,
282cb93a386Sopenharmony_ci        EGL_NONE
283cb93a386Sopenharmony_ci    };
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci    EGLConfig surfaceConfig;
286cb93a386Sopenharmony_ci    if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
287cb93a386Sopenharmony_ci        SkDebugf("Could not create choose config!");
288cb93a386Sopenharmony_ci        this->destroyGLContext();
289cb93a386Sopenharmony_ci        return;
290cb93a386Sopenharmony_ci    }
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ci    int versionNum = ANGLEContextVersion::kES2 == version ? 2 : 3;
293cb93a386Sopenharmony_ci    std::vector<EGLint> contextAttribs = {
294cb93a386Sopenharmony_ci        EGL_CONTEXT_CLIENT_VERSION, versionNum,
295cb93a386Sopenharmony_ci    };
296cb93a386Sopenharmony_ci
297cb93a386Sopenharmony_ci    const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
298cb93a386Sopenharmony_ci    if (strstr(extensions, "EGL_ANGLE_create_context_backwards_compatible")) {
299cb93a386Sopenharmony_ci        contextAttribs.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
300cb93a386Sopenharmony_ci        contextAttribs.push_back(EGL_FALSE);
301cb93a386Sopenharmony_ci    }
302cb93a386Sopenharmony_ci
303cb93a386Sopenharmony_ci    contextAttribs.push_back(EGL_NONE);
304cb93a386Sopenharmony_ci
305cb93a386Sopenharmony_ci    EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
306cb93a386Sopenharmony_ci    fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext, contextAttribs.data());
307cb93a386Sopenharmony_ci    if (EGL_NO_CONTEXT == fContext) {
308cb93a386Sopenharmony_ci        SkDebugf("Could not create context!");
309cb93a386Sopenharmony_ci        this->destroyGLContext();
310cb93a386Sopenharmony_ci        return;
311cb93a386Sopenharmony_ci    }
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_ci    static const EGLint surfaceAttribs[] = {
314cb93a386Sopenharmony_ci        EGL_WIDTH, 1,
315cb93a386Sopenharmony_ci        EGL_HEIGHT, 1,
316cb93a386Sopenharmony_ci        EGL_NONE
317cb93a386Sopenharmony_ci    };
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci    fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
320cb93a386Sopenharmony_ci
321cb93a386Sopenharmony_ci    SkScopeExit restorer(context_restorer());
322cb93a386Sopenharmony_ci    if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
323cb93a386Sopenharmony_ci        SkDebugf("Could not set the context.");
324cb93a386Sopenharmony_ci        this->destroyGLContext();
325cb93a386Sopenharmony_ci        return;
326cb93a386Sopenharmony_ci    }
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci    sk_sp<const GrGLInterface> gl = sk_gpu_test::CreateANGLEGLInterface();
329cb93a386Sopenharmony_ci    if (nullptr == gl.get()) {
330cb93a386Sopenharmony_ci        SkDebugf("Could not create ANGLE GL interface!\n");
331cb93a386Sopenharmony_ci        this->destroyGLContext();
332cb93a386Sopenharmony_ci        return;
333cb93a386Sopenharmony_ci    }
334cb93a386Sopenharmony_ci    if (!gl->validate()) {
335cb93a386Sopenharmony_ci        SkDebugf("Could not validate ANGLE GL interface!\n");
336cb93a386Sopenharmony_ci        this->destroyGLContext();
337cb93a386Sopenharmony_ci        return;
338cb93a386Sopenharmony_ci    }
339cb93a386Sopenharmony_ci
340cb93a386Sopenharmony_ci#ifdef SK_DEBUG
341cb93a386Sopenharmony_ci    // Verify that the interface we requested was actually returned to us
342cb93a386Sopenharmony_ci    const GrGLubyte* rendererUByte;
343cb93a386Sopenharmony_ci    GR_GL_CALL_RET(gl.get(), rendererUByte, GetString(GR_GL_RENDERER));
344cb93a386Sopenharmony_ci    const char* renderer = reinterpret_cast<const char*>(rendererUByte);
345cb93a386Sopenharmony_ci    switch (type) {
346cb93a386Sopenharmony_ci    case ANGLEBackend::kD3D9:
347cb93a386Sopenharmony_ci        SkASSERT(strstr(renderer, "Direct3D9"));
348cb93a386Sopenharmony_ci        break;
349cb93a386Sopenharmony_ci    case ANGLEBackend::kD3D11:
350cb93a386Sopenharmony_ci        SkASSERT(strstr(renderer, "Direct3D11"));
351cb93a386Sopenharmony_ci        break;
352cb93a386Sopenharmony_ci    case ANGLEBackend::kOpenGL:
353cb93a386Sopenharmony_ci        SkASSERT(strstr(renderer, "OpenGL"));
354cb93a386Sopenharmony_ci        break;
355cb93a386Sopenharmony_ci    }
356cb93a386Sopenharmony_ci#endif
357cb93a386Sopenharmony_ci    if (strstr(extensions, "EGL_KHR_image")) {
358cb93a386Sopenharmony_ci        fCreateImage = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
359cb93a386Sopenharmony_ci        fDestroyImage = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
360cb93a386Sopenharmony_ci    }
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ci    this->init(std::move(gl));
363cb93a386Sopenharmony_ci}
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_ciANGLEGLContext::~ANGLEGLContext() {
366cb93a386Sopenharmony_ci    this->teardown();
367cb93a386Sopenharmony_ci    this->destroyGLContext();
368cb93a386Sopenharmony_ci}
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ciGrEGLImage ANGLEGLContext::texture2DToEGLImage(GrGLuint texID) const {
371cb93a386Sopenharmony_ci    if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
372cb93a386Sopenharmony_ci        return GR_EGL_NO_IMAGE;
373cb93a386Sopenharmony_ci    }
374cb93a386Sopenharmony_ci    EGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0,
375cb93a386Sopenharmony_ci                         GR_EGL_IMAGE_PRESERVED, GR_EGL_TRUE,
376cb93a386Sopenharmony_ci                         GR_EGL_NONE };
377cb93a386Sopenharmony_ci    // 64 bit cast is to shut Visual C++ up about casting 32 bit value to a pointer.
378cb93a386Sopenharmony_ci    GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>((uint64_t)texID);
379cb93a386Sopenharmony_ci    return fCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer, attribs);
380cb93a386Sopenharmony_ci}
381cb93a386Sopenharmony_ci
382cb93a386Sopenharmony_civoid ANGLEGLContext::destroyEGLImage(GrEGLImage image) const { fDestroyImage(fDisplay, image); }
383cb93a386Sopenharmony_ci
384cb93a386Sopenharmony_ciGrGLuint ANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
385cb93a386Sopenharmony_ci    while (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {}
386cb93a386Sopenharmony_ci    if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
387cb93a386Sopenharmony_ci        return 0;
388cb93a386Sopenharmony_ci    }
389cb93a386Sopenharmony_ci    typedef GrGLvoid (EGLAPIENTRY *EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
390cb93a386Sopenharmony_ci    EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
391cb93a386Sopenharmony_ci        (EGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2DOES");
392cb93a386Sopenharmony_ci    if (!glEGLImageTargetTexture2D) {
393cb93a386Sopenharmony_ci        return 0;
394cb93a386Sopenharmony_ci    }
395cb93a386Sopenharmony_ci    GrGLuint texID;
396cb93a386Sopenharmony_ci    GR_GL_CALL(this->gl(), GenTextures(1, &texID));
397cb93a386Sopenharmony_ci    if (!texID) {
398cb93a386Sopenharmony_ci        return 0;
399cb93a386Sopenharmony_ci    }
400cb93a386Sopenharmony_ci    GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
401cb93a386Sopenharmony_ci    if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
402cb93a386Sopenharmony_ci        GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
403cb93a386Sopenharmony_ci        return 0;
404cb93a386Sopenharmony_ci    }
405cb93a386Sopenharmony_ci    glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
406cb93a386Sopenharmony_ci    if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
407cb93a386Sopenharmony_ci        GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
408cb93a386Sopenharmony_ci        return 0;
409cb93a386Sopenharmony_ci    }
410cb93a386Sopenharmony_ci    return texID;
411cb93a386Sopenharmony_ci}
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_cistd::unique_ptr<sk_gpu_test::GLTestContext> ANGLEGLContext::makeNew() const {
414cb93a386Sopenharmony_ci    // For EGLImage sharing between contexts to work in ANGLE the two contexts
415cb93a386Sopenharmony_ci    // need to share the same display
416cb93a386Sopenharmony_ci    std::unique_ptr<sk_gpu_test::GLTestContext> ctx =
417cb93a386Sopenharmony_ci        sk_gpu_test::MakeANGLETestContext(fType, fVersion, nullptr, fDisplay);
418cb93a386Sopenharmony_ci    if (ctx) {
419cb93a386Sopenharmony_ci        ctx->makeCurrent();
420cb93a386Sopenharmony_ci    }
421cb93a386Sopenharmony_ci    return ctx;
422cb93a386Sopenharmony_ci}
423cb93a386Sopenharmony_ci
424cb93a386Sopenharmony_civoid ANGLEGLContext::destroyGLContext() {
425cb93a386Sopenharmony_ci    if (EGL_NO_DISPLAY != fDisplay) {
426cb93a386Sopenharmony_ci        if (eglGetCurrentContext() == fContext) {
427cb93a386Sopenharmony_ci            // This will ensure that the context is immediately deleted.
428cb93a386Sopenharmony_ci            eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
429cb93a386Sopenharmony_ci        }
430cb93a386Sopenharmony_ci
431cb93a386Sopenharmony_ci        if (EGL_NO_CONTEXT != fContext) {
432cb93a386Sopenharmony_ci            eglDestroyContext(fDisplay, fContext);
433cb93a386Sopenharmony_ci            fContext = EGL_NO_CONTEXT;
434cb93a386Sopenharmony_ci        }
435cb93a386Sopenharmony_ci
436cb93a386Sopenharmony_ci        if (EGL_NO_SURFACE != fSurface) {
437cb93a386Sopenharmony_ci            eglDestroySurface(fDisplay, fSurface);
438cb93a386Sopenharmony_ci            fSurface = EGL_NO_SURFACE;
439cb93a386Sopenharmony_ci        }
440cb93a386Sopenharmony_ci
441cb93a386Sopenharmony_ci        if (fResetPlatform) {
442cb93a386Sopenharmony_ci            fResetPlatform(fDisplay);
443cb93a386Sopenharmony_ci        }
444cb93a386Sopenharmony_ci
445cb93a386Sopenharmony_ci        if (fOwnsDisplay) {
446cb93a386Sopenharmony_ci            // Only terminate the display if we created it. If we were a context created by makeNew,
447cb93a386Sopenharmony_ci            // the parent context might still have work to do on the display. If we terminate now,
448cb93a386Sopenharmony_ci            // that context might be deleted once it no longer becomes current, and we may hit
449cb93a386Sopenharmony_ci            // undefined behavior in this destructor when calling eglDestroy[Context|Surface] on a
450cb93a386Sopenharmony_ci            // terminated display.
451cb93a386Sopenharmony_ci            eglTerminate(fDisplay);
452cb93a386Sopenharmony_ci        }
453cb93a386Sopenharmony_ci        fDisplay = EGL_NO_DISPLAY;
454cb93a386Sopenharmony_ci        fOwnsDisplay = false;
455cb93a386Sopenharmony_ci    }
456cb93a386Sopenharmony_ci
457cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_WIN
458cb93a386Sopenharmony_ci    if (fWindow) {
459cb93a386Sopenharmony_ci        if (fDeviceContext) {
460cb93a386Sopenharmony_ci            ReleaseDC(fWindow, fDeviceContext);
461cb93a386Sopenharmony_ci            fDeviceContext = 0;
462cb93a386Sopenharmony_ci        }
463cb93a386Sopenharmony_ci
464cb93a386Sopenharmony_ci        DestroyWindow(fWindow);
465cb93a386Sopenharmony_ci        fWindow = 0;
466cb93a386Sopenharmony_ci    }
467cb93a386Sopenharmony_ci#endif
468cb93a386Sopenharmony_ci}
469cb93a386Sopenharmony_ci
470cb93a386Sopenharmony_civoid ANGLEGLContext::onPlatformMakeNotCurrent() const {
471cb93a386Sopenharmony_ci    if (!eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
472cb93a386Sopenharmony_ci        SkDebugf("Could not reset the context 0x%x.\n", eglGetError());
473cb93a386Sopenharmony_ci    }
474cb93a386Sopenharmony_ci}
475cb93a386Sopenharmony_ci
476cb93a386Sopenharmony_civoid ANGLEGLContext::onPlatformMakeCurrent() const {
477cb93a386Sopenharmony_ci    if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
478cb93a386Sopenharmony_ci        SkDebugf("Could not set the context 0x%x.\n", eglGetError());
479cb93a386Sopenharmony_ci    }
480cb93a386Sopenharmony_ci}
481cb93a386Sopenharmony_ci
482cb93a386Sopenharmony_cistd::function<void()> ANGLEGLContext::onPlatformGetAutoContextRestore() const {
483cb93a386Sopenharmony_ci    if (eglGetCurrentContext() == fContext) {
484cb93a386Sopenharmony_ci        return nullptr;
485cb93a386Sopenharmony_ci    }
486cb93a386Sopenharmony_ci    return context_restorer();
487cb93a386Sopenharmony_ci}
488cb93a386Sopenharmony_ci
489cb93a386Sopenharmony_ciGrGLFuncPtr ANGLEGLContext::onPlatformGetProcAddress(const char* name) const {
490cb93a386Sopenharmony_ci    return eglGetProcAddress(name);
491cb93a386Sopenharmony_ci}
492cb93a386Sopenharmony_ci}  // anonymous namespace
493cb93a386Sopenharmony_ci
494cb93a386Sopenharmony_cinamespace sk_gpu_test {
495cb93a386Sopenharmony_cisk_sp<const GrGLInterface> CreateANGLEGLInterface() {
496cb93a386Sopenharmony_ci    static Libs gLibs = { nullptr, nullptr };
497cb93a386Sopenharmony_ci
498cb93a386Sopenharmony_ci    if (nullptr == gLibs.fGLLib) {
499cb93a386Sopenharmony_ci        // We load the ANGLE library and never let it go
500cb93a386Sopenharmony_ci#if defined _WIN32
501cb93a386Sopenharmony_ci        gLibs.fGLLib = SkLoadDynamicLibrary("libGLESv2.dll");
502cb93a386Sopenharmony_ci        gLibs.fEGLLib = SkLoadDynamicLibrary("libEGL.dll");
503cb93a386Sopenharmony_ci#elif defined SK_BUILD_FOR_MAC
504cb93a386Sopenharmony_ci        gLibs.fGLLib = SkLoadDynamicLibrary("libGLESv2.dylib");
505cb93a386Sopenharmony_ci        gLibs.fEGLLib = SkLoadDynamicLibrary("libEGL.dylib");
506cb93a386Sopenharmony_ci#else
507cb93a386Sopenharmony_ci        gLibs.fGLLib = SkLoadDynamicLibrary("libGLESv2.so");
508cb93a386Sopenharmony_ci        gLibs.fEGLLib = SkLoadDynamicLibrary("libEGL.so");
509cb93a386Sopenharmony_ci#endif
510cb93a386Sopenharmony_ci    }
511cb93a386Sopenharmony_ci
512cb93a386Sopenharmony_ci    if (nullptr == gLibs.fGLLib || nullptr == gLibs.fEGLLib) {
513cb93a386Sopenharmony_ci        // We can't setup the interface correctly w/o the so
514cb93a386Sopenharmony_ci        return nullptr;
515cb93a386Sopenharmony_ci    }
516cb93a386Sopenharmony_ci
517cb93a386Sopenharmony_ci    return GrGLMakeAssembledGLESInterface(&gLibs, angle_get_gl_proc);
518cb93a386Sopenharmony_ci}
519cb93a386Sopenharmony_ci
520cb93a386Sopenharmony_cistd::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend type, ANGLEContextVersion version,
521cb93a386Sopenharmony_ci                                                    GLTestContext* shareContext, void* display) {
522cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_WIN) && defined(_M_ARM64)
523cb93a386Sopenharmony_ci    // Windows-on-ARM only has D3D11. This will fail correctly, but it produces huge amounts of
524cb93a386Sopenharmony_ci    // debug output for every unit test from both ANGLE and our context factory.
525cb93a386Sopenharmony_ci    if (ANGLEBackend::kD3D11 != type) {
526cb93a386Sopenharmony_ci        return nullptr;
527cb93a386Sopenharmony_ci    }
528cb93a386Sopenharmony_ci#endif
529cb93a386Sopenharmony_ci
530cb93a386Sopenharmony_ci    ANGLEGLContext* angleShareContext = reinterpret_cast<ANGLEGLContext*>(shareContext);
531cb93a386Sopenharmony_ci    std::unique_ptr<GLTestContext> ctx(new ANGLEGLContext(type, version,
532cb93a386Sopenharmony_ci                                                          angleShareContext, display));
533cb93a386Sopenharmony_ci    if (!ctx->isValid()) {
534cb93a386Sopenharmony_ci        return nullptr;
535cb93a386Sopenharmony_ci    }
536cb93a386Sopenharmony_ci    return ctx;
537cb93a386Sopenharmony_ci}
538cb93a386Sopenharmony_ci}  // namespace sk_gpu_test
539