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