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.
4
5 #include "gpu/gles2_conform_support/egl/display.h"
6
7 #include <vector>
8 #include "base/bind.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"
19
20 namespace {
21 const int32 kCommandBufferSize = 1024 * 1024;
22 const int32 kTransferBufferSize = 512 * 1024;
23 }
24
25 namespace egl {
26
Display(EGLNativeDisplayType display_id)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) {
33 }
34
~Display()35 Display::~Display() {
36 gles2::Terminate();
37 }
38
Initialize()39 bool Display::Initialize() {
40 gles2::Initialize();
41 is_initialized_ = true;
42 return true;
43 }
44
IsValidConfig(EGLConfig config)45 bool Display::IsValidConfig(EGLConfig config) {
46 return (config != NULL) && (config == config_.get());
47 }
48
ChooseConfigs(EGLConfig * configs,EGLint config_size,EGLint * num_config)49 bool Display::ChooseConfigs(EGLConfig* configs,
50 EGLint config_size,
51 EGLint* num_config) {
52 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
53 // does not support finding or choosing configs.
54 *num_config = 1;
55 if (configs != NULL) {
56 if (config_ == NULL) {
57 config_.reset(new Config);
58 }
59 configs[0] = config_.get();
60 }
61 return true;
62 }
63
GetConfigs(EGLConfig * configs,EGLint config_size,EGLint * num_config)64 bool Display::GetConfigs(EGLConfig* configs,
65 EGLint config_size,
66 EGLint* num_config) {
67 // TODO(alokp): Find out a way to find all configs. CommandBuffer currently
68 // does not support finding or choosing configs.
69 *num_config = 1;
70 if (configs != NULL) {
71 if (config_ == NULL) {
72 config_.reset(new Config);
73 }
74 configs[0] = config_.get();
75 }
76 return true;
77 }
78
GetConfigAttrib(EGLConfig config,EGLint attribute,EGLint * value)79 bool Display::GetConfigAttrib(EGLConfig config,
80 EGLint attribute,
81 EGLint* value) {
82 const egl::Config* cfg = static_cast<egl::Config*>(config);
83 return cfg->GetAttrib(attribute, value);
84 }
85
IsValidNativeWindow(EGLNativeWindowType win)86 bool Display::IsValidNativeWindow(EGLNativeWindowType win) {
87 #if defined OS_WIN
88 return ::IsWindow(win) != FALSE;
89 #else
90 // TODO(alokp): Validate window handle.
91 return true;
92 #endif // OS_WIN
93 }
94
IsValidSurface(EGLSurface surface)95 bool Display::IsValidSurface(EGLSurface surface) {
96 return (surface != NULL) && (surface == surface_.get());
97 }
98
CreateWindowSurface(EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)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;
105 }
106
107 {
108 gpu::TransferBufferManager* manager = new gpu::TransferBufferManager();
109 transfer_buffer_manager_.reset(manager);
110 manager->Initialize();
111 }
112 scoped_ptr<gpu::CommandBufferService> command_buffer(
113 new gpu::CommandBufferService(transfer_buffer_manager_.get()));
114 if (!command_buffer->Initialize())
115 return NULL;
116
117 scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
118 NULL, NULL, new gpu::gles2::ShaderTranslatorCache, NULL, true));
119
120 decoder_.reset(gpu::gles2::GLES2Decoder::Create(group.get()));
121 if (!decoder_.get())
122 return EGL_NO_SURFACE;
123
124 gpu_scheduler_.reset(new gpu::GpuScheduler(command_buffer.get(),
125 decoder_.get(),
126 NULL));
127
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;
135 } else {
136 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(win);
137 }
138 if (!gl_surface_.get())
139 return EGL_NO_SURFACE;
140
141 gl_context_ = gfx::GLContext::CreateGLContext(NULL,
142 gl_surface_.get(),
143 gfx::PreferDiscreteGpu);
144 if (!gl_context_.get())
145 return EGL_NO_SURFACE;
146
147 gl_context_->MakeCurrent(gl_surface_.get());
148
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);
164
165 if (!decoder_->Initialize(gl_surface_.get(),
166 gl_context_.get(),
167 gl_surface_->IsOffscreen(),
168 size,
169 gpu::gles2::DisallowedFeatures(),
170 attribs)) {
171 return EGL_NO_SURFACE;
172 }
173
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())));
180
181 scoped_ptr<gpu::gles2::GLES2CmdHelper> cmd_helper(
182 new gpu::gles2::GLES2CmdHelper(command_buffer.get()));
183 if (!cmd_helper->Initialize(kCommandBufferSize))
184 return NULL;
185
186 scoped_ptr<gpu::TransferBuffer> transfer_buffer(new gpu::TransferBuffer(
187 cmd_helper.get()));
188
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));
193
194 return surface_.get();
195 }
196
DestroySurface(EGLSurface surface)197 void Display::DestroySurface(EGLSurface surface) {
198 DCHECK(IsValidSurface(surface));
199 gpu_scheduler_.reset();
200 if (decoder_.get()) {
201 decoder_->Destroy(true);
202 }
203 decoder_.reset();
204 gl_surface_ = NULL;
205 gl_context_ = NULL;
206 surface_.reset();
207 }
208
SwapBuffers(EGLSurface surface)209 void Display::SwapBuffers(EGLSurface surface) {
210 DCHECK(IsValidSurface(surface));
211 context_->SwapBuffers();
212 }
213
IsValidContext(EGLContext ctx)214 bool Display::IsValidContext(EGLContext ctx) {
215 return (ctx != NULL) && (ctx == context_.get());
216 }
217
CreateContext(EGLConfig config,EGLContext share_ctx,const EGLint * attrib_list)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;
225
226 DCHECK(command_buffer_ != NULL);
227 DCHECK(transfer_buffer_.get());
228
229 bool bind_generates_resources = true;
230 bool lose_context_when_out_of_memory = false;
231
232 context_.reset(
233 new gpu::gles2::GLES2Implementation(gles2_cmd_helper_.get(),
234 NULL,
235 transfer_buffer_.get(),
236 bind_generates_resources,
237 lose_context_when_out_of_memory,
238 this));
239
240 if (!context_->Initialize(
241 kTransferBufferSize,
242 kTransferBufferSize / 2,
243 kTransferBufferSize * 2,
244 gpu::gles2::GLES2Implementation::kNoLimit)) {
245 return EGL_NO_CONTEXT;
246 }
247
248 context_->EnableFeatureCHROMIUM("pepper3d_allow_buffers_on_multiple_targets");
249 context_->EnableFeatureCHROMIUM("pepper3d_support_fixed_attribs");
250
251 return context_.get();
252 }
253
DestroyContext(EGLContext ctx)254 void Display::DestroyContext(EGLContext ctx) {
255 DCHECK(IsValidContext(ctx));
256 context_.reset();
257 transfer_buffer_.reset();
258 }
259
MakeCurrent(EGLSurface draw,EGLSurface read,EGLContext ctx)260 bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) {
261 if (ctx == EGL_NO_CONTEXT) {
262 gles2::SetGLContext(NULL);
263 } else {
264 DCHECK(IsValidSurface(draw));
265 DCHECK(IsValidSurface(read));
266 DCHECK(IsValidContext(ctx));
267 gles2::SetGLContext(context_.get());
268 }
269 return true;
270 }
271
GetCapabilities()272 gpu::Capabilities Display::GetCapabilities() {
273 return decoder_->GetCapabilities();
274 }
275
CreateGpuMemoryBuffer(size_t width,size_t height,unsigned internalformat,unsigned usage,int32 * id)276 gfx::GpuMemoryBuffer* Display::CreateGpuMemoryBuffer(
277 size_t width,
278 size_t height,
279 unsigned internalformat,
280 unsigned usage,
281 int32* id) {
282 NOTIMPLEMENTED();
283 return NULL;
284 }
285
DestroyGpuMemoryBuffer(int32 id)286 void Display::DestroyGpuMemoryBuffer(int32 id) {
287 NOTIMPLEMENTED();
288 }
289
InsertSyncPoint()290 uint32 Display::InsertSyncPoint() {
291 NOTIMPLEMENTED();
292 return 0u;
293 }
294
InsertFutureSyncPoint()295 uint32 Display::InsertFutureSyncPoint() {
296 NOTIMPLEMENTED();
297 return 0u;
298 }
299
RetireSyncPoint(uint32 sync_point)300 void Display::RetireSyncPoint(uint32 sync_point) {
301 NOTIMPLEMENTED();
302 }
303
SignalSyncPoint(uint32 sync_point,const base::Closure & callback)304 void Display::SignalSyncPoint(uint32 sync_point,
305 const base::Closure& callback) {
306 NOTIMPLEMENTED();
307 }
308
SignalQuery(uint32 query,const base::Closure & callback)309 void Display::SignalQuery(uint32 query, const base::Closure& callback) {
310 NOTIMPLEMENTED();
311 }
312
SetSurfaceVisible(bool visible)313 void Display::SetSurfaceVisible(bool visible) {
314 NOTIMPLEMENTED();
315 }
316
Echo(const base::Closure & callback)317 void Display::Echo(const base::Closure& callback) {
318 NOTIMPLEMENTED();
319 }
320
CreateStreamTexture(uint32 texture_id)321 uint32 Display::CreateStreamTexture(uint32 texture_id) {
322 NOTIMPLEMENTED();
323 return 0;
324 }
325
326 } // namespace egl
327