OLD | NEW |
| (Empty) |
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 | |
23 void* SkANGLEGLContext::GetD3DEGLDisplay(void* nativeDisplay, bool useGLBackend)
{ | |
24 PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; | |
25 eglGetPlatformDisplayEXT = | |
26 (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDispla
yEXT"); | |
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, nativeDispl
ay, 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,nativeDi
splay, attribs[i]); | |
62 } | |
63 } | |
64 return display; | |
65 } | |
66 | |
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.release()); | |
127 } | |
128 | |
129 SkANGLEGLContext::~SkANGLEGLContext() { | |
130 this->teardown(); | |
131 this->destroyGLContext(); | |
132 } | |
133 | |
134 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 poin
ter. | |
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, clie
ntBuffer, | |
146 attribs)); | |
147 return img; | |
148 } | |
149 | |
150 void SkANGLEGLContext::destroyEGLImage(GrEGLImage image) const { | |
151 GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image)); | |
152 } | |
153 | |
154 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 typedef GrGLvoid (*EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage); | |
160 | |
161 EGLImageTargetTexture2DProc glEGLImageTargetTexture2D = | |
162 (EGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2
DOES"); | |
163 if (!glEGLImageTargetTexture2D) { | |
164 return 0; | |
165 } | |
166 GrGLuint texID; | |
167 GR_GL_CALL(this->gl(), GenTextures(1, &texID)); | |
168 if (!texID) { | |
169 return 0; | |
170 } | |
171 GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID)); | |
172 if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) { | |
173 GR_GL_CALL(this->gl(), DeleteTextures(1, &texID)); | |
174 return 0; | |
175 } | |
176 glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image); | |
177 if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) { | |
178 GR_GL_CALL(this->gl(), DeleteTextures(1, &texID)); | |
179 return 0; | |
180 } | |
181 return texID; | |
182 } | |
183 | |
184 SkGLContext* SkANGLEGLContext::createNew() const { | |
185 #ifdef SK_BUILD_FOR_WIN | |
186 SkGLContext* ctx = fIsGLBackend ? SkANGLEGLContext::CreateOpenGL() | |
187 : SkANGLEGLContext::CreateDirectX(); | |
188 #else | |
189 SkGLContext* ctx = SkANGLEGLContext::CreateOpenGL(); | |
190 #endif | |
191 if (ctx) { | |
192 ctx->makeCurrent(); | |
193 } | |
194 return ctx; | |
195 } | |
196 | |
197 void SkANGLEGLContext::destroyGLContext() { | |
198 if (fDisplay) { | |
199 eglMakeCurrent(fDisplay, 0, 0, 0); | |
200 | |
201 if (fContext) { | |
202 eglDestroyContext(fDisplay, fContext); | |
203 fContext = EGL_NO_CONTEXT; | |
204 } | |
205 | |
206 if (fSurface) { | |
207 eglDestroySurface(fDisplay, fSurface); | |
208 fSurface = EGL_NO_SURFACE; | |
209 } | |
210 | |
211 //TODO should we close the display? | |
212 fDisplay = EGL_NO_DISPLAY; | |
213 } | |
214 } | |
215 | |
216 void SkANGLEGLContext::onPlatformMakeCurrent() const { | |
217 if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { | |
218 SkDebugf("Could not set the context.\n"); | |
219 } | |
220 } | |
221 | |
222 void SkANGLEGLContext::onPlatformSwapBuffers() const { | |
223 if (!eglSwapBuffers(fDisplay, fSurface)) { | |
224 SkDebugf("Could not complete eglSwapBuffers.\n"); | |
225 } | |
226 } | |
227 | |
228 GrGLFuncPtr SkANGLEGLContext::onPlatformGetProcAddress(const char* name) const { | |
229 return eglGetProcAddress(name); | |
230 } | |
OLD | NEW |