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>
9 #include <GLES2/gl2extchromium.h>
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_cmd_helper.h"
17 #include "gpu/command_buffer/client/gles2_implementation.h"
18 #include "gpu/command_buffer/client/gles2_lib.h"
19 #include "gpu/command_buffer/client/transfer_buffer.h"
20 #include "gpu/command_buffer/common/constants.h"
21 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
22 #include "gpu/command_buffer/common/value_state.h"
23 #include "gpu/command_buffer/service/command_buffer_service.h"
24 #include "gpu/command_buffer/service/context_group.h"
25 #include "gpu/command_buffer/service/gl_context_virtual.h"
26 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
27 #include "gpu/command_buffer/service/gpu_scheduler.h"
28 #include "gpu/command_buffer/service/image_manager.h"
29 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
30 #include "gpu/command_buffer/service/memory_tracking.h"
31 #include "gpu/command_buffer/service/valuebuffer_manager.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
34 #include "ui/gl/gl_context.h"
35 #include "ui/gl/gl_image_ref_counted_memory.h"
36 #include "ui/gl/gl_share_group.h"
37 #include "ui/gl/gl_surface.h"
42 size_t NumberOfPlanesForGpuMemoryBufferFormat(
43 gfx::GpuMemoryBuffer::Format format
) {
45 case gfx::GpuMemoryBuffer::ATC
:
46 case gfx::GpuMemoryBuffer::ATCIA
:
47 case gfx::GpuMemoryBuffer::DXT1
:
48 case gfx::GpuMemoryBuffer::DXT5
:
49 case gfx::GpuMemoryBuffer::ETC1
:
50 case gfx::GpuMemoryBuffer::R_8
:
51 case gfx::GpuMemoryBuffer::RGBA_4444
:
52 case gfx::GpuMemoryBuffer::RGBA_8888
:
53 case gfx::GpuMemoryBuffer::RGBX_8888
:
54 case gfx::GpuMemoryBuffer::BGRA_8888
:
56 case gfx::GpuMemoryBuffer::YUV_420
:
63 size_t SubsamplingFactor(gfx::GpuMemoryBuffer::Format format
, int plane
) {
65 case gfx::GpuMemoryBuffer::ATC
:
66 case gfx::GpuMemoryBuffer::ATCIA
:
67 case gfx::GpuMemoryBuffer::DXT1
:
68 case gfx::GpuMemoryBuffer::DXT5
:
69 case gfx::GpuMemoryBuffer::ETC1
:
70 case gfx::GpuMemoryBuffer::R_8
:
71 case gfx::GpuMemoryBuffer::RGBA_4444
:
72 case gfx::GpuMemoryBuffer::RGBA_8888
:
73 case gfx::GpuMemoryBuffer::RGBX_8888
:
74 case gfx::GpuMemoryBuffer::BGRA_8888
:
76 case gfx::GpuMemoryBuffer::YUV_420
: {
77 static size_t factor
[] = {1, 2, 2};
78 DCHECK_LT(static_cast<size_t>(plane
), arraysize(factor
));
86 size_t StrideInBytes(size_t width
,
87 gfx::GpuMemoryBuffer::Format format
,
90 case gfx::GpuMemoryBuffer::ATCIA
:
91 case gfx::GpuMemoryBuffer::DXT5
:
94 case gfx::GpuMemoryBuffer::ATC
:
95 case gfx::GpuMemoryBuffer::DXT1
:
96 case gfx::GpuMemoryBuffer::ETC1
:
98 DCHECK_EQ(width
% 2, 0U);
100 case gfx::GpuMemoryBuffer::R_8
:
101 return (width
+ 3) & ~0x3;
102 case gfx::GpuMemoryBuffer::RGBA_4444
:
105 case gfx::GpuMemoryBuffer::RGBA_8888
:
106 case gfx::GpuMemoryBuffer::BGRA_8888
:
109 case gfx::GpuMemoryBuffer::RGBX_8888
:
112 case gfx::GpuMemoryBuffer::YUV_420
:
113 return width
/ SubsamplingFactor(format
, plane
);
120 size_t BufferSizeInBytes(const gfx::Size
& size
,
121 gfx::GpuMemoryBuffer::Format format
) {
122 size_t size_in_bytes
= 0;
123 size_t num_planes
= NumberOfPlanesForGpuMemoryBufferFormat(format
);
124 for (size_t i
= 0; i
< num_planes
; ++i
) {
125 size_in_bytes
+= StrideInBytes(size
.width(), format
, i
) *
126 (size
.height() / SubsamplingFactor(format
, i
));
128 return size_in_bytes
;
131 class GpuMemoryBufferImpl
: public gfx::GpuMemoryBuffer
{
133 GpuMemoryBufferImpl(base::RefCountedBytes
* bytes
,
134 const gfx::Size
& size
,
135 gfx::GpuMemoryBuffer::Format format
)
136 : bytes_(bytes
), size_(size
), format_(format
), mapped_(false) {}
138 static GpuMemoryBufferImpl
* FromClientBuffer(ClientBuffer buffer
) {
139 return reinterpret_cast<GpuMemoryBufferImpl
*>(buffer
);
142 // Overridden from gfx::GpuMemoryBuffer:
143 bool Map(void** data
) override
{
145 size_t num_planes
= NumberOfPlanesForGpuMemoryBufferFormat(format_
);
146 for (size_t i
= 0; i
< num_planes
; ++i
) {
147 data
[i
] = reinterpret_cast<uint8
*>(&bytes_
->data().front()) + offset
;
148 offset
+= StrideInBytes(size_
.width(), format_
, i
) *
149 (size_
.height() / SubsamplingFactor(format_
, i
));
154 void Unmap() override
{ mapped_
= false; }
155 bool IsMapped() const override
{ return mapped_
; }
156 Format
GetFormat() const override
{ return format_
; }
157 void GetStride(int* stride
) const override
{
158 size_t num_planes
= NumberOfPlanesForGpuMemoryBufferFormat(format_
);
159 for (size_t i
= 0; i
< num_planes
; ++i
)
160 stride
[i
] = StrideInBytes(size_
.width(), format_
, i
);
162 gfx::GpuMemoryBufferId
GetId() const override
{
166 gfx::GpuMemoryBufferHandle
GetHandle() const override
{
168 return gfx::GpuMemoryBufferHandle();
170 ClientBuffer
AsClientBuffer() override
{
171 return reinterpret_cast<ClientBuffer
>(this);
174 base::RefCountedBytes
* bytes() { return bytes_
.get(); }
177 scoped_refptr
<base::RefCountedBytes
> bytes_
;
178 const gfx::Size size_
;
179 gfx::GpuMemoryBuffer::Format format_
;
185 int GLManager::use_count_
;
186 scoped_refptr
<gfx::GLShareGroup
>* GLManager::base_share_group_
;
187 scoped_refptr
<gfx::GLSurface
>* GLManager::base_surface_
;
188 scoped_refptr
<gfx::GLContext
>* GLManager::base_context_
;
190 GLManager::Options::Options()
192 share_group_manager(NULL
),
193 share_mailbox_manager(NULL
),
194 virtual_manager(NULL
),
195 bind_generates_resource(false),
196 lose_context_when_out_of_memory(false),
197 context_lost_allowed(false),
201 GLManager::GLManager() : context_lost_allowed_(false) {
205 GLManager::~GLManager() {
208 if (base_share_group_
) {
209 delete base_context_
;
210 base_context_
= NULL
;
213 delete base_surface_
;
214 base_surface_
= NULL
;
217 delete base_context_
;
218 base_context_
= NULL
;
224 scoped_ptr
<gfx::GpuMemoryBuffer
> GLManager::CreateGpuMemoryBuffer(
225 const gfx::Size
& size
,
226 gfx::GpuMemoryBuffer::Format format
) {
227 std::vector
<unsigned char> data(BufferSizeInBytes(size
, format
), 0);
228 scoped_refptr
<base::RefCountedBytes
> bytes(new base::RefCountedBytes(data
));
229 return make_scoped_ptr
<gfx::GpuMemoryBuffer
>(
230 new GpuMemoryBufferImpl(bytes
.get(), size
, format
));
233 void GLManager::Initialize(const GLManager::Options
& options
) {
234 InitializeWithCommandLine(options
, nullptr);
236 void GLManager::InitializeWithCommandLine(const GLManager::Options
& options
,
237 base::CommandLine
* command_line
) {
238 const int32 kCommandBufferSize
= 1024 * 1024;
239 const size_t kStartTransferBufferSize
= 4 * 1024 * 1024;
240 const size_t kMinTransferBufferSize
= 1 * 256 * 1024;
241 const size_t kMaxTransferBufferSize
= 16 * 1024 * 1024;
243 context_lost_allowed_
= options
.context_lost_allowed
;
245 gles2::MailboxManager
* mailbox_manager
= NULL
;
246 if (options
.share_mailbox_manager
) {
247 mailbox_manager
= options
.share_mailbox_manager
->mailbox_manager();
248 } else if (options
.share_group_manager
) {
249 mailbox_manager
= options
.share_group_manager
->mailbox_manager();
252 gfx::GLShareGroup
* share_group
= NULL
;
253 if (options
.share_group_manager
) {
254 share_group
= options
.share_group_manager
->share_group();
255 } else if (options
.share_mailbox_manager
) {
256 share_group
= options
.share_mailbox_manager
->share_group();
259 gles2::ContextGroup
* context_group
= NULL
;
260 gles2::ShareGroup
* client_share_group
= NULL
;
261 if (options
.share_group_manager
) {
262 context_group
= options
.share_group_manager
->decoder_
->GetContextGroup();
264 options
.share_group_manager
->gles2_implementation()->share_group();
267 gfx::GLContext
* real_gl_context
= NULL
;
268 if (options
.virtual_manager
) {
269 real_gl_context
= options
.virtual_manager
->context();
273 mailbox_manager
? mailbox_manager
: new gles2::MailboxManagerImpl
;
275 share_group
? share_group
: new gfx::GLShareGroup
;
277 gfx::GpuPreference
gpu_preference(gfx::PreferDiscreteGpu
);
278 std::vector
<int32
> attribs
;
279 gles2::ContextCreationAttribHelper attrib_helper
;
280 attrib_helper
.red_size
= 8;
281 attrib_helper
.green_size
= 8;
282 attrib_helper
.blue_size
= 8;
283 attrib_helper
.alpha_size
= 8;
284 attrib_helper
.depth_size
= 16;
285 attrib_helper
.stencil_size
= 8;
286 attrib_helper
.webgl_version
= options
.webgl_version
;
287 attrib_helper
.Serialize(&attribs
);
289 DCHECK(!command_line
|| !context_group
);
290 if (!context_group
) {
291 scoped_refptr
<gles2::FeatureInfo
> feature_info
;
293 feature_info
= new gles2::FeatureInfo(*command_line
);
295 new gles2::ContextGroup(mailbox_manager_
.get(),
297 new gpu::gles2::ShaderTranslatorCache
,
301 options
.bind_generates_resource
);
304 decoder_
.reset(::gpu::gles2::GLES2Decoder::Create(context_group
));
306 command_buffer_
.reset(new CommandBufferService(
307 decoder_
->GetContextGroup()->transfer_buffer_manager()));
308 ASSERT_TRUE(command_buffer_
->Initialize())
309 << "could not create command buffer service";
311 gpu_scheduler_
.reset(new GpuScheduler(command_buffer_
.get(),
315 decoder_
->set_engine(gpu_scheduler_
.get());
317 surface_
= gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size());
318 ASSERT_TRUE(surface_
.get() != NULL
) << "could not create offscreen surface";
321 context_
= scoped_refptr
<gfx::GLContext
>(new gpu::GLContextVirtual(
322 share_group_
.get(), base_context_
->get(), decoder_
->AsWeakPtr()));
323 ASSERT_TRUE(context_
->Initialize(
324 surface_
.get(), gfx::PreferIntegratedGpu
));
326 if (real_gl_context
) {
327 context_
= scoped_refptr
<gfx::GLContext
>(new gpu::GLContextVirtual(
328 share_group_
.get(), real_gl_context
, decoder_
->AsWeakPtr()));
329 ASSERT_TRUE(context_
->Initialize(
330 surface_
.get(), gfx::PreferIntegratedGpu
));
332 context_
= gfx::GLContext::CreateGLContext(share_group_
.get(),
337 ASSERT_TRUE(context_
.get() != NULL
) << "could not create GL context";
339 ASSERT_TRUE(context_
->MakeCurrent(surface_
.get()));
341 ASSERT_TRUE(decoder_
->Initialize(
346 ::gpu::gles2::DisallowedFeatures(),
347 attribs
)) << "could not initialize decoder";
349 command_buffer_
->SetPutOffsetChangeCallback(
350 base::Bind(&GLManager::PumpCommands
, base::Unretained(this)));
351 command_buffer_
->SetGetBufferChangeCallback(
352 base::Bind(&GLManager::GetBufferChanged
, base::Unretained(this)));
354 // Create the GLES2 helper, which writes the command buffer protocol.
355 gles2_helper_
.reset(new gles2::GLES2CmdHelper(command_buffer_
.get()));
356 ASSERT_TRUE(gles2_helper_
->Initialize(kCommandBufferSize
));
358 // Create a transfer buffer.
359 transfer_buffer_
.reset(new TransferBuffer(gles2_helper_
.get()));
361 // Create the object exposing the OpenGL API.
362 const bool support_client_side_arrays
= true;
363 gles2_implementation_
.reset(
364 new gles2::GLES2Implementation(gles2_helper_
.get(),
366 transfer_buffer_
.get(),
367 options
.bind_generates_resource
,
368 options
.lose_context_when_out_of_memory
,
369 support_client_side_arrays
,
372 ASSERT_TRUE(gles2_implementation_
->Initialize(
373 kStartTransferBufferSize
,
374 kMinTransferBufferSize
,
375 kMaxTransferBufferSize
,
376 gpu::gles2::GLES2Implementation::kNoLimit
))
377 << "Could not init GLES2Implementation";
382 void GLManager::SetupBaseContext() {
384 #if defined(OS_ANDROID)
385 base_share_group_
= new scoped_refptr
<gfx::GLShareGroup
>(
386 new gfx::GLShareGroup
);
387 gfx::Size
size(4, 4);
388 base_surface_
= new scoped_refptr
<gfx::GLSurface
>(
389 gfx::GLSurface::CreateOffscreenGLSurface(size
));
390 gfx::GpuPreference
gpu_preference(gfx::PreferDiscreteGpu
);
391 base_context_
= new scoped_refptr
<gfx::GLContext
>(
392 gfx::GLContext::CreateGLContext(base_share_group_
->get(),
393 base_surface_
->get(),
400 void GLManager::MakeCurrent() {
401 ::gles2::SetGLContext(gles2_implementation_
.get());
404 void GLManager::SetSurface(gfx::GLSurface
* surface
) {
405 decoder_
->SetSurface(surface
);
408 void GLManager::Destroy() {
409 if (gles2_implementation_
.get()) {
411 EXPECT_TRUE(glGetError() == GL_NONE
);
412 gles2_implementation_
->Flush();
413 gles2_implementation_
.reset();
415 transfer_buffer_
.reset();
416 gles2_helper_
.reset();
417 command_buffer_
.reset();
418 if (decoder_
.get()) {
419 bool have_context
= decoder_
->GetGLContext()->MakeCurrent(surface_
.get());
420 decoder_
->Destroy(have_context
);
425 const gpu::gles2::FeatureInfo::Workarounds
& GLManager::workarounds() const {
426 return decoder_
->GetContextGroup()->feature_info()->workarounds();
429 void GLManager::PumpCommands() {
430 if (!decoder_
->MakeCurrent()) {
431 command_buffer_
->SetContextLostReason(decoder_
->GetContextLostReason());
432 command_buffer_
->SetParseError(::gpu::error::kLostContext
);
435 gpu_scheduler_
->PutChanged();
436 ::gpu::CommandBuffer::State state
= command_buffer_
->GetLastState();
437 if (!context_lost_allowed_
) {
438 ASSERT_EQ(::gpu::error::kNoError
, state
.error
);
442 bool GLManager::GetBufferChanged(int32 transfer_buffer_id
) {
443 return gpu_scheduler_
->SetGetBuffer(transfer_buffer_id
);
446 Capabilities
GLManager::GetCapabilities() {
447 return decoder_
->GetCapabilities();
450 int32
GLManager::CreateImage(ClientBuffer buffer
,
453 unsigned internalformat
) {
454 GpuMemoryBufferImpl
* gpu_memory_buffer
=
455 GpuMemoryBufferImpl::FromClientBuffer(buffer
);
457 scoped_refptr
<gfx::GLImageRefCountedMemory
> image(
458 new gfx::GLImageRefCountedMemory(gfx::Size(width
, height
),
460 if (!image
->Initialize(gpu_memory_buffer
->bytes(),
461 gpu_memory_buffer
->GetFormat())) {
465 static int32 next_id
= 1;
466 int32 new_id
= next_id
++;
468 gpu::gles2::ImageManager
* image_manager
= decoder_
->GetImageManager();
469 DCHECK(image_manager
);
470 image_manager
->AddImage(image
.get(), new_id
);
474 int32
GLManager::CreateGpuMemoryBufferImage(size_t width
,
476 unsigned internalformat
,
478 DCHECK_EQ(usage
, static_cast<unsigned>(GL_MAP_CHROMIUM
));
479 scoped_ptr
<gfx::GpuMemoryBuffer
> buffer
= GLManager::CreateGpuMemoryBuffer(
480 gfx::Size(width
, height
), gfx::GpuMemoryBuffer::RGBA_8888
);
481 return CreateImage(buffer
->AsClientBuffer(), width
, height
, internalformat
);
484 void GLManager::DestroyImage(int32 id
) {
485 gpu::gles2::ImageManager
* image_manager
= decoder_
->GetImageManager();
486 DCHECK(image_manager
);
487 image_manager
->RemoveImage(id
);
490 uint32
GLManager::InsertSyncPoint() {
495 uint32
GLManager::InsertFutureSyncPoint() {
500 void GLManager::RetireSyncPoint(uint32 sync_point
) {
504 void GLManager::SignalSyncPoint(uint32 sync_point
,
505 const base::Closure
& callback
) {
509 void GLManager::SignalQuery(uint32 query
, const base::Closure
& callback
) {
513 void GLManager::SetSurfaceVisible(bool visible
) {
517 uint32
GLManager::CreateStreamTexture(uint32 texture_id
) {
522 void GLManager::SetLock(base::Lock
*) {
526 bool GLManager::IsGpuChannelLost() {