- add sources.
[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 <vector>
8
9 #include "base/at_exit.h"
10 #include "base/bind.h"
11 #include "gpu/command_buffer/client/gles2_implementation.h"
12 #include "gpu/command_buffer/client/gles2_lib.h"
13 #include "gpu/command_buffer/client/transfer_buffer.h"
14 #include "gpu/command_buffer/common/constants.h"
15 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
16 #include "gpu/command_buffer/service/command_buffer_service.h"
17 #include "gpu/command_buffer/service/context_group.h"
18 #include "gpu/command_buffer/service/gl_context_virtual.h"
19 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
20 #include "gpu/command_buffer/service/gpu_control_service.h"
21 #include "gpu/command_buffer/service/gpu_scheduler.h"
22 #include "gpu/command_buffer/service/image_manager.h"
23 #include "gpu/command_buffer/service/mailbox_manager.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/gl/gl_context.h"
26 #include "ui/gl/gl_share_group.h"
27 #include "ui/gl/gl_surface.h"
28
29 namespace gpu {
30
31 int GLManager::use_count_;
32 scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_;
33 scoped_refptr<gfx::GLSurface>* GLManager::base_surface_;
34 scoped_refptr<gfx::GLContext>* GLManager::base_context_;
35
36 GLManager::Options::Options()
37     : size(4, 4),
38       share_group_manager(NULL),
39       share_mailbox_manager(NULL),
40       virtual_manager(NULL),
41       bind_generates_resource(false),
42       context_lost_allowed(false),
43       image_manager(NULL) {
44 }
45
46 GLManager::GLManager()
47     : context_lost_allowed_(false) {
48   SetupBaseContext();
49 }
50
51 GLManager::~GLManager() {
52   --use_count_;
53   if (!use_count_) {
54     if (base_share_group_) {
55       delete base_context_;
56       base_context_ = NULL;
57     }
58     if (base_surface_) {
59       delete base_surface_;
60       base_surface_ = NULL;
61     }
62     if (base_context_) {
63       delete base_context_;
64       base_context_ = NULL;
65     }
66   }
67 }
68
69 void GLManager::Initialize(const GLManager::Options& options) {
70   const int32 kCommandBufferSize = 1024 * 1024;
71   const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
72   const size_t kMinTransferBufferSize = 1 * 256 * 1024;
73   const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
74
75   context_lost_allowed_ = options.context_lost_allowed;
76
77   gles2::MailboxManager* mailbox_manager = NULL;
78   if (options.share_mailbox_manager) {
79     mailbox_manager = options.share_mailbox_manager->mailbox_manager();
80   } else if (options.share_group_manager) {
81     mailbox_manager = options.share_group_manager->mailbox_manager();
82   }
83
84   gfx::GLShareGroup* share_group = NULL;
85   if (options.share_group_manager) {
86     share_group = options.share_group_manager->share_group();
87   } else if (options.share_mailbox_manager) {
88     share_group = options.share_mailbox_manager->share_group();
89   }
90
91   gles2::ContextGroup* context_group = NULL;
92   gles2::ShareGroup* client_share_group = NULL;
93   if (options.share_group_manager) {
94     context_group = options.share_group_manager->decoder_->GetContextGroup();
95     client_share_group =
96       options.share_group_manager->gles2_implementation()->share_group();
97   }
98
99   gfx::GLContext* real_gl_context = NULL;
100   if (options.virtual_manager) {
101     real_gl_context = options.virtual_manager->context();
102   }
103
104   mailbox_manager_ =
105       mailbox_manager ? mailbox_manager : new gles2::MailboxManager;
106   share_group_ =
107       share_group ? share_group : new gfx::GLShareGroup;
108
109   gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
110   std::vector<int32> attribs;
111   gles2::ContextCreationAttribHelper attrib_helper;
112   attrib_helper.red_size_ = 8;
113   attrib_helper.green_size_ = 8;
114   attrib_helper.blue_size_ = 8;
115   attrib_helper.alpha_size_ = 8;
116   attrib_helper.depth_size_ = 16;
117   attrib_helper.Serialize(&attribs);
118
119   if (!context_group) {
120     context_group = new gles2::ContextGroup(mailbox_manager_.get(),
121                                             options.image_manager,
122                                             NULL,
123                                             NULL,
124                                             options.bind_generates_resource);
125   }
126
127   decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group));
128
129   command_buffer_.reset(new CommandBufferService(
130       decoder_->GetContextGroup()->transfer_buffer_manager()));
131   ASSERT_TRUE(command_buffer_->Initialize())
132       << "could not create command buffer service";
133
134   gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
135                                         decoder_.get(),
136                                         decoder_.get()));
137
138   decoder_->set_engine(gpu_scheduler_.get());
139
140   surface_ = gfx::GLSurface::CreateOffscreenGLSurface(options.size);
141   ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface";
142
143   if (real_gl_context) {
144     context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
145         share_group_.get(), real_gl_context, decoder_->AsWeakPtr()));
146     ASSERT_TRUE(context_->Initialize(
147         surface_.get(), gfx::PreferIntegratedGpu));
148   } else {
149     if (base_context_) {
150       context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
151           share_group_.get(), base_context_->get(), decoder_->AsWeakPtr()));
152       ASSERT_TRUE(context_->Initialize(
153           surface_.get(), gfx::PreferIntegratedGpu));
154     } else {
155       context_ = gfx::GLContext::CreateGLContext(share_group_.get(),
156                                                  surface_.get(),
157                                                  gpu_preference);
158     }
159   }
160   ASSERT_TRUE(context_.get() != NULL) << "could not create GL context";
161
162   ASSERT_TRUE(context_->MakeCurrent(surface_.get()));
163
164   ASSERT_TRUE(decoder_->Initialize(
165       surface_.get(),
166       context_.get(),
167       true,
168       options.size,
169       ::gpu::gles2::DisallowedFeatures(),
170       attribs)) << "could not initialize decoder";
171
172   gpu_control_.reset(
173       new GpuControlService(decoder_->GetContextGroup()->image_manager(),
174                             options.gpu_memory_buffer_factory,
175                             decoder_->GetContextGroup()->mailbox_manager(),
176                             decoder_->GetQueryManager()));
177
178   command_buffer_->SetPutOffsetChangeCallback(
179       base::Bind(&GLManager::PumpCommands, base::Unretained(this)));
180   command_buffer_->SetGetBufferChangeCallback(
181       base::Bind(&GLManager::GetBufferChanged, base::Unretained(this)));
182
183   // Create the GLES2 helper, which writes the command buffer protocol.
184   gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
185   ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize));
186
187   // Create a transfer buffer.
188   transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
189
190   // Create the object exposing the OpenGL API.
191   gles2_implementation_.reset(new gles2::GLES2Implementation(
192       gles2_helper_.get(),
193       client_share_group,
194       transfer_buffer_.get(),
195       options.bind_generates_resource,
196       gpu_control_.get()));
197
198   ASSERT_TRUE(gles2_implementation_->Initialize(
199       kStartTransferBufferSize,
200       kMinTransferBufferSize,
201       kMaxTransferBufferSize,
202       gpu::gles2::GLES2Implementation::kNoLimit))
203           << "Could not init GLES2Implementation";
204
205   MakeCurrent();
206 }
207
208 void GLManager::SetupBaseContext() {
209   if (use_count_) {
210     #if defined(OS_ANDROID)
211       base_share_group_ = new scoped_refptr<gfx::GLShareGroup>(
212           new gfx::GLShareGroup);
213       gfx::Size size(4, 4);
214       base_surface_ = new scoped_refptr<gfx::GLSurface>(
215           gfx::GLSurface::CreateOffscreenGLSurface(size));
216       gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
217       base_context_ = new scoped_refptr<gfx::GLContext>(
218           gfx::GLContext::CreateGLContext(base_share_group_->get(),
219                                           base_surface_->get(),
220                                           gpu_preference));
221     #endif
222   }
223   ++use_count_;
224 }
225
226 void GLManager::MakeCurrent() {
227   ::gles2::SetGLContext(gles2_implementation_.get());
228 }
229
230 void GLManager::SetSurface(gfx::GLSurface* surface) {
231   decoder_->SetSurface(surface);
232 }
233
234 void GLManager::Destroy() {
235   if (gles2_implementation_.get()) {
236     MakeCurrent();
237     EXPECT_TRUE(glGetError() == GL_NONE);
238     gles2_implementation_->Flush();
239     gles2_implementation_.reset();
240   }
241   transfer_buffer_.reset();
242   gles2_helper_.reset();
243   command_buffer_.reset();
244   if (decoder_.get()) {
245     decoder_->MakeCurrent();
246     decoder_->Destroy(true);
247     decoder_.reset();
248   }
249 }
250
251 const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const {
252   return decoder_->GetContextGroup()->feature_info()->workarounds();
253 }
254
255 void GLManager::PumpCommands() {
256   decoder_->MakeCurrent();
257   gpu_scheduler_->PutChanged();
258   ::gpu::CommandBuffer::State state = command_buffer_->GetState();
259   if (!context_lost_allowed_) {
260     ASSERT_EQ(::gpu::error::kNoError, state.error);
261   }
262 }
263
264 bool GLManager::GetBufferChanged(int32 transfer_buffer_id) {
265   return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
266 }
267
268 }  // namespace gpu