OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/gfx/gl/gl_surface_egl.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "base/message_loop.h" | |
10 #include "build/build_config.h" | |
11 #if !defined(OS_ANDROID) | |
12 #include "third_party/angle/include/EGL/egl.h" | |
13 #include "third_party/angle/include/EGL/eglext.h" | |
14 #endif | |
15 #include "ui/gfx/gl/egl_util.h" | |
16 #include "ui/gfx/gl/gl_context.h" | |
17 | |
18 #if defined(OS_ANDROID) | |
19 #include <EGL/egl.h> | |
20 #endif | |
21 | |
22 // This header must come after the above third-party include, as | |
23 // it brings in #defines that cause conflicts. | |
24 #include "ui/gfx/gl/gl_bindings.h" | |
25 | |
26 #if defined(USE_X11) | |
27 extern "C" { | |
28 #include <X11/Xlib.h> | |
29 } | |
30 #endif | |
31 | |
32 namespace gfx { | |
33 | |
34 namespace { | |
35 EGLConfig g_config; | |
36 EGLDisplay g_display; | |
37 EGLNativeDisplayType g_native_display; | |
38 EGLConfig g_software_config; | |
39 EGLDisplay g_software_display; | |
40 EGLNativeDisplayType g_software_native_display; | |
41 } | |
42 | |
43 GLSurfaceEGL::GLSurfaceEGL() : software_(false) { | |
44 } | |
45 | |
46 GLSurfaceEGL::~GLSurfaceEGL() { | |
47 } | |
48 | |
49 bool GLSurfaceEGL::InitializeOneOff() { | |
50 static bool initialized = false; | |
51 if (initialized) | |
52 return true; | |
53 | |
54 #if defined(USE_X11) | |
55 g_native_display = base::MessagePumpForUI::GetDefaultXDisplay(); | |
56 #else | |
57 g_native_display = EGL_DEFAULT_DISPLAY; | |
58 #endif | |
59 g_display = eglGetDisplay(g_native_display); | |
60 if (!g_display) { | |
61 LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString(); | |
62 return false; | |
63 } | |
64 | |
65 if (!eglInitialize(g_display, NULL, NULL)) { | |
66 LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString(); | |
67 return false; | |
68 } | |
69 | |
70 // Choose an EGL configuration. | |
71 static const EGLint kConfigAttribs[] = { | |
72 EGL_BUFFER_SIZE, 32, | |
73 EGL_ALPHA_SIZE, 8, | |
74 EGL_BLUE_SIZE, 8, | |
75 EGL_GREEN_SIZE, 8, | |
76 EGL_RED_SIZE, 8, | |
77 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
78 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, | |
79 EGL_NONE | |
80 }; | |
81 | |
82 EGLint num_configs; | |
83 if (!eglChooseConfig(g_display, | |
84 kConfigAttribs, | |
85 NULL, | |
86 0, | |
87 &num_configs)) { | |
88 LOG(ERROR) << "eglChooseConfig failed failed with error " | |
89 << GetLastEGLErrorString(); | |
90 return false; | |
91 } | |
92 | |
93 if (num_configs == 0) { | |
94 LOG(ERROR) << "No suitable EGL configs found."; | |
95 return false; | |
96 } | |
97 | |
98 if (!eglChooseConfig(g_display, | |
99 kConfigAttribs, | |
100 &g_config, | |
101 1, | |
102 &num_configs)) { | |
103 LOG(ERROR) << "eglChooseConfig failed with error " | |
104 << GetLastEGLErrorString(); | |
105 return false; | |
106 } | |
107 | |
108 initialized = true; | |
109 | |
110 #if defined(USE_X11) || defined(OS_ANDROID) | |
111 return true; | |
112 #else | |
113 g_software_native_display = EGL_SOFTWARE_DISPLAY_ANGLE; | |
114 #endif | |
115 g_software_display = eglGetDisplay(g_software_native_display); | |
116 if (!g_software_display) { | |
117 return true; | |
118 } | |
119 | |
120 if (!eglInitialize(g_software_display, NULL, NULL)) { | |
121 return true; | |
122 } | |
123 | |
124 if (!eglChooseConfig(g_software_display, | |
125 kConfigAttribs, | |
126 NULL, | |
127 0, | |
128 &num_configs)) { | |
129 g_software_display = NULL; | |
130 return true; | |
131 } | |
132 | |
133 if (num_configs == 0) { | |
134 g_software_display = NULL; | |
135 return true; | |
136 } | |
137 | |
138 if (!eglChooseConfig(g_software_display, | |
139 kConfigAttribs, | |
140 &g_software_config, | |
141 1, | |
142 &num_configs)) { | |
143 g_software_display = NULL; | |
144 return false; | |
145 } | |
146 | |
147 return true; | |
148 } | |
149 | |
150 EGLDisplay GLSurfaceEGL::GetDisplay() { | |
151 return software_ ? g_software_display : g_display; | |
152 } | |
153 | |
154 EGLConfig GLSurfaceEGL::GetConfig() { | |
155 return software_ ? g_software_config : g_config; | |
156 } | |
157 | |
158 EGLDisplay GLSurfaceEGL::GetHardwareDisplay() { | |
159 return g_display; | |
160 } | |
161 | |
162 EGLDisplay GLSurfaceEGL::GetSoftwareDisplay() { | |
163 return g_software_display; | |
164 } | |
165 | |
166 EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() { | |
167 return g_native_display; | |
168 } | |
169 | |
170 NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(bool software, | |
171 gfx::AcceleratedWidget window) | |
172 : window_(window), | |
173 surface_(NULL), | |
174 supports_post_sub_buffer_(false) | |
175 { | |
176 software_ = software; | |
177 } | |
178 | |
179 NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() { | |
180 Destroy(); | |
181 } | |
182 | |
183 bool NativeViewGLSurfaceEGL::Initialize() { | |
184 #if defined(OS_ANDROID) | |
185 NOTREACHED(); | |
186 return false; | |
187 #else | |
188 DCHECK(!surface_); | |
189 | |
190 if (!GetDisplay()) { | |
191 LOG(ERROR) << "Trying to create surface with invalid display."; | |
192 return false; | |
193 } | |
194 | |
195 static const EGLint egl_window_attributes_sub_buffer[] = { | |
196 EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_TRUE, | |
197 EGL_NONE | |
198 }; | |
199 | |
200 // Create a surface for the native window. | |
201 surface_ = eglCreateWindowSurface(GetDisplay(), | |
202 GetConfig(), | |
203 window_, | |
204 gfx::g_EGL_NV_post_sub_buffer ? | |
205 egl_window_attributes_sub_buffer : | |
206 NULL); | |
207 | |
208 if (!surface_) { | |
209 LOG(ERROR) << "eglCreateWindowSurface failed with error " | |
210 << GetLastEGLErrorString(); | |
211 Destroy(); | |
212 return false; | |
213 } | |
214 | |
215 EGLint surfaceVal; | |
216 EGLBoolean retVal = eglQuerySurface(GetDisplay(), | |
217 surface_, | |
218 EGL_POST_SUB_BUFFER_SUPPORTED_NV, | |
219 &surfaceVal); | |
220 supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE; | |
221 | |
222 return true; | |
223 #endif | |
224 } | |
225 | |
226 void NativeViewGLSurfaceEGL::Destroy() { | |
227 if (surface_) { | |
228 if (!eglDestroySurface(GetDisplay(), surface_)) { | |
229 LOG(ERROR) << "eglDestroySurface failed with error " | |
230 << GetLastEGLErrorString(); | |
231 } | |
232 surface_ = NULL; | |
233 } | |
234 } | |
235 | |
236 bool NativeViewGLSurfaceEGL::IsOffscreen() { | |
237 return false; | |
238 } | |
239 | |
240 bool NativeViewGLSurfaceEGL::SwapBuffers() { | |
241 if (!eglSwapBuffers(GetDisplay(), surface_)) { | |
242 DVLOG(1) << "eglSwapBuffers failed with error " | |
243 << GetLastEGLErrorString(); | |
244 return false; | |
245 } | |
246 | |
247 return true; | |
248 } | |
249 | |
250 gfx::Size NativeViewGLSurfaceEGL::GetSize() { | |
251 EGLint width; | |
252 EGLint height; | |
253 if (!eglQuerySurface(GetDisplay(), surface_, EGL_WIDTH, &width) || | |
254 !eglQuerySurface(GetDisplay(), surface_, EGL_HEIGHT, &height)) { | |
255 NOTREACHED() << "eglQuerySurface failed with error " | |
256 << GetLastEGLErrorString(); | |
257 return gfx::Size(); | |
258 } | |
259 | |
260 return gfx::Size(width, height); | |
261 } | |
262 | |
263 EGLSurface NativeViewGLSurfaceEGL::GetHandle() { | |
264 return surface_; | |
265 } | |
266 | |
267 std::string NativeViewGLSurfaceEGL::GetExtensions() { | |
268 std::string extensions = GLSurface::GetExtensions(); | |
269 if (supports_post_sub_buffer_) { | |
270 extensions += extensions.empty() ? "" : " "; | |
271 extensions += "GL_CHROMIUM_post_sub_buffer"; | |
272 } | |
273 return extensions; | |
274 } | |
275 | |
276 bool NativeViewGLSurfaceEGL::PostSubBuffer( | |
277 int x, int y, int width, int height) { | |
278 DCHECK(supports_post_sub_buffer_); | |
279 if (!eglPostSubBufferNV(GetDisplay(), surface_, x, y, width, height)) { | |
280 DVLOG(1) << "eglPostSubBufferNV failed with error " | |
281 << GetLastEGLErrorString(); | |
282 return false; | |
283 } | |
284 return true; | |
285 } | |
286 | |
287 void NativeViewGLSurfaceEGL::SetHandle(EGLSurface surface) { | |
288 surface_ = surface; | |
289 } | |
290 | |
291 PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(bool software, const gfx::Size& size) | |
292 : size_(size), | |
293 surface_(NULL) { | |
294 software_ = software; | |
295 } | |
296 | |
297 PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() { | |
298 Destroy(); | |
299 } | |
300 | |
301 bool PbufferGLSurfaceEGL::Initialize() { | |
302 DCHECK(!surface_); | |
303 | |
304 if (!GetDisplay()) { | |
305 LOG(ERROR) << "Trying to create surface with invalid display."; | |
306 return false; | |
307 } | |
308 | |
309 const EGLint pbuffer_attribs[] = { | |
310 EGL_WIDTH, size_.width(), | |
311 EGL_HEIGHT, size_.height(), | |
312 EGL_NONE | |
313 }; | |
314 | |
315 surface_ = eglCreatePbufferSurface(GetDisplay(), | |
316 GetConfig(), | |
317 pbuffer_attribs); | |
318 if (!surface_) { | |
319 LOG(ERROR) << "eglCreatePbufferSurface failed with error " | |
320 << GetLastEGLErrorString(); | |
321 Destroy(); | |
322 return false; | |
323 } | |
324 | |
325 return true; | |
326 } | |
327 | |
328 void PbufferGLSurfaceEGL::Destroy() { | |
329 if (surface_) { | |
330 if (!eglDestroySurface(GetDisplay(), surface_)) { | |
331 LOG(ERROR) << "eglDestroySurface failed with error " | |
332 << GetLastEGLErrorString(); | |
333 } | |
334 surface_ = NULL; | |
335 } | |
336 } | |
337 | |
338 bool PbufferGLSurfaceEGL::IsOffscreen() { | |
339 return true; | |
340 } | |
341 | |
342 bool PbufferGLSurfaceEGL::SwapBuffers() { | |
343 NOTREACHED() << "Attempted to call SwapBuffers on a PbufferGLSurfaceEGL."; | |
344 return false; | |
345 } | |
346 | |
347 gfx::Size PbufferGLSurfaceEGL::GetSize() { | |
348 return size_; | |
349 } | |
350 | |
351 bool PbufferGLSurfaceEGL::Resize(const gfx::Size& size) { | |
352 if (size == size_) | |
353 return true; | |
354 | |
355 GLContext* current_context = GLContext::GetCurrent(); | |
356 bool was_current = current_context && current_context->IsCurrent(this); | |
357 if (was_current) | |
358 current_context->ReleaseCurrent(this); | |
359 | |
360 Destroy(); | |
361 | |
362 size_ = size; | |
363 | |
364 if (!Initialize()) | |
365 return false; | |
366 | |
367 if (was_current) | |
368 return current_context->MakeCurrent(this); | |
369 | |
370 return true; | |
371 } | |
372 | |
373 EGLSurface PbufferGLSurfaceEGL::GetHandle() { | |
374 return surface_; | |
375 } | |
376 | |
377 void* PbufferGLSurfaceEGL::GetShareHandle() { | |
378 #if defined(OS_ANDROID) | |
379 NOTREACHED(); | |
380 return NULL; | |
381 #else | |
382 const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS); | |
383 if (!strstr(extensions, "EGL_ANGLE_query_surface_pointer")) | |
384 return NULL; | |
385 | |
386 void* handle; | |
387 if (!eglQuerySurfacePointerANGLE(g_display, | |
388 GetHandle(), | |
389 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, | |
390 &handle)) { | |
391 return NULL; | |
392 } | |
393 | |
394 return handle; | |
395 #endif | |
396 } | |
397 | |
398 } // namespace gfx | |
OLD | NEW |