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.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/webgraphicscontext3d_command_buffer_impl.h"
16 #include "content/renderer/render_thread_impl.h"
17 #include "gpu/command_buffer/client/gles2_implementation.h"
18 #include "media/video/video_decode_accelerator.h"
19 #include "media/video/video_encode_accelerator.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "third_party/skia/include/core/SkPixelRef.h"
26 scoped_refptr<RendererGpuVideoAcceleratorFactories>
27 RendererGpuVideoAcceleratorFactories::Create(
28 GpuChannelHost* gpu_channel_host,
29 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
30 const scoped_refptr<ContextProviderCommandBuffer>& context_provider) {
31 scoped_refptr<RendererGpuVideoAcceleratorFactories> factories =
32 new RendererGpuVideoAcceleratorFactories(
33 gpu_channel_host, task_runner, context_provider);
34 // Post task from outside constructor, since AddRef()/Release() is unsafe from
36 task_runner->PostTask(
38 base::Bind(&RendererGpuVideoAcceleratorFactories::BindContext,
43 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
44 GpuChannelHost* gpu_channel_host,
45 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
46 const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
47 : task_runner_(task_runner),
48 gpu_channel_host_(gpu_channel_host),
49 context_provider_(context_provider),
50 thread_safe_sender_(ChildThread::current()->thread_safe_sender()) {}
52 RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
54 void RendererGpuVideoAcceleratorFactories::BindContext() {
55 DCHECK(task_runner_->BelongsToCurrentThread());
56 if (!context_provider_->BindToCurrentThread())
57 context_provider_ = NULL;
60 WebGraphicsContext3DCommandBufferImpl*
61 RendererGpuVideoAcceleratorFactories::GetContext3d() {
62 DCHECK(task_runner_->BelongsToCurrentThread());
63 if (!context_provider_.get())
65 if (context_provider_->IsContextLost()) {
66 context_provider_->VerifyContexts();
67 context_provider_ = NULL;
68 gl_helper_.reset(NULL);
71 return context_provider_->WebContext3D();
74 GLHelper* RendererGpuVideoAcceleratorFactories::GetGLHelper() {
78 if (gl_helper_.get() == NULL) {
79 gl_helper_.reset(new GLHelper(GetContext3d()->GetImplementation(),
80 GetContext3d()->GetContextSupport()));
83 return gl_helper_.get();
86 scoped_ptr<media::VideoDecodeAccelerator>
87 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
88 DCHECK(task_runner_->BelongsToCurrentThread());
90 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
91 if (context && context->GetCommandBufferProxy()) {
92 return gpu_channel_host_->CreateVideoDecoder(
93 context->GetCommandBufferProxy()->GetRouteID());
96 return scoped_ptr<media::VideoDecodeAccelerator>();
99 scoped_ptr<media::VideoEncodeAccelerator>
100 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
101 DCHECK(task_runner_->BelongsToCurrentThread());
103 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
104 if (context && context->GetCommandBufferProxy()) {
105 return gpu_channel_host_->CreateVideoEncoder(
106 context->GetCommandBufferProxy()->GetRouteID());
109 return scoped_ptr<media::VideoEncodeAccelerator>();
112 bool RendererGpuVideoAcceleratorFactories::CreateTextures(
114 const gfx::Size& size,
115 std::vector<uint32>* texture_ids,
116 std::vector<gpu::Mailbox>* texture_mailboxes,
117 uint32 texture_target) {
118 DCHECK(task_runner_->BelongsToCurrentThread());
119 DCHECK(texture_target);
121 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
125 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
126 texture_ids->resize(count);
127 texture_mailboxes->resize(count);
128 gles2->GenTextures(count, &texture_ids->at(0));
129 for (int i = 0; i < count; ++i) {
130 gles2->ActiveTexture(GL_TEXTURE0);
131 uint32 texture_id = texture_ids->at(i);
132 gles2->BindTexture(texture_target, texture_id);
133 gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
134 gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
135 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
136 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
137 if (texture_target == GL_TEXTURE_2D) {
138 gles2->TexImage2D(texture_target,
148 gles2->GenMailboxCHROMIUM(texture_mailboxes->at(i).name);
149 gles2->ProduceTextureCHROMIUM(texture_target,
150 texture_mailboxes->at(i).name);
153 // We need ShallowFlushCHROMIUM() here to order the command buffer commands
154 // with respect to IPC to the GPU process, to guarantee that the decoder in
155 // the GPU process can use these textures as soon as it receives IPC
156 // notification of them.
157 gles2->ShallowFlushCHROMIUM();
158 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
162 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) {
163 DCHECK(task_runner_->BelongsToCurrentThread());
165 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
169 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
170 gles2->DeleteTextures(1, &texture_id);
171 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
174 void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) {
175 DCHECK(task_runner_->BelongsToCurrentThread());
177 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
181 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
182 gles2->WaitSyncPointCHROMIUM(sync_point);
184 // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to
185 // flush the command buffers to ensure that.
186 gles2->ShallowFlushCHROMIUM();
189 void RendererGpuVideoAcceleratorFactories::ReadPixels(
191 const gfx::Rect& visible_rect,
192 const SkBitmap& pixels) {
193 DCHECK(task_runner_->BelongsToCurrentThread());
195 GLHelper* gl_helper = GetGLHelper();
196 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
198 if (!gl_helper || !context)
201 // Copy texture from texture_id to tmp_texture as texture might be external
202 // (GL_TEXTURE_EXTERNAL_OES)
204 tmp_texture = gl_helper->CreateTexture();
205 context->copyTextureCHROMIUM(
206 GL_TEXTURE_2D, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
208 unsigned char* pixel_data =
209 static_cast<unsigned char*>(pixels.pixelRef()->pixels());
211 if (gl_helper->IsReadbackConfigSupported(pixels.colorType())) {
212 gl_helper->ReadbackTextureSync(
213 tmp_texture, visible_rect, pixel_data, pixels.colorType());
214 } else if (pixels.colorType() == kN32_SkColorType) {
215 gl_helper->ReadbackTextureSync(
216 tmp_texture, visible_rect, pixel_data, kRGBA_8888_SkColorType);
218 int pixel_count = visible_rect.width() * visible_rect.height();
219 uint32_t* pixels_ptr = static_cast<uint32_t*>(pixels.pixelRef()->pixels());
220 for (int i = 0; i < pixel_count; ++i) {
221 uint32_t r = pixels_ptr[i] & 0xFF;
222 uint32_t g = (pixels_ptr[i] >> 8) & 0xFF;
223 uint32_t b = (pixels_ptr[i] >> 16) & 0xFF;
224 uint32_t a = (pixels_ptr[i] >> 24) & 0xFF;
225 pixels_ptr[i] = (r << SK_R32_SHIFT) |
226 (g << SK_G32_SHIFT) |
227 (b << SK_B32_SHIFT) |
234 gl_helper->DeleteTexture(tmp_texture);
237 base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory(
239 DCHECK(task_runner_->BelongsToCurrentThread());
240 return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get());
243 scoped_refptr<base::SingleThreadTaskRunner>
244 RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
248 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
249 RendererGpuVideoAcceleratorFactories::
250 GetVideoEncodeAcceleratorSupportedProfiles() {
251 return gpu_channel_host_->gpu_info()
252 .video_encode_accelerator_supported_profiles;
255 } // namespace content