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