We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / content / common / gpu / stream_texture_android.cc
blob5985821862f418f8de2ae73981b8decd2bcb9bc3
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"
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/geometry/size.h"
16 #include "ui/gl/scoped_make_current.h"
18 namespace content {
20 using gpu::gles2::ContextGroup;
21 using gpu::gles2::GLES2Decoder;
22 using gpu::gles2::TextureManager;
23 using gpu::gles2::TextureRef;
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);
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,
47 GL_RGBA,
48 size.width(),
49 size.height(),
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;
60 return false;
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()));
81 StreamTexture::~StreamTexture() {
82 if (owner_stub_) {
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_);
91 owner_stub_ = NULL;
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) {
99 NOTREACHED();
102 void StreamTexture::WillUseTexImage() {
103 if (!owner_stub_ || !surface_texture_.get())
104 return;
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()));
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);
140 if (has_listener_ && has_valid_frame_) {
141 float mtx[16];
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(&params.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() {
165 return size_;
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()
177 DCHECK(handled);
178 return handled;
181 void StreamTexture::OnStartListening() {
182 DCHECK(!has_listener_);
183 has_listener_ = true;
186 void StreamTexture::OnEstablishPeer(int32 primary_id, int32 secondary_id) {
187 if (!owner_stub_)
188 return;
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) {
197 NOTREACHED();
198 return false;
201 void StreamTexture::ReleaseTexImage(unsigned target) {
202 NOTREACHED();
205 bool StreamTexture::CopyTexImage(unsigned target) {
206 return false;
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;
218 } // namespace content