Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ui / gl / gl_surface_ozone.cc
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.h"
6
7 #include "base/logging.h"
8 #include "base/memory/ref_counted.h"
9 #include "ui/gfx/native_widget_types.h"
10 #include "ui/gl/gl_context.h"
11 #include "ui/gl/gl_image.h"
12 #include "ui/gl/gl_implementation.h"
13 #include "ui/gl/gl_surface_egl.h"
14 #include "ui/gl/gl_surface_osmesa.h"
15 #include "ui/gl/gl_surface_stub.h"
16 #include "ui/gl/scoped_make_current.h"
17 #include "ui/ozone/public/surface_factory_ozone.h"
18 #include "ui/ozone/public/surface_ozone_egl.h"
19
20 namespace gfx {
21
22 namespace {
23
24 // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow
25 class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
26  public:
27   GLSurfaceOzoneEGL(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
28                     AcceleratedWidget widget)
29       : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()),
30         ozone_surface_(ozone_surface.Pass()),
31         widget_(widget) {}
32
33   virtual bool Initialize() OVERRIDE {
34     return Initialize(ozone_surface_->CreateVSyncProvider());
35   }
36   virtual bool Resize(const gfx::Size& size) OVERRIDE {
37     if (!ozone_surface_->ResizeNativeWindow(size)) {
38       if (!ReinitializeNativeSurface() ||
39           !ozone_surface_->ResizeNativeWindow(size))
40         return false;
41     }
42
43     return NativeViewGLSurfaceEGL::Resize(size);
44   }
45   virtual bool SwapBuffers() OVERRIDE {
46     if (!NativeViewGLSurfaceEGL::SwapBuffers())
47       return false;
48
49     return ozone_surface_->OnSwapBuffers();
50   }
51   virtual bool ScheduleOverlayPlane(int z_order,
52                                     OverlayTransform transform,
53                                     GLImage* image,
54                                     const Rect& bounds_rect,
55                                     const RectF& crop_rect) OVERRIDE {
56     return image->ScheduleOverlayPlane(
57         widget_, z_order, transform, bounds_rect, crop_rect);
58   }
59
60  private:
61   using NativeViewGLSurfaceEGL::Initialize;
62
63   virtual ~GLSurfaceOzoneEGL() {
64     Destroy();  // EGL surface must be destroyed before SurfaceOzone
65   }
66
67   bool ReinitializeNativeSurface() {
68     scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
69     GLContext* current_context = GLContext::GetCurrent();
70     bool was_current =
71         current_context && current_context->IsCurrent(this);
72     if (was_current) {
73       scoped_make_current.reset(
74           new ui::ScopedMakeCurrent(current_context, this));
75     }
76
77     Destroy();
78     ozone_surface_ =
79         ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
80             widget_).Pass();
81     if (!ozone_surface_) {
82       LOG(ERROR) << "Failed to create native surface.";
83       return false;
84     }
85
86     window_ = ozone_surface_->GetNativeWindow();
87     if (!Initialize()) {
88       LOG(ERROR) << "Failed to initialize.";
89       return false;
90     }
91
92     return true;
93   }
94
95   // The native surface. Deleting this is allowed to free the EGLNativeWindow.
96   scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
97   AcceleratedWidget widget_;
98
99   DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneEGL);
100 };
101
102 class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
103  public:
104   GLSurfaceOzoneSurfaceless(scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface,
105                             AcceleratedWidget widget)
106       : SurfacelessEGL(gfx::Size()),
107         ozone_surface_(ozone_surface.Pass()),
108         widget_(widget) {}
109
110   virtual bool Initialize() OVERRIDE {
111     if (!SurfacelessEGL::Initialize())
112       return false;
113     vsync_provider_ = ozone_surface_->CreateVSyncProvider();
114     if (!vsync_provider_)
115       return false;
116     return true;
117   }
118   virtual bool Resize(const gfx::Size& size) OVERRIDE {
119     if (!ozone_surface_->ResizeNativeWindow(size))
120       return false;
121
122     return SurfacelessEGL::Resize(size);
123   }
124   virtual bool SwapBuffers() OVERRIDE {
125     // TODO: this should be replaced by a fence when supported by the driver.
126     glFinish();
127     return ozone_surface_->OnSwapBuffers();
128   }
129   virtual bool ScheduleOverlayPlane(int z_order,
130                                     OverlayTransform transform,
131                                     GLImage* image,
132                                     const Rect& bounds_rect,
133                                     const RectF& crop_rect) OVERRIDE {
134     return image->ScheduleOverlayPlane(
135         widget_, z_order, transform, bounds_rect, crop_rect);
136   }
137   virtual bool IsOffscreen() OVERRIDE { return false; }
138   virtual VSyncProvider* GetVSyncProvider() OVERRIDE {
139     return vsync_provider_.get();
140   }
141   virtual bool SupportsPostSubBuffer() OVERRIDE { return true; }
142   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE {
143     // The actual sub buffer handling is handled at higher layers.
144     SwapBuffers();
145     return true;
146   }
147   virtual bool IsSurfaceless() const OVERRIDE { return true; }
148
149  private:
150   virtual ~GLSurfaceOzoneSurfaceless() {
151     Destroy();  // EGL surface must be destroyed before SurfaceOzone
152   }
153
154   // The native surface. Deleting this is allowed to free the EGLNativeWindow.
155   scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
156   AcceleratedWidget widget_;
157   scoped_ptr<VSyncProvider> vsync_provider_;
158
159   DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
160 };
161
162 }  // namespace
163
164 // static
165 bool GLSurface::InitializeOneOffInternal() {
166   switch (GetGLImplementation()) {
167     case kGLImplementationEGLGLES2:
168       if (!GLSurfaceEGL::InitializeOneOff()) {
169         LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
170         return false;
171       }
172
173       return true;
174     case kGLImplementationOSMesaGL:
175     case kGLImplementationMockGL:
176       return true;
177     default:
178       return false;
179   }
180 }
181
182 // static
183 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
184     gfx::AcceleratedWidget window) {
185   if (GetGLImplementation() == kGLImplementationOSMesaGL) {
186     scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
187     if (!surface->Initialize())
188       return NULL;
189     return surface;
190   }
191   DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
192   if (window != kNullAcceleratedWidget) {
193     scoped_refptr<GLSurface> surface;
194     if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
195         ui::SurfaceFactoryOzone::GetInstance()
196             ->CanShowPrimaryPlaneAsOverlay()) {
197       scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
198           ui::SurfaceFactoryOzone::GetInstance()
199               ->CreateSurfacelessEGLSurfaceForWidget(window);
200       if (!surface_ozone)
201         return NULL;
202       surface = new GLSurfaceOzoneSurfaceless(surface_ozone.Pass(), window);
203     } else {
204       scoped_ptr<ui::SurfaceOzoneEGL> surface_ozone =
205           ui::SurfaceFactoryOzone::GetInstance()->CreateEGLSurfaceForWidget(
206               window);
207       if (!surface_ozone)
208         return NULL;
209
210       surface = new GLSurfaceOzoneEGL(surface_ozone.Pass(), window);
211     }
212     if (!surface->Initialize())
213       return NULL;
214     return surface;
215   } else {
216     scoped_refptr<GLSurface> surface = new GLSurfaceStub();
217     if (surface->Initialize())
218       return surface;
219   }
220   return NULL;
221 }
222
223 // static
224 scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
225     const gfx::Size& size) {
226   switch (GetGLImplementation()) {
227     case kGLImplementationOSMesaGL: {
228       scoped_refptr<GLSurface> surface(
229           new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, size));
230       if (!surface->Initialize())
231         return NULL;
232
233       return surface;
234     }
235     case kGLImplementationEGLGLES2: {
236       scoped_refptr<GLSurface> surface;
237       if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
238           (size.width() == 0 && size.height() == 0)) {
239         surface = new SurfacelessEGL(size);
240       } else
241         surface = new PbufferGLSurfaceEGL(size);
242
243       if (!surface->Initialize())
244         return NULL;
245       return surface;
246     }
247     default:
248       NOTREACHED();
249       return NULL;
250   }
251 }
252
253 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
254   return ui::SurfaceFactoryOzone::GetInstance()->GetNativeDisplay();
255 }
256
257 }  // namespace gfx