• 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 "gl/angle/SkANGLEGLContext.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 #define EGL_PLATFORM_ANGLE_ANGLE                0x3202
18 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE           0x3203
19 #define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE      0x3207
20 #define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE     0x3208
21 #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE    0x320D
22 
GetD3DEGLDisplay(void * nativeDisplay,bool useGLBackend)23 void* SkANGLEGLContext::GetD3DEGLDisplay(void* nativeDisplay, bool useGLBackend) {
24     PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
25     eglGetPlatformDisplayEXT =
26         (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
27 
28     if (!eglGetPlatformDisplayEXT) {
29         return eglGetDisplay(static_cast<EGLNativeDisplayType>(nativeDisplay));
30     }
31 
32     EGLDisplay display = EGL_NO_DISPLAY;
33     if (useGLBackend) {
34         // Try for an ANGLE D3D11 context, fall back to D3D9.
35         EGLint attribs[3] = {
36               EGL_PLATFORM_ANGLE_TYPE_ANGLE,
37               EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
38               EGL_NONE
39         };
40         display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, attribs);
41     } else {
42         // Try for an ANGLE D3D11 context, fall back to D3D9, and finally GL.
43         EGLint attribs[3][3] = {
44             {
45                 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
46                 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
47                 EGL_NONE
48             },
49             {
50                 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
51                 EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
52                 EGL_NONE
53             },
54             {
55                 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
56                 EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
57                 EGL_NONE
58             }
59         };
60         for (int i = 0; i < 3 && display == EGL_NO_DISPLAY; ++i) {
61             display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,nativeDisplay, attribs[i]);
62         }
63     }
64     return display;
65 }
66 
SkANGLEGLContext(bool useGLBackend)67 SkANGLEGLContext::SkANGLEGLContext(bool useGLBackend)
68     : fContext(EGL_NO_CONTEXT)
69     , fDisplay(EGL_NO_DISPLAY)
70     , fSurface(EGL_NO_SURFACE) {
71 
72     EGLint numConfigs;
73     static const EGLint configAttribs[] = {
74         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
75         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
76         EGL_RED_SIZE, 8,
77         EGL_GREEN_SIZE, 8,
78         EGL_BLUE_SIZE, 8,
79         EGL_ALPHA_SIZE, 8,
80         EGL_NONE
81     };
82 
83     fIsGLBackend = useGLBackend;
84     fDisplay = GetD3DEGLDisplay(EGL_DEFAULT_DISPLAY, useGLBackend);
85     if (EGL_NO_DISPLAY == fDisplay) {
86         SkDebugf("Could not create EGL display!");
87         return;
88     }
89 
90     EGLint majorVersion;
91     EGLint minorVersion;
92     eglInitialize(fDisplay, &majorVersion, &minorVersion);
93 
94     EGLConfig surfaceConfig;
95     eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs);
96 
97     static const EGLint contextAttribs[] = {
98         EGL_CONTEXT_CLIENT_VERSION, 2,
99         EGL_NONE
100     };
101     fContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
102 
103 
104     static const EGLint surfaceAttribs[] = {
105         EGL_WIDTH, 1,
106         EGL_HEIGHT, 1,
107         EGL_NONE
108     };
109 
110     fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
111 
112     eglMakeCurrent(fDisplay, fSurface, fSurface, fContext);
113 
114     SkAutoTUnref<const GrGLInterface> gl(GrGLCreateANGLEInterface());
115     if (nullptr == gl.get()) {
116         SkDebugf("Could not create ANGLE GL interface!\n");
117         this->destroyGLContext();
118         return;
119     }
120     if (!gl->validate()) {
121         SkDebugf("Could not validate ANGLE GL interface!\n");
122         this->destroyGLContext();
123         return;
124     }
125 
126     this->init(gl.detach());
127 }
128 
~SkANGLEGLContext()129 SkANGLEGLContext::~SkANGLEGLContext() {
130     this->teardown();
131     this->destroyGLContext();
132 }
133 
texture2DToEGLImage(GrGLuint texID) const134 GrEGLImage SkANGLEGLContext::texture2DToEGLImage(GrGLuint texID) const {
135     if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
136         return GR_EGL_NO_IMAGE;
137     }
138     GrEGLImage img;
139     GrEGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0,
140                            GR_EGL_IMAGE_PRESERVED, GR_EGL_TRUE,
141                            GR_EGL_NONE };
142     // 64 bit cast is to shut Visual C++ up about casting 32 bit value to a pointer.
143     GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>((uint64_t)texID);
144     GR_GL_CALL_RET(this->gl(), img,
145                    EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer,
146                                   attribs));
147     return img;
148 }
149 
destroyEGLImage(GrEGLImage image) const150 void SkANGLEGLContext::destroyEGLImage(GrEGLImage image) const {
151     GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
152 }
153 
eglImageToExternalTexture(GrEGLImage image) const154 GrGLuint SkANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
155     GrGLClearErr(this->gl());
156     if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
157         return 0;
158     }
159     GrGLEGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
160         (GrGLEGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2DOES");
161     if (!glEGLImageTargetTexture2D) {
162         return 0;
163     }
164     GrGLuint texID;
165     GR_GL_CALL(this->gl(), GenTextures(1, &texID));
166     if (!texID) {
167         return 0;
168     }
169     GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
170     if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
171         GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
172         return 0;
173     }
174     glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
175     if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
176         GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
177         return 0;
178     }
179     return texID;
180 }
181 
createNew() const182 SkGLContext* SkANGLEGLContext::createNew() const {
183 #ifdef SK_BUILD_FOR_WIN
184     SkGLContext* ctx = fIsGLBackend ? SkANGLEGLContext::CreateOpenGL()
185                                     : SkANGLEGLContext::CreateDirectX();
186 #else
187     SkGLContext* ctx = SkANGLEGLContext::CreateOpenGL();
188 #endif
189     if (ctx) {
190         ctx->makeCurrent();
191     }
192     return ctx;
193 }
194 
destroyGLContext()195 void SkANGLEGLContext::destroyGLContext() {
196     if (fDisplay) {
197         eglMakeCurrent(fDisplay, 0, 0, 0);
198 
199         if (fContext) {
200             eglDestroyContext(fDisplay, fContext);
201             fContext = EGL_NO_CONTEXT;
202         }
203 
204         if (fSurface) {
205             eglDestroySurface(fDisplay, fSurface);
206             fSurface = EGL_NO_SURFACE;
207         }
208 
209         //TODO should we close the display?
210         fDisplay = EGL_NO_DISPLAY;
211     }
212 }
213 
onPlatformMakeCurrent() const214 void SkANGLEGLContext::onPlatformMakeCurrent() const {
215     if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
216         SkDebugf("Could not set the context.\n");
217     }
218 }
219 
onPlatformSwapBuffers() const220 void SkANGLEGLContext::onPlatformSwapBuffers() const {
221     if (!eglSwapBuffers(fDisplay, fSurface)) {
222         SkDebugf("Could not complete eglSwapBuffers.\n");
223     }
224 }
225 
onPlatformGetProcAddress(const char * name) const226 GrGLFuncPtr SkANGLEGLContext::onPlatformGetProcAddress(const char* name) const {
227     return eglGetProcAddress(name);
228 }
229