Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / tests / gl_manager.cc
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/command_buffer/tests/gl_manager.h"
6
7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h>
9 #include <GLES2/gl2extchromium.h>
10
11 #include <vector>
12
13 #include "base/at_exit.h"
14 #include "base/bind.h"
15 #include "base/memory/ref_counted_memory.h"
16 #include "gpu/command_buffer/client/gles2_implementation.h"
17 #include "gpu/command_buffer/client/gles2_lib.h"
18 #include "gpu/command_buffer/client/transfer_buffer.h"
19 #include "gpu/command_buffer/common/constants.h"
20 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
21 #include "gpu/command_buffer/service/command_buffer_service.h"
22 #include "gpu/command_buffer/service/context_group.h"
23 #include "gpu/command_buffer/service/gl_context_virtual.h"
24 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
25 #include "gpu/command_buffer/service/gpu_scheduler.h"
26 #include "gpu/command_buffer/service/image_manager.h"
27 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
28 #include "gpu/command_buffer/service/memory_tracking.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "ui/gfx/gpu_memory_buffer.h"
31 #include "ui/gl/gl_context.h"
32 #include "ui/gl/gl_image_ref_counted_memory.h"
33 #include "ui/gl/gl_share_group.h"
34 #include "ui/gl/gl_surface.h"
35
36 namespace gpu {
37 namespace {
38
39 size_t BytesPerPixel(gfx::GpuMemoryBuffer::Format format) {
40   switch (format) {
41     case gfx::GpuMemoryBuffer::RGBA_8888:
42     case gfx::GpuMemoryBuffer::BGRA_8888:
43       return 4;
44     case gfx::GpuMemoryBuffer::RGBX_8888:
45       NOTREACHED();
46       return 0;
47   }
48
49   NOTREACHED();
50   return 0;
51 }
52
53 class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
54  public:
55   GpuMemoryBufferImpl(base::RefCountedBytes* bytes,
56                       const gfx::Size& size,
57                       gfx::GpuMemoryBuffer::Format format)
58       : bytes_(bytes), size_(size), format_(format), mapped_(false) {}
59
60   static GpuMemoryBufferImpl* FromClientBuffer(ClientBuffer buffer) {
61     return reinterpret_cast<GpuMemoryBufferImpl*>(buffer);
62   }
63
64   // Overridden from gfx::GpuMemoryBuffer:
65   void* Map() override {
66     mapped_ = true;
67     return &bytes_->data().front();
68   }
69   void Unmap() override { mapped_ = false; }
70   bool IsMapped() const override { return mapped_; }
71   Format GetFormat() const override { return format_; }
72   uint32 GetStride() const override {
73     return size_.width() * BytesPerPixel(format_);
74   }
75   gfx::GpuMemoryBufferHandle GetHandle() const override {
76     NOTREACHED();
77     return gfx::GpuMemoryBufferHandle();
78   }
79   ClientBuffer AsClientBuffer() override {
80     return reinterpret_cast<ClientBuffer>(this);
81   }
82
83   base::RefCountedBytes* bytes() { return bytes_.get(); }
84
85  private:
86   scoped_refptr<base::RefCountedBytes> bytes_;
87   const gfx::Size size_;
88   gfx::GpuMemoryBuffer::Format format_;
89   bool mapped_;
90 };
91
92 }  // namespace
93
94 int GLManager::use_count_;
95 scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_;
96 scoped_refptr<gfx::GLSurface>* GLManager::base_surface_;
97 scoped_refptr<gfx::GLContext>* GLManager::base_context_;
98
99 GLManager::Options::Options()
100     : size(4, 4),
101       share_group_manager(NULL),
102       share_mailbox_manager(NULL),
103       virtual_manager(NULL),
104       bind_generates_resource(false),
105       lose_context_when_out_of_memory(false),
106       context_lost_allowed(false) {
107 }
108
109 GLManager::GLManager() : context_lost_allowed_(false) {
110   SetupBaseContext();
111 }
112
113 GLManager::~GLManager() {
114   --use_count_;
115   if (!use_count_) {
116     if (base_share_group_) {
117       delete base_context_;
118       base_context_ = NULL;
119     }
120     if (base_surface_) {
121       delete base_surface_;
122       base_surface_ = NULL;
123     }
124     if (base_context_) {
125       delete base_context_;
126       base_context_ = NULL;
127     }
128   }
129 }
130
131 // static
132 scoped_ptr<gfx::GpuMemoryBuffer> GLManager::CreateGpuMemoryBuffer(
133     const gfx::Size& size,
134     gfx::GpuMemoryBuffer::Format format) {
135   std::vector<unsigned char> data(size.GetArea() * BytesPerPixel(format), 0);
136   scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes(data));
137   return make_scoped_ptr<gfx::GpuMemoryBuffer>(
138       new GpuMemoryBufferImpl(bytes.get(), size, format));
139 }
140
141 void GLManager::Initialize(const GLManager::Options& options) {
142   const int32 kCommandBufferSize = 1024 * 1024;
143   const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
144   const size_t kMinTransferBufferSize = 1 * 256 * 1024;
145   const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
146
147   context_lost_allowed_ = options.context_lost_allowed;
148
149   gles2::MailboxManager* mailbox_manager = NULL;
150   if (options.share_mailbox_manager) {
151     mailbox_manager = options.share_mailbox_manager->mailbox_manager();
152   } else if (options.share_group_manager) {
153     mailbox_manager = options.share_group_manager->mailbox_manager();
154   }
155
156   gfx::GLShareGroup* share_group = NULL;
157   if (options.share_group_manager) {
158     share_group = options.share_group_manager->share_group();
159   } else if (options.share_mailbox_manager) {
160     share_group = options.share_mailbox_manager->share_group();
161   }
162
163   gles2::ContextGroup* context_group = NULL;
164   gles2::ShareGroup* client_share_group = NULL;
165   if (options.share_group_manager) {
166     context_group = options.share_group_manager->decoder_->GetContextGroup();
167     client_share_group =
168       options.share_group_manager->gles2_implementation()->share_group();
169   }
170
171   gfx::GLContext* real_gl_context = NULL;
172   if (options.virtual_manager) {
173     real_gl_context = options.virtual_manager->context();
174   }
175
176   mailbox_manager_ =
177       mailbox_manager ? mailbox_manager : new gles2::MailboxManagerImpl;
178   share_group_ =
179       share_group ? share_group : new gfx::GLShareGroup;
180
181   gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
182   std::vector<int32> attribs;
183   gles2::ContextCreationAttribHelper attrib_helper;
184   attrib_helper.red_size = 8;
185   attrib_helper.green_size = 8;
186   attrib_helper.blue_size = 8;
187   attrib_helper.alpha_size = 8;
188   attrib_helper.depth_size = 16;
189   attrib_helper.Serialize(&attribs);
190
191   if (!context_group) {
192     context_group =
193         new gles2::ContextGroup(mailbox_manager_.get(),
194                                 NULL,
195                                 new gpu::gles2::ShaderTranslatorCache,
196                                 NULL,
197                                 options.bind_generates_resource);
198   }
199
200   decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group));
201
202   command_buffer_.reset(new CommandBufferService(
203       decoder_->GetContextGroup()->transfer_buffer_manager()));
204   ASSERT_TRUE(command_buffer_->Initialize())
205       << "could not create command buffer service";
206
207   gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
208                                         decoder_.get(),
209                                         decoder_.get()));
210
211   decoder_->set_engine(gpu_scheduler_.get());
212
213   surface_ = gfx::GLSurface::CreateOffscreenGLSurface(options.size);
214   ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface";
215
216   if (base_context_) {
217     context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
218         share_group_.get(), base_context_->get(), decoder_->AsWeakPtr()));
219     ASSERT_TRUE(context_->Initialize(
220         surface_.get(), gfx::PreferIntegratedGpu));
221   } else {
222     if (real_gl_context) {
223       context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
224           share_group_.get(), real_gl_context, decoder_->AsWeakPtr()));
225       ASSERT_TRUE(context_->Initialize(
226           surface_.get(), gfx::PreferIntegratedGpu));
227     } else {
228       context_ = gfx::GLContext::CreateGLContext(share_group_.get(),
229                                                  surface_.get(),
230                                                  gpu_preference);
231     }
232   }
233   ASSERT_TRUE(context_.get() != NULL) << "could not create GL context";
234
235   ASSERT_TRUE(context_->MakeCurrent(surface_.get()));
236
237   ASSERT_TRUE(decoder_->Initialize(
238       surface_.get(),
239       context_.get(),
240       true,
241       options.size,
242       ::gpu::gles2::DisallowedFeatures(),
243       attribs)) << "could not initialize decoder";
244
245   command_buffer_->SetPutOffsetChangeCallback(
246       base::Bind(&GLManager::PumpCommands, base::Unretained(this)));
247   command_buffer_->SetGetBufferChangeCallback(
248       base::Bind(&GLManager::GetBufferChanged, base::Unretained(this)));
249
250   // Create the GLES2 helper, which writes the command buffer protocol.
251   gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
252   ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize));
253
254   // Create a transfer buffer.
255   transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
256
257   // Create the object exposing the OpenGL API.
258   const bool support_client_side_arrays = true;
259   gles2_implementation_.reset(
260       new gles2::GLES2Implementation(gles2_helper_.get(),
261                                      client_share_group,
262                                      transfer_buffer_.get(),
263                                      options.bind_generates_resource,
264                                      options.lose_context_when_out_of_memory,
265                                      support_client_side_arrays,
266                                      this));
267
268   ASSERT_TRUE(gles2_implementation_->Initialize(
269       kStartTransferBufferSize,
270       kMinTransferBufferSize,
271       kMaxTransferBufferSize,
272       gpu::gles2::GLES2Implementation::kNoLimit))
273           << "Could not init GLES2Implementation";
274
275   MakeCurrent();
276 }
277
278 void GLManager::SetupBaseContext() {
279   if (use_count_) {
280     #if defined(OS_ANDROID)
281       base_share_group_ = new scoped_refptr<gfx::GLShareGroup>(
282           new gfx::GLShareGroup);
283       gfx::Size size(4, 4);
284       base_surface_ = new scoped_refptr<gfx::GLSurface>(
285           gfx::GLSurface::CreateOffscreenGLSurface(size));
286       gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
287       base_context_ = new scoped_refptr<gfx::GLContext>(
288           gfx::GLContext::CreateGLContext(base_share_group_->get(),
289                                           base_surface_->get(),
290                                           gpu_preference));
291     #endif
292   }
293   ++use_count_;
294 }
295
296 void GLManager::MakeCurrent() {
297   ::gles2::SetGLContext(gles2_implementation_.get());
298 }
299
300 void GLManager::SetSurface(gfx::GLSurface* surface) {
301   decoder_->SetSurface(surface);
302 }
303
304 void GLManager::Destroy() {
305   if (gles2_implementation_.get()) {
306     MakeCurrent();
307     EXPECT_TRUE(glGetError() == GL_NONE);
308     gles2_implementation_->Flush();
309     gles2_implementation_.reset();
310   }
311   transfer_buffer_.reset();
312   gles2_helper_.reset();
313   command_buffer_.reset();
314   if (decoder_.get()) {
315     decoder_->MakeCurrent();
316     decoder_->Destroy(true);
317     decoder_.reset();
318   }
319 }
320
321 const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const {
322   return decoder_->GetContextGroup()->feature_info()->workarounds();
323 }
324
325 void GLManager::PumpCommands() {
326   decoder_->MakeCurrent();
327   gpu_scheduler_->PutChanged();
328   ::gpu::CommandBuffer::State state = command_buffer_->GetLastState();
329   if (!context_lost_allowed_) {
330     ASSERT_EQ(::gpu::error::kNoError, state.error);
331   }
332 }
333
334 bool GLManager::GetBufferChanged(int32 transfer_buffer_id) {
335   return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
336 }
337
338 Capabilities GLManager::GetCapabilities() {
339   return decoder_->GetCapabilities();
340 }
341
342 int32 GLManager::CreateImage(ClientBuffer buffer,
343                              size_t width,
344                              size_t height,
345                              unsigned internalformat) {
346   GpuMemoryBufferImpl* gpu_memory_buffer =
347       GpuMemoryBufferImpl::FromClientBuffer(buffer);
348
349   scoped_refptr<gfx::GLImageRefCountedMemory> image(
350       new gfx::GLImageRefCountedMemory(gfx::Size(width, height),
351                                        internalformat));
352   if (!image->Initialize(gpu_memory_buffer->bytes(),
353                          gpu_memory_buffer->GetFormat())) {
354     return -1;
355   }
356
357   static int32 next_id = 1;
358   int32 new_id = next_id++;
359
360   gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
361   DCHECK(image_manager);
362   image_manager->AddImage(image.get(), new_id);
363   return new_id;
364 }
365
366 int32 GLManager::CreateGpuMemoryBufferImage(size_t width,
367                                             size_t height,
368                                             unsigned internalformat,
369                                             unsigned usage) {
370   DCHECK_EQ(usage, static_cast<unsigned>(GL_MAP_CHROMIUM));
371   scoped_ptr<gfx::GpuMemoryBuffer> buffer = GLManager::CreateGpuMemoryBuffer(
372       gfx::Size(width, height), gfx::GpuMemoryBuffer::RGBA_8888);
373   return CreateImage(buffer->AsClientBuffer(), width, height, internalformat);
374 }
375
376 void GLManager::DestroyImage(int32 id) {
377   gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
378   DCHECK(image_manager);
379   image_manager->RemoveImage(id);
380 }
381
382 uint32 GLManager::InsertSyncPoint() {
383   NOTIMPLEMENTED();
384   return 0u;
385 }
386
387 uint32 GLManager::InsertFutureSyncPoint() {
388   NOTIMPLEMENTED();
389   return 0u;
390 }
391
392 void GLManager::RetireSyncPoint(uint32 sync_point) {
393   NOTIMPLEMENTED();
394 }
395
396 void GLManager::SignalSyncPoint(uint32 sync_point,
397                                 const base::Closure& callback) {
398   NOTIMPLEMENTED();
399 }
400
401 void GLManager::SignalQuery(uint32 query, const base::Closure& callback) {
402   NOTIMPLEMENTED();
403 }
404
405 void GLManager::SetSurfaceVisible(bool visible) {
406   NOTIMPLEMENTED();
407 }
408
409 uint32 GLManager::CreateStreamTexture(uint32 texture_id) {
410   NOTIMPLEMENTED();
411   return 0;
412 }
413
414 }  // namespace gpu