Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / gpu / command_buffer / tests / gl_manager.cc
blob6dc8a103f055efa7f1707ad134c8a181fb6f09d2
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"
7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h>
9 #include <GLES2/gl2extchromium.h>
11 #include <vector>
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"
39 namespace gpu {
40 namespace {
42 size_t NumberOfPlanesForGpuMemoryBufferFormat(
43 gfx::GpuMemoryBuffer::Format format) {
44 switch (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:
55 return 1;
56 case gfx::GpuMemoryBuffer::YUV_420:
57 return 3;
59 NOTREACHED();
60 return 0;
63 size_t SubsamplingFactor(gfx::GpuMemoryBuffer::Format format, int plane) {
64 switch (format) {
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:
75 return 1;
76 case gfx::GpuMemoryBuffer::YUV_420: {
77 static size_t factor[] = {1, 2, 2};
78 DCHECK_LT(static_cast<size_t>(plane), arraysize(factor));
79 return factor[plane];
82 NOTREACHED();
83 return 0;
86 size_t StrideInBytes(size_t width,
87 gfx::GpuMemoryBuffer::Format format,
88 int plane) {
89 switch (format) {
90 case gfx::GpuMemoryBuffer::ATCIA:
91 case gfx::GpuMemoryBuffer::DXT5:
92 DCHECK_EQ(plane, 0);
93 return width;
94 case gfx::GpuMemoryBuffer::ATC:
95 case gfx::GpuMemoryBuffer::DXT1:
96 case gfx::GpuMemoryBuffer::ETC1:
97 DCHECK_EQ(plane, 0);
98 DCHECK_EQ(width % 2, 0U);
99 return width / 2;
100 case gfx::GpuMemoryBuffer::R_8:
101 return (width + 3) & ~0x3;
102 case gfx::GpuMemoryBuffer::RGBA_4444:
103 DCHECK_EQ(plane, 0);
104 return width * 2;
105 case gfx::GpuMemoryBuffer::RGBA_8888:
106 case gfx::GpuMemoryBuffer::BGRA_8888:
107 DCHECK_EQ(plane, 0);
108 return width * 4;
109 case gfx::GpuMemoryBuffer::RGBX_8888:
110 NOTREACHED();
111 return 0;
112 case gfx::GpuMemoryBuffer::YUV_420:
113 return width / SubsamplingFactor(format, plane);
116 NOTREACHED();
117 return 0;
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 {
132 public:
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 {
144 size_t offset = 0;
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));
151 mapped_ = true;
152 return true;
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 {
163 NOTREACHED();
164 return 0;
166 gfx::GpuMemoryBufferHandle GetHandle() const override {
167 NOTREACHED();
168 return gfx::GpuMemoryBufferHandle();
170 ClientBuffer AsClientBuffer() override {
171 return reinterpret_cast<ClientBuffer>(this);
174 base::RefCountedBytes* bytes() { return bytes_.get(); }
176 private:
177 scoped_refptr<base::RefCountedBytes> bytes_;
178 const gfx::Size size_;
179 gfx::GpuMemoryBuffer::Format format_;
180 bool mapped_;
183 } // namespace
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()
191 : size(4, 4),
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),
198 webgl_version(0) {
201 GLManager::GLManager() : context_lost_allowed_(false) {
202 SetupBaseContext();
205 GLManager::~GLManager() {
206 --use_count_;
207 if (!use_count_) {
208 if (base_share_group_) {
209 delete base_context_;
210 base_context_ = NULL;
212 if (base_surface_) {
213 delete base_surface_;
214 base_surface_ = NULL;
216 if (base_context_) {
217 delete base_context_;
218 base_context_ = NULL;
223 // static
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();
263 client_share_group =
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();
272 mailbox_manager_ =
273 mailbox_manager ? mailbox_manager : new gles2::MailboxManagerImpl;
274 share_group_ =
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;
292 if (command_line)
293 feature_info = new gles2::FeatureInfo(*command_line);
294 context_group =
295 new gles2::ContextGroup(mailbox_manager_.get(),
296 NULL,
297 new gpu::gles2::ShaderTranslatorCache,
298 feature_info,
299 NULL,
300 NULL,
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(),
312 decoder_.get(),
313 decoder_.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";
320 if (base_context_) {
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));
325 } else {
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));
331 } else {
332 context_ = gfx::GLContext::CreateGLContext(share_group_.get(),
333 surface_.get(),
334 gpu_preference);
337 ASSERT_TRUE(context_.get() != NULL) << "could not create GL context";
339 ASSERT_TRUE(context_->MakeCurrent(surface_.get()));
341 ASSERT_TRUE(decoder_->Initialize(
342 surface_.get(),
343 context_.get(),
344 true,
345 options.size,
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(),
365 client_share_group,
366 transfer_buffer_.get(),
367 options.bind_generates_resource,
368 options.lose_context_when_out_of_memory,
369 support_client_side_arrays,
370 this));
372 ASSERT_TRUE(gles2_implementation_->Initialize(
373 kStartTransferBufferSize,
374 kMinTransferBufferSize,
375 kMaxTransferBufferSize,
376 gpu::gles2::GLES2Implementation::kNoLimit))
377 << "Could not init GLES2Implementation";
379 MakeCurrent();
382 void GLManager::SetupBaseContext() {
383 if (use_count_) {
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(),
394 gpu_preference));
395 #endif
397 ++use_count_;
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()) {
410 MakeCurrent();
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);
421 decoder_.reset();
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);
433 return;
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,
451 size_t width,
452 size_t height,
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),
459 internalformat));
460 if (!image->Initialize(gpu_memory_buffer->bytes(),
461 gpu_memory_buffer->GetFormat())) {
462 return -1;
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);
471 return new_id;
474 int32 GLManager::CreateGpuMemoryBufferImage(size_t width,
475 size_t height,
476 unsigned internalformat,
477 unsigned usage) {
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() {
491 NOTIMPLEMENTED();
492 return 0u;
495 uint32 GLManager::InsertFutureSyncPoint() {
496 NOTIMPLEMENTED();
497 return 0u;
500 void GLManager::RetireSyncPoint(uint32 sync_point) {
501 NOTIMPLEMENTED();
504 void GLManager::SignalSyncPoint(uint32 sync_point,
505 const base::Closure& callback) {
506 NOTIMPLEMENTED();
509 void GLManager::SignalQuery(uint32 query, const base::Closure& callback) {
510 NOTIMPLEMENTED();
513 void GLManager::SetSurfaceVisible(bool visible) {
514 NOTIMPLEMENTED();
517 uint32 GLManager::CreateStreamTexture(uint32 texture_id) {
518 NOTIMPLEMENTED();
519 return 0;
522 void GLManager::SetLock(base::Lock*) {
523 NOTIMPLEMENTED();
526 bool GLManager::IsGpuChannelLost() {
527 NOTIMPLEMENTED();
528 return false;
531 } // namespace gpu