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/gl_context.h"
17 #include "ui/gl/scoped_make_current.h"
21 using gpu::gles2::ContextGroup
;
22 using gpu::gles2::GLES2Decoder
;
23 using gpu::gles2::TextureManager
;
24 using gpu::gles2::TextureRef
;
27 bool StreamTexture::Create(
28 GpuCommandBufferStub
* owner_stub
,
29 uint32 client_texture_id
,
31 GLES2Decoder
* decoder
= owner_stub
->decoder();
32 TextureManager
* texture_manager
=
33 decoder
->GetContextGroup()->texture_manager();
34 TextureRef
* texture
= texture_manager
->GetTexture(client_texture_id
);
36 if (texture
&& (!texture
->texture()->target() ||
37 texture
->texture()->target() == GL_TEXTURE_EXTERNAL_OES
)) {
39 // TODO: Ideally a valid image id was returned to the client so that
40 // it could then call glBindTexImage2D() for doing the following.
41 scoped_refptr
<gfx::GLImage
> gl_image(
42 new StreamTexture(owner_stub
, stream_id
, texture
->service_id()));
43 gfx::Size size
= gl_image
->GetSize();
44 texture_manager
->SetTarget(texture
, GL_TEXTURE_EXTERNAL_OES
);
45 texture_manager
->SetLevelInfo(texture
, GL_TEXTURE_EXTERNAL_OES
, 0, GL_RGBA
,
46 size
.width(), size
.height(), 1, 0, GL_RGBA
,
47 GL_UNSIGNED_BYTE
, gfx::Rect(size
));
48 texture_manager
->SetLevelImage(
49 texture
, GL_TEXTURE_EXTERNAL_OES
, 0, gl_image
.get());
56 StreamTexture::StreamTexture(GpuCommandBufferStub
* owner_stub
,
59 : surface_texture_(gfx::SurfaceTexture::Create(texture_id
)),
61 has_valid_frame_(false),
62 has_pending_frame_(false),
63 owner_stub_(owner_stub
),
67 owner_stub
->AddDestructionObserver(this);
68 memset(current_matrix_
, 0, sizeof(current_matrix_
));
69 owner_stub
->channel()->AddRoute(route_id
, this);
70 surface_texture_
->SetFrameAvailableCallback(base::Bind(
71 &StreamTexture::OnFrameAvailable
, weak_factory_
.GetWeakPtr()));
74 StreamTexture::~StreamTexture() {
76 owner_stub_
->RemoveDestructionObserver(this);
77 owner_stub_
->channel()->RemoveRoute(route_id_
);
81 void StreamTexture::OnWillDestroyStub() {
82 owner_stub_
->RemoveDestructionObserver(this);
83 owner_stub_
->channel()->RemoveRoute(route_id_
);
86 // If the owner goes away, there is no need to keep the SurfaceTexture around.
87 // The GL texture will keep working regardless with the currently bound frame.
88 surface_texture_
= NULL
;
91 void StreamTexture::Destroy(bool have_context
) {
95 void StreamTexture::WillUseTexImage() {
96 if (!owner_stub_
|| !surface_texture_
.get())
99 if (has_pending_frame_
) {
100 scoped_ptr
<ui::ScopedMakeCurrent
> scoped_make_current
;
101 bool needs_make_current
=
102 !owner_stub_
->decoder()->GetGLContext()->IsCurrent(NULL
);
103 // On Android we should not have to perform a real context switch here when
104 // using virtual contexts.
105 DCHECK(!needs_make_current
|| !owner_stub_
->decoder()
109 .use_virtualized_gl_contexts
);
110 if (needs_make_current
) {
111 scoped_make_current
.reset(new ui::ScopedMakeCurrent(
112 owner_stub_
->decoder()->GetGLContext(), owner_stub_
->surface()));
114 surface_texture_
->UpdateTexImage();
115 has_valid_frame_
= true;
116 has_pending_frame_
= false;
117 if (scoped_make_current
.get()) {
118 // UpdateTexImage() implies glBindTexture().
119 // The cmd decoder takes care of restoring the binding for this GLImage as
120 // far as the current context is concerned, but if we temporarily change
121 // it, we have to keep the state intact in *that* context also.
122 const gpu::gles2::ContextState
* state
=
123 owner_stub_
->decoder()->GetContextState();
124 const gpu::gles2::TextureUnit
& active_unit
=
125 state
->texture_units
[state
->active_texture_unit
];
126 glBindTexture(GL_TEXTURE_EXTERNAL_OES
,
127 active_unit
.bound_texture_external_oes
.get()
128 ? active_unit
.bound_texture_external_oes
->service_id()
133 if (has_listener_
&& has_valid_frame_
) {
135 surface_texture_
->GetTransformMatrix(mtx
);
137 // Only query the matrix once we have bound a valid frame.
138 if (memcmp(current_matrix_
, mtx
, sizeof(mtx
)) != 0) {
139 memcpy(current_matrix_
, mtx
, sizeof(mtx
));
141 GpuStreamTextureMsg_MatrixChanged_Params params
;
142 memcpy(¶ms
.m00
, mtx
, sizeof(mtx
));
143 owner_stub_
->channel()->Send(
144 new GpuStreamTextureMsg_MatrixChanged(route_id_
, params
));
149 void StreamTexture::OnFrameAvailable() {
150 has_pending_frame_
= true;
151 if (has_listener_
&& owner_stub_
) {
152 owner_stub_
->channel()->Send(
153 new GpuStreamTextureMsg_FrameAvailable(route_id_
));
157 gfx::Size
StreamTexture::GetSize() {
161 unsigned StreamTexture::GetInternalFormat() {
165 bool StreamTexture::OnMessageReceived(const IPC::Message
& message
) {
167 IPC_BEGIN_MESSAGE_MAP(StreamTexture
, message
)
168 IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_StartListening
, OnStartListening
)
169 IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_EstablishPeer
, OnEstablishPeer
)
170 IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_SetSize
, OnSetSize
)
171 IPC_MESSAGE_UNHANDLED(handled
= false)
172 IPC_END_MESSAGE_MAP()
178 void StreamTexture::OnStartListening() {
179 DCHECK(!has_listener_
);
180 has_listener_
= true;
183 void StreamTexture::OnEstablishPeer(int32 primary_id
, int32 secondary_id
) {
187 base::ProcessHandle process
= owner_stub_
->channel()->renderer_pid();
189 SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
190 process
, surface_texture_
, primary_id
, secondary_id
);
193 bool StreamTexture::BindTexImage(unsigned target
) {
198 void StreamTexture::ReleaseTexImage(unsigned target
) {
202 bool StreamTexture::CopyTexSubImage(unsigned target
,
203 const gfx::Point
& offset
,
204 const gfx::Rect
& rect
) {
208 bool StreamTexture::ScheduleOverlayPlane(gfx::AcceleratedWidget widget
,
210 gfx::OverlayTransform transform
,
211 const gfx::Rect
& bounds_rect
,
212 const gfx::RectF
& crop_rect
) {
217 } // namespace content