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"
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"
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
35 task_runner
->PostTask(
37 base::Bind(&RendererGpuVideoAcceleratorFactories::BindContext
,
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())
64 if (context_provider_
->IsContextLost()) {
65 context_provider_
->VerifyContexts();
66 context_provider_
= NULL
;
67 gl_helper_
.reset(NULL
);
70 return context_provider_
->WebContext3D();
73 GLHelper
* RendererGpuVideoAcceleratorFactories::GetGLHelper() {
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(
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();
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
,
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
));
161 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id
) {
162 DCHECK(task_runner_
->BelongsToCurrentThread());
164 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
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();
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
))
198 scoped_refptr
<base::SingleThreadTaskRunner
>
199 RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
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