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.
5 #include "gpu/gles2_conform_support/egl/display.h"
8 #include "base/at_exit.h"
10 #include "base/bind_helpers.h"
11 #include "gpu/command_buffer/client/gles2_implementation.h"
12 #include "gpu/command_buffer/client/gles2_lib.h"
13 #include "gpu/command_buffer/client/transfer_buffer.h"
14 #include "gpu/command_buffer/common/value_state.h"
15 #include "gpu/command_buffer/service/context_group.h"
16 #include "gpu/command_buffer/service/mailbox_manager.h"
17 #include "gpu/command_buffer/service/memory_tracking.h"
18 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
19 #include "gpu/command_buffer/service/valuebuffer_manager.h"
20 #include "gpu/gles2_conform_support/egl/config.h"
21 #include "gpu/gles2_conform_support/egl/surface.h"
24 const int32 kCommandBufferSize
= 1024 * 1024;
25 const int32 kTransferBufferSize
= 512 * 1024;
30 Display::Display(EGLNativeDisplayType display_id
)
31 : display_id_(display_id
),
32 is_initialized_(false),
33 #if defined(COMMAND_BUFFER_GLES_LIB_SUPPORT_ONLY)
34 exit_manager_(new base::AtExitManager
),
36 create_offscreen_(false),
37 create_offscreen_width_(0),
38 create_offscreen_height_(0) {
45 bool Display::Initialize() {
47 is_initialized_
= true;
51 bool Display::IsValidConfig(EGLConfig config
) {
52 return (config
!= NULL
) && (config
== config_
.get());
55 bool Display::ChooseConfigs(EGLConfig
* configs
,
58 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
59 // does not support finding or choosing configs.
61 if (configs
!= NULL
) {
62 if (config_
== NULL
) {
63 config_
.reset(new Config
);
65 configs
[0] = config_
.get();
70 bool Display::GetConfigs(EGLConfig
* configs
,
73 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
74 // does not support finding or choosing configs.
76 if (configs
!= NULL
) {
77 if (config_
== NULL
) {
78 config_
.reset(new Config
);
80 configs
[0] = config_
.get();
85 bool Display::GetConfigAttrib(EGLConfig config
,
88 const egl::Config
* cfg
= static_cast<egl::Config
*>(config
);
89 return cfg
->GetAttrib(attribute
, value
);
92 bool Display::IsValidNativeWindow(EGLNativeWindowType win
) {
94 return ::IsWindow(win
) != FALSE
;
96 // TODO(alokp): Validate window handle.
101 bool Display::IsValidSurface(EGLSurface surface
) {
102 return (surface
!= NULL
) && (surface
== surface_
.get());
105 EGLSurface
Display::CreateWindowSurface(EGLConfig config
,
106 EGLNativeWindowType win
,
107 const EGLint
* attrib_list
) {
108 if (surface_
!= NULL
) {
109 // We do not support more than one window surface.
110 return EGL_NO_SURFACE
;
114 gpu::TransferBufferManager
* manager
=
115 new gpu::TransferBufferManager(nullptr);
116 transfer_buffer_manager_
= manager
;
117 manager
->Initialize();
119 scoped_ptr
<gpu::CommandBufferService
> command_buffer(
120 new gpu::CommandBufferService(transfer_buffer_manager_
.get()));
121 if (!command_buffer
->Initialize())
124 scoped_refptr
<gpu::gles2::ContextGroup
> group(new gpu::gles2::ContextGroup(
125 NULL
, NULL
, new gpu::gles2::ShaderTranslatorCache
,
126 new gpu::gles2::FramebufferCompletenessCache
, NULL
, NULL
, NULL
, true));
128 decoder_
.reset(gpu::gles2::GLES2Decoder::Create(group
.get()));
130 return EGL_NO_SURFACE
;
132 gpu_scheduler_
.reset(new gpu::GpuScheduler(command_buffer
.get(),
136 decoder_
->set_engine(gpu_scheduler_
.get());
137 gfx::Size
size(create_offscreen_width_
, create_offscreen_height_
);
138 if (create_offscreen_
) {
139 gl_surface_
= gfx::GLSurface::CreateOffscreenGLSurface(size
);
140 create_offscreen_
= false;
141 create_offscreen_width_
= 0;
142 create_offscreen_height_
= 0;
144 gl_surface_
= gfx::GLSurface::CreateViewGLSurface(win
);
146 if (!gl_surface_
.get())
147 return EGL_NO_SURFACE
;
149 gl_context_
= gfx::GLContext::CreateGLContext(NULL
,
151 gfx::PreferDiscreteGpu
);
152 if (!gl_context_
.get())
153 return EGL_NO_SURFACE
;
155 gl_context_
->MakeCurrent(gl_surface_
.get());
157 EGLint depth_size
= 0;
158 EGLint alpha_size
= 0;
159 EGLint stencil_size
= 0;
160 GetConfigAttrib(config
, EGL_DEPTH_SIZE
, &depth_size
);
161 GetConfigAttrib(config
, EGL_ALPHA_SIZE
, &alpha_size
);
162 GetConfigAttrib(config
, EGL_STENCIL_SIZE
, &stencil_size
);
163 std::vector
<int32
> attribs
;
164 attribs
.push_back(EGL_DEPTH_SIZE
);
165 attribs
.push_back(depth_size
);
166 attribs
.push_back(EGL_ALPHA_SIZE
);
167 attribs
.push_back(alpha_size
);
168 attribs
.push_back(EGL_STENCIL_SIZE
);
169 attribs
.push_back(stencil_size
);
170 // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null
171 attribs
.push_back(EGL_NONE
);
173 if (!decoder_
->Initialize(gl_surface_
.get(),
175 gl_surface_
->IsOffscreen(),
177 gpu::gles2::DisallowedFeatures(),
179 return EGL_NO_SURFACE
;
182 command_buffer
->SetPutOffsetChangeCallback(
183 base::Bind(&gpu::GpuScheduler::PutChanged
,
184 base::Unretained(gpu_scheduler_
.get())));
185 command_buffer
->SetGetBufferChangeCallback(
186 base::Bind(&gpu::GpuScheduler::SetGetBuffer
,
187 base::Unretained(gpu_scheduler_
.get())));
189 scoped_ptr
<gpu::gles2::GLES2CmdHelper
> cmd_helper(
190 new gpu::gles2::GLES2CmdHelper(command_buffer
.get()));
191 if (!cmd_helper
->Initialize(kCommandBufferSize
))
194 scoped_ptr
<gpu::TransferBuffer
> transfer_buffer(new gpu::TransferBuffer(
197 command_buffer_
.reset(command_buffer
.release());
198 transfer_buffer_
.reset(transfer_buffer
.release());
199 gles2_cmd_helper_
.reset(cmd_helper
.release());
200 surface_
.reset(new Surface(win
));
202 return surface_
.get();
205 void Display::DestroySurface(EGLSurface surface
) {
206 DCHECK(IsValidSurface(surface
));
207 gpu_scheduler_
.reset();
208 if (decoder_
.get()) {
209 decoder_
->Destroy(true);
217 void Display::SwapBuffers(EGLSurface surface
) {
218 DCHECK(IsValidSurface(surface
));
219 context_
->SwapBuffers();
222 bool Display::IsValidContext(EGLContext ctx
) {
223 return (ctx
!= NULL
) && (ctx
== context_
.get());
226 EGLContext
Display::CreateContext(EGLConfig config
,
227 EGLContext share_ctx
,
228 const EGLint
* attrib_list
) {
229 DCHECK(IsValidConfig(config
));
230 // TODO(alokp): Add support for shared contexts.
231 if (share_ctx
!= NULL
)
232 return EGL_NO_CONTEXT
;
234 DCHECK(command_buffer_
!= NULL
);
235 DCHECK(transfer_buffer_
.get());
237 bool bind_generates_resources
= true;
238 bool lose_context_when_out_of_memory
= false;
239 bool support_client_side_arrays
= true;
242 new gpu::gles2::GLES2Implementation(gles2_cmd_helper_
.get(),
244 transfer_buffer_
.get(),
245 bind_generates_resources
,
246 lose_context_when_out_of_memory
,
247 support_client_side_arrays
,
250 if (!context_
->Initialize(
252 kTransferBufferSize
/ 2,
253 kTransferBufferSize
* 2,
254 gpu::gles2::GLES2Implementation::kNoLimit
)) {
255 return EGL_NO_CONTEXT
;
258 context_
->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
259 context_
->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
261 return context_
.get();
264 void Display::DestroyContext(EGLContext ctx
) {
265 DCHECK(IsValidContext(ctx
));
267 transfer_buffer_
.reset();
270 bool Display::MakeCurrent(EGLSurface draw
, EGLSurface read
, EGLContext ctx
) {
271 if (ctx
== EGL_NO_CONTEXT
) {
272 gles2::SetGLContext(NULL
);
274 DCHECK(IsValidSurface(draw
));
275 DCHECK(IsValidSurface(read
));
276 DCHECK(IsValidContext(ctx
));
277 gles2::SetGLContext(context_
.get());
282 gpu::Capabilities
Display::GetCapabilities() {
283 return decoder_
->GetCapabilities();
286 int32_t Display::CreateImage(ClientBuffer buffer
,
289 unsigned internalformat
) {
294 void Display::DestroyImage(int32 id
) {
298 int32_t Display::CreateGpuMemoryBufferImage(size_t width
,
300 unsigned internalformat
,
306 uint32
Display::InsertSyncPoint() {
311 uint32
Display::InsertFutureSyncPoint() {
316 void Display::RetireSyncPoint(uint32 sync_point
) {
320 void Display::SignalSyncPoint(uint32 sync_point
,
321 const base::Closure
& callback
) {
325 void Display::SignalQuery(uint32 query
, const base::Closure
& callback
) {
329 void Display::SetSurfaceVisible(bool visible
) {
333 uint32
Display::CreateStreamTexture(uint32 texture_id
) {
338 void Display::SetLock(base::Lock
*) {
342 bool Display::IsGpuChannelLost() {
347 gpu::CommandBufferNamespace
Display::GetNamespaceID() const {
348 return gpu::CommandBufferNamespace::IN_PROCESS
;
351 uint64_t Display::GetCommandBufferID() const {