Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / renderer_gpu_video_accelerator_factories.cc
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.
4
5 #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
6
7 #include <GLES2/gl2.h>
8 #include <GLES2/gl2ext.h>
9
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/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"
21 #include "third_party/skia/include/core/SkBitmap.h"
22 #include "third_party/skia/include/core/SkPixelRef.h"
23
24 namespace content {
25
26 // static
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   scoped_refptr<RendererGpuVideoAcceleratorFactories> factories =
33       new RendererGpuVideoAcceleratorFactories(
34           gpu_channel_host, task_runner, context_provider);
35   // Post task from outside constructor, since AddRef()/Release() is unsafe from
36   // within.
37   task_runner->PostTask(
38       FROM_HERE,
39       base::Bind(&RendererGpuVideoAcceleratorFactories::BindContext,
40                  factories));
41   return factories;
42 }
43
44 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
45     GpuChannelHost* gpu_channel_host,
46     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
47     const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
48     : task_runner_(task_runner),
49       gpu_channel_host_(gpu_channel_host),
50       context_provider_(context_provider),
51       thread_safe_sender_(ChildThread::current()->thread_safe_sender()) {}
52
53 RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}
54
55 void RendererGpuVideoAcceleratorFactories::BindContext() {
56   DCHECK(task_runner_->BelongsToCurrentThread());
57   if (!context_provider_->BindToCurrentThread())
58     context_provider_ = NULL;
59 }
60
61 WebGraphicsContext3DCommandBufferImpl*
62 RendererGpuVideoAcceleratorFactories::GetContext3d() {
63   DCHECK(task_runner_->BelongsToCurrentThread());
64   if (!context_provider_.get())
65     return NULL;
66   if (context_provider_->IsContextLost()) {
67     context_provider_->VerifyContexts();
68     context_provider_ = NULL;
69     gl_helper_.reset(NULL);
70     return NULL;
71   }
72   return context_provider_->WebContext3D();
73 }
74
75 GLHelper* RendererGpuVideoAcceleratorFactories::GetGLHelper() {
76   if (!GetContext3d())
77     return NULL;
78
79   if (gl_helper_.get() == NULL) {
80     gl_helper_.reset(new GLHelper(GetContext3d()->GetImplementation(),
81                                   GetContext3d()->GetContextSupport()));
82   }
83
84   return gl_helper_.get();
85 }
86
87 scoped_ptr<media::VideoDecodeAccelerator>
88 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
89   DCHECK(task_runner_->BelongsToCurrentThread());
90
91   WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
92   if (context && context->GetCommandBufferProxy()) {
93     return gpu_channel_host_->CreateVideoDecoder(
94         context->GetCommandBufferProxy()->GetRouteID());
95   }
96
97   return scoped_ptr<media::VideoDecodeAccelerator>();
98 }
99
100 scoped_ptr<media::VideoEncodeAccelerator>
101 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
102   DCHECK(task_runner_->BelongsToCurrentThread());
103
104   WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
105   if (context && context->GetCommandBufferProxy()) {
106     return gpu_channel_host_->CreateVideoEncoder(
107         context->GetCommandBufferProxy()->GetRouteID());
108   }
109
110   return scoped_ptr<media::VideoEncodeAccelerator>();
111 }
112
113 bool RendererGpuVideoAcceleratorFactories::CreateTextures(
114     int32 count,
115     const gfx::Size& size,
116     std::vector<uint32>* texture_ids,
117     std::vector<gpu::Mailbox>* texture_mailboxes,
118     uint32 texture_target) {
119   DCHECK(task_runner_->BelongsToCurrentThread());
120   DCHECK(texture_target);
121
122   WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
123   if (!context)
124     return false;
125
126   gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
127   texture_ids->resize(count);
128   texture_mailboxes->resize(count);
129   gles2->GenTextures(count, &texture_ids->at(0));
130   for (int i = 0; i < count; ++i) {
131     gles2->ActiveTexture(GL_TEXTURE0);
132     uint32 texture_id = texture_ids->at(i);
133     gles2->BindTexture(texture_target, texture_id);
134     gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
135     gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
136     gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
137     gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
138     if (texture_target == GL_TEXTURE_2D) {
139       gles2->TexImage2D(texture_target,
140                         0,
141                         GL_RGBA,
142                         size.width(),
143                         size.height(),
144                         0,
145                         GL_RGBA,
146                         GL_UNSIGNED_BYTE,
147                         NULL);
148     }
149     gles2->GenMailboxCHROMIUM(texture_mailboxes->at(i).name);
150     gles2->ProduceTextureCHROMIUM(texture_target,
151                                   texture_mailboxes->at(i).name);
152   }
153
154   // We need ShallowFlushCHROMIUM() here to order the command buffer commands
155   // with respect to IPC to the GPU process, to guarantee that the decoder in
156   // the GPU process can use these textures as soon as it receives IPC
157   // notification of them.
158   gles2->ShallowFlushCHROMIUM();
159   DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
160   return true;
161 }
162
163 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) {
164   DCHECK(task_runner_->BelongsToCurrentThread());
165
166   WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
167   if (!context)
168     return;
169
170   gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
171   gles2->DeleteTextures(1, &texture_id);
172   DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
173 }
174
175 void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) {
176   DCHECK(task_runner_->BelongsToCurrentThread());
177
178   WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
179   if (!context)
180     return;
181
182   gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
183   gles2->WaitSyncPointCHROMIUM(sync_point);
184
185   // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to
186   // flush the command buffers to ensure that.
187   gles2->ShallowFlushCHROMIUM();
188 }
189
190 void RendererGpuVideoAcceleratorFactories::ReadPixels(
191     uint32 texture_id,
192     const gfx::Rect& visible_rect,
193     const SkBitmap& pixels) {
194   DCHECK(task_runner_->BelongsToCurrentThread());
195
196   GLHelper* gl_helper = GetGLHelper();
197   WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
198
199   if (!gl_helper || !context)
200     return;
201
202   // Copy texture from texture_id to tmp_texture as texture might be external
203   // (GL_TEXTURE_EXTERNAL_OES)
204   GLuint tmp_texture;
205   tmp_texture = gl_helper->CreateTexture();
206   context->copyTextureCHROMIUM(
207       GL_TEXTURE_2D, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
208
209   unsigned char* pixel_data =
210       static_cast<unsigned char*>(pixels.pixelRef()->pixels());
211
212   if (gl_helper->IsReadbackConfigSupported(pixels.colorType())) {
213     gl_helper->ReadbackTextureSync(
214         tmp_texture, visible_rect, pixel_data, pixels.colorType());
215   } else if (pixels.colorType() == kN32_SkColorType) {
216     gl_helper->ReadbackTextureSync(
217         tmp_texture, visible_rect, pixel_data, kRGBA_8888_SkColorType);
218
219     int pixel_count = visible_rect.width() * visible_rect.height();
220     uint32_t* pixels_ptr = static_cast<uint32_t*>(pixels.pixelRef()->pixels());
221     for (int i = 0; i < pixel_count; ++i) {
222         uint32_t r = pixels_ptr[i] & 0xFF;
223         uint32_t g = (pixels_ptr[i] >> 8) & 0xFF;
224         uint32_t b = (pixels_ptr[i] >> 16) & 0xFF;
225         uint32_t a = (pixels_ptr[i] >> 24) & 0xFF;
226         pixels_ptr[i] = (r << SK_R32_SHIFT) |
227                         (g << SK_G32_SHIFT) |
228                         (b << SK_B32_SHIFT) |
229                         (a << SK_A32_SHIFT);
230     }
231   } else {
232     NOTREACHED();
233   }
234
235   gl_helper->DeleteTexture(tmp_texture);
236 }
237
238 base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory(
239     size_t size) {
240   DCHECK(task_runner_->BelongsToCurrentThread());
241   return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get());
242 }
243
244 scoped_refptr<base::SingleThreadTaskRunner>
245 RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
246   return task_runner_;
247 }
248
249 std::vector<media::VideoEncodeAccelerator::SupportedProfile>
250 RendererGpuVideoAcceleratorFactories::
251     GetVideoEncodeAcceleratorSupportedProfiles() {
252   return GpuVideoEncodeAcceleratorHost::ConvertGpuToMediaProfiles(
253       gpu_channel_host_->gpu_info()
254           .video_encode_accelerator_supported_profiles);
255 }
256
257 }  // namespace content