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.
5 #include "content/common/gpu/stream_texture_android.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/geometry/size.h"
16 #include "ui/gl/scoped_make_current.h"
20 using gpu::gles2::ContextGroup
;
21 using gpu::gles2::GLES2Decoder
;
22 using gpu::gles2::TextureManager
;
23 using gpu::gles2::TextureRef
;
26 bool StreamTexture::Create(
27 GpuCommandBufferStub
* owner_stub
,
28 uint32 client_texture_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
);
35 if (texture
&& (!texture
->texture()->target() ||
36 texture
->texture()->target() == GL_TEXTURE_EXTERNAL_OES
)) {
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
,
55 texture_manager
->SetLevelImage(
56 texture
, GL_TEXTURE_EXTERNAL_OES
, 0, gl_image
.get());
63 StreamTexture::StreamTexture(GpuCommandBufferStub
* owner_stub
,
66 : surface_texture_(gfx::SurfaceTexture::Create(texture_id
)),
68 has_valid_frame_(false),
69 has_pending_frame_(false),
70 owner_stub_(owner_stub
),
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()));
81 StreamTexture::~StreamTexture() {
83 owner_stub_
->RemoveDestructionObserver(this);
84 owner_stub_
->channel()->RemoveRoute(route_id_
);
88 void StreamTexture::OnWillDestroyStub() {
89 owner_stub_
->RemoveDestructionObserver(this);
90 owner_stub_
->channel()->RemoveRoute(route_id_
);
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
;
98 void StreamTexture::Destroy(bool have_context
) {
102 void StreamTexture::WillUseTexImage() {
103 if (!owner_stub_
|| !surface_texture_
.get())
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()
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()));
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()
140 if (has_listener_
&& has_valid_frame_
) {
142 surface_texture_
->GetTransformMatrix(mtx
);
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
));
148 GpuStreamTextureMsg_MatrixChanged_Params params
;
149 memcpy(¶ms
.m00
, mtx
, sizeof(mtx
));
150 owner_stub_
->channel()->Send(
151 new GpuStreamTextureMsg_MatrixChanged(route_id_
, params
));
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_
));
164 gfx::Size
StreamTexture::GetSize() {
168 bool StreamTexture::OnMessageReceived(const IPC::Message
& message
) {
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()
181 void StreamTexture::OnStartListening() {
182 DCHECK(!has_listener_
);
183 has_listener_
= true;
186 void StreamTexture::OnEstablishPeer(int32 primary_id
, int32 secondary_id
) {
190 base::ProcessHandle process
= owner_stub_
->channel()->renderer_pid();
192 SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
193 process
, surface_texture_
, primary_id
, secondary_id
);
196 bool StreamTexture::BindTexImage(unsigned target
) {
201 void StreamTexture::ReleaseTexImage(unsigned target
) {
205 bool StreamTexture::CopyTexImage(unsigned target
) {
209 bool StreamTexture::ScheduleOverlayPlane(gfx::AcceleratedWidget widget
,
211 gfx::OverlayTransform transform
,
212 const gfx::Rect
& bounds_rect
,
213 const gfx::RectF
& crop_rect
) {
218 } // namespace content