Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / renderer / media / renderer_gpu_video_accelerator_factories.cc
blob23fd238736df450fdf6bbc98e6b7e65c305a5d0a
1 // Copyright 2013 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 "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h>
10 #include "base/bind.h"
11 #include "content/child/child_thread_impl.h"
12 #include "content/common/gpu/client/context_provider_command_buffer.h"
13 #include "content/common/gpu/client/gl_helper.h"
14 #include "content/common/gpu/client/gpu_channel_host.h"
15 #include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
16 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
17 #include "content/renderer/render_thread_impl.h"
18 #include "gpu/command_buffer/client/gles2_implementation.h"
19 #include "media/video/video_decode_accelerator.h"
20 #include "media/video/video_encode_accelerator.h"
22 namespace content {
24 // static
25 scoped_refptr<RendererGpuVideoAcceleratorFactories>
26 RendererGpuVideoAcceleratorFactories::Create(
27 GpuChannelHost* gpu_channel_host,
28 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
29 const scoped_refptr<ContextProviderCommandBuffer>& context_provider) {
30 scoped_refptr<RendererGpuVideoAcceleratorFactories> factories =
31 new RendererGpuVideoAcceleratorFactories(
32 gpu_channel_host, task_runner, context_provider);
33 // Post task from outside constructor, since AddRef()/Release() is unsafe from
34 // within.
35 task_runner->PostTask(
36 FROM_HERE,
37 base::Bind(&RendererGpuVideoAcceleratorFactories::BindContext,
38 factories));
39 return factories;
42 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
43 GpuChannelHost* gpu_channel_host,
44 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
45 const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
46 : task_runner_(task_runner),
47 gpu_channel_host_(gpu_channel_host),
48 context_provider_(context_provider),
49 thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()) {}
51 RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
53 void RendererGpuVideoAcceleratorFactories::BindContext() {
54 DCHECK(task_runner_->BelongsToCurrentThread());
55 if (!context_provider_->BindToCurrentThread())
56 context_provider_ = NULL;
59 WebGraphicsContext3DCommandBufferImpl*
60 RendererGpuVideoAcceleratorFactories::GetContext3d() {
61 DCHECK(task_runner_->BelongsToCurrentThread());
62 if (!context_provider_.get())
63 return NULL;
64 if (context_provider_->IsContextLost()) {
65 context_provider_->VerifyContexts();
66 context_provider_ = NULL;
67 gl_helper_.reset(NULL);
68 return NULL;
70 return context_provider_->WebContext3D();
73 GLHelper* RendererGpuVideoAcceleratorFactories::GetGLHelper() {
74 if (!GetContext3d())
75 return NULL;
77 if (gl_helper_.get() == NULL) {
78 gl_helper_.reset(new GLHelper(GetContext3d()->GetImplementation(),
79 GetContext3d()->GetContextSupport()));
82 return gl_helper_.get();
85 scoped_ptr<media::VideoDecodeAccelerator>
86 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
87 DCHECK(task_runner_->BelongsToCurrentThread());
89 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
90 if (context && context->GetCommandBufferProxy()) {
91 return gpu_channel_host_->CreateVideoDecoder(
92 context->GetCommandBufferProxy()->GetRouteID());
95 return scoped_ptr<media::VideoDecodeAccelerator>();
98 scoped_ptr<media::VideoEncodeAccelerator>
99 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
100 DCHECK(task_runner_->BelongsToCurrentThread());
102 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
103 if (context && context->GetCommandBufferProxy()) {
104 return gpu_channel_host_->CreateVideoEncoder(
105 context->GetCommandBufferProxy()->GetRouteID());
108 return scoped_ptr<media::VideoEncodeAccelerator>();
111 bool RendererGpuVideoAcceleratorFactories::CreateTextures(
112 int32 count,
113 const gfx::Size& size,
114 std::vector<uint32>* texture_ids,
115 std::vector<gpu::Mailbox>* texture_mailboxes,
116 uint32 texture_target) {
117 DCHECK(task_runner_->BelongsToCurrentThread());
118 DCHECK(texture_target);
120 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
121 if (!context)
122 return false;
124 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
125 texture_ids->resize(count);
126 texture_mailboxes->resize(count);
127 gles2->GenTextures(count, &texture_ids->at(0));
128 for (int i = 0; i < count; ++i) {
129 gles2->ActiveTexture(GL_TEXTURE0);
130 uint32 texture_id = texture_ids->at(i);
131 gles2->BindTexture(texture_target, texture_id);
132 gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
133 gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
134 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
135 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
136 if (texture_target == GL_TEXTURE_2D) {
137 gles2->TexImage2D(texture_target,
139 GL_RGBA,
140 size.width(),
141 size.height(),
143 GL_RGBA,
144 GL_UNSIGNED_BYTE,
145 NULL);
147 gles2->GenMailboxCHROMIUM(texture_mailboxes->at(i).name);
148 gles2->ProduceTextureCHROMIUM(texture_target,
149 texture_mailboxes->at(i).name);
152 // We need ShallowFlushCHROMIUM() here to order the command buffer commands
153 // with respect to IPC to the GPU process, to guarantee that the decoder in
154 // the GPU process can use these textures as soon as it receives IPC
155 // notification of them.
156 gles2->ShallowFlushCHROMIUM();
157 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
158 return true;
161 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) {
162 DCHECK(task_runner_->BelongsToCurrentThread());
164 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
165 if (!context)
166 return;
168 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
169 gles2->DeleteTextures(1, &texture_id);
170 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
173 void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) {
174 DCHECK(task_runner_->BelongsToCurrentThread());
176 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
177 if (!context)
178 return;
180 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
181 gles2->WaitSyncPointCHROMIUM(sync_point);
183 // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to
184 // flush the command buffers to ensure that.
185 gles2->ShallowFlushCHROMIUM();
188 scoped_ptr<base::SharedMemory>
189 RendererGpuVideoAcceleratorFactories::CreateSharedMemory(size_t size) {
190 DCHECK(task_runner_->BelongsToCurrentThread());
191 scoped_ptr<base::SharedMemory> mem(
192 ChildThreadImpl::AllocateSharedMemory(size, thread_safe_sender_.get()));
193 if (mem && !mem->Map(size))
194 return nullptr;
195 return mem;
198 scoped_refptr<base::SingleThreadTaskRunner>
199 RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
200 return task_runner_;
203 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
204 RendererGpuVideoAcceleratorFactories::
205 GetVideoEncodeAcceleratorSupportedProfiles() {
206 return GpuVideoEncodeAcceleratorHost::ConvertGpuToMediaProfiles(
207 gpu_channel_host_->gpu_info()
208 .video_encode_accelerator_supported_profiles);
211 } // namespace content