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