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"
9 #include "base/bind_helpers.h"
10 #include "gpu/command_buffer/client/gles2_implementation.h"
11 #include "gpu/command_buffer/client/gles2_lib.h"
12 #include "gpu/command_buffer/client/transfer_buffer.h"
13 #include "gpu/command_buffer/service/context_group.h"
14 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
15 #include "gpu/gles2_conform_support/egl/config.h"
16 #include "gpu/gles2_conform_support/egl/surface.h"
19 const int32 kCommandBufferSize
= 1024 * 1024;
20 const int32 kTransferBufferSize
= 512 * 1024;
25 Display::Display(EGLNativeDisplayType display_id
)
26 : display_id_(display_id
),
27 is_initialized_(false),
28 create_offscreen_(false),
29 create_offscreen_width_(0),
30 create_offscreen_height_(0) {
37 bool Display::Initialize() {
39 is_initialized_
= true;
43 bool Display::IsValidConfig(EGLConfig config
) {
44 return (config
!= NULL
) && (config
== config_
.get());
47 bool Display::ChooseConfigs(EGLConfig
* configs
,
50 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
51 // does not support finding or choosing configs.
53 if (configs
!= NULL
) {
54 if (config_
== NULL
) {
55 config_
.reset(new Config
);
57 configs
[0] = config_
.get();
62 bool Display::GetConfigs(EGLConfig
* configs
,
65 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
66 // does not support finding or choosing configs.
68 if (configs
!= NULL
) {
69 if (config_
== NULL
) {
70 config_
.reset(new Config
);
72 configs
[0] = config_
.get();
77 bool Display::GetConfigAttrib(EGLConfig config
,
80 const egl::Config
* cfg
= static_cast<egl::Config
*>(config
);
81 return cfg
->GetAttrib(attribute
, value
);
84 bool Display::IsValidNativeWindow(EGLNativeWindowType win
) {
86 return ::IsWindow(win
) != FALSE
;
88 // TODO(alokp): Validate window handle.
93 bool Display::IsValidSurface(EGLSurface surface
) {
94 return (surface
!= NULL
) && (surface
== surface_
.get());
97 EGLSurface
Display::CreateWindowSurface(EGLConfig config
,
98 EGLNativeWindowType win
,
99 const EGLint
* attrib_list
) {
100 if (surface_
!= NULL
) {
101 // We do not support more than one window surface.
102 return EGL_NO_SURFACE
;
106 gpu::TransferBufferManager
* manager
= new gpu::TransferBufferManager();
107 transfer_buffer_manager_
.reset(manager
);
108 manager
->Initialize();
110 scoped_ptr
<gpu::CommandBufferService
> command_buffer(
111 new gpu::CommandBufferService(transfer_buffer_manager_
.get()));
112 if (!command_buffer
->Initialize())
115 scoped_refptr
<gpu::gles2::ContextGroup
> group(new gpu::gles2::ContextGroup(
116 NULL
, NULL
, new gpu::gles2::ShaderTranslatorCache
, NULL
, true));
118 decoder_
.reset(gpu::gles2::GLES2Decoder::Create(group
.get()));
120 return EGL_NO_SURFACE
;
122 gpu_scheduler_
.reset(new gpu::GpuScheduler(command_buffer
.get(),
126 decoder_
->set_engine(gpu_scheduler_
.get());
127 gfx::Size
size(create_offscreen_width_
, create_offscreen_height_
);
128 if (create_offscreen_
) {
129 gl_surface_
= gfx::GLSurface::CreateOffscreenGLSurface(size
);
130 create_offscreen_
= false;
131 create_offscreen_width_
= 0;
132 create_offscreen_height_
= 0;
134 gl_surface_
= gfx::GLSurface::CreateViewGLSurface(win
);
136 if (!gl_surface_
.get())
137 return EGL_NO_SURFACE
;
139 gl_context_
= gfx::GLContext::CreateGLContext(NULL
,
141 gfx::PreferDiscreteGpu
);
142 if (!gl_context_
.get())
143 return EGL_NO_SURFACE
;
145 gl_context_
->MakeCurrent(gl_surface_
.get());
147 EGLint depth_size
= 0;
148 EGLint alpha_size
= 0;
149 EGLint stencil_size
= 0;
150 GetConfigAttrib(config
, EGL_DEPTH_SIZE
, &depth_size
);
151 GetConfigAttrib(config
, EGL_ALPHA_SIZE
, &alpha_size
);
152 GetConfigAttrib(config
, EGL_STENCIL_SIZE
, &stencil_size
);
153 std::vector
<int32
> attribs
;
154 attribs
.push_back(EGL_DEPTH_SIZE
);
155 attribs
.push_back(depth_size
);
156 attribs
.push_back(EGL_ALPHA_SIZE
);
157 attribs
.push_back(alpha_size
);
158 attribs
.push_back(EGL_STENCIL_SIZE
);
159 attribs
.push_back(stencil_size
);
160 // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null
161 attribs
.push_back(EGL_NONE
);
163 if (!decoder_
->Initialize(gl_surface_
.get(),
165 gl_surface_
->IsOffscreen(),
167 gpu::gles2::DisallowedFeatures(),
169 return EGL_NO_SURFACE
;
172 command_buffer
->SetPutOffsetChangeCallback(
173 base::Bind(&gpu::GpuScheduler::PutChanged
,
174 base::Unretained(gpu_scheduler_
.get())));
175 command_buffer
->SetGetBufferChangeCallback(
176 base::Bind(&gpu::GpuScheduler::SetGetBuffer
,
177 base::Unretained(gpu_scheduler_
.get())));
179 scoped_ptr
<gpu::gles2::GLES2CmdHelper
> cmd_helper(
180 new gpu::gles2::GLES2CmdHelper(command_buffer
.get()));
181 if (!cmd_helper
->Initialize(kCommandBufferSize
))
184 scoped_ptr
<gpu::TransferBuffer
> transfer_buffer(new gpu::TransferBuffer(
187 command_buffer_
.reset(command_buffer
.release());
188 transfer_buffer_
.reset(transfer_buffer
.release());
189 gles2_cmd_helper_
.reset(cmd_helper
.release());
190 surface_
.reset(new Surface(win
));
192 return surface_
.get();
195 void Display::DestroySurface(EGLSurface surface
) {
196 DCHECK(IsValidSurface(surface
));
197 gpu_scheduler_
.reset();
198 if (decoder_
.get()) {
199 decoder_
->Destroy(true);
207 void Display::SwapBuffers(EGLSurface surface
) {
208 DCHECK(IsValidSurface(surface
));
209 context_
->SwapBuffers();
212 bool Display::IsValidContext(EGLContext ctx
) {
213 return (ctx
!= NULL
) && (ctx
== context_
.get());
216 EGLContext
Display::CreateContext(EGLConfig config
,
217 EGLContext share_ctx
,
218 const EGLint
* attrib_list
) {
219 DCHECK(IsValidConfig(config
));
220 // TODO(alokp): Add support for shared contexts.
221 if (share_ctx
!= NULL
)
222 return EGL_NO_CONTEXT
;
224 DCHECK(command_buffer_
!= NULL
);
225 DCHECK(transfer_buffer_
.get());
227 bool bind_generates_resources
= true;
228 bool lose_context_when_out_of_memory
= false;
231 new gpu::gles2::GLES2Implementation(gles2_cmd_helper_
.get(),
233 transfer_buffer_
.get(),
234 bind_generates_resources
,
235 lose_context_when_out_of_memory
,
238 if (!context_
->Initialize(
240 kTransferBufferSize
/ 2,
241 kTransferBufferSize
* 2,
242 gpu::gles2::GLES2Implementation::kNoLimit
)) {
243 return EGL_NO_CONTEXT
;
246 context_
->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
247 context_
->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
249 return context_
.get();
252 void Display::DestroyContext(EGLContext ctx
) {
253 DCHECK(IsValidContext(ctx
));
255 transfer_buffer_
.reset();
258 bool Display::MakeCurrent(EGLSurface draw
, EGLSurface read
, EGLContext ctx
) {
259 if (ctx
== EGL_NO_CONTEXT
) {
260 gles2::SetGLContext(NULL
);
262 DCHECK(IsValidSurface(draw
));
263 DCHECK(IsValidSurface(read
));
264 DCHECK(IsValidContext(ctx
));
265 gles2::SetGLContext(context_
.get());
270 gpu::Capabilities
Display::GetCapabilities() {
271 return decoder_
->GetCapabilities();
274 gfx::GpuMemoryBuffer
* Display::CreateGpuMemoryBuffer(
277 unsigned internalformat
,
284 void Display::DestroyGpuMemoryBuffer(int32 id
) {
288 uint32
Display::InsertSyncPoint() {
293 uint32
Display::InsertFutureSyncPoint() {
298 void Display::RetireSyncPoint(uint32 sync_point
) {
302 void Display::SignalSyncPoint(uint32 sync_point
,
303 const base::Closure
& callback
) {
307 void Display::SignalQuery(uint32 query
, const base::Closure
& callback
) {
311 void Display::SetSurfaceVisible(bool visible
) {
315 void Display::Echo(const base::Closure
& callback
) {
319 uint32
Display::CreateStreamTexture(uint32 texture_id
) {