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.
5 #include "gpu/command_buffer/tests/gl_manager.h"
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/service/command_buffer_service.h"
16 #include "gpu/command_buffer/service/context_group.h"
17 #include "gpu/command_buffer/service/gl_context_virtual.h"
18 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
19 #include "gpu/command_buffer/service/gpu_scheduler.h"
20 #include "gpu/command_buffer/service/image_manager.h"
21 #include "gpu/command_buffer/service/mailbox_manager.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gl/gl_context.h"
24 #include "ui/gl/gl_share_group.h"
25 #include "ui/gl/gl_surface.h"
29 int GLManager::use_count_
;
30 scoped_refptr
<gfx::GLShareGroup
>* GLManager::base_share_group_
;
31 scoped_refptr
<gfx::GLSurface
>* GLManager::base_surface_
;
32 scoped_refptr
<gfx::GLContext
>* GLManager::base_context_
;
34 GLManager::Options::Options()
36 share_group_manager(NULL
),
37 share_mailbox_manager(NULL
),
38 virtual_manager(NULL
),
39 bind_generates_resource(false),
40 context_lost_allowed(false),
45 GLManager::GLManager()
46 : context_lost_allowed_(false) {
50 GLManager::~GLManager() {
53 if (base_share_group_
) {
68 void GLManager::Initialize(const GLManager::Options
& options
) {
69 const int32 kCommandBufferSize
= 1024 * 1024;
70 const size_t kStartTransferBufferSize
= 4 * 1024 * 1024;
71 const size_t kMinTransferBufferSize
= 1 * 256 * 1024;
72 const size_t kMaxTransferBufferSize
= 16 * 1024 * 1024;
74 context_lost_allowed_
= options
.context_lost_allowed
;
76 gles2::MailboxManager
* mailbox_manager
= NULL
;
77 if (options
.share_mailbox_manager
) {
78 mailbox_manager
= options
.share_mailbox_manager
->mailbox_manager();
79 } else if (options
.share_group_manager
) {
80 mailbox_manager
= options
.share_group_manager
->mailbox_manager();
83 gfx::GLShareGroup
* share_group
= NULL
;
84 if (options
.share_group_manager
) {
85 share_group
= options
.share_group_manager
->share_group();
86 } else if (options
.share_mailbox_manager
) {
87 share_group
= options
.share_mailbox_manager
->share_group();
90 gles2::ContextGroup
* context_group
= NULL
;
91 gles2::ShareGroup
* client_share_group
= NULL
;
92 if (options
.share_group_manager
) {
93 context_group
= options
.share_group_manager
->decoder_
->GetContextGroup();
95 options
.share_group_manager
->gles2_implementation()->share_group();
98 gfx::GLContext
* real_gl_context
= NULL
;
99 if (options
.virtual_manager
) {
100 real_gl_context
= options
.virtual_manager
->context();
104 const int32 EGL_ALPHA_SIZE
= 0x3021;
105 const int32 EGL_BLUE_SIZE
= 0x3022;
106 const int32 EGL_GREEN_SIZE
= 0x3023;
107 const int32 EGL_RED_SIZE
= 0x3024;
108 const int32 EGL_DEPTH_SIZE
= 0x3025;
109 const int32 EGL_NONE
= 0x3038;
112 mailbox_manager
? mailbox_manager
: new gles2::MailboxManager
;
114 share_group
? share_group
: new gfx::GLShareGroup
;
116 gfx::GpuPreference
gpu_preference(gfx::PreferDiscreteGpu
);
117 const char* allowed_extensions
= "*";
118 std::vector
<int32
> attribs
;
119 attribs
.push_back(EGL_RED_SIZE
);
120 attribs
.push_back(8);
121 attribs
.push_back(EGL_GREEN_SIZE
);
122 attribs
.push_back(8);
123 attribs
.push_back(EGL_BLUE_SIZE
);
124 attribs
.push_back(8);
125 attribs
.push_back(EGL_ALPHA_SIZE
);
126 attribs
.push_back(8);
127 attribs
.push_back(EGL_DEPTH_SIZE
);
128 attribs
.push_back(16);
129 attribs
.push_back(EGL_NONE
);
131 if (!context_group
) {
132 context_group
= new gles2::ContextGroup(mailbox_manager_
.get(),
133 options
.image_manager
,
136 options
.bind_generates_resource
);
139 decoder_
.reset(::gpu::gles2::GLES2Decoder::Create(context_group
));
141 command_buffer_
.reset(new CommandBufferService(
142 decoder_
->GetContextGroup()->transfer_buffer_manager()));
143 ASSERT_TRUE(command_buffer_
->Initialize())
144 << "could not create command buffer service";
146 gpu_scheduler_
.reset(new GpuScheduler(command_buffer_
.get(),
150 decoder_
->set_engine(gpu_scheduler_
.get());
152 surface_
= gfx::GLSurface::CreateOffscreenGLSurface(options
.size
);
153 ASSERT_TRUE(surface_
.get() != NULL
) << "could not create offscreen surface";
155 if (real_gl_context
) {
156 context_
= scoped_refptr
<gfx::GLContext
>(new gpu::GLContextVirtual(
157 share_group_
.get(), real_gl_context
, decoder_
->AsWeakPtr()));
158 ASSERT_TRUE(context_
->Initialize(
159 surface_
.get(), gfx::PreferIntegratedGpu
));
162 context_
= scoped_refptr
<gfx::GLContext
>(new gpu::GLContextVirtual(
163 share_group_
.get(), base_context_
->get(), decoder_
->AsWeakPtr()));
164 ASSERT_TRUE(context_
->Initialize(
165 surface_
.get(), gfx::PreferIntegratedGpu
));
167 context_
= gfx::GLContext::CreateGLContext(share_group_
.get(),
172 ASSERT_TRUE(context_
.get() != NULL
) << "could not create GL context";
174 ASSERT_TRUE(context_
->MakeCurrent(surface_
.get()));
176 ASSERT_TRUE(decoder_
->Initialize(
181 ::gpu::gles2::DisallowedFeatures(),
183 attribs
)) << "could not initialize decoder";
185 command_buffer_
->SetPutOffsetChangeCallback(
186 base::Bind(&GLManager::PumpCommands
, base::Unretained(this)));
187 command_buffer_
->SetGetBufferChangeCallback(
188 base::Bind(&GLManager::GetBufferChanged
, base::Unretained(this)));
190 // Create the GLES2 helper, which writes the command buffer protocol.
191 gles2_helper_
.reset(new gles2::GLES2CmdHelper(command_buffer_
.get()));
192 ASSERT_TRUE(gles2_helper_
->Initialize(kCommandBufferSize
));
194 // Create a transfer buffer.
195 transfer_buffer_
.reset(new TransferBuffer(gles2_helper_
.get()));
197 // Create the object exposing the OpenGL API.
198 gles2_implementation_
.reset(new gles2::GLES2Implementation(
201 transfer_buffer_
.get(),
202 options
.bind_generates_resource
,
203 options
.image_factory
));
205 ASSERT_TRUE(gles2_implementation_
->Initialize(
206 kStartTransferBufferSize
,
207 kMinTransferBufferSize
,
208 kMaxTransferBufferSize
)) << "Could not init GLES2Implementation";
213 void GLManager::SetupBaseContext() {
215 #if defined(OS_ANDROID)
216 base_share_group_
= new scoped_refptr
<gfx::GLShareGroup
>(
217 new gfx::GLShareGroup
);
218 gfx::Size
size(4, 4);
219 base_surface_
= new scoped_refptr
<gfx::GLSurface
>(
220 gfx::GLSurface::CreateOffscreenGLSurface(size
));
221 gfx::GpuPreference
gpu_preference(gfx::PreferDiscreteGpu
);
222 base_context_
= new scoped_refptr
<gfx::GLContext
>(
223 gfx::GLContext::CreateGLContext(base_share_group_
->get(),
224 base_surface_
->get(),
231 void GLManager::MakeCurrent() {
232 ::gles2::SetGLContext(gles2_implementation_
.get());
235 void GLManager::SetSurface(gfx::GLSurface
* surface
) {
236 decoder_
->SetSurface(surface
);
239 void GLManager::Destroy() {
240 if (gles2_implementation_
.get()) {
242 EXPECT_TRUE(glGetError() == GL_NONE
);
243 gles2_implementation_
->Flush();
244 gles2_implementation_
.reset();
246 transfer_buffer_
.reset();
247 gles2_helper_
.reset();
248 command_buffer_
.reset();
249 if (decoder_
.get()) {
250 decoder_
->MakeCurrent();
251 decoder_
->Destroy(true);
256 const gpu::gles2::FeatureInfo::Workarounds
& GLManager::workarounds() const {
257 return decoder_
->GetContextGroup()->feature_info()->workarounds();
260 void GLManager::PumpCommands() {
261 decoder_
->MakeCurrent();
262 gpu_scheduler_
->PutChanged();
263 ::gpu::CommandBuffer::State state
= command_buffer_
->GetState();
264 if (!context_lost_allowed_
) {
265 ASSERT_EQ(::gpu::error::kNoError
, state
.error
);
269 bool GLManager::GetBufferChanged(int32 transfer_buffer_id
) {
270 return gpu_scheduler_
->SetGetBuffer(transfer_buffer_id
);