Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / stream_texture_android.cc
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
3 // found in the LICENSE file.
4
5 #include "content/common/gpu/stream_texture_android.h"
6
7 #include "base/bind.h"
8 #include "content/common/android/surface_texture_peer.h"
9 #include "content/common/gpu/gpu_channel.h"
10 #include "content/common/gpu/gpu_messages.h"
11 #include "gpu/command_buffer/service/context_group.h"
12 #include "gpu/command_buffer/service/context_state.h"
13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
14 #include "gpu/command_buffer/service/texture_manager.h"
15 #include "ui/gfx/size.h"
16 #include "ui/gl/scoped_make_current.h"
17
18 namespace content {
19
20 using gpu::gles2::ContextGroup;
21 using gpu::gles2::GLES2Decoder;
22 using gpu::gles2::TextureManager;
23 using gpu::gles2::TextureRef;
24
25 // static
26 bool StreamTexture::Create(
27     GpuCommandBufferStub* owner_stub,
28     uint32 client_texture_id,
29     int stream_id) {
30   GLES2Decoder* decoder = owner_stub->decoder();
31   TextureManager* texture_manager =
32       decoder->GetContextGroup()->texture_manager();
33   TextureRef* texture = texture_manager->GetTexture(client_texture_id);
34
35   if (texture && (!texture->texture()->target() ||
36                   texture->texture()->target() == GL_TEXTURE_EXTERNAL_OES)) {
37
38     // TODO: Ideally a valid image id was returned to the client so that
39     // it could then call glBindTexImage2D() for doing the following.
40     scoped_refptr<gfx::GLImage> gl_image(
41         new StreamTexture(owner_stub, stream_id, texture->service_id()));
42     gfx::Size size = gl_image->GetSize();
43     texture_manager->SetTarget(texture, GL_TEXTURE_EXTERNAL_OES);
44     texture_manager->SetLevelInfo(texture,
45                                   GL_TEXTURE_EXTERNAL_OES,
46                                   0,
47                                   GL_RGBA,
48                                   size.width(),
49                                   size.height(),
50                                   1,
51                                   0,
52                                   GL_RGBA,
53                                   GL_UNSIGNED_BYTE,
54                                   true);
55     texture_manager->SetLevelImage(
56         texture, GL_TEXTURE_EXTERNAL_OES, 0, gl_image.get());
57     return true;
58   }
59
60   return false;
61 }
62
63 StreamTexture::StreamTexture(GpuCommandBufferStub* owner_stub,
64                              int32 route_id,
65                              uint32 texture_id)
66     : surface_texture_(gfx::SurfaceTexture::Create(texture_id)),
67       size_(0, 0),
68       has_valid_frame_(false),
69       has_pending_frame_(false),
70       owner_stub_(owner_stub),
71       route_id_(route_id),
72       has_listener_(false),
73       weak_factory_(this) {
74   owner_stub->AddDestructionObserver(this);
75   memset(current_matrix_, 0, sizeof(current_matrix_));
76   owner_stub->channel()->AddRoute(route_id, this);
77   surface_texture_->SetFrameAvailableCallback(base::Bind(
78       &StreamTexture::OnFrameAvailable, weak_factory_.GetWeakPtr()));
79 }
80
81 StreamTexture::~StreamTexture() {
82   if (owner_stub_) {
83     owner_stub_->RemoveDestructionObserver(this);
84     owner_stub_->channel()->RemoveRoute(route_id_);
85   }
86 }
87
88 void StreamTexture::OnWillDestroyStub() {
89   owner_stub_->RemoveDestructionObserver(this);
90   owner_stub_->channel()->RemoveRoute(route_id_);
91   owner_stub_ = NULL;
92
93   // If the owner goes away, there is no need to keep the SurfaceTexture around.
94   // The GL texture will keep working regardless with the currently bound frame.
95   surface_texture_ = NULL;
96 }
97
98 void StreamTexture::Destroy(bool have_context) {
99   NOTREACHED();
100 }
101
102 void StreamTexture::WillUseTexImage() {
103   if (!owner_stub_ || !surface_texture_.get())
104     return;
105
106   if (has_pending_frame_) {
107     scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
108     bool needs_make_current =
109         !owner_stub_->decoder()->GetGLContext()->IsCurrent(NULL);
110     // On Android we should not have to perform a real context switch here when
111     // using virtual contexts.
112     DCHECK(!needs_make_current || !owner_stub_->decoder()
113                                        ->GetContextGroup()
114                                        ->feature_info()
115                                        ->workarounds()
116                                        .use_virtualized_gl_contexts);
117     if (needs_make_current) {
118       scoped_make_current.reset(new ui::ScopedMakeCurrent(
119           owner_stub_->decoder()->GetGLContext(), owner_stub_->surface()));
120     }
121     surface_texture_->UpdateTexImage();
122     has_valid_frame_ = true;
123     has_pending_frame_ = false;
124     if (scoped_make_current.get()) {
125       // UpdateTexImage() implies glBindTexture().
126       // The cmd decoder takes care of restoring the binding for this GLImage as
127       // far as the current context is concerned, but if we temporarily change
128       // it, we have to keep the state intact in *that* context also.
129       const gpu::gles2::ContextState* state =
130           owner_stub_->decoder()->GetContextState();
131       const gpu::gles2::TextureUnit& active_unit =
132           state->texture_units[state->active_texture_unit];
133       glBindTexture(GL_TEXTURE_EXTERNAL_OES,
134                     active_unit.bound_texture_external_oes.get()
135                         ? active_unit.bound_texture_external_oes->service_id()
136                         : 0);
137     }
138   }
139
140   if (has_listener_ && has_valid_frame_) {
141     float mtx[16];
142     surface_texture_->GetTransformMatrix(mtx);
143
144     // Only query the matrix once we have bound a valid frame.
145     if (memcmp(current_matrix_, mtx, sizeof(mtx)) != 0) {
146       memcpy(current_matrix_, mtx, sizeof(mtx));
147
148       GpuStreamTextureMsg_MatrixChanged_Params params;
149       memcpy(&params.m00, mtx, sizeof(mtx));
150       owner_stub_->channel()->Send(
151           new GpuStreamTextureMsg_MatrixChanged(route_id_, params));
152     }
153   }
154 }
155
156 void StreamTexture::OnFrameAvailable() {
157   has_pending_frame_ = true;
158   if (has_listener_ && owner_stub_) {
159     owner_stub_->channel()->Send(
160         new GpuStreamTextureMsg_FrameAvailable(route_id_));
161   }
162 }
163
164 gfx::Size StreamTexture::GetSize() {
165   return size_;
166 }
167
168 bool StreamTexture::OnMessageReceived(const IPC::Message& message) {
169   bool handled = true;
170   IPC_BEGIN_MESSAGE_MAP(StreamTexture, message)
171     IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_StartListening, OnStartListening)
172     IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_EstablishPeer, OnEstablishPeer)
173     IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_SetSize, OnSetSize)
174     IPC_MESSAGE_UNHANDLED(handled = false)
175   IPC_END_MESSAGE_MAP()
176
177   DCHECK(handled);
178   return handled;
179 }
180
181 void StreamTexture::OnStartListening() {
182   DCHECK(!has_listener_);
183   has_listener_ = true;
184 }
185
186 void StreamTexture::OnEstablishPeer(int32 primary_id, int32 secondary_id) {
187   if (!owner_stub_)
188     return;
189
190   base::ProcessHandle process = owner_stub_->channel()->renderer_pid();
191
192   SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
193       process, surface_texture_, primary_id, secondary_id);
194 }
195
196 bool StreamTexture::BindTexImage(unsigned target) {
197   NOTREACHED();
198   return false;
199 }
200
201 void StreamTexture::ReleaseTexImage(unsigned target) {
202   NOTREACHED();
203 }
204
205 bool StreamTexture::CopyTexImage(unsigned target) {
206   return false;
207 }
208
209 bool StreamTexture::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
210                                          int z_order,
211                                          gfx::OverlayTransform transform,
212                                          const gfx::Rect& bounds_rect,
213                                          const gfx::RectF& crop_rect) {
214   NOTREACHED();
215   return false;
216 }
217
218 }  // namespace content