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"
8 #include <GLES2/gl2ext.h>
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"
37 int BytesPerPixel(unsigned internalformat
) {
38 switch (internalformat
) {
47 class GpuMemoryBufferImpl
: public gfx::GpuMemoryBuffer
{
49 GpuMemoryBufferImpl(base::RefCountedBytes
* bytes
,
50 const gfx::Size
& size
,
51 unsigned internalformat
)
54 internalformat_(internalformat
),
57 // Overridden from gfx::GpuMemoryBuffer:
58 virtual void* Map() OVERRIDE
{
60 return &bytes_
->data().front();
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_
);
67 virtual gfx::GpuMemoryBufferHandle
GetHandle() const OVERRIDE
{
69 return gfx::GpuMemoryBufferHandle();
73 scoped_refptr
<base::RefCountedBytes
> bytes_
;
74 const gfx::Size size_
;
75 unsigned internalformat_
;
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_
;
86 GLManager::Options::Options()
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) {
96 GLManager::GLManager() : context_lost_allowed_(false) {
100 GLManager::~GLManager() {
103 if (base_share_group_
) {
104 delete base_context_
;
105 base_context_
= NULL
;
108 delete base_surface_
;
109 base_surface_
= NULL
;
112 delete base_context_
;
113 base_context_
= NULL
;
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;
124 context_lost_allowed_
= options
.context_lost_allowed
;
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();
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();
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();
145 options
.share_group_manager
->gles2_implementation()->share_group();
148 gfx::GLContext
* real_gl_context
= NULL
;
149 if (options
.virtual_manager
) {
150 real_gl_context
= options
.virtual_manager
->context();
154 mailbox_manager
? mailbox_manager
: new gles2::MailboxManager
;
156 share_group
? share_group
: new gfx::GLShareGroup
;
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
);
168 if (!context_group
) {
170 new gles2::ContextGroup(mailbox_manager_
.get(),
172 new gpu::gles2::ShaderTranslatorCache
,
174 options
.bind_generates_resource
);
177 decoder_
.reset(::gpu::gles2::GLES2Decoder::Create(context_group
));
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";
184 gpu_scheduler_
.reset(new GpuScheduler(command_buffer_
.get(),
188 decoder_
->set_engine(gpu_scheduler_
.get());
190 surface_
= gfx::GLSurface::CreateOffscreenGLSurface(options
.size
);
191 ASSERT_TRUE(surface_
.get() != NULL
) << "could not create offscreen surface";
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
));
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
));
205 context_
= gfx::GLContext::CreateGLContext(share_group_
.get(),
210 ASSERT_TRUE(context_
.get() != NULL
) << "could not create GL context";
212 ASSERT_TRUE(context_
->MakeCurrent(surface_
.get()));
214 ASSERT_TRUE(decoder_
->Initialize(
219 ::gpu::gles2::DisallowedFeatures(),
220 attribs
)) << "could not initialize decoder";
222 command_buffer_
->SetPutOffsetChangeCallback(
223 base::Bind(&GLManager::PumpCommands
, base::Unretained(this)));
224 command_buffer_
->SetGetBufferChangeCallback(
225 base::Bind(&GLManager::GetBufferChanged
, base::Unretained(this)));
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
));
231 // Create a transfer buffer.
232 transfer_buffer_
.reset(new TransferBuffer(gles2_helper_
.get()));
234 // Create the object exposing the OpenGL API.
235 gles2_implementation_
.reset(
236 new gles2::GLES2Implementation(gles2_helper_
.get(),
238 transfer_buffer_
.get(),
239 options
.bind_generates_resource
,
240 options
.lose_context_when_out_of_memory
,
243 ASSERT_TRUE(gles2_implementation_
->Initialize(
244 kStartTransferBufferSize
,
245 kMinTransferBufferSize
,
246 kMaxTransferBufferSize
,
247 gpu::gles2::GLES2Implementation::kNoLimit
))
248 << "Could not init GLES2Implementation";
253 void GLManager::SetupBaseContext() {
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(),
271 void GLManager::MakeCurrent() {
272 ::gles2::SetGLContext(gles2_implementation_
.get());
275 void GLManager::SetSurface(gfx::GLSurface
* surface
) {
276 decoder_
->SetSurface(surface
);
279 void GLManager::Destroy() {
280 if (gles2_implementation_
.get()) {
282 EXPECT_TRUE(glGetError() == GL_NONE
);
283 gles2_implementation_
->Flush();
284 gles2_implementation_
.reset();
286 transfer_buffer_
.reset();
287 gles2_helper_
.reset();
288 command_buffer_
.reset();
289 if (decoder_
.get()) {
290 decoder_
->MakeCurrent();
291 decoder_
->Destroy(true);
296 const gpu::gles2::FeatureInfo::Workarounds
& GLManager::workarounds() const {
297 return decoder_
->GetContextGroup()->feature_info()->workarounds();
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
);
309 bool GLManager::GetBufferChanged(int32 transfer_buffer_id
) {
310 return gpu_scheduler_
->SetGetBuffer(transfer_buffer_id
);
313 Capabilities
GLManager::GetCapabilities() {
314 return decoder_
->GetCapabilities();
317 gfx::GpuMemoryBuffer
* GLManager::CreateGpuMemoryBuffer(
320 unsigned internalformat
,
323 gfx::Size
size(width
, height
);
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
));
333 static int32 next_id
= 1;
334 int32 new_id
= next_id
++;
336 scoped_refptr
<gfx::GLImageRefCountedMemory
> image(
337 new gfx::GLImageRefCountedMemory(size
, internalformat
));
338 if (!image
->Initialize(bytes
.get()))
341 gpu::gles2::ImageManager
* image_manager
= decoder_
->GetImageManager();
342 DCHECK(image_manager
);
343 image_manager
->AddImage(image
.get(), 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
;
350 void GLManager::DestroyGpuMemoryBuffer(int32 id
) {
351 gpu::gles2::ImageManager
* image_manager
= decoder_
->GetImageManager();
352 DCHECK(image_manager
);
353 image_manager
->RemoveImage(id
);
355 gpu_memory_buffers_
.erase(id
);
358 uint32
GLManager::InsertSyncPoint() {
363 uint32
GLManager::InsertFutureSyncPoint() {
368 void GLManager::RetireSyncPoint(uint32 sync_point
) {
372 void GLManager::SignalSyncPoint(uint32 sync_point
,
373 const base::Closure
& callback
) {
377 void GLManager::SignalQuery(uint32 query
, const base::Closure
& callback
) {
381 void GLManager::SetSurfaceVisible(bool visible
) {
385 void GLManager::Echo(const base::Closure
& callback
) {
389 uint32
GLManager::CreateStreamTexture(uint32 texture_id
) {