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
3 // found in the LICENSE file.
5 #include "ui/ozone/platform/cast/surface_factory_cast.h"
7 #include "base/callback_helpers.h"
8 #include "chromecast/public/cast_egl_platform.h"
9 #include "chromecast/public/graphics_types.h"
10 #include "ui/gfx/geometry/quad_f.h"
11 #include "ui/ozone/platform/cast/surface_ozone_egl_cast.h"
12 #include "ui/ozone/public/native_pixmap.h"
14 using chromecast::CastEglPlatform
;
18 chromecast::Size
FromGfxSize(const gfx::Size
& size
) {
19 return chromecast::Size(size
.width(), size
.height());
22 // Initial display size to create, needed before first window is created.
23 gfx::Size
GetInitialDisplaySize() {
24 return gfx::Size(1280, 720);
27 // Hard lower bound on display resolution
28 gfx::Size
GetMinDisplaySize() {
29 return gfx::Size(1280, 720);
34 SurfaceFactoryCast::SurfaceFactoryCast(scoped_ptr
<CastEglPlatform
> egl_platform
)
35 : state_(kUninitialized
),
36 destroy_window_pending_state_(kNoDestroyPending
),
38 have_display_type_(false),
40 display_size_(GetInitialDisplaySize()),
41 new_display_size_(GetInitialDisplaySize()),
42 egl_platform_(egl_platform
.Pass()) {
45 SurfaceFactoryCast::~SurfaceFactoryCast() {
46 DestroyDisplayTypeAndWindow();
49 void SurfaceFactoryCast::InitializeHardware() {
50 if (state_
== kInitialized
) {
53 CHECK_EQ(state_
, kUninitialized
);
55 if (egl_platform_
->InitializeHardware()) {
56 state_
= kInitialized
;
63 void SurfaceFactoryCast::ShutdownHardware() {
64 DestroyDisplayTypeAndWindow();
66 egl_platform_
->ShutdownHardware();
68 state_
= kUninitialized
;
71 intptr_t SurfaceFactoryCast::GetNativeDisplay() {
72 CreateDisplayTypeAndWindowIfNeeded();
73 return reinterpret_cast<intptr_t>(display_type_
);
76 void SurfaceFactoryCast::CreateDisplayTypeAndWindowIfNeeded() {
77 if (state_
== kUninitialized
) {
80 if (new_display_size_
!= display_size_
) {
81 DestroyDisplayTypeAndWindow();
82 display_size_
= new_display_size_
;
84 DCHECK_EQ(state_
, kInitialized
);
85 if (!have_display_type_
) {
86 chromecast::Size create_size
= FromGfxSize(display_size_
);
87 display_type_
= egl_platform_
->CreateDisplayType(create_size
);
88 have_display_type_
= true;
89 window_
= egl_platform_
->CreateWindow(display_type_
, create_size
);
91 DestroyDisplayTypeAndWindow();
93 LOG(FATAL
) << "Create EGLNativeWindowType(" << display_size_
.ToString()
99 intptr_t SurfaceFactoryCast::GetNativeWindow() {
100 CreateDisplayTypeAndWindowIfNeeded();
101 return reinterpret_cast<intptr_t>(window_
);
104 bool SurfaceFactoryCast::ResizeDisplay(gfx::Size size
) {
105 // set size to at least 1280x720 even if passed 1x1
106 size
.SetToMax(GetMinDisplaySize());
107 if (have_display_type_
&& size
!= display_size_
) {
108 DestroyDisplayTypeAndWindow();
110 display_size_
= size
;
114 void SurfaceFactoryCast::DestroyDisplayTypeAndWindow() {
116 egl_platform_
->DestroyWindow(window_
);
119 if (have_display_type_
) {
120 egl_platform_
->DestroyDisplayType(display_type_
);
122 have_display_type_
= false;
126 scoped_ptr
<SurfaceOzoneEGL
> SurfaceFactoryCast::CreateEGLSurfaceForWidget(
127 gfx::AcceleratedWidget widget
) {
128 new_display_size_
= gfx::Size(widget
>> 16, widget
& 0xFFFF);
129 new_display_size_
.SetToMax(GetMinDisplaySize());
130 destroy_window_pending_state_
= kSurfaceExists
;
131 SendRelinquishResponse();
132 return make_scoped_ptr
<SurfaceOzoneEGL
>(new SurfaceOzoneEglCast(this));
135 void SurfaceFactoryCast::SetToRelinquishDisplay(const base::Closure
& callback
) {
136 // This is called in response to a RelinquishDisplay message from the
137 // browser task. This call may come before or after the display surface
138 // is actually destroyed.
139 relinquish_display_callback_
= callback
;
140 switch (destroy_window_pending_state_
) {
141 case kNoDestroyPending
:
142 case kSurfaceDestroyedRecently
:
143 DestroyDisplayTypeAndWindow();
144 SendRelinquishResponse();
145 destroy_window_pending_state_
= kNoDestroyPending
;
148 destroy_window_pending_state_
= kWindowDestroyPending
;
150 case kWindowDestroyPending
:
157 void SurfaceFactoryCast::ChildDestroyed() {
158 if (destroy_window_pending_state_
== kWindowDestroyPending
) {
159 DestroyDisplayTypeAndWindow();
160 SendRelinquishResponse();
161 destroy_window_pending_state_
= kNoDestroyPending
;
163 destroy_window_pending_state_
= kSurfaceDestroyedRecently
;
167 void SurfaceFactoryCast::SendRelinquishResponse() {
168 if (!relinquish_display_callback_
.is_null()) {
169 base::ResetAndReturn(&relinquish_display_callback_
).Run();
173 const int32
* SurfaceFactoryCast::GetEGLSurfaceProperties(
174 const int32
* desired_list
) {
175 return egl_platform_
->GetEGLSurfaceProperties(desired_list
);
178 scoped_refptr
<NativePixmap
> SurfaceFactoryCast::CreateNativePixmap(
179 gfx::AcceleratedWidget w
,
183 class CastPixmap
: public NativePixmap
{
187 void* GetEGLClientBuffer() override
{
188 // TODO(halliwell): try to implement this through CastEglPlatform.
191 int GetDmaBufFd() override
{ return 0; }
192 int GetDmaBufPitch() override
{ return 0; }
193 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget
,
195 gfx::OverlayTransform plane_transform
,
196 const gfx::Rect
& display_bounds
,
197 const gfx::RectF
& crop_rect
) override
{
200 void SetScalingCallback(const ScalingCallback
& scaling_callback
) override
{}
201 scoped_refptr
<NativePixmap
> GetScaledPixmap(gfx::Size new_size
) override
{
206 ~CastPixmap() override
{}
208 DISALLOW_COPY_AND_ASSIGN(CastPixmap
);
210 return make_scoped_refptr(new CastPixmap
);
213 bool SurfaceFactoryCast::LoadEGLGLES2Bindings(
214 AddGLLibraryCallback add_gl_library
,
215 SetGLGetProcAddressProcCallback set_gl_get_proc_address
) {
216 if (state_
!= kInitialized
) {
217 InitializeHardware();
218 if (state_
!= kInitialized
) {
223 void* lib_egl
= egl_platform_
->GetEglLibrary();
224 void* lib_gles2
= egl_platform_
->GetGles2Library();
225 GLGetProcAddressProc gl_proc
= egl_platform_
->GetGLProcAddressProc();
226 if (!lib_egl
|| !lib_gles2
|| !gl_proc
) {
230 set_gl_get_proc_address
.Run(gl_proc
);
231 add_gl_library
.Run(lib_egl
);
232 add_gl_library
.Run(lib_gles2
);