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, 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 gpu_control_service_.reset(new gpu::GpuControlService(NULL, NULL));
174 command_buffer->SetPutOffsetChangeCallback(
175 base::Bind(&gpu::GpuScheduler::PutChanged,
176 base::Unretained(gpu_scheduler_.get())));
177 command_buffer->SetGetBufferChangeCallback(
178 base::Bind(&gpu::GpuScheduler::SetGetBuffer,
179 base::Unretained(gpu_scheduler_.get())));
181 scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper(
182 new gpu::gles2::GLES2CmdHelper(command_buffer.get()));
183 if (!cmd_helper->Initialize(kCommandBufferSize))
186 scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer(
189 command_buffer_.reset(command_buffer.release());
190 transfer_buffer_.reset(transfer_buffer.release());
191 gles2_cmd_helper_.reset(cmd_helper.release());
192 surface_.reset(new Surface(win));
194 return surface_.get();
197 void Display::DestroySurface(EGLSurface surface) {
198 DCHECK(IsValidSurface(surface));
199 gpu_scheduler_.reset();
200 if (decoder_.get()) {
201 decoder_->Destroy(true);
209 void Display::SwapBuffers(EGLSurface surface) {
210 DCHECK(IsValidSurface(surface));
211 context_->SwapBuffers();
214 bool Display::IsValidContext(EGLContext ctx) {
215 return (ctx != NULL) && (ctx == context_.get());
218 EGLContext Display::CreateContext(EGLConfig config,
219 EGLContext share_ctx,
220 const EGLint* attrib_list) {
221 DCHECK(IsValidConfig(config));
222 // TODO(alokp): Add support for shared contexts.
223 if (share_ctx != NULL)
224 return EGL_NO_CONTEXT;
226 DCHECK(command_buffer_ != NULL);
227 DCHECK(transfer_buffer_.get());
229 bool bind_generates_resources = true;
230 bool lose_context_when_out_of_memory = false;
233 new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(),
235 transfer_buffer_.get(),
236 bind_generates_resources,
237 lose_context_when_out_of_memory,
240 if (!context_->Initialize(
242 kTransferBufferSize / 2,
243 kTransferBufferSize * 2,
244 gpu::gles2::GLES2Implementation::kNoLimit)) {
245 return EGL_NO_CONTEXT;
248 context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
249 context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
251 return context_.get();
254 void Display::DestroyContext(EGLContext ctx) {
255 DCHECK(IsValidContext(ctx));
257 transfer_buffer_.reset();
260 bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) {
261 if (ctx == EGL_NO_CONTEXT) {
262 gles2::SetGLContext(NULL);
264 DCHECK(IsValidSurface(draw));
265 DCHECK(IsValidSurface(read));
266 DCHECK(IsValidContext(ctx));
267 gles2::SetGLContext(context_.get());
272 gpu::Capabilities Display::GetCapabilities() {
273 return decoder_->GetCapabilities();
276 gfx::GpuMemoryBuffer* Display::CreateGpuMemoryBuffer(
279 unsigned internalformat,
286 void Display::DestroyGpuMemoryBuffer(int32 id) {
290 uint32 Display::InsertSyncPoint() {
295 void Display::SignalSyncPoint(uint32 sync_point,
296 const base::Closure& callback) {
300 void Display::SignalQuery(uint32 query, const base::Closure& callback) {
304 void Display::SetSurfaceVisible(bool visible) {
308 void Display::SendManagedMemoryStats(const gpu::ManagedMemoryStats& stats) {
312 void Display::Echo(const base::Closure& callback) {
316 uint32 Display::CreateStreamTexture(uint32 texture_id) {