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_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/service/command_buffer_service.h"
22 #include "gpu/command_buffer/service/context_group.h"
23 #include "gpu/command_buffer/service/gl_context_virtual.h"
24 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
25 #include "gpu/command_buffer/service/gpu_scheduler.h"
26 #include "gpu/command_buffer/service/image_manager.h"
27 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
28 #include "gpu/command_buffer/service/memory_tracking.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "ui/gfx/gpu_memory_buffer.h"
31 #include "ui/gl/gl_context.h"
32 #include "ui/gl/gl_image_ref_counted_memory.h"
33 #include "ui/gl/gl_share_group.h"
34 #include "ui/gl/gl_surface.h"
39 size_t BytesPerPixel(gfx::GpuMemoryBuffer::Format format) {
41 case gfx::GpuMemoryBuffer::RGBA_8888:
42 case gfx::GpuMemoryBuffer::BGRA_8888:
44 case gfx::GpuMemoryBuffer::RGBX_8888:
53 class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
55 GpuMemoryBufferImpl(base::RefCountedBytes* bytes,
56 const gfx::Size& size,
57 gfx::GpuMemoryBuffer::Format format)
58 : bytes_(bytes), size_(size), format_(format), mapped_(false) {}
60 static GpuMemoryBufferImpl* FromClientBuffer(ClientBuffer buffer) {
61 return reinterpret_cast<GpuMemoryBufferImpl*>(buffer);
64 // Overridden from gfx::GpuMemoryBuffer:
65 void* Map() override {
67 return &bytes_->data().front();
69 void Unmap() override { mapped_ = false; }
70 bool IsMapped() const override { return mapped_; }
71 Format GetFormat() const override { return format_; }
72 uint32 GetStride() const override {
73 return size_.width() * BytesPerPixel(format_);
75 gfx::GpuMemoryBufferHandle GetHandle() const override {
77 return gfx::GpuMemoryBufferHandle();
79 ClientBuffer AsClientBuffer() override {
80 return reinterpret_cast<ClientBuffer>(this);
83 base::RefCountedBytes* bytes() { return bytes_.get(); }
86 scoped_refptr<base::RefCountedBytes> bytes_;
87 const gfx::Size size_;
88 gfx::GpuMemoryBuffer::Format format_;
94 int GLManager::use_count_;
95 scoped_refptr<gfx::GLShareGroup>* GLManager::base_share_group_;
96 scoped_refptr<gfx::GLSurface>* GLManager::base_surface_;
97 scoped_refptr<gfx::GLContext>* GLManager::base_context_;
99 GLManager::Options::Options()
101 share_group_manager(NULL),
102 share_mailbox_manager(NULL),
103 virtual_manager(NULL),
104 bind_generates_resource(false),
105 lose_context_when_out_of_memory(false),
106 context_lost_allowed(false) {
109 GLManager::GLManager() : context_lost_allowed_(false) {
113 GLManager::~GLManager() {
116 if (base_share_group_) {
117 delete base_context_;
118 base_context_ = NULL;
121 delete base_surface_;
122 base_surface_ = NULL;
125 delete base_context_;
126 base_context_ = NULL;
132 scoped_ptr<gfx::GpuMemoryBuffer> GLManager::CreateGpuMemoryBuffer(
133 const gfx::Size& size,
134 gfx::GpuMemoryBuffer::Format format) {
135 std::vector<unsigned char> data(size.GetArea() * BytesPerPixel(format), 0);
136 scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes(data));
137 return make_scoped_ptr<gfx::GpuMemoryBuffer>(
138 new GpuMemoryBufferImpl(bytes.get(), size, format));
141 void GLManager::Initialize(const GLManager::Options& options) {
142 const int32 kCommandBufferSize = 1024 * 1024;
143 const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
144 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
145 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
147 context_lost_allowed_ = options.context_lost_allowed;
149 gles2::MailboxManager* mailbox_manager = NULL;
150 if (options.share_mailbox_manager) {
151 mailbox_manager = options.share_mailbox_manager->mailbox_manager();
152 } else if (options.share_group_manager) {
153 mailbox_manager = options.share_group_manager->mailbox_manager();
156 gfx::GLShareGroup* share_group = NULL;
157 if (options.share_group_manager) {
158 share_group = options.share_group_manager->share_group();
159 } else if (options.share_mailbox_manager) {
160 share_group = options.share_mailbox_manager->share_group();
163 gles2::ContextGroup* context_group = NULL;
164 gles2::ShareGroup* client_share_group = NULL;
165 if (options.share_group_manager) {
166 context_group = options.share_group_manager->decoder_->GetContextGroup();
168 options.share_group_manager->gles2_implementation()->share_group();
171 gfx::GLContext* real_gl_context = NULL;
172 if (options.virtual_manager) {
173 real_gl_context = options.virtual_manager->context();
177 mailbox_manager ? mailbox_manager : new gles2::MailboxManagerImpl;
179 share_group ? share_group : new gfx::GLShareGroup;
181 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
182 std::vector<int32> attribs;
183 gles2::ContextCreationAttribHelper attrib_helper;
184 attrib_helper.red_size = 8;
185 attrib_helper.green_size = 8;
186 attrib_helper.blue_size = 8;
187 attrib_helper.alpha_size = 8;
188 attrib_helper.depth_size = 16;
189 attrib_helper.Serialize(&attribs);
191 if (!context_group) {
193 new gles2::ContextGroup(mailbox_manager_.get(),
195 new gpu::gles2::ShaderTranslatorCache,
197 options.bind_generates_resource);
200 decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group));
202 command_buffer_.reset(new CommandBufferService(
203 decoder_->GetContextGroup()->transfer_buffer_manager()));
204 ASSERT_TRUE(command_buffer_->Initialize())
205 << "could not create command buffer service";
207 gpu_scheduler_.reset(new GpuScheduler(command_buffer_.get(),
211 decoder_->set_engine(gpu_scheduler_.get());
213 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(options.size);
214 ASSERT_TRUE(surface_.get() != NULL) << "could not create offscreen surface";
217 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
218 share_group_.get(), base_context_->get(), decoder_->AsWeakPtr()));
219 ASSERT_TRUE(context_->Initialize(
220 surface_.get(), gfx::PreferIntegratedGpu));
222 if (real_gl_context) {
223 context_ = scoped_refptr<gfx::GLContext>(new gpu::GLContextVirtual(
224 share_group_.get(), real_gl_context, decoder_->AsWeakPtr()));
225 ASSERT_TRUE(context_->Initialize(
226 surface_.get(), gfx::PreferIntegratedGpu));
228 context_ = gfx::GLContext::CreateGLContext(share_group_.get(),
233 ASSERT_TRUE(context_.get() != NULL) << "could not create GL context";
235 ASSERT_TRUE(context_->MakeCurrent(surface_.get()));
237 ASSERT_TRUE(decoder_->Initialize(
242 ::gpu::gles2::DisallowedFeatures(),
243 attribs)) << "could not initialize decoder";
245 command_buffer_->SetPutOffsetChangeCallback(
246 base::Bind(&GLManager::PumpCommands, base::Unretained(this)));
247 command_buffer_->SetGetBufferChangeCallback(
248 base::Bind(&GLManager::GetBufferChanged, base::Unretained(this)));
250 // Create the GLES2 helper, which writes the command buffer protocol.
251 gles2_helper_.reset(new gles2::GLES2CmdHelper(command_buffer_.get()));
252 ASSERT_TRUE(gles2_helper_->Initialize(kCommandBufferSize));
254 // Create a transfer buffer.
255 transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get()));
257 // Create the object exposing the OpenGL API.
258 const bool support_client_side_arrays = true;
259 gles2_implementation_.reset(
260 new gles2::GLES2Implementation(gles2_helper_.get(),
262 transfer_buffer_.get(),
263 options.bind_generates_resource,
264 options.lose_context_when_out_of_memory,
265 support_client_side_arrays,
268 ASSERT_TRUE(gles2_implementation_->Initialize(
269 kStartTransferBufferSize,
270 kMinTransferBufferSize,
271 kMaxTransferBufferSize,
272 gpu::gles2::GLES2Implementation::kNoLimit))
273 << "Could not init GLES2Implementation";
278 void GLManager::SetupBaseContext() {
280 #if defined(OS_ANDROID)
281 base_share_group_ = new scoped_refptr<gfx::GLShareGroup>(
282 new gfx::GLShareGroup);
283 gfx::Size size(4, 4);
284 base_surface_ = new scoped_refptr<gfx::GLSurface>(
285 gfx::GLSurface::CreateOffscreenGLSurface(size));
286 gfx::GpuPreference gpu_preference(gfx::PreferDiscreteGpu);
287 base_context_ = new scoped_refptr<gfx::GLContext>(
288 gfx::GLContext::CreateGLContext(base_share_group_->get(),
289 base_surface_->get(),
296 void GLManager::MakeCurrent() {
297 ::gles2::SetGLContext(gles2_implementation_.get());
300 void GLManager::SetSurface(gfx::GLSurface* surface) {
301 decoder_->SetSurface(surface);
304 void GLManager::Destroy() {
305 if (gles2_implementation_.get()) {
307 EXPECT_TRUE(glGetError() == GL_NONE);
308 gles2_implementation_->Flush();
309 gles2_implementation_.reset();
311 transfer_buffer_.reset();
312 gles2_helper_.reset();
313 command_buffer_.reset();
314 if (decoder_.get()) {
315 decoder_->MakeCurrent();
316 decoder_->Destroy(true);
321 const gpu::gles2::FeatureInfo::Workarounds& GLManager::workarounds() const {
322 return decoder_->GetContextGroup()->feature_info()->workarounds();
325 void GLManager::PumpCommands() {
326 decoder_->MakeCurrent();
327 gpu_scheduler_->PutChanged();
328 ::gpu::CommandBuffer::State state = command_buffer_->GetLastState();
329 if (!context_lost_allowed_) {
330 ASSERT_EQ(::gpu::error::kNoError, state.error);
334 bool GLManager::GetBufferChanged(int32 transfer_buffer_id) {
335 return gpu_scheduler_->SetGetBuffer(transfer_buffer_id);
338 Capabilities GLManager::GetCapabilities() {
339 return decoder_->GetCapabilities();
342 int32 GLManager::CreateImage(ClientBuffer buffer,
345 unsigned internalformat) {
346 GpuMemoryBufferImpl* gpu_memory_buffer =
347 GpuMemoryBufferImpl::FromClientBuffer(buffer);
349 scoped_refptr<gfx::GLImageRefCountedMemory> image(
350 new gfx::GLImageRefCountedMemory(gfx::Size(width, height),
352 if (!image->Initialize(gpu_memory_buffer->bytes(),
353 gpu_memory_buffer->GetFormat())) {
357 static int32 next_id = 1;
358 int32 new_id = next_id++;
360 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
361 DCHECK(image_manager);
362 image_manager->AddImage(image.get(), new_id);
366 int32 GLManager::CreateGpuMemoryBufferImage(size_t width,
368 unsigned internalformat,
370 DCHECK_EQ(usage, static_cast<unsigned>(GL_MAP_CHROMIUM));
371 scoped_ptr<gfx::GpuMemoryBuffer> buffer = GLManager::CreateGpuMemoryBuffer(
372 gfx::Size(width, height), gfx::GpuMemoryBuffer::RGBA_8888);
373 return CreateImage(buffer->AsClientBuffer(), width, height, internalformat);
376 void GLManager::DestroyImage(int32 id) {
377 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
378 DCHECK(image_manager);
379 image_manager->RemoveImage(id);
382 uint32 GLManager::InsertSyncPoint() {
387 uint32 GLManager::InsertFutureSyncPoint() {
392 void GLManager::RetireSyncPoint(uint32 sync_point) {
396 void GLManager::SignalSyncPoint(uint32 sync_point,
397 const base::Closure& callback) {
401 void GLManager::SignalQuery(uint32 query, const base::Closure& callback) {
405 void GLManager::SetSurfaceVisible(bool visible) {
409 uint32 GLManager::CreateStreamTexture(uint32 texture_id) {