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_gpu_memory_buffer_manager.h"
12 #include "content/child/child_thread_impl.h"
13 #include "content/common/gpu/client/context_provider_command_buffer.h"
14 #include "content/common/gpu/client/gl_helper.h"
15 #include "content/common/gpu/client/gpu_channel_host.h"
16 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
17 #include "content/common/gpu/media/gpu_video_accelerator_util.h"
18 #include "content/renderer/render_thread_impl.h"
19 #include "gpu/command_buffer/client/gles2_implementation.h"
20 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
21 #include "media/video/video_decode_accelerator.h"
22 #include "media/video/video_encode_accelerator.h"
27 scoped_refptr
<RendererGpuVideoAcceleratorFactories
>
28 RendererGpuVideoAcceleratorFactories::Create(
29 GpuChannelHost
* gpu_channel_host
,
30 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
31 const scoped_refptr
<ContextProviderCommandBuffer
>& context_provider
,
32 unsigned image_texture_target
,
33 bool enable_video_accelerator
) {
34 scoped_refptr
<RendererGpuVideoAcceleratorFactories
> factories
=
35 new RendererGpuVideoAcceleratorFactories(gpu_channel_host
, task_runner
,
38 enable_video_accelerator
);
39 // Post task from outside constructor, since AddRef()/Release() is unsafe from
41 task_runner
->PostTask(
43 base::Bind(&RendererGpuVideoAcceleratorFactories::BindContext
,
48 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
49 GpuChannelHost
* gpu_channel_host
,
50 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
51 const scoped_refptr
<ContextProviderCommandBuffer
>& context_provider
,
52 unsigned image_texture_target
,
53 bool enable_video_accelerator
)
54 : task_runner_(task_runner
),
55 gpu_channel_host_(gpu_channel_host
),
56 context_provider_(context_provider
),
57 image_texture_target_(image_texture_target
),
58 video_accelerator_enabled_(enable_video_accelerator
),
59 gpu_memory_buffer_manager_(
60 ChildThreadImpl::current()->gpu_memory_buffer_manager()),
61 thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()) {
64 RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
66 void RendererGpuVideoAcceleratorFactories::BindContext() {
67 DCHECK(task_runner_
->BelongsToCurrentThread());
68 if (!context_provider_
->BindToCurrentThread())
69 context_provider_
= NULL
;
72 WebGraphicsContext3DCommandBufferImpl
*
73 RendererGpuVideoAcceleratorFactories::GetContext3d() {
74 DCHECK(task_runner_
->BelongsToCurrentThread());
75 if (!context_provider_
.get())
77 if (context_provider_
->ContextGL()->GetGraphicsResetStatusKHR() !=
79 context_provider_
->VerifyContexts();
80 context_provider_
= NULL
;
81 gl_helper_
.reset(NULL
);
84 return context_provider_
->WebContext3D();
87 GLHelper
* RendererGpuVideoAcceleratorFactories::GetGLHelper() {
91 if (gl_helper_
.get() == NULL
) {
92 gl_helper_
.reset(new GLHelper(GetContext3d()->GetImplementation(),
93 GetContext3d()->GetContextSupport()));
96 return gl_helper_
.get();
99 bool RendererGpuVideoAcceleratorFactories::IsGpuVideoAcceleratorEnabled() {
100 return video_accelerator_enabled_
;
103 scoped_ptr
<media::VideoDecodeAccelerator
>
104 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
105 DCHECK(video_accelerator_enabled_
);
106 DCHECK(task_runner_
->BelongsToCurrentThread());
108 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
109 if (context
&& context
->GetCommandBufferProxy()) {
110 return gpu_channel_host_
->CreateVideoDecoder(
111 context
->GetCommandBufferProxy()->GetRouteID());
114 return scoped_ptr
<media::VideoDecodeAccelerator
>();
117 scoped_ptr
<media::VideoEncodeAccelerator
>
118 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
119 DCHECK(video_accelerator_enabled_
);
120 DCHECK(task_runner_
->BelongsToCurrentThread());
122 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
123 if (context
&& context
->GetCommandBufferProxy()) {
124 return gpu_channel_host_
->CreateVideoEncoder(
125 context
->GetCommandBufferProxy()->GetRouteID());
128 return scoped_ptr
<media::VideoEncodeAccelerator
>();
131 bool RendererGpuVideoAcceleratorFactories::CreateTextures(
133 const gfx::Size
& size
,
134 std::vector
<uint32
>* texture_ids
,
135 std::vector
<gpu::Mailbox
>* texture_mailboxes
,
136 uint32 texture_target
) {
137 DCHECK(task_runner_
->BelongsToCurrentThread());
138 DCHECK(texture_target
);
140 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
144 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
145 texture_ids
->resize(count
);
146 texture_mailboxes
->resize(count
);
147 gles2
->GenTextures(count
, &texture_ids
->at(0));
148 for (int i
= 0; i
< count
; ++i
) {
149 gles2
->ActiveTexture(GL_TEXTURE0
);
150 uint32 texture_id
= texture_ids
->at(i
);
151 gles2
->BindTexture(texture_target
, texture_id
);
152 gles2
->TexParameteri(texture_target
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
153 gles2
->TexParameteri(texture_target
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
154 gles2
->TexParameteri(texture_target
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
155 gles2
->TexParameteri(texture_target
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
156 if (texture_target
== GL_TEXTURE_2D
) {
157 gles2
->TexImage2D(texture_target
,
167 gles2
->GenMailboxCHROMIUM(texture_mailboxes
->at(i
).name
);
168 gles2
->ProduceTextureCHROMIUM(texture_target
,
169 texture_mailboxes
->at(i
).name
);
172 // We need ShallowFlushCHROMIUM() here to order the command buffer commands
173 // with respect to IPC to the GPU process, to guarantee that the decoder in
174 // the GPU process can use these textures as soon as it receives IPC
175 // notification of them.
176 gles2
->ShallowFlushCHROMIUM();
177 DCHECK_EQ(gles2
->GetError(), static_cast<GLenum
>(GL_NO_ERROR
));
181 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id
) {
182 DCHECK(task_runner_
->BelongsToCurrentThread());
184 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
188 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
189 gles2
->DeleteTextures(1, &texture_id
);
190 DCHECK_EQ(gles2
->GetError(), static_cast<GLenum
>(GL_NO_ERROR
));
193 void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point
) {
194 DCHECK(task_runner_
->BelongsToCurrentThread());
196 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
200 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
201 gles2
->WaitSyncPointCHROMIUM(sync_point
);
203 // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to
204 // flush the command buffers to ensure that.
205 gles2
->ShallowFlushCHROMIUM();
208 scoped_ptr
<gfx::GpuMemoryBuffer
>
209 RendererGpuVideoAcceleratorFactories::AllocateGpuMemoryBuffer(
210 const gfx::Size
& size
,
211 gfx::GpuMemoryBuffer::Format format
,
212 gfx::GpuMemoryBuffer::Usage usage
) {
213 DCHECK(task_runner_
->BelongsToCurrentThread());
214 scoped_ptr
<gfx::GpuMemoryBuffer
> buffer
=
215 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(size
, format
, usage
);
216 return buffer
.Pass();
219 bool RendererGpuVideoAcceleratorFactories::IsTextureRGSupported() {
220 DCHECK(task_runner_
->BelongsToCurrentThread());
222 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
225 return context
->GetImplementation()->capabilities().texture_rg
;
228 unsigned RendererGpuVideoAcceleratorFactories::ImageTextureTarget() {
229 return image_texture_target_
;
232 gpu::gles2::GLES2Interface
*
233 RendererGpuVideoAcceleratorFactories::GetGLES2Interface() {
234 DCHECK(task_runner_
->BelongsToCurrentThread());
236 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
239 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
243 scoped_ptr
<base::SharedMemory
>
244 RendererGpuVideoAcceleratorFactories::CreateSharedMemory(size_t size
) {
245 DCHECK(task_runner_
->BelongsToCurrentThread());
246 scoped_ptr
<base::SharedMemory
> mem(
247 ChildThreadImpl::AllocateSharedMemory(size
, thread_safe_sender_
.get()));
248 if (mem
&& !mem
->Map(size
))
253 scoped_refptr
<base::SingleThreadTaskRunner
>
254 RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
258 media::VideoDecodeAccelerator::SupportedProfiles
259 RendererGpuVideoAcceleratorFactories::
260 GetVideoDecodeAcceleratorSupportedProfiles() {
261 return GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeProfiles(
262 gpu_channel_host_
->gpu_info()
263 .video_decode_accelerator_supported_profiles
);
266 media::VideoEncodeAccelerator::SupportedProfiles
267 RendererGpuVideoAcceleratorFactories::
268 GetVideoEncodeAcceleratorSupportedProfiles() {
269 return GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
270 gpu_channel_host_
->gpu_info()
271 .video_encode_accelerator_supported_profiles
);
274 } // namespace content