• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2012 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #include "GLTestContext_angle.h"
10 
11 #include <EGL/egl.h>
12 #include <EGL/eglext.h>
13 
14 #include "gl/GrGLDefines.h"
15 #include "gl/GrGLUtil.h"
16 
17 #include "gl/GrGLInterface.h"
18 #include "gl/GrGLAssembleInterface.h"
19 #include "../ports/SkOSLibrary.h"
20 
21 #include <EGL/egl.h>
22 
23 #define EGL_PLATFORM_ANGLE_ANGLE                0x3202
24 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE           0x3203
25 #define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE      0x3207
26 #define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE     0x3208
27 #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE    0x320D
28 
29 using sk_gpu_test::ANGLEBackend;
30 using sk_gpu_test::ANGLEContextVersion;
31 
32 namespace {
33 struct Libs {
34     void* fGLLib;
35     void* fEGLLib;
36 };
37 
angle_get_gl_proc(void * ctx,const char name[])38 static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
39     const Libs* libs = reinterpret_cast<const Libs*>(ctx);
40     GrGLFuncPtr proc = (GrGLFuncPtr) GetProcedureAddress(libs->fGLLib, name);
41     if (proc) {
42         return proc;
43     }
44     proc = (GrGLFuncPtr) GetProcedureAddress(libs->fEGLLib, name);
45     if (proc) {
46         return proc;
47     }
48     return eglGetProcAddress(name);
49 }
50 
get_angle_egl_display(void * nativeDisplay,ANGLEBackend type)51 void* get_angle_egl_display(void* nativeDisplay, ANGLEBackend type) {
52     PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
53     eglGetPlatformDisplayEXT =
54         (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
55 
56     // We expect ANGLE to support this extension
57     if (!eglGetPlatformDisplayEXT) {
58         return EGL_NO_DISPLAY;
59     }
60 
61     EGLint typeNum = 0;
62     switch (type) {
63         case ANGLEBackend::kD3D9:
64             typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
65             break;
66         case ANGLEBackend::kD3D11:
67             typeNum = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
68             break;
69         case ANGLEBackend::kOpenGL:
70             typeNum = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
71             break;
72     }
73     const EGLint attribs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, typeNum, EGL_NONE };
74     return eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, attribs);
75 }
76 
77 class ANGLEGLContext : public sk_gpu_test::GLTestContext {
78 public:
79     ANGLEGLContext(ANGLEBackend, ANGLEContextVersion, ANGLEGLContext* shareContext);
80     ~ANGLEGLContext() override;
81 
82     GrEGLImage texture2DToEGLImage(GrGLuint texID) const override;
83     void destroyEGLImage(GrEGLImage) const override;
84     GrGLuint eglImageToExternalTexture(GrEGLImage) const override;
85     std::unique_ptr<sk_gpu_test::GLTestContext> makeNew() const override;
86 
87 private:
88     void destroyGLContext();
89 
90     void onPlatformMakeCurrent() const override;
91     void onPlatformSwapBuffers() const override;
92     GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
93 
94     void*                       fContext;
95     void*                       fDisplay;
96     void*                       fSurface;
97     ANGLEBackend                fType;
98     ANGLEContextVersion         fVersion;
99 };
100 
ANGLEGLContext(ANGLEBackend type,ANGLEContextVersion version,ANGLEGLContext * shareContext)101 ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
102                                ANGLEGLContext* shareContext)
103     : fContext(EGL_NO_CONTEXT)
104     , fDisplay(EGL_NO_DISPLAY)
105     , fSurface(EGL_NO_SURFACE)
106     , fType(type)
107     , fVersion(version) {
108 
109     EGLint numConfigs;
110     static const EGLint configAttribs[] = {
111         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
112         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
113         EGL_RED_SIZE, 8,
114         EGL_GREEN_SIZE, 8,
115         EGL_BLUE_SIZE, 8,
116         EGL_ALPHA_SIZE, 8,
117         EGL_NONE
118     };
119 
120     fDisplay = get_angle_egl_display(EGL_DEFAULT_DISPLAY, type);
121     if (EGL_NO_DISPLAY == fDisplay) {
122         SkDebugf("Could not create EGL display!");
123         return;
124     }
125 
126     EGLint majorVersion;
127     EGLint minorVersion;
128     eglInitialize(fDisplay, &majorVersion, &minorVersion);
129 
130     EGLConfig surfaceConfig;
131     eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs);
132 
133     int versionNum = ANGLEContextVersion::kES2 == version ? 2 : 3;
134     const EGLint contextAttribs[] = {
135         EGL_CONTEXT_CLIENT_VERSION, versionNum,
136         EGL_NONE
137     };
138     EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
139     fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext, contextAttribs);
140 
141 
142     static const EGLint surfaceAttribs[] = {
143         EGL_WIDTH, 1,
144         EGL_HEIGHT, 1,
145         EGL_NONE
146     };
147 
148     fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
149 
150     eglMakeCurrent(fDisplay, fSurface, fSurface, fContext);
151 
152     sk_sp<const GrGLInterface> gl(sk_gpu_test::CreateANGLEGLInterface());
153     if (nullptr == gl.get()) {
154         SkDebugf("Could not create ANGLE GL interface!\n");
155         this->destroyGLContext();
156         return;
157     }
158     if (!gl->validate()) {
159         SkDebugf("Could not validate ANGLE GL interface!\n");
160         this->destroyGLContext();
161         return;
162     }
163 
164     this->init(gl.release());
165 }
166 
~ANGLEGLContext()167 ANGLEGLContext::~ANGLEGLContext() {
168     this->teardown();
169     this->destroyGLContext();
170 }
171 
texture2DToEGLImage(GrGLuint texID) const172 GrEGLImage ANGLEGLContext::texture2DToEGLImage(GrGLuint texID) const {
173     if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
174         return GR_EGL_NO_IMAGE;
175     }
176     GrEGLImage img;
177     GrEGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0,
178                            GR_EGL_IMAGE_PRESERVED, GR_EGL_TRUE,
179                            GR_EGL_NONE };
180     // 64 bit cast is to shut Visual C++ up about casting 32 bit value to a pointer.
181     GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>((uint64_t)texID);
182     GR_GL_CALL_RET(this->gl(), img,
183                    EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer,
184                                   attribs));
185     return img;
186 }
187 
destroyEGLImage(GrEGLImage image) const188 void ANGLEGLContext::destroyEGLImage(GrEGLImage image) const {
189     GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
190 }
191 
eglImageToExternalTexture(GrEGLImage image) const192 GrGLuint ANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
193     GrGLClearErr(this->gl());
194     if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
195         return 0;
196     }
197     typedef GrGLvoid (EGLAPIENTRY *EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
198     EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
199         (EGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2DOES");
200     if (!glEGLImageTargetTexture2D) {
201         return 0;
202     }
203     GrGLuint texID;
204     GR_GL_CALL(this->gl(), GenTextures(1, &texID));
205     if (!texID) {
206         return 0;
207     }
208     GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
209     if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
210         GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
211         return 0;
212     }
213     glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
214     if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
215         GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
216         return 0;
217     }
218     return texID;
219 }
220 
makeNew() const221 std::unique_ptr<sk_gpu_test::GLTestContext> ANGLEGLContext::makeNew() const {
222     std::unique_ptr<sk_gpu_test::GLTestContext> ctx =
223         sk_gpu_test::MakeANGLETestContext(fType, fVersion);
224     if (ctx) {
225         ctx->makeCurrent();
226     }
227     return ctx;
228 }
229 
destroyGLContext()230 void ANGLEGLContext::destroyGLContext() {
231     if (fDisplay) {
232         eglMakeCurrent(fDisplay, 0, 0, 0);
233 
234         if (fContext) {
235             eglDestroyContext(fDisplay, fContext);
236             fContext = EGL_NO_CONTEXT;
237         }
238 
239         if (fSurface) {
240             eglDestroySurface(fDisplay, fSurface);
241             fSurface = EGL_NO_SURFACE;
242         }
243 
244         //TODO should we close the display?
245         fDisplay = EGL_NO_DISPLAY;
246     }
247 }
248 
onPlatformMakeCurrent() const249 void ANGLEGLContext::onPlatformMakeCurrent() const {
250     if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
251         SkDebugf("Could not set the context.\n");
252     }
253 }
254 
onPlatformSwapBuffers() const255 void ANGLEGLContext::onPlatformSwapBuffers() const {
256     if (!eglSwapBuffers(fDisplay, fSurface)) {
257         SkDebugf("Could not complete eglSwapBuffers.\n");
258     }
259 }
260 
onPlatformGetProcAddress(const char * name) const261 GrGLFuncPtr ANGLEGLContext::onPlatformGetProcAddress(const char* name) const {
262     return eglGetProcAddress(name);
263 }
264 }  // anonymous namespace
265 
266 namespace sk_gpu_test {
CreateANGLEGLInterface()267 const GrGLInterface* CreateANGLEGLInterface() {
268     static Libs gLibs = { nullptr, nullptr };
269 
270     if (nullptr == gLibs.fGLLib) {
271         // We load the ANGLE library and never let it go
272 #if defined _WIN32
273         gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.dll");
274         gLibs.fEGLLib = DynamicLoadLibrary("libEGL.dll");
275 #elif defined SK_BUILD_FOR_MAC
276         gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.dylib");
277         gLibs.fEGLLib = DynamicLoadLibrary("libEGL.dylib");
278 #else
279         gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.so");
280         gLibs.fEGLLib = DynamicLoadLibrary("libEGL.so");
281 #endif
282     }
283 
284     if (nullptr == gLibs.fGLLib || nullptr == gLibs.fEGLLib) {
285         // We can't setup the interface correctly w/o the so
286         return nullptr;
287     }
288 
289     return GrGLAssembleGLESInterface(&gLibs, angle_get_gl_proc);
290 }
291 
MakeANGLETestContext(ANGLEBackend type,ANGLEContextVersion version,GLTestContext * shareContext)292 std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend type, ANGLEContextVersion version,
293                                                     GLTestContext* shareContext){
294     ANGLEGLContext* angleShareContext = reinterpret_cast<ANGLEGLContext*>(shareContext);
295     std::unique_ptr<GLTestContext> ctx(new ANGLEGLContext(type, version, angleShareContext));
296     if (!ctx->isValid()) {
297         return nullptr;
298     }
299     return ctx;
300 }
301 }  // namespace sk_gpu_test
302