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/mailbox_manager.h"
15 #include "gpu/command_buffer/service/memory_tracking.h"
16 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
17 #include "gpu/gles2_conform_support/egl/config.h"
18 #include "gpu/gles2_conform_support/egl/surface.h"
21 const int32 kCommandBufferSize = 1024 * 1024;
22 const int32 kTransferBufferSize = 512 * 1024;
27 Display::Display(EGLNativeDisplayType display_id)
28 : display_id_(display_id),
29 is_initialized_(false),
30 create_offscreen_(false),
31 create_offscreen_width_(0),
32 create_offscreen_height_(0) {
39 bool Display::Initialize() {
41 is_initialized_ = true;
45 bool Display::IsValidConfig(EGLConfig config) {
46 return (config != NULL) && (config == config_.get());
49 bool Display::ChooseConfigs(EGLConfig* configs,
52 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
53 // does not support finding or choosing configs.
55 if (configs != NULL) {
56 if (config_ == NULL) {
57 config_.reset(new Config);
59 configs[0] = config_.get();
64 bool Display::GetConfigs(EGLConfig* configs,
67 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
68 // does not support finding or choosing configs.
70 if (configs != NULL) {
71 if (config_ == NULL) {
72 config_.reset(new Config);
74 configs[0] = config_.get();
79 bool Display::GetConfigAttrib(EGLConfig config,
82 const egl::Config* cfg = static_cast<egl::Config*>(config);
83 return cfg->GetAttrib(attribute, value);
86 bool Display::IsValidNativeWindow(EGLNativeWindowType win) {
88 return ::IsWindow(win) != FALSE;
90 // TODO(alokp): Validate window handle.
95 bool Display::IsValidSurface(EGLSurface surface) {
96 return (surface != NULL) && (surface == surface_.get());
99 EGLSurface Display::CreateWindowSurface(EGLConfig config,
100 EGLNativeWindowType win,
101 const EGLint* attrib_list) {
102 if (surface_ != NULL) {
103 // We do not support more than one window surface.
104 return EGL_NO_SURFACE;
108 gpu::TransferBufferManager* manager = new gpu::TransferBufferManager();
109 transfer_buffer_manager_.reset(manager);
110 manager->Initialize();
112 scoped_ptr<gpu::CommandBufferService> command_buffer(
113 new gpu::CommandBufferService(transfer_buffer_manager_.get()));
114 if (!command_buffer->Initialize())
117 scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
118 NULL, NULL, new gpu::gles2::ShaderTranslatorCache, NULL, true));
120 decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get()));
122 return EGL_NO_SURFACE;
124 gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(),
128 decoder_->set_engine(gpu_scheduler_.get());
129 gfx::Size size(create_offscreen_width_, create_offscreen_height_);
130 if (create_offscreen_) {
131 gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size);
132 create_offscreen_ = false;
133 create_offscreen_width_ = 0;
134 create_offscreen_height_ = 0;
136 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win);
138 if (!gl_surface_.get())
139 return EGL_NO_SURFACE;
141 gl_context_ = gfx::GLContext::CreateGLContext(NULL,
143 gfx::PreferDiscreteGpu);
144 if (!gl_context_.get())
145 return EGL_NO_SURFACE;
147 gl_context_->MakeCurrent(gl_surface_.get());
149 EGLint depth_size = 0;
150 EGLint alpha_size = 0;
151 EGLint stencil_size = 0;
152 GetConfigAttrib(config, EGL_DEPTH_SIZE, &depth_size);
153 GetConfigAttrib(config, EGL_ALPHA_SIZE, &alpha_size);
154 GetConfigAttrib(config, EGL_STENCIL_SIZE, &stencil_size);
155 std::vector<int32> attribs;
156 attribs.push_back(EGL_DEPTH_SIZE);
157 attribs.push_back(depth_size);
158 attribs.push_back(EGL_ALPHA_SIZE);
159 attribs.push_back(alpha_size);
160 attribs.push_back(EGL_STENCIL_SIZE);
161 attribs.push_back(stencil_size);
162 // TODO(gman): Insert attrib_list. Although ES 1.1 says it must be null
163 attribs.push_back(EGL_NONE);
165 if (!decoder_->Initialize(gl_surface_.get(),
167 gl_surface_->IsOffscreen(),
169 gpu::gles2::DisallowedFeatures(),
171 return EGL_NO_SURFACE;
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;
231 bool support_client_side_arrays = true;
234 new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(),
236 transfer_buffer_.get(),
237 bind_generates_resources,
238 lose_context_when_out_of_memory,
239 support_client_side_arrays,
242 if (!context_->Initialize(
244 kTransferBufferSize / 2,
245 kTransferBufferSize * 2,
246 gpu::gles2::GLES2Implementation::kNoLimit)) {
247 return EGL_NO_CONTEXT;
250 context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
251 context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
253 return context_.get();
256 void Display::DestroyContext(EGLContext ctx) {
257 DCHECK(IsValidContext(ctx));
259 transfer_buffer_.reset();
262 bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) {
263 if (ctx == EGL_NO_CONTEXT) {
264 gles2::SetGLContext(NULL);
266 DCHECK(IsValidSurface(draw));
267 DCHECK(IsValidSurface(read));
268 DCHECK(IsValidContext(ctx));
269 gles2::SetGLContext(context_.get());
274 gpu::Capabilities Display::GetCapabilities() {
275 return decoder_->GetCapabilities();
278 int32_t Display::CreateImage(ClientBuffer buffer,
281 unsigned internalformat) {
286 void Display::DestroyImage(int32 id) {
290 int32_t Display::CreateGpuMemoryBufferImage(size_t width,
292 unsigned internalformat,
298 uint32 Display::InsertSyncPoint() {
303 uint32 Display::InsertFutureSyncPoint() {
308 void Display::RetireSyncPoint(uint32 sync_point) {
312 void Display::SignalSyncPoint(uint32 sync_point,
313 const base::Closure& callback) {
317 void Display::SignalQuery(uint32 query, const base::Closure& callback) {
321 void Display::SetSurfaceVisible(bool visible) {
325 uint32 Display::CreateStreamTexture(uint32 texture_id) {