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 bool enable_gpu_memory_buffer_video_frames
,
33 unsigned image_texture_target
,
34 bool enable_video_accelerator
) {
35 scoped_refptr
<RendererGpuVideoAcceleratorFactories
> factories
=
36 new RendererGpuVideoAcceleratorFactories(
37 gpu_channel_host
, task_runner
, context_provider
,
38 enable_gpu_memory_buffer_video_frames
, image_texture_target
,
39 enable_video_accelerator
);
40 // Post task from outside constructor, since AddRef()/Release() is unsafe from
42 task_runner
->PostTask(
44 base::Bind(&RendererGpuVideoAcceleratorFactories::BindContext
,
49 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
50 GpuChannelHost
* gpu_channel_host
,
51 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
52 const scoped_refptr
<ContextProviderCommandBuffer
>& context_provider
,
53 bool enable_gpu_memory_buffer_video_frames
,
54 unsigned image_texture_target
,
55 bool enable_video_accelerator
)
56 : task_runner_(task_runner
),
57 gpu_channel_host_(gpu_channel_host
),
58 context_provider_(context_provider
),
59 enable_gpu_memory_buffer_video_frames_(
60 enable_gpu_memory_buffer_video_frames
),
61 image_texture_target_(image_texture_target
),
62 video_accelerator_enabled_(enable_video_accelerator
),
63 gpu_memory_buffer_manager_(ChildThreadImpl::current()
64 ->gpu_memory_buffer_manager()),
65 thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()) {
66 DCHECK(gpu_channel_host_
.get());
69 RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
71 void RendererGpuVideoAcceleratorFactories::BindContext() {
72 DCHECK(task_runner_
->BelongsToCurrentThread());
73 if (!context_provider_
->BindToCurrentThread())
74 context_provider_
= NULL
;
77 WebGraphicsContext3DCommandBufferImpl
*
78 RendererGpuVideoAcceleratorFactories::GetContext3d() {
79 DCHECK(task_runner_
->BelongsToCurrentThread());
80 if (!context_provider_
.get())
82 if (context_provider_
->ContextGL()->GetGraphicsResetStatusKHR() !=
84 context_provider_
->VerifyContexts();
85 context_provider_
= NULL
;
86 gl_helper_
.reset(NULL
);
89 return context_provider_
->WebContext3D();
92 GLHelper
* RendererGpuVideoAcceleratorFactories::GetGLHelper() {
96 if (gl_helper_
.get() == NULL
) {
97 gl_helper_
.reset(new GLHelper(GetContext3d()->GetImplementation(),
98 GetContext3d()->GetContextSupport()));
101 return gl_helper_
.get();
104 bool RendererGpuVideoAcceleratorFactories::IsGpuVideoAcceleratorEnabled() {
105 return video_accelerator_enabled_
;
108 scoped_ptr
<media::VideoDecodeAccelerator
>
109 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
110 DCHECK(video_accelerator_enabled_
);
111 DCHECK(task_runner_
->BelongsToCurrentThread());
113 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
114 if (context
&& context
->GetCommandBufferProxy())
115 return context
->GetCommandBufferProxy()->CreateVideoDecoder();
120 scoped_ptr
<media::VideoEncodeAccelerator
>
121 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
122 DCHECK(video_accelerator_enabled_
);
123 DCHECK(task_runner_
->BelongsToCurrentThread());
125 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
126 if (context
&& context
->GetCommandBufferProxy())
127 return context
->GetCommandBufferProxy()->CreateVideoEncoder();
132 bool RendererGpuVideoAcceleratorFactories::CreateTextures(
134 const gfx::Size
& size
,
135 std::vector
<uint32
>* texture_ids
,
136 std::vector
<gpu::Mailbox
>* texture_mailboxes
,
137 uint32 texture_target
) {
138 DCHECK(task_runner_
->BelongsToCurrentThread());
139 DCHECK(texture_target
);
141 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
145 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
146 texture_ids
->resize(count
);
147 texture_mailboxes
->resize(count
);
148 gles2
->GenTextures(count
, &texture_ids
->at(0));
149 for (int i
= 0; i
< count
; ++i
) {
150 gles2
->ActiveTexture(GL_TEXTURE0
);
151 uint32 texture_id
= texture_ids
->at(i
);
152 gles2
->BindTexture(texture_target
, texture_id
);
153 gles2
->TexParameteri(texture_target
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
154 gles2
->TexParameteri(texture_target
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
155 gles2
->TexParameteri(texture_target
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
156 gles2
->TexParameteri(texture_target
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
157 if (texture_target
== GL_TEXTURE_2D
) {
158 gles2
->TexImage2D(texture_target
,
168 gles2
->GenMailboxCHROMIUM(texture_mailboxes
->at(i
).name
);
169 gles2
->ProduceTextureCHROMIUM(texture_target
,
170 texture_mailboxes
->at(i
).name
);
173 // We need ShallowFlushCHROMIUM() here to order the command buffer commands
174 // with respect to IPC to the GPU process, to guarantee that the decoder in
175 // the GPU process can use these textures as soon as it receives IPC
176 // notification of them.
177 gles2
->ShallowFlushCHROMIUM();
178 DCHECK_EQ(gles2
->GetError(), static_cast<GLenum
>(GL_NO_ERROR
));
182 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id
) {
183 DCHECK(task_runner_
->BelongsToCurrentThread());
185 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
189 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
190 gles2
->DeleteTextures(1, &texture_id
);
191 DCHECK_EQ(gles2
->GetError(), static_cast<GLenum
>(GL_NO_ERROR
));
194 void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point
) {
195 DCHECK(task_runner_
->BelongsToCurrentThread());
197 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
201 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
202 gles2
->WaitSyncPointCHROMIUM(sync_point
);
204 // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to
205 // flush the command buffers to ensure that.
206 gles2
->ShallowFlushCHROMIUM();
209 scoped_ptr
<gfx::GpuMemoryBuffer
>
210 RendererGpuVideoAcceleratorFactories::AllocateGpuMemoryBuffer(
211 const gfx::Size
& size
,
212 gfx::BufferFormat format
,
213 gfx::BufferUsage usage
) {
214 DCHECK(task_runner_
->BelongsToCurrentThread());
215 scoped_ptr
<gfx::GpuMemoryBuffer
> buffer
=
216 gpu_memory_buffer_manager_
->AllocateGpuMemoryBuffer(size
, format
, usage
);
217 return buffer
.Pass();
219 bool RendererGpuVideoAcceleratorFactories::
220 ShouldUseGpuMemoryBuffersForVideoFrames() const {
221 return enable_gpu_memory_buffer_video_frames_
;
224 unsigned RendererGpuVideoAcceleratorFactories::ImageTextureTarget() {
225 return image_texture_target_
;
228 media::VideoPixelFormat
229 RendererGpuVideoAcceleratorFactories::VideoFrameOutputFormat() {
230 DCHECK(task_runner_
->BelongsToCurrentThread());
232 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
234 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
235 if (gles2
->capabilities().image_ycbcr_422
)
236 return media::PIXEL_FORMAT_UYVY
;
237 if (gles2
->capabilities().texture_rg
)
238 return media::PIXEL_FORMAT_I420
;
241 return media::PIXEL_FORMAT_UNKNOWN
;
244 gpu::gles2::GLES2Interface
*
245 RendererGpuVideoAcceleratorFactories::GetGLES2Interface() {
246 DCHECK(task_runner_
->BelongsToCurrentThread());
248 WebGraphicsContext3DCommandBufferImpl
* context
= GetContext3d();
251 gpu::gles2::GLES2Implementation
* gles2
= context
->GetImplementation();
255 scoped_ptr
<base::SharedMemory
>
256 RendererGpuVideoAcceleratorFactories::CreateSharedMemory(size_t size
) {
257 DCHECK(task_runner_
->BelongsToCurrentThread());
258 scoped_ptr
<base::SharedMemory
> mem(
259 ChildThreadImpl::AllocateSharedMemory(size
, thread_safe_sender_
.get()));
260 if (mem
&& !mem
->Map(size
))
265 scoped_refptr
<base::SingleThreadTaskRunner
>
266 RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
270 media::VideoDecodeAccelerator::SupportedProfiles
271 RendererGpuVideoAcceleratorFactories::
272 GetVideoDecodeAcceleratorSupportedProfiles() {
273 return GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeProfiles(
274 gpu_channel_host_
->gpu_info()
275 .video_decode_accelerator_supported_profiles
);
278 media::VideoEncodeAccelerator::SupportedProfiles
279 RendererGpuVideoAcceleratorFactories::
280 GetVideoEncodeAcceleratorSupportedProfiles() {
281 return GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
282 gpu_channel_host_
->gpu_info()
283 .video_encode_accelerator_supported_profiles
);
286 } // namespace content