Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / gpu / command_buffer / tests / gl_manager.cc
blob4e4eccb2abed4026fc23ec1c918f52a9f3af8d74
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_implementation.h"
17 #include "gpu/command_buffer/client/gles2_lib.h"
18 #include "gpu/command_buffer/client/transfer_buffer.h"
19 #include "gpu/command_buffer/common/constants.h"
20 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
21 #include "gpu/command_buffer/common/value_state.h"
22 #include "gpu/command_buffer/service/command_buffer_service.h"
23 #include "gpu/command_buffer/service/context_group.h"
24 #include "gpu/command_buffer/service/gl_context_virtual.h"
25 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
26 #include "gpu/command_buffer/service/gpu_scheduler.h"
27 #include "gpu/command_buffer/service/image_manager.h"
28 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
29 #include "gpu/command_buffer/service/memory_tracking.h"
30 #include "gpu/command_buffer/service/valuebuffer_manager.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "ui/gfx/gpu_memory_buffer.h"
33 #include "ui/gl/gl_context.h"
34 #include "ui/gl/gl_image_ref_counted_memory.h"
35 #include "ui/gl/gl_share_group.h"
36 #include "ui/gl/gl_surface.h"
38 namespace gpu {
39 namespace {
41 size_t StrideInBytes(size_t width, gfx::GpuMemoryBuffer::Format format) {
42 switch (format) {
43 case gfx::GpuMemoryBuffer::ATCIA:
44 case gfx::GpuMemoryBuffer::DXT5:
45 return width;
46 case gfx::GpuMemoryBuffer::ATC:
47 case gfx::GpuMemoryBuffer::DXT1:
48 case gfx::GpuMemoryBuffer::ETC1:
49 DCHECK_EQ(width % 2, 0U);
50 return width / 2;
51 case gfx::GpuMemoryBuffer::RGBA_8888:
52 case gfx::GpuMemoryBuffer::BGRA_8888:
53 return width * 4;
54 case gfx::GpuMemoryBuffer::RGBX_8888:
55 NOTREACHED();
56 return 0;
59 NOTREACHED();
60 return 0;
63 class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
64 public:
65 GpuMemoryBufferImpl(base::RefCountedBytes* bytes,
66 const gfx::Size& size,
67 gfx::GpuMemoryBuffer::Format format)
68 : bytes_(bytes), size_(size), format_(format), mapped_(false) {}
70 static GpuMemoryBufferImpl* FromClientBuffer(ClientBuffer buffer) {
71 return reinterpret_cast<GpuMemoryBufferImpl*>(buffer);
74 // Overridden from gfx::GpuMemoryBuffer:
75 void* Map() override {
76 mapped_ = true;
77 return &bytes_->data().front();
79 void Unmap() override { mapped_ = false; }
80 bool IsMapped() const override { return mapped_; }
81 Format GetFormat() const override { return format_; }
82 uint32 GetStride() const override {
83 return StrideInBytes(size_.width(), format_);
85 gfx::GpuMemoryBufferHandle GetHandle() const override {
86 NOTREACHED();
87 return gfx::GpuMemoryBufferHandle();
89 ClientBuffer AsClientBuffer() override {
90 return reinterpret_cast<ClientBuffer>(this);
93 base::RefCountedBytes* bytes() { return bytes_.get(); }
95 private:
96 scoped_refptr<base::RefCountedBytes> bytes_;
97 const gfx::Size size_;
98 gfx::GpuMemoryBuffer::Format format_;
99 bool mapped_;
102 } // namespace
104 int GLManager::use_count_;
105 scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_;
106 scoped_refptr<gfx::GLSurface>* GLManager::base_surface_;
107 scoped_refptr<gfx::GLContext>* GLManager::base_context_;
109 GLManager::Options::Options()
110 : size(4, 4),
111 share_group_manager(NULL),
112 share_mailbox_manager(NULL),
113 virtual_manager(NULL),
114 bind_generates_resource(false),
115 lose_context_when_out_of_memory(false),
116 context_lost_allowed(false) {
119 GLManager::GLManager() : context_lost_allowed_(false) {
120 SetupBaseContext();
123 GLManager::~GLManager() {
124 --use_count_;
125 if (!use_count_) {
126 if (base_share_group_) {
127 delete base_context_;
128 base_context_ = NULL;
130 if (base_surface_) {
131 delete base_surface_;
132 base_surface_ = NULL;
134 if (base_context_) {
135 delete base_context_;
136 base_context_ = NULL;
141 // static
142 scoped_ptr<gfx::GpuMemoryBuffer> GLManager::CreateGpuMemoryBuffer(
143 const gfx::Size& size,
144 gfx::GpuMemoryBuffer::Format format) {
145 std::vector<unsigned char> data(
146 StrideInBytes(size.width(), format) * size.height(), 0);
147 scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes(data));
148 return make_scoped_ptr<gfx::GpuMemoryBuffer>(
149 new GpuMemoryBufferImpl(bytes.get(), size, format));
152 void GLManager::Initialize(const GLManager::Options& options) {
153 InitializeWithCommandLine(options, nullptr);
155 void GLManager::InitializeWithCommandLine(const GLManager::Options& options,
156 base::CommandLine* command_line) {
157 const int32 kCommandBufferSize = 1024 * 1024;
158 const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
159 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
160 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
162 context_lost_allowed_ = options.context_lost_allowed;
164 gles2::MailboxManager* mailbox_manager = NULL;
165 if (options.share_mailbox_manager) {
166 mailbox_manager = options.share_mailbox_manager->mailbox_manager();
167 } else if (options.share_group_manager) {
168 mailbox_manager = options.share_group_manager->mailbox_manager();
171 gfx::GLShareGroup* share_group = NULL;
172 if (options.share_group_manager) {
173 share_group = options.share_group_manager->share_group();
174 } else if (options.share_mailbox_manager) {
175 share_group = options.share_mailbox_manager->share_group();
178 gles2::ContextGroup* context_group = NULL;
179 gles2::ShareGroup* client_share_group = NULL;
180 if (options.share_group_manager) {
181 context_group = options.share_group_manager->decoder_->GetContextGroup();
182 client_share_group =
183 options.share_group_manager->gles2_implementation()->share_group();
186 gfx::GLContext* real_gl_context = NULL;
187 if (options.virtual_manager) {
188 real_gl_context = options.virtual_manager->context();
191 mailbox_manager_ =
192 mailbox_manager ? mailbox_manager : new gles2::MailboxManagerImpl;
193 share_group_ =
194 share_group ? share_group : new gfx::GLShareGroup;
196 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
197 std::vector<int32> attribs;
198 gles2::ContextCreationAttribHelper attrib_helper;
199 attrib_helper.red_size = 8;
200 attrib_helper.green_size = 8;
201 attrib_helper.blue_size = 8;
202 attrib_helper.alpha_size = 8;
203 attrib_helper.depth_size = 16;
204 attrib_helper.stencil_size = 8;
205 attrib_helper.Serialize(&attribs);
207 DCHECK(!command_line || !context_group);
208 if (!context_group) {
209 scoped_refptr<gles2::FeatureInfo> feature_info;
210 if (command_line)
211 feature_info = new gles2::FeatureInfo(*command_line);
212 context_group =
213 new gles2::ContextGroup(mailbox_manager_.get(),
214 NULL,
215 new gpu::gles2::ShaderTranslatorCache,
216 feature_info,
217 NULL,
218 NULL,
219 options.bind_generates_resource);
222 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group));
224 command_buffer_.reset(new CommandBufferService(
225 decoder_->GetContextGroup()->transfer_buffer_manager()));
226 ASSERT_TRUE(command_buffer_->Initialize())
227 << "could not create command buffer service";
229 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
230 decoder_.get(),
231 decoder_.get()));
233 decoder_->set_engine(gpu_scheduler_.get());
235 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(options.size);
236 ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface";
238 if (base_context_) {
239 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
240 share_group_.get(), base_context_->get(), decoder_->AsWeakPtr()));
241 ASSERT_TRUE(context_->Initialize(
242 surface_.get(), gfx::PreferIntegratedGpu));
243 } else {
244 if (real_gl_context) {
245 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
246 share_group_.get(), real_gl_context, decoder_->AsWeakPtr()));
247 ASSERT_TRUE(context_->Initialize(
248 surface_.get(), gfx::PreferIntegratedGpu));
249 } else {
250 context_ = gfx::GLContext::CreateGLContext(share_group_.get(),
251 surface_.get(),
252 gpu_preference);
255 ASSERT_TRUE(context_.get() != NULL) << "could not create GL context";
257 ASSERT_TRUE(context_->MakeCurrent(surface_.get()));
259 ASSERT_TRUE(decoder_->Initialize(
260 surface_.get(),
261 context_.get(),
262 true,
263 options.size,
264 ::gpu::gles2::DisallowedFeatures(),
265 attribs)) << "could not initialize decoder";
267 command_buffer_->SetPutOffsetChangeCallback(
268 base::Bind(&GLManager::PumpCommands, base::Unretained(this)));
269 command_buffer_->SetGetBufferChangeCallback(
270 base::Bind(&GLManager::GetBufferChanged, base::Unretained(this)));
272 // Create the GLES2 helper, which writes the command buffer protocol.
273 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
274 ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize));
276 // Create a transfer buffer.
277 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
279 // Create the object exposing the OpenGL API.
280 const bool support_client_side_arrays = true;
281 gles2_implementation_.reset(
282 new gles2::GLES2Implementation(gles2_helper_.get(),
283 client_share_group,
284 transfer_buffer_.get(),
285 options.bind_generates_resource,
286 options.lose_context_when_out_of_memory,
287 support_client_side_arrays,
288 this));
290 ASSERT_TRUE(gles2_implementation_->Initialize(
291 kStartTransferBufferSize,
292 kMinTransferBufferSize,
293 kMaxTransferBufferSize,
294 gpu::gles2::GLES2Implementation::kNoLimit))
295 << "Could not init GLES2Implementation";
297 MakeCurrent();
300 void GLManager::SetupBaseContext() {
301 if (use_count_) {
302 #if defined(OS_ANDROID)
303 base_share_group_ = new scoped_refptr<gfx::GLShareGroup>(
304 new gfx::GLShareGroup);
305 gfx::Size size(4, 4);
306 base_surface_ = new scoped_refptr<gfx::GLSurface>(
307 gfx::GLSurface::CreateOffscreenGLSurface(size));
308 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
309 base_context_ = new scoped_refptr<gfx::GLContext>(
310 gfx::GLContext::CreateGLContext(base_share_group_->get(),
311 base_surface_->get(),
312 gpu_preference));
313 #endif
315 ++use_count_;
318 void GLManager::MakeCurrent() {
319 ::gles2::SetGLContext(gles2_implementation_.get());
322 void GLManager::SetSurface(gfx::GLSurface* surface) {
323 decoder_->SetSurface(surface);
326 void GLManager::Destroy() {
327 if (gles2_implementation_.get()) {
328 MakeCurrent();
329 EXPECT_TRUE(glGetError() == GL_NONE);
330 gles2_implementation_->Flush();
331 gles2_implementation_.reset();
333 transfer_buffer_.reset();
334 gles2_helper_.reset();
335 command_buffer_.reset();
336 if (decoder_.get()) {
337 decoder_->MakeCurrent();
338 decoder_->Destroy(true);
339 decoder_.reset();
343 const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const {
344 return decoder_->GetContextGroup()->feature_info()->workarounds();
347 void GLManager::PumpCommands() {
348 if (!decoder_->MakeCurrent()) {
349 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
350 command_buffer_->SetParseError(::gpu::error::kLostContext);
351 return;
353 gpu_scheduler_->PutChanged();
354 ::gpu::CommandBuffer::State state = command_buffer_->GetLastState();
355 if (!context_lost_allowed_) {
356 ASSERT_EQ(::gpu::error::kNoError, state.error);
360 bool GLManager::GetBufferChanged(int32 transfer_buffer_id) {
361 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
364 Capabilities GLManager::GetCapabilities() {
365 return decoder_->GetCapabilities();
368 int32 GLManager::CreateImage(ClientBuffer buffer,
369 size_t width,
370 size_t height,
371 unsigned internalformat) {
372 GpuMemoryBufferImpl* gpu_memory_buffer =
373 GpuMemoryBufferImpl::FromClientBuffer(buffer);
375 scoped_refptr<gfx::GLImageRefCountedMemory> image(
376 new gfx::GLImageRefCountedMemory(gfx::Size(width, height),
377 internalformat));
378 if (!image->Initialize(gpu_memory_buffer->bytes(),
379 gpu_memory_buffer->GetFormat())) {
380 return -1;
383 static int32 next_id = 1;
384 int32 new_id = next_id++;
386 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
387 DCHECK(image_manager);
388 image_manager->AddImage(image.get(), new_id);
389 return new_id;
392 int32 GLManager::CreateGpuMemoryBufferImage(size_t width,
393 size_t height,
394 unsigned internalformat,
395 unsigned usage) {
396 DCHECK_EQ(usage, static_cast<unsigned>(GL_MAP_CHROMIUM));
397 scoped_ptr<gfx::GpuMemoryBuffer> buffer = GLManager::CreateGpuMemoryBuffer(
398 gfx::Size(width, height), gfx::GpuMemoryBuffer::RGBA_8888);
399 return CreateImage(buffer->AsClientBuffer(), width, height, internalformat);
402 void GLManager::DestroyImage(int32 id) {
403 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
404 DCHECK(image_manager);
405 image_manager->RemoveImage(id);
408 uint32 GLManager::InsertSyncPoint() {
409 NOTIMPLEMENTED();
410 return 0u;
413 uint32 GLManager::InsertFutureSyncPoint() {
414 NOTIMPLEMENTED();
415 return 0u;
418 void GLManager::RetireSyncPoint(uint32 sync_point) {
419 NOTIMPLEMENTED();
422 void GLManager::SignalSyncPoint(uint32 sync_point,
423 const base::Closure& callback) {
424 NOTIMPLEMENTED();
427 void GLManager::SignalQuery(uint32 query, const base::Closure& callback) {
428 NOTIMPLEMENTED();
431 void GLManager::SetSurfaceVisible(bool visible) {
432 NOTIMPLEMENTED();
435 uint32 GLManager::CreateStreamTexture(uint32 texture_id) {
436 NOTIMPLEMENTED();
437 return 0;
440 void GLManager::SetLock(base::Lock*) {
441 NOTIMPLEMENTED();
444 } // namespace gpu