chrome.bluetoothSocket: clean-up Listen functions
[chromium-blink-merge.git] / content / renderer / media / renderer_gpu_video_accelerator_factories.cc
blob94e0d78217fa621974b945fd79bbaee2756e8fd3
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"
7 #include <GLES2/gl2.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/gpu_channel_host.h"
14 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
15 #include "content/renderer/render_thread_impl.h"
16 #include "gpu/command_buffer/client/gles2_implementation.h"
17 #include "media/video/video_decode_accelerator.h"
18 #include "media/video/video_encode_accelerator.h"
19 #include "third_party/skia/include/core/SkBitmap.h"
20 #include "third_party/skia/include/core/SkPixelRef.h"
22 namespace content {
24 // static
25 scoped_refptr<RendererGpuVideoAcceleratorFactories>
26 RendererGpuVideoAcceleratorFactories::Create(
27 GpuChannelHost* gpu_channel_host,
28 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
29 const scoped_refptr<ContextProviderCommandBuffer>& context_provider) {
30 scoped_refptr<RendererGpuVideoAcceleratorFactories> factories =
31 new RendererGpuVideoAcceleratorFactories(
32 gpu_channel_host, message_loop_proxy, context_provider);
33 // Post task from outside constructor, since AddRef()/Release() is unsafe from
34 // within.
35 message_loop_proxy->PostTask(
36 FROM_HERE,
37 base::Bind(&RendererGpuVideoAcceleratorFactories::BindContext,
38 factories));
39 return factories;
42 RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
43 GpuChannelHost* gpu_channel_host,
44 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
45 const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
46 : task_runner_(message_loop_proxy),
47 gpu_channel_host_(gpu_channel_host),
48 context_provider_(context_provider),
49 thread_safe_sender_(ChildThread::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_)
63 return NULL;
64 if (context_provider_->IsContextLost()) {
65 context_provider_->VerifyContexts();
66 context_provider_ = NULL;
67 return NULL;
69 return context_provider_->WebContext3D();
72 scoped_ptr<media::VideoDecodeAccelerator>
73 RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
74 DCHECK(task_runner_->BelongsToCurrentThread());
76 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
77 if (context && context->GetCommandBufferProxy()) {
78 return gpu_channel_host_->CreateVideoDecoder(
79 context->GetCommandBufferProxy()->GetRouteID());
82 return scoped_ptr<media::VideoDecodeAccelerator>();
85 scoped_ptr<media::VideoEncodeAccelerator>
86 RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
87 DCHECK(task_runner_->BelongsToCurrentThread());
89 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
90 if (context && context->GetCommandBufferProxy()) {
91 return gpu_channel_host_->CreateVideoEncoder(
92 context->GetCommandBufferProxy()->GetRouteID());
95 return scoped_ptr<media::VideoEncodeAccelerator>();
98 bool RendererGpuVideoAcceleratorFactories::CreateTextures(
99 int32 count,
100 const gfx::Size& size,
101 std::vector<uint32>* texture_ids,
102 std::vector<gpu::Mailbox>* texture_mailboxes,
103 uint32 texture_target) {
104 DCHECK(task_runner_->BelongsToCurrentThread());
105 DCHECK(texture_target);
107 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
108 if (!context)
109 return false;
111 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
112 texture_ids->resize(count);
113 texture_mailboxes->resize(count);
114 gles2->GenTextures(count, &texture_ids->at(0));
115 for (int i = 0; i < count; ++i) {
116 gles2->ActiveTexture(GL_TEXTURE0);
117 uint32 texture_id = texture_ids->at(i);
118 gles2->BindTexture(texture_target, texture_id);
119 gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
120 gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
121 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
122 gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
123 if (texture_target == GL_TEXTURE_2D) {
124 gles2->TexImage2D(texture_target,
126 GL_RGBA,
127 size.width(),
128 size.height(),
130 GL_RGBA,
131 GL_UNSIGNED_BYTE,
132 NULL);
134 gles2->GenMailboxCHROMIUM(texture_mailboxes->at(i).name);
135 gles2->ProduceTextureCHROMIUM(texture_target,
136 texture_mailboxes->at(i).name);
139 // We need ShallowFlushCHROMIUM() here to order the command buffer commands
140 // with respect to IPC to the GPU process, to guarantee that the decoder in
141 // the GPU process can use these textures as soon as it receives IPC
142 // notification of them.
143 gles2->ShallowFlushCHROMIUM();
144 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
145 return true;
148 void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) {
149 DCHECK(task_runner_->BelongsToCurrentThread());
151 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
152 if (!context)
153 return;
155 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
156 gles2->DeleteTextures(1, &texture_id);
157 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
160 void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) {
161 DCHECK(task_runner_->BelongsToCurrentThread());
163 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
164 if (!context)
165 return;
167 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
168 gles2->WaitSyncPointCHROMIUM(sync_point);
170 // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to
171 // flush the command buffers to ensure that.
172 gles2->ShallowFlushCHROMIUM();
175 void RendererGpuVideoAcceleratorFactories::ReadPixels(
176 uint32 texture_id,
177 const gfx::Rect& visible_rect,
178 const SkBitmap& pixels) {
179 DCHECK(task_runner_->BelongsToCurrentThread());
181 WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
182 if (!context)
183 return;
185 gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
187 GLuint tmp_texture;
188 gles2->GenTextures(1, &tmp_texture);
189 gles2->BindTexture(GL_TEXTURE_2D, tmp_texture);
190 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
191 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
192 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
193 gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
194 context->copyTextureCHROMIUM(
195 GL_TEXTURE_2D, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
197 GLuint fb;
198 gles2->GenFramebuffers(1, &fb);
199 gles2->BindFramebuffer(GL_FRAMEBUFFER, fb);
200 gles2->FramebufferTexture2D(
201 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0);
202 gles2->PixelStorei(GL_PACK_ALIGNMENT, 4);
204 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
205 SK_A32_SHIFT == 24
206 GLenum skia_format = GL_BGRA_EXT;
207 GLenum read_format = GL_BGRA_EXT;
208 GLint supported_format = 0;
209 GLint supported_type = 0;
210 gles2->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &supported_format);
211 gles2->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &supported_type);
212 if (supported_format != GL_BGRA_EXT || supported_type != GL_UNSIGNED_BYTE) {
213 read_format = GL_RGBA;
215 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
216 SK_A32_SHIFT == 24
217 GLenum skia_format = GL_RGBA;
218 GLenum read_format = GL_RGBA;
219 #else
220 #error Unexpected Skia ARGB_8888 layout!
221 #endif
222 gles2->ReadPixels(visible_rect.x(),
223 visible_rect.y(),
224 visible_rect.width(),
225 visible_rect.height(),
226 read_format,
227 GL_UNSIGNED_BYTE,
228 pixels.pixelRef()->pixels());
229 gles2->DeleteFramebuffers(1, &fb);
230 gles2->DeleteTextures(1, &tmp_texture);
232 if (skia_format != read_format) {
233 DCHECK(read_format == GL_RGBA);
234 int pixel_count = visible_rect.width() * visible_rect.height();
235 uint32_t* pixels_ptr = static_cast<uint32_t*>(pixels.pixelRef()->pixels());
236 for (int i = 0; i < pixel_count; ++i) {
237 uint32_t r = pixels_ptr[i] & 0xFF;
238 uint32_t g = (pixels_ptr[i] >> 8) & 0xFF;
239 uint32_t b = (pixels_ptr[i] >> 16) & 0xFF;
240 uint32_t a = (pixels_ptr[i] >> 24) & 0xFF;
241 pixels_ptr[i] = (r << SK_R32_SHIFT) |
242 (g << SK_G32_SHIFT) |
243 (b << SK_B32_SHIFT) |
244 (a << SK_A32_SHIFT);
248 DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
251 base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory(
252 size_t size) {
253 DCHECK(task_runner_->BelongsToCurrentThread());
254 return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get());
257 scoped_refptr<base::SingleThreadTaskRunner>
258 RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
259 return task_runner_;
262 } // namespace content