OLD | NEW |
| (Empty) |
1 // Copyright 2014 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/gl/gl_surface_ozone.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include <vector> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/callback.h" | |
13 #include "base/location.h" | |
14 #include "base/logging.h" | |
15 #include "base/macros.h" | |
16 #include "base/memory/scoped_vector.h" | |
17 #include "base/memory/weak_ptr.h" | |
18 #include "base/threading/worker_pool.h" | |
19 #include "ui/gl/egl_util.h" | |
20 #include "ui/gl/gl_context.h" | |
21 #include "ui/gl/gl_image.h" | |
22 #include "ui/gl/gl_image_ozone_native_pixmap.h" | |
23 #include "ui/gl/gl_implementation.h" | |
24 #include "ui/gl/gl_surface_egl.h" | |
25 #include "ui/gl/gl_surface_osmesa.h" | |
26 #include "ui/gl/gl_surface_overlay.h" | |
27 #include "ui/gl/gl_surface_stub.h" | |
28 #include "ui/gl/scoped_binders.h" | |
29 #include "ui/gl/scoped_make_current.h" | |
30 #include "ui/ozone/public/native_pixmap.h" | |
31 #include "ui/ozone/public/ozone_platform.h" | |
32 #include "ui/ozone/public/surface_factory_ozone.h" | |
33 #include "ui/ozone/public/surface_ozone_egl.h" | |
34 | |
35 namespace gl { | |
36 | |
37 namespace { | |
38 | |
39 // Helper function for base::Bind to create callback to eglChooseConfig. | |
40 bool EglChooseConfig(EGLDisplay display, | |
41 const int32_t* attribs, | |
42 EGLConfig* configs, | |
43 int32_t config_size, | |
44 int32_t* num_configs) { | |
45 return eglChooseConfig(display, attribs, configs, config_size, num_configs); | |
46 } | |
47 | |
48 // Helper function for base::Bind to create callback to eglGetConfigAttrib. | |
49 bool EglGetConfigAttribute(EGLDisplay display, | |
50 EGLConfig config, | |
51 int32_t attribute, | |
52 int32_t* value) { | |
53 return eglGetConfigAttrib(display, config, attribute, value); | |
54 } | |
55 | |
56 // Populates EglConfigCallbacks with appropriate callbacks. | |
57 ui::EglConfigCallbacks GetEglConfigCallbacks(EGLDisplay display) { | |
58 ui::EglConfigCallbacks callbacks; | |
59 callbacks.choose_config = base::Bind(EglChooseConfig, display); | |
60 callbacks.get_config_attribute = base::Bind(EglGetConfigAttribute, display); | |
61 callbacks.get_last_error_string = base::Bind(&ui::GetLastEGLErrorString); | |
62 return callbacks; | |
63 } | |
64 | |
65 void WaitForFence(EGLDisplay display, EGLSyncKHR fence) { | |
66 eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, | |
67 EGL_FOREVER_KHR); | |
68 } | |
69 | |
70 // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow. | |
71 class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL { | |
72 public: | |
73 GLSurfaceOzoneEGL(std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface, | |
74 gfx::AcceleratedWidget widget); | |
75 | |
76 // GLSurface: | |
77 bool Initialize(GLSurface::Format format) override; | |
78 bool Resize(const gfx::Size& size, | |
79 float scale_factor, | |
80 bool has_alpha) override; | |
81 gfx::SwapResult SwapBuffers() override; | |
82 bool ScheduleOverlayPlane(int z_order, | |
83 gfx::OverlayTransform transform, | |
84 GLImage* image, | |
85 const gfx::Rect& bounds_rect, | |
86 const gfx::RectF& crop_rect) override; | |
87 EGLConfig GetConfig() override; | |
88 | |
89 private: | |
90 using NativeViewGLSurfaceEGL::Initialize; | |
91 | |
92 ~GLSurfaceOzoneEGL() override; | |
93 | |
94 bool ReinitializeNativeSurface(); | |
95 | |
96 // The native surface. Deleting this is allowed to free the EGLNativeWindow. | |
97 std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface_; | |
98 gfx::AcceleratedWidget widget_; | |
99 | |
100 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL); | |
101 }; | |
102 | |
103 GLSurfaceOzoneEGL::GLSurfaceOzoneEGL( | |
104 std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface, | |
105 gfx::AcceleratedWidget widget) | |
106 : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()), | |
107 ozone_surface_(std::move(ozone_surface)), | |
108 widget_(widget) {} | |
109 | |
110 bool GLSurfaceOzoneEGL::Initialize(GLSurface::Format format) { | |
111 format_ = format; | |
112 return Initialize(ozone_surface_->CreateVSyncProvider()); | |
113 } | |
114 | |
115 bool GLSurfaceOzoneEGL::Resize(const gfx::Size& size, | |
116 float scale_factor, | |
117 bool has_alpha) { | |
118 if (!ozone_surface_->ResizeNativeWindow(size)) { | |
119 if (!ReinitializeNativeSurface() || | |
120 !ozone_surface_->ResizeNativeWindow(size)) | |
121 return false; | |
122 } | |
123 | |
124 return NativeViewGLSurfaceEGL::Resize(size, scale_factor, has_alpha); | |
125 } | |
126 | |
127 gfx::SwapResult GLSurfaceOzoneEGL::SwapBuffers() { | |
128 gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers(); | |
129 if (result != gfx::SwapResult::SWAP_ACK) | |
130 return result; | |
131 | |
132 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK | |
133 : gfx::SwapResult::SWAP_FAILED; | |
134 } | |
135 | |
136 bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order, | |
137 gfx::OverlayTransform transform, | |
138 GLImage* image, | |
139 const gfx::Rect& bounds_rect, | |
140 const gfx::RectF& crop_rect) { | |
141 return image->ScheduleOverlayPlane(widget_, z_order, transform, bounds_rect, | |
142 crop_rect); | |
143 } | |
144 | |
145 EGLConfig GLSurfaceOzoneEGL::GetConfig() { | |
146 if (!config_) { | |
147 ui::EglConfigCallbacks callbacks = GetEglConfigCallbacks(GetDisplay()); | |
148 config_ = ozone_surface_->GetEGLSurfaceConfig(callbacks); | |
149 } | |
150 if (config_) | |
151 return config_; | |
152 return NativeViewGLSurfaceEGL::GetConfig(); | |
153 } | |
154 | |
155 GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() { | |
156 Destroy(); // The EGL surface must be destroyed before SurfaceOzone. | |
157 } | |
158 | |
159 bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() { | |
160 std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current; | |
161 GLContext* current_context = GLContext::GetCurrent(); | |
162 bool was_current = current_context && current_context->IsCurrent(this); | |
163 if (was_current) { | |
164 scoped_make_current.reset(new ui::ScopedMakeCurrent(current_context, this)); | |
165 } | |
166 | |
167 Destroy(); | |
168 ozone_surface_ = ui::OzonePlatform::GetInstance() | |
169 ->GetSurfaceFactoryOzone() | |
170 ->CreateEGLSurfaceForWidget(widget_); | |
171 if (!ozone_surface_) { | |
172 LOG(ERROR) << "Failed to create native surface."; | |
173 return false; | |
174 } | |
175 | |
176 window_ = ozone_surface_->GetNativeWindow(); | |
177 if (!Initialize(format_)) { | |
178 LOG(ERROR) << "Failed to initialize."; | |
179 return false; | |
180 } | |
181 | |
182 return true; | |
183 } | |
184 | |
185 class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL { | |
186 public: | |
187 GLSurfaceOzoneSurfaceless(std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface, | |
188 gfx::AcceleratedWidget widget); | |
189 | |
190 // GLSurface: | |
191 bool Initialize(GLSurface::Format format) override; | |
192 bool Resize(const gfx::Size& size, | |
193 float scale_factor, | |
194 bool has_alpha) override; | |
195 gfx::SwapResult SwapBuffers() override; | |
196 bool ScheduleOverlayPlane(int z_order, | |
197 gfx::OverlayTransform transform, | |
198 GLImage* image, | |
199 const gfx::Rect& bounds_rect, | |
200 const gfx::RectF& crop_rect) override; | |
201 bool IsOffscreen() override; | |
202 gfx::VSyncProvider* GetVSyncProvider() override; | |
203 bool SupportsAsyncSwap() override; | |
204 bool SupportsPostSubBuffer() override; | |
205 gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override; | |
206 void SwapBuffersAsync(const SwapCompletionCallback& callback) override; | |
207 void PostSubBufferAsync(int x, | |
208 int y, | |
209 int width, | |
210 int height, | |
211 const SwapCompletionCallback& callback) override; | |
212 EGLConfig GetConfig() override; | |
213 | |
214 protected: | |
215 struct PendingFrame { | |
216 PendingFrame(); | |
217 | |
218 bool ScheduleOverlayPlanes(gfx::AcceleratedWidget widget); | |
219 | |
220 bool ready; | |
221 std::vector<GLSurfaceOverlay> overlays; | |
222 SwapCompletionCallback callback; | |
223 }; | |
224 | |
225 ~GLSurfaceOzoneSurfaceless() override; | |
226 | |
227 void SubmitFrame(); | |
228 | |
229 EGLSyncKHR InsertFence(); | |
230 void FenceRetired(EGLSyncKHR fence, PendingFrame* frame); | |
231 | |
232 void SwapCompleted(const SwapCompletionCallback& callback, | |
233 gfx::SwapResult result); | |
234 | |
235 // The native surface. Deleting this is allowed to free the EGLNativeWindow. | |
236 std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface_; | |
237 gfx::AcceleratedWidget widget_; | |
238 std::unique_ptr<gfx::VSyncProvider> vsync_provider_; | |
239 ScopedVector<PendingFrame> unsubmitted_frames_; | |
240 bool has_implicit_external_sync_; | |
241 bool last_swap_buffers_result_; | |
242 bool swap_buffers_pending_; | |
243 | |
244 base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_; | |
245 | |
246 private: | |
247 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); | |
248 }; | |
249 | |
250 GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {} | |
251 | |
252 bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes( | |
253 gfx::AcceleratedWidget widget) { | |
254 for (const auto& overlay : overlays) | |
255 if (!overlay.ScheduleOverlayPlane(widget)) | |
256 return false; | |
257 return true; | |
258 } | |
259 | |
260 GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless( | |
261 std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface, | |
262 gfx::AcceleratedWidget widget) | |
263 : SurfacelessEGL(gfx::Size()), | |
264 ozone_surface_(std::move(ozone_surface)), | |
265 widget_(widget), | |
266 has_implicit_external_sync_( | |
267 HasEGLExtension("EGL_ARM_implicit_external_sync")), | |
268 last_swap_buffers_result_(true), | |
269 swap_buffers_pending_(false), | |
270 weak_factory_(this) { | |
271 unsubmitted_frames_.push_back(new PendingFrame()); | |
272 } | |
273 | |
274 bool GLSurfaceOzoneSurfaceless::Initialize(GLSurface::Format format) { | |
275 if (!SurfacelessEGL::Initialize(format)) | |
276 return false; | |
277 vsync_provider_ = ozone_surface_->CreateVSyncProvider(); | |
278 if (!vsync_provider_) | |
279 return false; | |
280 return true; | |
281 } | |
282 | |
283 bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size& size, | |
284 float scale_factor, | |
285 bool has_alpha) { | |
286 if (!ozone_surface_->ResizeNativeWindow(size)) | |
287 return false; | |
288 | |
289 return SurfacelessEGL::Resize(size, scale_factor, has_alpha); | |
290 } | |
291 | |
292 gfx::SwapResult GLSurfaceOzoneSurfaceless::SwapBuffers() { | |
293 glFlush(); | |
294 // TODO: the following should be replaced by a per surface flush as it gets | |
295 // implemented in GL drivers. | |
296 if (has_implicit_external_sync_) { | |
297 EGLSyncKHR fence = InsertFence(); | |
298 if (!fence) | |
299 return gfx::SwapResult::SWAP_FAILED; | |
300 | |
301 EGLDisplay display = GetDisplay(); | |
302 WaitForFence(display, fence); | |
303 eglDestroySyncKHR(display, fence); | |
304 } | |
305 | |
306 unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_); | |
307 unsubmitted_frames_.back()->overlays.clear(); | |
308 | |
309 if (ozone_surface_->IsUniversalDisplayLinkDevice()) | |
310 glFinish(); | |
311 | |
312 return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK | |
313 : gfx::SwapResult::SWAP_FAILED; | |
314 } | |
315 | |
316 bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane( | |
317 int z_order, | |
318 gfx::OverlayTransform transform, | |
319 GLImage* image, | |
320 const gfx::Rect& bounds_rect, | |
321 const gfx::RectF& crop_rect) { | |
322 unsubmitted_frames_.back()->overlays.push_back( | |
323 GLSurfaceOverlay(z_order, transform, image, bounds_rect, crop_rect)); | |
324 return true; | |
325 } | |
326 | |
327 bool GLSurfaceOzoneSurfaceless::IsOffscreen() { | |
328 return false; | |
329 } | |
330 | |
331 gfx::VSyncProvider* GLSurfaceOzoneSurfaceless::GetVSyncProvider() { | |
332 return vsync_provider_.get(); | |
333 } | |
334 | |
335 bool GLSurfaceOzoneSurfaceless::SupportsAsyncSwap() { | |
336 return true; | |
337 } | |
338 | |
339 bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() { | |
340 return true; | |
341 } | |
342 | |
343 gfx::SwapResult GLSurfaceOzoneSurfaceless::PostSubBuffer(int x, | |
344 int y, | |
345 int width, | |
346 int height) { | |
347 // The actual sub buffer handling is handled at higher layers. | |
348 NOTREACHED(); | |
349 return gfx::SwapResult::SWAP_FAILED; | |
350 } | |
351 | |
352 void GLSurfaceOzoneSurfaceless::SwapBuffersAsync( | |
353 const SwapCompletionCallback& callback) { | |
354 // If last swap failed, don't try to schedule new ones. | |
355 if (!last_swap_buffers_result_) { | |
356 callback.Run(gfx::SwapResult::SWAP_FAILED); | |
357 return; | |
358 } | |
359 | |
360 glFlush(); | |
361 | |
362 SwapCompletionCallback surface_swap_callback = | |
363 base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted, | |
364 weak_factory_.GetWeakPtr(), callback); | |
365 | |
366 PendingFrame* frame = unsubmitted_frames_.back(); | |
367 frame->callback = surface_swap_callback; | |
368 unsubmitted_frames_.push_back(new PendingFrame()); | |
369 | |
370 // TODO: the following should be replaced by a per surface flush as it gets | |
371 // implemented in GL drivers. | |
372 if (has_implicit_external_sync_) { | |
373 EGLSyncKHR fence = InsertFence(); | |
374 if (!fence) { | |
375 callback.Run(gfx::SwapResult::SWAP_FAILED); | |
376 return; | |
377 } | |
378 | |
379 base::Closure fence_wait_task = | |
380 base::Bind(&WaitForFence, GetDisplay(), fence); | |
381 | |
382 base::Closure fence_retired_callback = | |
383 base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired, | |
384 weak_factory_.GetWeakPtr(), fence, frame); | |
385 | |
386 base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, | |
387 fence_retired_callback, false); | |
388 return; // Defer frame submission until fence signals. | |
389 } | |
390 | |
391 frame->ready = true; | |
392 SubmitFrame(); | |
393 } | |
394 | |
395 void GLSurfaceOzoneSurfaceless::PostSubBufferAsync( | |
396 int x, | |
397 int y, | |
398 int width, | |
399 int height, | |
400 const SwapCompletionCallback& callback) { | |
401 // The actual sub buffer handling is handled at higher layers. | |
402 SwapBuffersAsync(callback); | |
403 } | |
404 | |
405 EGLConfig GLSurfaceOzoneSurfaceless::GetConfig() { | |
406 if (!config_) { | |
407 ui::EglConfigCallbacks callbacks = GetEglConfigCallbacks(GetDisplay()); | |
408 config_ = ozone_surface_->GetEGLSurfaceConfig(callbacks); | |
409 } | |
410 if (config_) | |
411 return config_; | |
412 return SurfacelessEGL::GetConfig(); | |
413 } | |
414 | |
415 GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() { | |
416 Destroy(); // The EGL surface must be destroyed before SurfaceOzone. | |
417 } | |
418 | |
419 void GLSurfaceOzoneSurfaceless::SubmitFrame() { | |
420 DCHECK(!unsubmitted_frames_.empty()); | |
421 | |
422 if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) { | |
423 std::unique_ptr<PendingFrame> frame(unsubmitted_frames_.front()); | |
424 unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin()); | |
425 swap_buffers_pending_ = true; | |
426 | |
427 if (!frame->ScheduleOverlayPlanes(widget_)) { | |
428 // |callback| is a wrapper for SwapCompleted(). Call it to properly | |
429 // propagate the failed state. | |
430 frame->callback.Run(gfx::SwapResult::SWAP_FAILED); | |
431 return; | |
432 } | |
433 | |
434 if (ozone_surface_->IsUniversalDisplayLinkDevice()) | |
435 glFinish(); | |
436 | |
437 ozone_surface_->OnSwapBuffersAsync(frame->callback); | |
438 } | |
439 } | |
440 | |
441 EGLSyncKHR GLSurfaceOzoneSurfaceless::InsertFence() { | |
442 const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, | |
443 EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, | |
444 EGL_NONE}; | |
445 return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); | |
446 } | |
447 | |
448 void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence, | |
449 PendingFrame* frame) { | |
450 eglDestroySyncKHR(GetDisplay(), fence); | |
451 frame->ready = true; | |
452 SubmitFrame(); | |
453 } | |
454 | |
455 void GLSurfaceOzoneSurfaceless::SwapCompleted( | |
456 const SwapCompletionCallback& callback, | |
457 gfx::SwapResult result) { | |
458 callback.Run(result); | |
459 swap_buffers_pending_ = false; | |
460 if (result == gfx::SwapResult::SWAP_FAILED) { | |
461 last_swap_buffers_result_ = false; | |
462 return; | |
463 } | |
464 | |
465 SubmitFrame(); | |
466 } | |
467 | |
468 // This provides surface-like semantics implemented through surfaceless. | |
469 // A framebuffer is bound automatically. | |
470 class GL_EXPORT GLSurfaceOzoneSurfacelessSurfaceImpl | |
471 : public GLSurfaceOzoneSurfaceless { | |
472 public: | |
473 GLSurfaceOzoneSurfacelessSurfaceImpl( | |
474 std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface, | |
475 gfx::AcceleratedWidget widget); | |
476 | |
477 // GLSurface: | |
478 unsigned int GetBackingFrameBufferObject() override; | |
479 bool OnMakeCurrent(GLContext* context) override; | |
480 bool Resize(const gfx::Size& size, | |
481 float scale_factor, | |
482 bool has_alpha) override; | |
483 bool SupportsPostSubBuffer() override; | |
484 gfx::SwapResult SwapBuffers() override; | |
485 void SwapBuffersAsync(const SwapCompletionCallback& callback) override; | |
486 void Destroy() override; | |
487 bool IsSurfaceless() const override; | |
488 | |
489 private: | |
490 ~GLSurfaceOzoneSurfacelessSurfaceImpl() override; | |
491 | |
492 void BindFramebuffer(); | |
493 bool CreatePixmaps(); | |
494 | |
495 scoped_refptr<GLContext> context_; | |
496 GLuint fbo_; | |
497 GLuint textures_[2]; | |
498 scoped_refptr<GLImage> images_[2]; | |
499 int current_surface_; | |
500 DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfacelessSurfaceImpl); | |
501 }; | |
502 | |
503 GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl( | |
504 std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface, | |
505 gfx::AcceleratedWidget widget) | |
506 : GLSurfaceOzoneSurfaceless(std::move(ozone_surface), widget), | |
507 context_(nullptr), | |
508 fbo_(0), | |
509 current_surface_(0) { | |
510 for (auto& texture : textures_) | |
511 texture = 0; | |
512 } | |
513 | |
514 unsigned int | |
515 GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() { | |
516 return fbo_; | |
517 } | |
518 | |
519 bool GLSurfaceOzoneSurfacelessSurfaceImpl::OnMakeCurrent(GLContext* context) { | |
520 DCHECK(!context_ || context == context_); | |
521 context_ = context; | |
522 if (!fbo_) { | |
523 glGenFramebuffersEXT(1, &fbo_); | |
524 if (!fbo_) | |
525 return false; | |
526 glGenTextures(arraysize(textures_), textures_); | |
527 if (!CreatePixmaps()) | |
528 return false; | |
529 } | |
530 BindFramebuffer(); | |
531 glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_); | |
532 return SurfacelessEGL::OnMakeCurrent(context); | |
533 } | |
534 | |
535 bool GLSurfaceOzoneSurfacelessSurfaceImpl::Resize(const gfx::Size& size, | |
536 float scale_factor, | |
537 bool has_alpha) { | |
538 if (size == GetSize()) | |
539 return true; | |
540 // Alpha value isn't actually used in allocating buffers yet, so always use | |
541 // true instead. | |
542 return GLSurfaceOzoneSurfaceless::Resize(size, scale_factor, true) && | |
543 CreatePixmaps(); | |
544 } | |
545 | |
546 bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() { | |
547 return false; | |
548 } | |
549 | |
550 gfx::SwapResult GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() { | |
551 if (!images_[current_surface_]->ScheduleOverlayPlane( | |
552 widget_, 0, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE, | |
553 gfx::Rect(GetSize()), gfx::RectF(1, 1))) | |
554 return gfx::SwapResult::SWAP_FAILED; | |
555 gfx::SwapResult result = GLSurfaceOzoneSurfaceless::SwapBuffers(); | |
556 if (result != gfx::SwapResult::SWAP_ACK) | |
557 return result; | |
558 current_surface_ ^= 1; | |
559 BindFramebuffer(); | |
560 return gfx::SwapResult::SWAP_ACK; | |
561 } | |
562 | |
563 void GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffersAsync( | |
564 const SwapCompletionCallback& callback) { | |
565 if (!images_[current_surface_]->ScheduleOverlayPlane( | |
566 widget_, 0, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE, | |
567 gfx::Rect(GetSize()), gfx::RectF(1, 1))) { | |
568 callback.Run(gfx::SwapResult::SWAP_FAILED); | |
569 return; | |
570 } | |
571 GLSurfaceOzoneSurfaceless::SwapBuffersAsync(callback); | |
572 current_surface_ ^= 1; | |
573 BindFramebuffer(); | |
574 } | |
575 | |
576 void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() { | |
577 if (!context_) | |
578 return; | |
579 scoped_refptr<GLContext> previous_context = GLContext::GetCurrent(); | |
580 scoped_refptr<GLSurface> previous_surface; | |
581 | |
582 bool was_current = previous_context && previous_context->IsCurrent(nullptr) && | |
583 GLSurface::GetCurrent() == this; | |
584 if (!was_current) { | |
585 // Only take a reference to previous surface if it's not |this| | |
586 // because otherwise we can take a self reference from our own dtor. | |
587 previous_surface = GLSurface::GetCurrent(); | |
588 context_->MakeCurrent(this); | |
589 } | |
590 | |
591 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | |
592 if (fbo_) { | |
593 glDeleteTextures(arraysize(textures_), textures_); | |
594 for (auto& texture : textures_) | |
595 texture = 0; | |
596 glDeleteFramebuffersEXT(1, &fbo_); | |
597 fbo_ = 0; | |
598 } | |
599 for (auto image : images_) { | |
600 if (image) | |
601 image->Destroy(true); | |
602 } | |
603 | |
604 if (!was_current) { | |
605 if (previous_context) { | |
606 previous_context->MakeCurrent(previous_surface.get()); | |
607 } else { | |
608 context_->ReleaseCurrent(this); | |
609 } | |
610 } | |
611 } | |
612 | |
613 bool GLSurfaceOzoneSurfacelessSurfaceImpl::IsSurfaceless() const { | |
614 return false; | |
615 } | |
616 | |
617 GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() { | |
618 Destroy(); | |
619 } | |
620 | |
621 void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() { | |
622 ScopedFrameBufferBinder fb(fbo_); | |
623 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
624 textures_[current_surface_], 0); | |
625 } | |
626 | |
627 bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() { | |
628 if (!fbo_) | |
629 return true; | |
630 for (size_t i = 0; i < arraysize(textures_); i++) { | |
631 scoped_refptr<ui::NativePixmap> pixmap = | |
632 ui::OzonePlatform::GetInstance() | |
633 ->GetSurfaceFactoryOzone() | |
634 ->CreateNativePixmap(widget_, GetSize(), | |
635 gfx::BufferFormat::BGRA_8888, | |
636 gfx::BufferUsage::SCANOUT); | |
637 if (!pixmap) | |
638 return false; | |
639 scoped_refptr<GLImageOzoneNativePixmap> image = | |
640 new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT); | |
641 if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888)) | |
642 return false; | |
643 // Image must have Destroy() called before destruction. | |
644 if (images_[i]) | |
645 images_[i]->Destroy(true); | |
646 images_[i] = image; | |
647 // Bind image to texture. | |
648 ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]); | |
649 if (!images_[i]->BindTexImage(GL_TEXTURE_2D)) | |
650 return false; | |
651 } | |
652 return true; | |
653 } | |
654 | |
655 } // namespace | |
656 | |
657 scoped_refptr<GLSurface> CreateViewGLSurfaceOzone( | |
658 gfx::AcceleratedWidget window) { | |
659 std::unique_ptr<ui::SurfaceOzoneEGL> surface_ozone = | |
660 ui::OzonePlatform::GetInstance() | |
661 ->GetSurfaceFactoryOzone() | |
662 ->CreateEGLSurfaceForWidget(window); | |
663 if (!surface_ozone) | |
664 return nullptr; | |
665 return InitializeGLSurface( | |
666 new GLSurfaceOzoneEGL(std::move(surface_ozone), window)); | |
667 } | |
668 | |
669 scoped_refptr<GLSurface> CreateViewGLSurfaceOzoneSurfaceless( | |
670 gfx::AcceleratedWidget window) { | |
671 std::unique_ptr<ui::SurfaceOzoneEGL> surface_ozone = | |
672 ui::OzonePlatform::GetInstance() | |
673 ->GetSurfaceFactoryOzone() | |
674 ->CreateSurfacelessEGLSurfaceForWidget(window); | |
675 if (!surface_ozone) | |
676 return nullptr; | |
677 return InitializeGLSurface( | |
678 new GLSurfaceOzoneSurfaceless(std::move(surface_ozone), window)); | |
679 } | |
680 | |
681 scoped_refptr<GLSurface> CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl( | |
682 gfx::AcceleratedWidget window) { | |
683 std::unique_ptr<ui::SurfaceOzoneEGL> surface_ozone = | |
684 ui::OzonePlatform::GetInstance() | |
685 ->GetSurfaceFactoryOzone() | |
686 ->CreateSurfacelessEGLSurfaceForWidget(window); | |
687 if (!surface_ozone) | |
688 return nullptr; | |
689 return InitializeGLSurface(new GLSurfaceOzoneSurfacelessSurfaceImpl( | |
690 std::move(surface_ozone), window)); | |
691 } | |
692 | |
693 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { | |
694 return ui::OzonePlatform::GetInstance() | |
695 ->GetSurfaceFactoryOzone() | |
696 ->GetNativeDisplay(); | |
697 } | |
698 | |
699 } // namespace gl | |
OLD | NEW |