Elim cr-checkbox
[chromium-blink-merge.git] / gpu / command_buffer / tests / gl_manager.cc
blobe485ac1d2e47af8d0917b839378e653fae324a54
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/transfer_buffer_manager.h"
32 #include "gpu/command_buffer/service/valuebuffer_manager.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "ui/gfx/buffer_format_util.h"
35 #include "ui/gfx/gpu_memory_buffer.h"
36 #include "ui/gl/gl_context.h"
37 #include "ui/gl/gl_image_ref_counted_memory.h"
38 #include "ui/gl/gl_share_group.h"
39 #include "ui/gl/gl_surface.h"
41 namespace gpu {
42 namespace {
44 class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
45 public:
46 GpuMemoryBufferImpl(base::RefCountedBytes* bytes,
47 const gfx::Size& size,
48 gfx::BufferFormat format)
49 : bytes_(bytes), size_(size), format_(format), mapped_(false) {}
51 static GpuMemoryBufferImpl* FromClientBuffer(ClientBuffer buffer) {
52 return reinterpret_cast<GpuMemoryBufferImpl*>(buffer);
55 // Overridden from gfx::GpuMemoryBuffer:
56 bool Map(void** data) override {
57 size_t offset = 0;
58 size_t num_planes = gfx::NumberOfPlanesForBufferFormat(format_);
59 for (size_t i = 0; i < num_planes; ++i) {
60 data[i] = reinterpret_cast<uint8*>(&bytes_->data().front()) + offset;
61 offset +=
62 gfx::RowSizeForBufferFormat(size_.width(), format_, i) *
63 (size_.height() / gfx::SubsamplingFactorForBufferFormat(format_, i));
65 mapped_ = true;
66 return true;
68 void Unmap() override { mapped_ = false; }
69 bool IsMapped() const override { return mapped_; }
70 gfx::BufferFormat GetFormat() const override { return format_; }
71 void GetStride(int* stride) const override {
72 size_t num_planes = gfx::NumberOfPlanesForBufferFormat(format_);
73 for (size_t i = 0; i < num_planes; ++i)
74 stride[i] = gfx::RowSizeForBufferFormat(size_.width(), format_, i);
76 gfx::GpuMemoryBufferId GetId() const override {
77 NOTREACHED();
78 return gfx::GpuMemoryBufferId(0);
80 gfx::GpuMemoryBufferHandle GetHandle() const override {
81 NOTREACHED();
82 return gfx::GpuMemoryBufferHandle();
84 ClientBuffer AsClientBuffer() override {
85 return reinterpret_cast<ClientBuffer>(this);
88 base::RefCountedBytes* bytes() { return bytes_.get(); }
90 private:
91 scoped_refptr<base::RefCountedBytes> bytes_;
92 const gfx::Size size_;
93 gfx::BufferFormat format_;
94 bool mapped_;
97 } // namespace
99 int GLManager::use_count_;
100 scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_;
101 scoped_refptr<gfx::GLSurface>* GLManager::base_surface_;
102 scoped_refptr<gfx::GLContext>* GLManager::base_context_;
104 GLManager::Options::Options()
105 : size(4, 4),
106 share_group_manager(NULL),
107 share_mailbox_manager(NULL),
108 virtual_manager(NULL),
109 bind_generates_resource(false),
110 lose_context_when_out_of_memory(false),
111 context_lost_allowed(false),
112 webgl_version(0) {
115 GLManager::GLManager() : context_lost_allowed_(false) {
116 SetupBaseContext();
119 GLManager::~GLManager() {
120 --use_count_;
121 if (!use_count_) {
122 if (base_share_group_) {
123 delete base_context_;
124 base_context_ = NULL;
126 if (base_surface_) {
127 delete base_surface_;
128 base_surface_ = NULL;
130 if (base_context_) {
131 delete base_context_;
132 base_context_ = NULL;
137 // static
138 scoped_ptr<gfx::GpuMemoryBuffer> GLManager::CreateGpuMemoryBuffer(
139 const gfx::Size& size,
140 gfx::BufferFormat format) {
141 std::vector<uint8> data(gfx::BufferSizeForBufferFormat(size, format), 0);
142 scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes(data));
143 return make_scoped_ptr<gfx::GpuMemoryBuffer>(
144 new GpuMemoryBufferImpl(bytes.get(), size, format));
147 void GLManager::Initialize(const GLManager::Options& options) {
148 InitializeWithCommandLine(options, nullptr);
150 void GLManager::InitializeWithCommandLine(const GLManager::Options& options,
151 base::CommandLine* command_line) {
152 const int32 kCommandBufferSize = 1024 * 1024;
153 const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
154 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
155 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
157 context_lost_allowed_ = options.context_lost_allowed;
159 gles2::MailboxManager* mailbox_manager = NULL;
160 if (options.share_mailbox_manager) {
161 mailbox_manager = options.share_mailbox_manager->mailbox_manager();
162 } else if (options.share_group_manager) {
163 mailbox_manager = options.share_group_manager->mailbox_manager();
166 gfx::GLShareGroup* share_group = NULL;
167 if (options.share_group_manager) {
168 share_group = options.share_group_manager->share_group();
169 } else if (options.share_mailbox_manager) {
170 share_group = options.share_mailbox_manager->share_group();
173 gles2::ContextGroup* context_group = NULL;
174 gles2::ShareGroup* client_share_group = NULL;
175 if (options.share_group_manager) {
176 context_group = options.share_group_manager->decoder_->GetContextGroup();
177 client_share_group =
178 options.share_group_manager->gles2_implementation()->share_group();
181 gfx::GLContext* real_gl_context = NULL;
182 if (options.virtual_manager) {
183 real_gl_context = options.virtual_manager->context();
186 mailbox_manager_ =
187 mailbox_manager ? mailbox_manager : new gles2::MailboxManagerImpl;
188 share_group_ =
189 share_group ? share_group : new gfx::GLShareGroup;
191 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
192 std::vector<int32> attribs;
193 gles2::ContextCreationAttribHelper attrib_helper;
194 attrib_helper.red_size = 8;
195 attrib_helper.green_size = 8;
196 attrib_helper.blue_size = 8;
197 attrib_helper.alpha_size = 8;
198 attrib_helper.depth_size = 16;
199 attrib_helper.stencil_size = 8;
200 attrib_helper.webgl_version = options.webgl_version;
201 attrib_helper.Serialize(&attribs);
203 DCHECK(!command_line || !context_group);
204 if (!context_group) {
205 scoped_refptr<gles2::FeatureInfo> feature_info;
206 if (command_line)
207 feature_info = new gles2::FeatureInfo(*command_line);
208 context_group = new gles2::ContextGroup(
209 mailbox_manager_.get(), NULL, new gpu::gles2::ShaderTranslatorCache,
210 new gpu::gles2::FramebufferCompletenessCache, feature_info, NULL, NULL,
211 options.bind_generates_resource);
214 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group));
216 command_buffer_.reset(new CommandBufferService(
217 decoder_->GetContextGroup()->transfer_buffer_manager()));
218 ASSERT_TRUE(command_buffer_->Initialize())
219 << "could not create command buffer service";
221 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
222 decoder_.get(),
223 decoder_.get()));
225 decoder_->set_engine(gpu_scheduler_.get());
227 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size());
228 ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface";
230 if (base_context_) {
231 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
232 share_group_.get(), base_context_->get(), decoder_->AsWeakPtr()));
233 ASSERT_TRUE(context_->Initialize(
234 surface_.get(), gfx::PreferIntegratedGpu));
235 } else {
236 if (real_gl_context) {
237 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
238 share_group_.get(), real_gl_context, decoder_->AsWeakPtr()));
239 ASSERT_TRUE(context_->Initialize(
240 surface_.get(), gfx::PreferIntegratedGpu));
241 } else {
242 context_ = gfx::GLContext::CreateGLContext(share_group_.get(),
243 surface_.get(),
244 gpu_preference);
247 ASSERT_TRUE(context_.get() != NULL) << "could not create GL context";
249 ASSERT_TRUE(context_->MakeCurrent(surface_.get()));
251 ASSERT_TRUE(decoder_->Initialize(
252 surface_.get(),
253 context_.get(),
254 true,
255 options.size,
256 ::gpu::gles2::DisallowedFeatures(),
257 attribs)) << "could not initialize decoder";
259 command_buffer_->SetPutOffsetChangeCallback(
260 base::Bind(&GLManager::PumpCommands, base::Unretained(this)));
261 command_buffer_->SetGetBufferChangeCallback(
262 base::Bind(&GLManager::GetBufferChanged, base::Unretained(this)));
264 // Create the GLES2 helper, which writes the command buffer protocol.
265 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
266 ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize));
268 // Create a transfer buffer.
269 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
271 // Create the object exposing the OpenGL API.
272 const bool support_client_side_arrays = true;
273 gles2_implementation_.reset(
274 new gles2::GLES2Implementation(gles2_helper_.get(),
275 client_share_group,
276 transfer_buffer_.get(),
277 options.bind_generates_resource,
278 options.lose_context_when_out_of_memory,
279 support_client_side_arrays,
280 this));
282 ASSERT_TRUE(gles2_implementation_->Initialize(
283 kStartTransferBufferSize,
284 kMinTransferBufferSize,
285 kMaxTransferBufferSize,
286 gpu::gles2::GLES2Implementation::kNoLimit))
287 << "Could not init GLES2Implementation";
289 MakeCurrent();
292 void GLManager::SetupBaseContext() {
293 if (use_count_) {
294 #if defined(OS_ANDROID)
295 base_share_group_ = new scoped_refptr<gfx::GLShareGroup>(
296 new gfx::GLShareGroup);
297 gfx::Size size(4, 4);
298 base_surface_ = new scoped_refptr<gfx::GLSurface>(
299 gfx::GLSurface::CreateOffscreenGLSurface(size));
300 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
301 base_context_ = new scoped_refptr<gfx::GLContext>(
302 gfx::GLContext::CreateGLContext(base_share_group_->get(),
303 base_surface_->get(),
304 gpu_preference));
305 #endif
307 ++use_count_;
310 void GLManager::MakeCurrent() {
311 ::gles2::SetGLContext(gles2_implementation_.get());
314 void GLManager::SetSurface(gfx::GLSurface* surface) {
315 decoder_->SetSurface(surface);
318 void GLManager::Destroy() {
319 if (gles2_implementation_.get()) {
320 MakeCurrent();
321 EXPECT_TRUE(glGetError() == GL_NONE);
322 gles2_implementation_->Flush();
323 gles2_implementation_.reset();
325 transfer_buffer_.reset();
326 gles2_helper_.reset();
327 command_buffer_.reset();
328 if (decoder_.get()) {
329 bool have_context = decoder_->GetGLContext()->MakeCurrent(surface_.get());
330 decoder_->Destroy(have_context);
331 decoder_.reset();
335 const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const {
336 return decoder_->GetContextGroup()->feature_info()->workarounds();
339 void GLManager::PumpCommands() {
340 if (!decoder_->MakeCurrent()) {
341 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
342 command_buffer_->SetParseError(::gpu::error::kLostContext);
343 return;
345 gpu_scheduler_->PutChanged();
346 ::gpu::CommandBuffer::State state = command_buffer_->GetLastState();
347 if (!context_lost_allowed_) {
348 ASSERT_EQ(::gpu::error::kNoError, state.error);
352 bool GLManager::GetBufferChanged(int32 transfer_buffer_id) {
353 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
356 Capabilities GLManager::GetCapabilities() {
357 return decoder_->GetCapabilities();
360 int32 GLManager::CreateImage(ClientBuffer buffer,
361 size_t width,
362 size_t height,
363 unsigned internalformat) {
364 GpuMemoryBufferImpl* gpu_memory_buffer =
365 GpuMemoryBufferImpl::FromClientBuffer(buffer);
367 scoped_refptr<gfx::GLImageRefCountedMemory> image(
368 new gfx::GLImageRefCountedMemory(gfx::Size(width, height),
369 internalformat));
370 if (!image->Initialize(gpu_memory_buffer->bytes(),
371 gpu_memory_buffer->GetFormat())) {
372 return -1;
375 static int32 next_id = 1;
376 int32 new_id = next_id++;
378 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
379 DCHECK(image_manager);
380 image_manager->AddImage(image.get(), new_id);
381 return new_id;
384 int32 GLManager::CreateGpuMemoryBufferImage(size_t width,
385 size_t height,
386 unsigned internalformat,
387 unsigned usage) {
388 DCHECK_EQ(usage, static_cast<unsigned>(GL_MAP_CHROMIUM));
389 scoped_ptr<gfx::GpuMemoryBuffer> buffer = GLManager::CreateGpuMemoryBuffer(
390 gfx::Size(width, height), gfx::BufferFormat::RGBA_8888);
391 return CreateImage(buffer->AsClientBuffer(), width, height, internalformat);
394 void GLManager::DestroyImage(int32 id) {
395 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
396 DCHECK(image_manager);
397 image_manager->RemoveImage(id);
400 uint32 GLManager::InsertSyncPoint() {
401 NOTIMPLEMENTED();
402 return 0u;
405 uint32 GLManager::InsertFutureSyncPoint() {
406 NOTIMPLEMENTED();
407 return 0u;
410 void GLManager::RetireSyncPoint(uint32 sync_point) {
411 NOTIMPLEMENTED();
414 void GLManager::SignalSyncPoint(uint32 sync_point,
415 const base::Closure& callback) {
416 NOTIMPLEMENTED();
419 void GLManager::SignalQuery(uint32 query, const base::Closure& callback) {
420 NOTIMPLEMENTED();
423 void GLManager::SetSurfaceVisible(bool visible) {
424 NOTIMPLEMENTED();
427 uint32 GLManager::CreateStreamTexture(uint32 texture_id) {
428 NOTIMPLEMENTED();
429 return 0;
432 void GLManager::SetLock(base::Lock*) {
433 NOTIMPLEMENTED();
436 bool GLManager::IsGpuChannelLost() {
437 NOTIMPLEMENTED();
438 return false;
441 gpu::CommandBufferNamespace GLManager::GetNamespaceID() const {
442 return gpu::CommandBufferNamespace::IN_PROCESS;
445 uint64_t GLManager::GetCommandBufferID() const {
446 return 0;
449 } // namespace gpu