Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: ui/ozone/platform/cast/surface_factory_cast.cc

Issue 2723583003: Convert Ozone cast to use GLOzone API. (Closed)
Patch Set: . Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/ozone/platform/cast/surface_factory_cast.h ('k') | ui/ozone/public/native_pixmap.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/ozone/platform/cast/surface_factory_cast.h" 5 #include "ui/ozone/platform/cast/surface_factory_cast.h"
6 6
7 #include <EGL/egl.h>
8 #include <dlfcn.h>
9
10 #include <utility> 7 #include <utility>
11 8
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/macros.h" 9 #include "base/macros.h"
15 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "chromecast/base/chromecast_switches.h"
18 #include "chromecast/public/cast_egl_platform.h" 11 #include "chromecast/public/cast_egl_platform.h"
19 #include "chromecast/public/graphics_types.h"
20 #include "third_party/skia/include/core/SkSurface.h" 12 #include "third_party/skia/include/core/SkSurface.h"
21 #include "ui/gfx/geometry/quad_f.h" 13 #include "ui/gfx/geometry/rect.h"
22 #include "ui/gfx/vsync_provider.h" 14 #include "ui/gfx/vsync_provider.h"
23 #include "ui/ozone/platform/cast/gl_surface_cast.h"
24 #include "ui/ozone/public/native_pixmap.h" 15 #include "ui/ozone/public/native_pixmap.h"
25 #include "ui/ozone/public/surface_ozone_canvas.h" 16 #include "ui/ozone/public/surface_ozone_canvas.h"
26 17
27 using chromecast::CastEglPlatform;
28
29 namespace ui { 18 namespace ui {
30 19
31 namespace { 20 namespace {
32 21
33 typedef EGLDisplay (*EGLGetDisplayFn)(NativeDisplayType);
34 typedef EGLBoolean (*EGLTerminateFn)(EGLDisplay);
35
36 chromecast::Size FromGfxSize(const gfx::Size& size) {
37 return chromecast::Size(size.width(), size.height());
38 }
39
40 // Display resolution, set in browser process and passed by switches.
41 gfx::Size GetDisplaySize() {
42 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
43 int width, height;
44 if (base::StringToInt(
45 cmd_line->GetSwitchValueASCII(switches::kCastInitialScreenWidth),
46 &width) &&
47 base::StringToInt(
48 cmd_line->GetSwitchValueASCII(switches::kCastInitialScreenHeight),
49 &height)) {
50 return gfx::Size(width, height);
51 }
52 LOG(WARNING) << "Unable to get initial screen resolution from command line,"
53 << "using default 720p";
54 return gfx::Size(1280, 720);
55 }
56
57 class DummySurface : public SurfaceOzoneCanvas { 22 class DummySurface : public SurfaceOzoneCanvas {
58 public: 23 public:
59 DummySurface() {} 24 DummySurface() {}
60 ~DummySurface() override {} 25 ~DummySurface() override {}
61 26
62 // SurfaceOzoneCanvas implementation: 27 // SurfaceOzoneCanvas implementation:
63 sk_sp<SkSurface> GetSurface() override { return surface_; } 28 sk_sp<SkSurface> GetSurface() override { return surface_; }
64 29
65 void ResizeCanvas(const gfx::Size& viewport_size) override { 30 void ResizeCanvas(const gfx::Size& viewport_size) override {
66 surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul( 31 surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(
67 viewport_size.width(), viewport_size.height())); 32 viewport_size.width(), viewport_size.height()));
68 } 33 }
69 34
70 void PresentCanvas(const gfx::Rect& damage) override {} 35 void PresentCanvas(const gfx::Rect& damage) override {}
71 36
72 std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override { 37 std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override {
73 return nullptr; 38 return nullptr;
74 } 39 }
75 40
76 private: 41 private:
77 sk_sp<SkSurface> surface_; 42 sk_sp<SkSurface> surface_;
78 43
79 DISALLOW_COPY_AND_ASSIGN(DummySurface); 44 DISALLOW_COPY_AND_ASSIGN(DummySurface);
80 }; 45 };
81 46
47 class CastPixmap : public NativePixmap {
48 public:
49 explicit CastPixmap(GLOzoneEglCast* parent) : parent_(parent) {}
50
51 void* GetEGLClientBuffer() const override {
52 // TODO(halliwell): try to implement this through CastEglPlatform.
53 return nullptr;
54 }
55 bool AreDmaBufFdsValid() const override { return false; }
56 size_t GetDmaBufFdCount() const override { return 0; }
57 int GetDmaBufFd(size_t plane) const override { return -1; }
58 int GetDmaBufPitch(size_t plane) const override { return 0; }
59 int GetDmaBufOffset(size_t plane) const override { return 0; }
60 uint64_t GetDmaBufModifier(size_t plane) const override { return 0; }
61 gfx::BufferFormat GetBufferFormat() const override {
62 return gfx::BufferFormat::BGRA_8888;
63 }
64 gfx::Size GetBufferSize() const override { return gfx::Size(); }
65
66 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
67 int plane_z_order,
68 gfx::OverlayTransform plane_transform,
69 const gfx::Rect& display_bounds,
70 const gfx::RectF& crop_rect) override {
71 parent_->OnOverlayScheduled(display_bounds);
72 return true;
73 }
74 void SetProcessingCallback(
75 const ProcessingCallback& processing_callback) override {}
76 gfx::NativePixmapHandle ExportHandle() override {
77 return gfx::NativePixmapHandle();
78 }
79
80 private:
81 ~CastPixmap() override {}
82
83 GLOzoneEglCast* parent_;
84
85 DISALLOW_COPY_AND_ASSIGN(CastPixmap);
86 };
87
82 } // namespace 88 } // namespace
83 89
84 SurfaceFactoryCast::SurfaceFactoryCast() : SurfaceFactoryCast(nullptr) {} 90 SurfaceFactoryCast::SurfaceFactoryCast() {}
85 91
86 SurfaceFactoryCast::SurfaceFactoryCast( 92 SurfaceFactoryCast::SurfaceFactoryCast(
87 std::unique_ptr<CastEglPlatform> egl_platform) 93 std::unique_ptr<chromecast::CastEglPlatform> egl_platform)
88 : state_(kUninitialized), 94 : egl_implementation_(
89 display_type_(0), 95 base::MakeUnique<GLOzoneEglCast>(std::move(egl_platform))) {}
90 have_display_type_(false),
91 window_(0),
92 display_size_(GetDisplaySize()),
93 egl_platform_(std::move(egl_platform)),
94 overlay_count_(0),
95 previous_frame_overlay_count_(0) {}
96 96
97 SurfaceFactoryCast::~SurfaceFactoryCast() { 97 SurfaceFactoryCast::~SurfaceFactoryCast() {}
98 // eglTerminate must be called first on display before releasing resources 98
99 // and shutting down hardware 99 std::vector<gl::GLImplementation>
100 TerminateDisplay(); 100 SurfaceFactoryCast::GetAllowedGLImplementations() {
101 ShutdownHardware(); 101 std::vector<gl::GLImplementation> impls;
102 if (egl_implementation_)
103 impls.push_back(gl::kGLImplementationEGLGLES2);
104 impls.push_back(gl::kGLImplementationOSMesaGL);
105 return impls;
102 } 106 }
103 107
104 void SurfaceFactoryCast::InitializeHardware() { 108 GLOzone* SurfaceFactoryCast::GetGLOzone(gl::GLImplementation implementation) {
105 if (state_ == kInitialized) { 109 switch (implementation) {
106 return; 110 case gl::kGLImplementationEGLGLES2:
111 return egl_implementation_.get();
112 default:
113 return nullptr;
107 } 114 }
108 CHECK_EQ(state_, kUninitialized);
109
110 if (egl_platform_->InitializeHardware()) {
111 state_ = kInitialized;
112 } else {
113 ShutdownHardware();
114 state_ = kFailed;
115 }
116 }
117
118 void SurfaceFactoryCast::TerminateDisplay() {
119 void* egl_lib_handle = egl_platform_->GetEglLibrary();
120 if (!egl_lib_handle)
121 return;
122
123 EGLGetDisplayFn get_display =
124 reinterpret_cast<EGLGetDisplayFn>(dlsym(egl_lib_handle, "eglGetDisplay"));
125 EGLTerminateFn terminate =
126 reinterpret_cast<EGLTerminateFn>(dlsym(egl_lib_handle, "eglTerminate"));
127 DCHECK(get_display);
128 DCHECK(terminate);
129
130 EGLDisplay display = get_display(GetNativeDisplay());
131 DCHECK_NE(display, EGL_NO_DISPLAY);
132
133 EGLBoolean terminate_result = terminate(display);
134 DCHECK_EQ(terminate_result, static_cast<EGLBoolean>(EGL_TRUE));
135 }
136
137 void SurfaceFactoryCast::ShutdownHardware() {
138 if (state_ != kInitialized)
139 return;
140
141 DestroyDisplayTypeAndWindow();
142
143 egl_platform_->ShutdownHardware();
144
145 state_ = kUninitialized;
146 }
147
148 void SurfaceFactoryCast::OnSwapBuffers() {
149 DCHECK(overlay_count_ == 0 || overlay_count_ == 1);
150
151 // Logging for overlays to help diagnose bugs when nothing is visible on
152 // screen. Logging this every frame would be overwhelming, so we just
153 // log on the transitions from 0 overlays -> 1 overlay and vice versa.
154 if (overlay_count_ == 0 && previous_frame_overlay_count_ != 0) {
155 LOG(INFO) << "Overlays deactivated";
156 } else if (overlay_count_ != 0 && previous_frame_overlay_count_ == 0) {
157 LOG(INFO) << "Overlays activated: " << overlay_bounds_.ToString();
158 } else if (overlay_count_ == previous_frame_overlay_count_ &&
159 overlay_bounds_ != previous_frame_overlay_bounds_) {
160 LOG(INFO) << "Overlay geometry changed to " << overlay_bounds_.ToString();
161 }
162
163 previous_frame_overlay_count_ = overlay_count_;
164 previous_frame_overlay_bounds_ = overlay_bounds_;
165 overlay_count_ = 0;
166 }
167
168 void SurfaceFactoryCast::OnOverlayScheduled(const gfx::Rect& display_bounds) {
169 ++overlay_count_;
170 overlay_bounds_ = display_bounds;
171 }
172
173 scoped_refptr<gl::GLSurface> SurfaceFactoryCast::CreateViewGLSurface(
174 gl::GLImplementation implementation,
175 gfx::AcceleratedWidget widget) {
176 if (implementation != gl::kGLImplementationEGLGLES2) {
177 NOTREACHED();
178 return nullptr;
179 }
180
181 // Verify requested widget dimensions match our current display size.
182 DCHECK_EQ(widget >> 16, display_size_.width());
183 DCHECK_EQ(widget & 0xffff, display_size_.height());
184
185 return gl::InitializeGLSurface(new GLSurfaceCast(widget, this));
186 }
187
188 scoped_refptr<gl::GLSurface> SurfaceFactoryCast::CreateOffscreenGLSurface(
189 gl::GLImplementation implementation,
190 const gfx::Size& size) {
191 if (implementation != gl::kGLImplementationEGLGLES2) {
192 NOTREACHED();
193 return nullptr;
194 }
195
196 return gl::InitializeGLSurface(new gl::PbufferGLSurfaceEGL(size));
197 } 115 }
198 116
199 std::unique_ptr<SurfaceOzoneCanvas> SurfaceFactoryCast::CreateCanvasForWidget( 117 std::unique_ptr<SurfaceOzoneCanvas> SurfaceFactoryCast::CreateCanvasForWidget(
200 gfx::AcceleratedWidget widget) { 118 gfx::AcceleratedWidget widget) {
201 // Software canvas support only in headless mode 119 // Software canvas support only in headless mode
202 if (egl_platform_) 120 if (egl_implementation_)
203 return nullptr; 121 return nullptr;
204 return base::WrapUnique<SurfaceOzoneCanvas>(new DummySurface()); 122 return base::WrapUnique<SurfaceOzoneCanvas>(new DummySurface());
205 } 123 }
206 124
207 intptr_t SurfaceFactoryCast::GetNativeDisplay() {
208 CreateDisplayTypeAndWindowIfNeeded();
209 return reinterpret_cast<intptr_t>(display_type_);
210 }
211
212 void SurfaceFactoryCast::CreateDisplayTypeAndWindowIfNeeded() {
213 if (state_ == kUninitialized) {
214 InitializeHardware();
215 }
216 DCHECK_EQ(state_, kInitialized);
217 if (!have_display_type_) {
218 chromecast::Size create_size = FromGfxSize(display_size_);
219 display_type_ = egl_platform_->CreateDisplayType(create_size);
220 have_display_type_ = true;
221 }
222 if (!window_) {
223 chromecast::Size create_size = FromGfxSize(display_size_);
224 window_ = egl_platform_->CreateWindow(display_type_, create_size);
225 if (!window_) {
226 DestroyDisplayTypeAndWindow();
227 state_ = kFailed;
228 LOG(FATAL) << "Create EGLNativeWindowType(" << display_size_.ToString()
229 << ") failed.";
230 }
231 }
232 }
233
234 intptr_t SurfaceFactoryCast::GetNativeWindow() {
235 CreateDisplayTypeAndWindowIfNeeded();
236 return reinterpret_cast<intptr_t>(window_);
237 }
238
239 bool SurfaceFactoryCast::ResizeDisplay(gfx::Size size) {
240 DCHECK_EQ(size.width(), display_size_.width());
241 DCHECK_EQ(size.height(), display_size_.height());
242 return true;
243 }
244
245 void SurfaceFactoryCast::DestroyWindow() {
246 if (window_) {
247 egl_platform_->DestroyWindow(window_);
248 window_ = 0;
249 }
250 }
251
252 void SurfaceFactoryCast::DestroyDisplayTypeAndWindow() {
253 DestroyWindow();
254 if (have_display_type_) {
255 egl_platform_->DestroyDisplayType(display_type_);
256 display_type_ = 0;
257 have_display_type_ = false;
258 }
259 }
260
261 void SurfaceFactoryCast::ChildDestroyed() {
262 if (egl_platform_->MultipleSurfaceUnsupported())
263 DestroyWindow();
264 }
265
266 scoped_refptr<NativePixmap> SurfaceFactoryCast::CreateNativePixmap( 125 scoped_refptr<NativePixmap> SurfaceFactoryCast::CreateNativePixmap(
267 gfx::AcceleratedWidget widget, 126 gfx::AcceleratedWidget widget,
268 gfx::Size size, 127 gfx::Size size,
269 gfx::BufferFormat format, 128 gfx::BufferFormat format,
270 gfx::BufferUsage usage) { 129 gfx::BufferUsage usage) {
271 class CastPixmap : public NativePixmap { 130 return make_scoped_refptr(new CastPixmap(egl_implementation_.get()));
272 public:
273 explicit CastPixmap(SurfaceFactoryCast* parent) : parent_(parent) {}
274
275 void* GetEGLClientBuffer() const override {
276 // TODO(halliwell): try to implement this through CastEglPlatform.
277 return nullptr;
278 }
279 bool AreDmaBufFdsValid() const override { return false; }
280 size_t GetDmaBufFdCount() const override { return 0; }
281 int GetDmaBufFd(size_t plane) const override { return -1; }
282 int GetDmaBufPitch(size_t plane) const override { return 0; }
283 int GetDmaBufOffset(size_t plane) const override { return 0; }
284 uint64_t GetDmaBufModifier(size_t plane) const override { return 0; }
285 gfx::BufferFormat GetBufferFormat() const override {
286 return gfx::BufferFormat::BGRA_8888;
287 }
288 gfx::Size GetBufferSize() const override { return gfx::Size(); }
289
290 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
291 int plane_z_order,
292 gfx::OverlayTransform plane_transform,
293 const gfx::Rect& display_bounds,
294 const gfx::RectF& crop_rect) override {
295 parent_->OnOverlayScheduled(display_bounds);
296 return true;
297 }
298 void SetProcessingCallback(
299 const ProcessingCallback& processing_callback) override {}
300 gfx::NativePixmapHandle ExportHandle() override {
301 return gfx::NativePixmapHandle();
302 }
303
304 private:
305 ~CastPixmap() override {}
306
307 SurfaceFactoryCast* parent_;
308
309 DISALLOW_COPY_AND_ASSIGN(CastPixmap);
310 };
311 return make_scoped_refptr(new CastPixmap(this));
312 }
313
314 bool SurfaceFactoryCast::LoadEGLGLES2Bindings() {
315 if (state_ != kInitialized) {
316 InitializeHardware();
317 if (state_ != kInitialized) {
318 return false;
319 }
320 }
321
322 void* lib_egl = egl_platform_->GetEglLibrary();
323 void* lib_gles2 = egl_platform_->GetGles2Library();
324 gl::GLGetProcAddressProc gl_proc = reinterpret_cast<gl::GLGetProcAddressProc>(
325 egl_platform_->GetGLProcAddressProc());
326 if (!lib_egl || !lib_gles2 || !gl_proc) {
327 return false;
328 }
329
330 gl::SetGLGetProcAddressProc(gl_proc);
331 gl::AddGLNativeLibrary(lib_egl);
332 gl::AddGLNativeLibrary(lib_gles2);
333 return true;
334 } 131 }
335 132
336 } // namespace ui 133 } // namespace ui
OLDNEW
« no previous file with comments | « ui/ozone/platform/cast/surface_factory_cast.h ('k') | ui/ozone/public/native_pixmap.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698