• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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