OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/stream_texture_android.h" | 5 #include "content/common/gpu/stream_texture_android.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "content/common/android/surface_texture_peer.h" | 8 #include "content/common/android/surface_texture_peer.h" |
9 #include "content/common/gpu/gpu_channel.h" | 9 #include "content/common/gpu/gpu_channel.h" |
10 #include "content/common/gpu/gpu_messages.h" | 10 #include "content/common/gpu/gpu_messages.h" |
11 #include "gpu/command_buffer/service/context_group.h" | 11 #include "gpu/command_buffer/service/context_group.h" |
12 #include "gpu/command_buffer/service/context_state.h" | 12 #include "gpu/command_buffer/service/context_state.h" |
13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
14 #include "gpu/command_buffer/service/texture_manager.h" | 14 #include "gpu/command_buffer/service/texture_manager.h" |
| 15 #include "ipc/ipc_listener.h" |
15 #include "ui/gfx/geometry/size.h" | 16 #include "ui/gfx/geometry/size.h" |
| 17 #include "ui/gl/android/surface_texture.h" |
16 #include "ui/gl/gl_context.h" | 18 #include "ui/gl/gl_context.h" |
| 19 #include "ui/gl/gl_image.h" |
17 #include "ui/gl/scoped_make_current.h" | 20 #include "ui/gl/scoped_make_current.h" |
18 | 21 |
19 namespace content { | 22 namespace content { |
20 | 23 |
21 using gpu::gles2::ContextGroup; | 24 using gpu::gles2::ContextGroup; |
22 using gpu::gles2::GLES2Decoder; | 25 using gpu::gles2::GLES2Decoder; |
23 using gpu::gles2::TextureManager; | 26 using gpu::gles2::TextureManager; |
24 using gpu::gles2::TextureRef; | 27 using gpu::gles2::TextureRef; |
25 | 28 |
| 29 class StreamTexture : public gl::GLImage, |
| 30 public IPC::Listener, |
| 31 public GpuCommandBufferStub::DestructionObserver { |
| 32 public: |
| 33 static scoped_refptr<StreamTexture> Create(GpuCommandBufferStub* owner_stub, |
| 34 uint32 client_texture_id, |
| 35 int32 stream_id); |
| 36 |
| 37 void SetReleaseCallback(const base::Closure& release_callback) { |
| 38 release_callback_ = release_callback; |
| 39 } |
| 40 void SetSize(GpuCommandBufferStub* owner_stub, |
| 41 uint32 client_texture_id, |
| 42 size_t width, |
| 43 size_t height) { |
| 44 size_.SetSize(width, height); |
| 45 |
| 46 GLES2Decoder* decoder = owner_stub->decoder(); |
| 47 TextureManager* texture_manager = |
| 48 decoder->GetContextGroup()->texture_manager(); |
| 49 TextureRef* texture = texture_manager->GetTexture(client_texture_id); |
| 50 if (!texture || (texture->texture()->target() && |
| 51 texture->texture()->target() != GL_TEXTURE_EXTERNAL_OES)) { |
| 52 return; |
| 53 } |
| 54 |
| 55 // Prevent deletion on SetLevelInfo() |
| 56 scoped_refptr<StreamTexture> gl_image = this; |
| 57 texture_manager->SetLevelInfo( |
| 58 texture, GL_TEXTURE_EXTERNAL_OES, 0, GetInternalFormat(), width, height, |
| 59 1, 0, GetInternalFormat(), GL_UNSIGNED_BYTE, gfx::Rect(size_)); |
| 60 texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, |
| 61 gl_image.get(), |
| 62 gpu::gles2::Texture::UNBOUND); |
| 63 } |
| 64 |
| 65 private: |
| 66 StreamTexture(GpuCommandBufferStub* owner_stub, |
| 67 int32 route_id, |
| 68 uint32 texture_id); |
| 69 ~StreamTexture() override; |
| 70 |
| 71 // gl::GLImage implementation: |
| 72 void Destroy(bool have_context) override; |
| 73 gfx::Size GetSize() override; |
| 74 unsigned GetInternalFormat() override; |
| 75 bool BindTexImage(unsigned target) override; |
| 76 void ReleaseTexImage(unsigned target) override; |
| 77 bool CopyTexImage(unsigned target) override; |
| 78 bool CopyTexSubImage(unsigned target, |
| 79 const gfx::Point& offset, |
| 80 const gfx::Rect& rect) override; |
| 81 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
| 82 int z_order, |
| 83 gfx::OverlayTransform transform, |
| 84 const gfx::Rect& bounds_rect, |
| 85 const gfx::RectF& crop_rect) override; |
| 86 void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
| 87 uint64_t process_tracing_id, |
| 88 const std::string& dump_name) override; |
| 89 |
| 90 // GpuCommandBufferStub::DestructionObserver implementation. |
| 91 void OnWillDestroyStub() override; |
| 92 |
| 93 // Called when a new frame is available for the SurfaceTexture. |
| 94 void OnFrameAvailable(); |
| 95 |
| 96 // IPC::Listener implementation: |
| 97 bool OnMessageReceived(const IPC::Message& message) override; |
| 98 |
| 99 // IPC message handlers: |
| 100 void OnStartListening(); |
| 101 void OnEstablishPeer(int32 primary_id, int32 secondary_id); |
| 102 |
| 103 scoped_refptr<gfx::SurfaceTexture> surface_texture_; |
| 104 |
| 105 // Current transform matrix of the surface texture. |
| 106 float current_matrix_[16]; |
| 107 |
| 108 // Current size of the surface texture. |
| 109 gfx::Size size_; |
| 110 |
| 111 // Whether we ever bound a valid frame. |
| 112 bool has_valid_frame_; |
| 113 |
| 114 // Whether a new frame is available that we should update to. |
| 115 bool has_pending_frame_; |
| 116 |
| 117 GpuCommandBufferStub* owner_stub_; |
| 118 int32 route_id_; |
| 119 bool has_listener_; |
| 120 uint32 texture_id_; |
| 121 |
| 122 base::Closure release_callback_; |
| 123 |
| 124 base::WeakPtrFactory<StreamTexture> weak_factory_; |
| 125 DISALLOW_COPY_AND_ASSIGN(StreamTexture); |
| 126 }; |
| 127 |
26 // static | 128 // static |
27 bool StreamTexture::Create( | 129 scoped_refptr<StreamTexture> StreamTexture::Create( |
28 GpuCommandBufferStub* owner_stub, | 130 GpuCommandBufferStub* owner_stub, |
29 uint32 client_texture_id, | 131 uint32 client_texture_id, |
30 int stream_id) { | 132 int32 stream_id) { |
31 GLES2Decoder* decoder = owner_stub->decoder(); | 133 GLES2Decoder* decoder = owner_stub->decoder(); |
32 TextureManager* texture_manager = | 134 TextureManager* texture_manager = |
33 decoder->GetContextGroup()->texture_manager(); | 135 decoder->GetContextGroup()->texture_manager(); |
34 TextureRef* texture = texture_manager->GetTexture(client_texture_id); | 136 TextureRef* texture = texture_manager->GetTexture(client_texture_id); |
35 | 137 |
36 if (texture && (!texture->texture()->target() || | 138 if (texture && (!texture->texture()->target() || |
37 texture->texture()->target() == GL_TEXTURE_EXTERNAL_OES)) { | 139 texture->texture()->target() == GL_TEXTURE_EXTERNAL_OES)) { |
38 | 140 |
39 // TODO: Ideally a valid image id was returned to the client so that | 141 // TODO: Ideally a valid image id was returned to the client so that |
40 // it could then call glBindTexImage2D() for doing the following. | 142 // it could then call glBindTexImage2D() for doing the following. |
41 scoped_refptr<gl::GLImage> gl_image( | 143 scoped_refptr<StreamTexture> gl_image( |
42 new StreamTexture(owner_stub, stream_id, texture->service_id())); | 144 new StreamTexture(owner_stub, stream_id, texture->service_id())); |
43 gfx::Size size = gl_image->GetSize(); | 145 gfx::Size size = gl_image->GetSize(); |
44 texture_manager->SetTarget(texture, GL_TEXTURE_EXTERNAL_OES); | 146 texture_manager->SetTarget(texture, GL_TEXTURE_EXTERNAL_OES); |
45 texture_manager->SetLevelInfo(texture, GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, | 147 texture_manager->SetLevelInfo(texture, GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, |
46 size.width(), size.height(), 1, 0, GL_RGBA, | 148 size.width(), size.height(), 1, 0, GL_RGBA, |
47 GL_UNSIGNED_BYTE, gfx::Rect(size)); | 149 GL_UNSIGNED_BYTE, gfx::Rect(size)); |
48 texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, | 150 texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0, |
49 gl_image.get(), | 151 gl_image.get(), |
50 gpu::gles2::Texture::UNBOUND); | 152 gpu::gles2::Texture::UNBOUND); |
51 return true; | 153 return gl_image; |
52 } | 154 } |
53 | 155 |
54 return false; | 156 return nullptr; |
55 } | 157 } |
56 | 158 |
57 StreamTexture::StreamTexture(GpuCommandBufferStub* owner_stub, | 159 StreamTexture::StreamTexture(GpuCommandBufferStub* owner_stub, |
58 int32 route_id, | 160 int32 route_id, |
59 uint32 texture_id) | 161 uint32 texture_id) |
60 : surface_texture_(gfx::SurfaceTexture::Create(texture_id)), | 162 : surface_texture_(gfx::SurfaceTexture::Create(texture_id)), |
61 size_(0, 0), | 163 size_(0, 0), |
62 has_valid_frame_(false), | 164 has_valid_frame_(false), |
63 has_pending_frame_(false), | 165 has_pending_frame_(false), |
64 owner_stub_(owner_stub), | 166 owner_stub_(owner_stub), |
65 route_id_(route_id), | 167 route_id_(route_id), |
66 has_listener_(false), | 168 has_listener_(false), |
67 texture_id_(texture_id), | 169 texture_id_(texture_id), |
68 weak_factory_(this) { | 170 weak_factory_(this) { |
69 owner_stub->AddDestructionObserver(this); | 171 owner_stub->AddDestructionObserver(this); |
70 memset(current_matrix_, 0, sizeof(current_matrix_)); | 172 memset(current_matrix_, 0, sizeof(current_matrix_)); |
71 owner_stub->channel()->AddRoute(route_id, this); | 173 owner_stub->channel()->AddRoute(route_id, this); |
72 surface_texture_->SetFrameAvailableCallback(base::Bind( | 174 surface_texture_->SetFrameAvailableCallback(base::Bind( |
73 &StreamTexture::OnFrameAvailable, weak_factory_.GetWeakPtr())); | 175 &StreamTexture::OnFrameAvailable, weak_factory_.GetWeakPtr())); |
74 } | 176 } |
75 | 177 |
76 StreamTexture::~StreamTexture() { | 178 StreamTexture::~StreamTexture() { |
77 if (owner_stub_) { | 179 if (owner_stub_) { |
78 owner_stub_->RemoveDestructionObserver(this); | 180 owner_stub_->RemoveDestructionObserver(this); |
79 owner_stub_->channel()->RemoveRoute(route_id_); | 181 owner_stub_->channel()->RemoveRoute(route_id_); |
80 } | 182 } |
| 183 release_callback_.Run(); |
81 } | 184 } |
82 | 185 |
83 void StreamTexture::OnWillDestroyStub() { | 186 void StreamTexture::OnWillDestroyStub() { |
84 owner_stub_->RemoveDestructionObserver(this); | 187 owner_stub_->RemoveDestructionObserver(this); |
85 owner_stub_->channel()->RemoveRoute(route_id_); | 188 owner_stub_->channel()->RemoveRoute(route_id_); |
86 owner_stub_ = NULL; | 189 owner_stub_ = NULL; |
87 | 190 |
88 // If the owner goes away, there is no need to keep the SurfaceTexture around. | 191 // If the owner goes away, there is no need to keep the SurfaceTexture around. |
89 // The GL texture will keep working regardless with the currently bound frame. | 192 // The GL texture will keep working regardless with the currently bound frame. |
90 surface_texture_ = NULL; | 193 surface_texture_ = NULL; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 | 291 |
189 unsigned StreamTexture::GetInternalFormat() { | 292 unsigned StreamTexture::GetInternalFormat() { |
190 return GL_RGBA; | 293 return GL_RGBA; |
191 } | 294 } |
192 | 295 |
193 bool StreamTexture::OnMessageReceived(const IPC::Message& message) { | 296 bool StreamTexture::OnMessageReceived(const IPC::Message& message) { |
194 bool handled = true; | 297 bool handled = true; |
195 IPC_BEGIN_MESSAGE_MAP(StreamTexture, message) | 298 IPC_BEGIN_MESSAGE_MAP(StreamTexture, message) |
196 IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_StartListening, OnStartListening) | 299 IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_StartListening, OnStartListening) |
197 IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_EstablishPeer, OnEstablishPeer) | 300 IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_EstablishPeer, OnEstablishPeer) |
198 IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_SetSize, OnSetSize) | |
199 IPC_MESSAGE_UNHANDLED(handled = false) | 301 IPC_MESSAGE_UNHANDLED(handled = false) |
200 IPC_END_MESSAGE_MAP() | 302 IPC_END_MESSAGE_MAP() |
201 | 303 |
202 DCHECK(handled); | 304 DCHECK(handled); |
203 return handled; | 305 return handled; |
204 } | 306 } |
205 | 307 |
206 void StreamTexture::OnStartListening() { | 308 void StreamTexture::OnStartListening() { |
207 DCHECK(!has_listener_); | 309 DCHECK(!has_listener_); |
208 has_listener_ = true; | 310 has_listener_ = true; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 NOTREACHED(); | 343 NOTREACHED(); |
242 return false; | 344 return false; |
243 } | 345 } |
244 | 346 |
245 void StreamTexture::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, | 347 void StreamTexture::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
246 uint64_t process_tracing_id, | 348 uint64_t process_tracing_id, |
247 const std::string& dump_name) { | 349 const std::string& dump_name) { |
248 // TODO(ericrk): Add OnMemoryDump for GLImages. crbug.com/514914 | 350 // TODO(ericrk): Add OnMemoryDump for GLImages. crbug.com/514914 |
249 } | 351 } |
250 | 352 |
| 353 StreamTextureManager::StreamTextureManager() : weak_factory_(this) {} |
| 354 |
| 355 StreamTextureManager::~StreamTextureManager() { |
| 356 if (!stream_textures_.empty()) { |
| 357 LOG(WARNING) << "Undestroyed stream textures while tearing down " |
| 358 "StreamTextureManager."; |
| 359 } |
| 360 } |
| 361 |
| 362 bool StreamTextureManager::CreateStreamTexture(GpuCommandBufferStub* owner_stub, |
| 363 uint32 client_texture_id, |
| 364 int32 stream_id) { |
| 365 CalledOnValidThread(); |
| 366 DCHECK_EQ(static_cast<size_t>(0), stream_textures_.count(stream_id)); |
| 367 scoped_refptr<StreamTexture> stream_texture = |
| 368 StreamTexture::Create(owner_stub, client_texture_id, stream_id); |
| 369 if (!stream_texture) |
| 370 return false; |
| 371 base::Closure release_callback = |
| 372 base::Bind(&StreamTextureManager::OnReleaseStreamTexture, |
| 373 weak_factory_.GetWeakPtr(), stream_id); |
| 374 stream_texture->SetReleaseCallback(release_callback); |
| 375 stream_textures_[stream_id] = stream_texture.get(); |
| 376 return true; |
| 377 } |
| 378 |
| 379 void StreamTextureManager::SetStreamTextureSize( |
| 380 GpuCommandBufferStub* owner_stub, |
| 381 uint32 client_texture_id, |
| 382 int32 stream_id, |
| 383 size_t width, |
| 384 size_t height) { |
| 385 CalledOnValidThread(); |
| 386 if (!stream_textures_.count(stream_id)) |
| 387 return; |
| 388 stream_textures_[stream_id]->SetSize(owner_stub, client_texture_id, width, |
| 389 height); |
| 390 } |
| 391 |
| 392 void StreamTextureManager::OnReleaseStreamTexture(int32 stream_id) { |
| 393 CalledOnValidThread(); |
| 394 DCHECK_EQ(static_cast<size_t>(1), stream_textures_.count(stream_id)); |
| 395 stream_textures_.erase(stream_id); |
| 396 } |
| 397 |
251 } // namespace content | 398 } // namespace content |
OLD | NEW |