Index: content/common/gpu/stream_texture_android.cc |
diff --git a/content/common/gpu/stream_texture_android.cc b/content/common/gpu/stream_texture_android.cc |
index 0636fce51e0561524365b0a106884f63815cb794..16f7b9468099fe8fcd1101bc8e61d861c4baec63 100644 |
--- a/content/common/gpu/stream_texture_android.cc |
+++ b/content/common/gpu/stream_texture_android.cc |
@@ -7,7 +7,6 @@ |
#include <string.h> |
#include "base/bind.h" |
-#include "base/strings/stringize_macros.h" |
#include "content/common/android/surface_texture_peer.h" |
#include "content/common/gpu/gpu_channel.h" |
#include "content/common/gpu/gpu_messages.h" |
@@ -17,8 +16,6 @@ |
#include "gpu/command_buffer/service/texture_manager.h" |
#include "ui/gfx/geometry/size.h" |
#include "ui/gl/gl_context.h" |
-#include "ui/gl/gl_helper.h" |
-#include "ui/gl/scoped_binders.h" |
#include "ui/gl/scoped_make_current.h" |
namespace content { |
@@ -69,12 +66,6 @@ |
route_id_(route_id), |
has_listener_(false), |
texture_id_(texture_id), |
- framebuffer_(0), |
- vertex_shader_(0), |
- fragment_shader_(0), |
- program_(0), |
- vertex_buffer_(0), |
- u_xform_location_(-1), |
weak_factory_(this) { |
owner_stub->AddDestructionObserver(this); |
memset(current_matrix_, 0, sizeof(current_matrix_)); |
@@ -93,23 +84,6 @@ |
void StreamTexture::OnWillDestroyStub() { |
owner_stub_->RemoveDestructionObserver(this); |
owner_stub_->channel()->RemoveRoute(route_id_); |
- |
- if (framebuffer_) { |
- scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current(MakeStubCurrent()); |
- |
- glDeleteProgram(program_); |
- glDeleteShader(vertex_shader_); |
- glDeleteShader(fragment_shader_); |
- glDeleteBuffersARB(1, &vertex_buffer_); |
- glDeleteFramebuffersEXT(1, &framebuffer_); |
- program_ = 0; |
- vertex_shader_ = 0; |
- fragment_shader_ = 0; |
- vertex_buffer_ = 0; |
- framebuffer_ = 0; |
- u_xform_location_ = -1; |
- } |
- |
owner_stub_ = NULL; |
// If the owner goes away, there is no need to keep the SurfaceTexture around. |
@@ -121,75 +95,7 @@ |
NOTREACHED(); |
} |
-scoped_ptr<ui::ScopedMakeCurrent> StreamTexture::MakeStubCurrent() { |
- scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current; |
- bool needs_make_current = |
- !owner_stub_->decoder()->GetGLContext()->IsCurrent(NULL); |
- // On Android we should not have to perform a real context switch here when |
- // using virtual contexts. |
- DCHECK(!needs_make_current || |
- !owner_stub_->decoder() |
- ->GetContextGroup() |
- ->feature_info() |
- ->workarounds() |
- .use_virtualized_gl_contexts); |
- if (needs_make_current) { |
- scoped_make_current.reset(new ui::ScopedMakeCurrent( |
- owner_stub_->decoder()->GetGLContext(), owner_stub_->surface())); |
- } |
- return scoped_make_current; |
-} |
- |
-void StreamTexture::UpdateTexImage() { |
- DCHECK(surface_texture_.get()); |
- DCHECK(owner_stub_); |
- |
- if (!has_pending_frame_) return; |
- |
- scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current(MakeStubCurrent()); |
- |
- surface_texture_->UpdateTexImage(); |
- |
- has_valid_frame_ = true; |
- has_pending_frame_ = false; |
- |
- float mtx[16]; |
- surface_texture_->GetTransformMatrix(mtx); |
- |
- if (memcmp(current_matrix_, mtx, sizeof(mtx)) != 0) { |
- memcpy(current_matrix_, mtx, sizeof(mtx)); |
- |
- if (has_listener_) { |
- GpuStreamTextureMsg_MatrixChanged_Params params; |
- memcpy(¶ms.m00, mtx, sizeof(mtx)); |
- owner_stub_->channel()->Send( |
- new GpuStreamTextureMsg_MatrixChanged(route_id_, params)); |
- } |
- } |
- |
- if (scoped_make_current.get()) { |
- // UpdateTexImage() implies glBindTexture(). |
- // The cmd decoder takes care of restoring the binding for this GLImage as |
- // far as the current context is concerned, but if we temporarily change |
- // it, we have to keep the state intact in *that* context also. |
- const gpu::gles2::ContextState* state = |
- owner_stub_->decoder()->GetContextState(); |
- const gpu::gles2::TextureUnit& active_unit = |
- state->texture_units[state->active_texture_unit]; |
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, |
- active_unit.bound_texture_external_oes.get() |
- ? active_unit.bound_texture_external_oes->service_id() |
- : 0); |
- } |
-} |
- |
bool StreamTexture::CopyTexImage(unsigned target) { |
- if (target == GL_TEXTURE_2D) { |
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.width(), size_.height(), 0, |
- GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
- return CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(), gfx::Rect(size_)); |
- } |
- |
if (target != GL_TEXTURE_EXTERNAL_OES) |
return false; |
@@ -205,7 +111,39 @@ |
if (static_cast<unsigned>(texture_id) != texture_id_) |
return false; |
- UpdateTexImage(); |
+ if (has_pending_frame_) { |
+ scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current; |
+ bool needs_make_current = |
+ !owner_stub_->decoder()->GetGLContext()->IsCurrent(NULL); |
+ // On Android we should not have to perform a real context switch here when |
+ // using virtual contexts. |
+ DCHECK(!needs_make_current || !owner_stub_->decoder() |
+ ->GetContextGroup() |
+ ->feature_info() |
+ ->workarounds() |
+ .use_virtualized_gl_contexts); |
+ if (needs_make_current) { |
+ scoped_make_current.reset(new ui::ScopedMakeCurrent( |
+ owner_stub_->decoder()->GetGLContext(), owner_stub_->surface())); |
+ } |
+ surface_texture_->UpdateTexImage(); |
+ has_valid_frame_ = true; |
+ has_pending_frame_ = false; |
+ if (scoped_make_current.get()) { |
+ // UpdateTexImage() implies glBindTexture(). |
+ // The cmd decoder takes care of restoring the binding for this GLImage as |
+ // far as the current context is concerned, but if we temporarily change |
+ // it, we have to keep the state intact in *that* context also. |
+ const gpu::gles2::ContextState* state = |
+ owner_stub_->decoder()->GetContextState(); |
+ const gpu::gles2::TextureUnit& active_unit = |
+ state->texture_units[state->active_texture_unit]; |
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, |
+ active_unit.bound_texture_external_oes.get() |
+ ? active_unit.bound_texture_external_oes->service_id() |
+ : 0); |
+ } |
+ } |
TextureManager* texture_manager = |
owner_stub_->decoder()->GetContextGroup()->texture_manager(); |
@@ -219,6 +157,21 @@ |
gpu::gles2::Texture::UNBOUND); |
} |
+ if (has_listener_ && has_valid_frame_) { |
+ float mtx[16]; |
+ surface_texture_->GetTransformMatrix(mtx); |
+ |
+ // Only query the matrix once we have bound a valid frame. |
+ if (memcmp(current_matrix_, mtx, sizeof(mtx)) != 0) { |
+ memcpy(current_matrix_, mtx, sizeof(mtx)); |
+ |
+ GpuStreamTextureMsg_MatrixChanged_Params params; |
+ memcpy(¶ms.m00, mtx, sizeof(mtx)); |
+ owner_stub_->channel()->Send( |
+ new GpuStreamTextureMsg_MatrixChanged(route_id_, params)); |
+ } |
+ } |
+ |
return true; |
} |
@@ -278,89 +231,7 @@ |
bool StreamTexture::CopyTexSubImage(unsigned target, |
const gfx::Point& offset, |
const gfx::Rect& rect) { |
- if (target != GL_TEXTURE_2D) |
- return false; |
- |
- if (!owner_stub_ || !surface_texture_.get()) |
- return true; |
- |
- if (!offset.IsOrigin()) { |
- LOG(ERROR) << "Non-origin offset is not supported"; |
- return false; |
- } |
- |
- if (rect != gfx::Rect(size_)) { |
- LOG(ERROR) << "Sub-rectangle is not supported"; |
- return false; |
- } |
- |
- GLint target_texture = 0; |
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &target_texture); |
- DCHECK(target_texture); |
- |
- UpdateTexImage(); |
- |
- if (!framebuffer_) { |
- glGenFramebuffersEXT(1, &framebuffer_); |
- |
- // clang-format off |
- const char kVertexShader[] = STRINGIZE( |
- attribute vec2 a_position; |
- varying vec2 v_texCoord; |
- uniform mat4 u_xform; |
- void main() { |
- gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); |
- vec2 uv_untransformed = (a_position + vec2(1.0, 1.0)) * 0.5; |
- v_texCoord = (u_xform * vec4(uv_untransformed, 0.0, 1.0)).xy; |
- } |
- ); |
- const char kFragmentShader[] = |
- "#extension GL_OES_EGL_image_external : require\n" STRINGIZE( |
- precision mediump float; |
- uniform samplerExternalOES a_texture; |
- varying vec2 v_texCoord; |
- void main() { |
- gl_FragColor = texture2D(a_texture, v_texCoord); |
- } |
- ); |
- // clang-format on |
- |
- vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer(); |
- vertex_shader_ = gfx::GLHelper::LoadShader(GL_VERTEX_SHADER, kVertexShader); |
- fragment_shader_ = |
- gfx::GLHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShader); |
- program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_); |
- gfx::ScopedUseProgram use_program(program_); |
- int sampler_location = glGetUniformLocation(program_, "a_texture"); |
- DCHECK_NE(-1, sampler_location); |
- glUniform1i(sampler_location, 0); |
- u_xform_location_ = glGetUniformLocation(program_, "u_xform"); |
- DCHECK_NE(-1, u_xform_location_); |
- } |
- |
- gfx::ScopedActiveTexture active_texture(GL_TEXTURE0); |
- // UpdateTexImage() call below will bind the surface texture to |
- // TEXTURE_EXTERNAL_OES. This scoped texture binder will restore the current |
- // binding before this function returns. |
- gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_EXTERNAL_OES, texture_id_); |
- |
- { |
- gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); |
- gfx::ScopedViewport viewport(0, 0, size_.width(), size_.height()); |
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
- GL_TEXTURE_2D, target_texture, 0); |
- DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), |
- glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); |
- gfx::ScopedUseProgram use_program(program_); |
- |
- glUniformMatrix4fv(u_xform_location_, 1, false, current_matrix_); |
- gfx::GLHelper::DrawQuad(vertex_buffer_); |
- |
- // Detach the output texture from the fbo. |
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
- GL_TEXTURE_2D, 0, 0); |
- } |
- return true; |
+ return false; |
} |
bool StreamTexture::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |