OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gl/gl_image_surface_texture.h" | 5 #include "ui/gl/gl_image_surface_texture.h" |
6 | 6 |
7 #include "base/strings/stringize_macros.h" | |
8 #include "base/strings/stringprintf.h" | |
7 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
8 #include "ui/gl/android/surface_texture.h" | 10 #include "ui/gl/android/surface_texture.h" |
11 #include "ui/gl/gl_helper.h" | |
12 #include "ui/gl/scoped_binders.h" | |
9 | 13 |
10 namespace gl { | 14 namespace gl { |
11 | 15 |
12 GLImageSurfaceTexture::GLImageSurfaceTexture(const gfx::Size& size) | 16 GLImageSurfaceTexture::GLImageSurfaceTexture(const gfx::Size& size) |
13 : size_(size), texture_id_(0) {} | 17 : size_(size) {} |
14 | 18 |
15 GLImageSurfaceTexture::~GLImageSurfaceTexture() { | 19 GLImageSurfaceTexture::~GLImageSurfaceTexture() { |
16 DCHECK(thread_checker_.CalledOnValidThread()); | 20 DCHECK(thread_checker_.CalledOnValidThread()); |
17 DCHECK(!surface_texture_.get()); | 21 DCHECK(!surface_texture_.get()); |
18 DCHECK_EQ(0, texture_id_); | |
19 } | 22 } |
20 | 23 |
21 bool GLImageSurfaceTexture::Initialize(gfx::SurfaceTexture* surface_texture) { | 24 bool GLImageSurfaceTexture::Initialize(gfx::SurfaceTexture* surface_texture) { |
22 DCHECK(thread_checker_.CalledOnValidThread()); | 25 DCHECK(thread_checker_.CalledOnValidThread()); |
23 DCHECK(!surface_texture_.get()); | 26 DCHECK(!surface_texture_.get()); |
24 surface_texture_ = surface_texture; | 27 surface_texture_ = surface_texture; |
25 return true; | 28 return true; |
26 } | 29 } |
27 | 30 |
28 void GLImageSurfaceTexture::Destroy(bool have_context) { | 31 void GLImageSurfaceTexture::Destroy(bool have_context) { |
29 DCHECK(thread_checker_.CalledOnValidThread()); | 32 DCHECK(thread_checker_.CalledOnValidThread()); |
30 surface_texture_ = NULL; | 33 if (have_context && framebuffer_) { |
31 texture_id_ = 0; | 34 glDeleteProgram(program_); |
35 glDeleteShader(vertex_shader_); | |
36 glDeleteShader(fragment_shader_); | |
37 glDeleteBuffersARB(1, &vertex_buffer_); | |
38 glDeleteFramebuffersEXT(1, &framebuffer_); | |
39 } | |
40 surface_texture_ = nullptr; | |
32 } | 41 } |
33 | 42 |
34 gfx::Size GLImageSurfaceTexture::GetSize() { | 43 gfx::Size GLImageSurfaceTexture::GetSize() { |
35 return size_; | 44 return size_; |
36 } | 45 } |
37 | 46 |
38 unsigned GLImageSurfaceTexture::GetInternalFormat() { return GL_RGBA; } | 47 unsigned GLImageSurfaceTexture::GetInternalFormat() { return GL_RGBA; } |
39 | 48 |
40 bool GLImageSurfaceTexture::BindTexImage(unsigned target) { | 49 bool GLImageSurfaceTexture::BindTexImage(unsigned target) { |
41 TRACE_EVENT0("gpu", "GLImageSurfaceTexture::BindTexImage"); | 50 // Binding of surface textures directly to a target is not supported as |
51 // an explicit release call is required before the buffer can be reused. | |
52 return false; | |
53 } | |
54 | |
55 bool GLImageSurfaceTexture::CopyTexImage(unsigned target) { | |
56 TRACE_EVENT0("gpu", "GLImageSurfaceTexture::CopyTexImage"); | |
42 DCHECK(thread_checker_.CalledOnValidThread()); | 57 DCHECK(thread_checker_.CalledOnValidThread()); |
43 | 58 |
44 if (target != GL_TEXTURE_EXTERNAL_OES) { | 59 if (target != GL_TEXTURE_2D) { |
45 LOG(ERROR) | 60 LOG(ERROR) << "CopyTexImage requires TEXTURE_2D target"; |
46 << "Surface texture can only be bound to TEXTURE_EXTERNAL_OES target"; | |
47 return false; | 61 return false; |
48 } | 62 } |
49 | 63 |
50 GLint texture_id; | 64 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.width(), size_.height(), 0, |
51 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id); | 65 GL_RGBA, GL_UNSIGNED_BYTE, nullptr); |
52 DCHECK(texture_id); | |
53 | 66 |
54 if (texture_id_ && texture_id_ != texture_id) { | 67 return CopyTexSubImage(target, gfx::Point(), gfx::Rect(size_)); |
55 LOG(ERROR) << "Surface texture can only be bound to one texture ID"; | |
56 return false; | |
57 } | |
58 | |
59 DCHECK(surface_texture_.get()); | |
60 if (texture_id != texture_id_) { | |
61 // Note: Surface textures used as gpu memory buffers are created with an | |
62 // initial dummy texture id of 0. We need to call DetachFromGLContext() here | |
63 // to detach from the dummy texture before we can attach to a real texture | |
64 // id. DetachFromGLContext() will delete the texture for the current | |
65 // attachment point so it's important that this is never called when | |
66 // attached to a real texture id. Detaching from the dummy texture id should | |
67 // not cause any problems as the GL should silently ignore 0 when passed to | |
68 // glDeleteTextures. | |
69 DCHECK_EQ(0, texture_id_); | |
70 surface_texture_->DetachFromGLContext(); | |
71 | |
72 // This will attach the surface texture to the texture currently bound to | |
73 // GL_TEXTURE_EXTERNAL_OES target. | |
74 surface_texture_->AttachToGLContext(); | |
75 texture_id_ = texture_id; | |
76 } | |
77 | |
78 surface_texture_->UpdateTexImage(); | |
79 return true; | |
80 } | |
81 | |
82 bool GLImageSurfaceTexture::CopyTexImage(unsigned target) { | |
83 return false; | |
84 } | 68 } |
85 | 69 |
86 bool GLImageSurfaceTexture::CopyTexSubImage(unsigned target, | 70 bool GLImageSurfaceTexture::CopyTexSubImage(unsigned target, |
87 const gfx::Point& offset, | 71 const gfx::Point& offset, |
88 const gfx::Rect& rect) { | 72 const gfx::Rect& rect) { |
89 return false; | 73 TRACE_EVENT0("gpu", "GLImageSurfaceTexture::CopyTexSubImage"); |
74 | |
75 if (!offset.IsOrigin()) { | |
76 LOG(ERROR) << "Non-origin offset is not supported"; | |
77 return false; | |
78 } | |
79 | |
80 if (rect != gfx::Rect(size_)) { | |
81 LOG(ERROR) << "Sub-rectangle is not supported"; | |
82 return false; | |
83 } | |
84 | |
85 if (!framebuffer_) { | |
86 // Framebuffer. | |
Daniele Castagna
2015/12/05 23:43:57
nit: this can be removed.
reveman
2015/12/05 23:54:07
Done.
| |
87 glGenFramebuffersEXT(1, &framebuffer_); | |
88 | |
89 // clang-format off | |
90 const char kVertexShader[] = STRINGIZE( | |
91 attribute vec2 a_position; | |
92 varying vec2 v_texCoord; | |
93 void main() { | |
94 gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); | |
95 v_texCoord = (a_position + vec2(1.0, 1.0)) * 0.5; | |
96 } | |
97 ); | |
98 const char kFragmentShader[] = STRINGIZE( | |
99 precision mediump float; | |
100 uniform samplerExternalOES a_texture; | |
101 varying vec2 v_texCoord; | |
102 void main() { | |
103 gl_FragColor = texture2D(a_texture, v_texCoord); | |
104 } | |
105 ); | |
106 // clang-format on | |
107 | |
108 vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer(); | |
109 vertex_shader_ = gfx::GLHelper::LoadShader(GL_VERTEX_SHADER, kVertexShader); | |
110 fragment_shader_ = gfx::GLHelper::LoadShader( | |
111 GL_FRAGMENT_SHADER, | |
112 base::StringPrintf("#extension GL_OES_EGL_image_external : require\n%s", | |
Daniele Castagna
2015/12/05 23:43:57
nit: Can this be part of kFragmentShader.
reveman
2015/12/05 23:54:07
Done.
| |
113 kFragmentShader) | |
114 .c_str()); | |
115 program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_); | |
116 gfx::ScopedUseProgram use_program(program_); | |
117 int sampler_location = glGetUniformLocation(program_, "a_texture"); | |
118 DCHECK_NE(-1, sampler_location); | |
119 glUniform1i(sampler_location, 0); | |
120 } | |
121 | |
122 GLint target_texture = 0; | |
123 glGetIntegerv(GL_TEXTURE_BINDING_2D, &target_texture); | |
124 DCHECK(target_texture); | |
125 | |
126 gfx::ScopedActiveTexture active_texture(GL_TEXTURE0); | |
127 // UpdateTexImage() call below will bind the surface texture to | |
128 // TEXTURE_EXTERNAL_OES. This scoped texture binder will restore the current | |
129 // binding before this function returns. | |
130 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_EXTERNAL_OES, 0); | |
131 | |
132 DCHECK(surface_texture_.get()); | |
133 surface_texture_->UpdateTexImage(); | |
134 | |
135 { | |
136 gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_); | |
137 gfx::ScopedViewport viewport(0, 0, size_.width(), size_.height()); | |
138 glViewport(0, 0, size_.width(), size_.height()); | |
Daniele Castagna
2015/12/05 23:43:57
This could be removed.
reveman
2015/12/05 23:54:07
Done.
| |
139 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
140 GL_TEXTURE_2D, target_texture, 0); | |
141 DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), | |
142 glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); | |
143 gfx::ScopedUseProgram use_program(program_); | |
144 | |
145 gfx::GLHelper::DrawQuad(vertex_buffer_); | |
146 | |
147 // Detach the output texture from the fbo. | |
148 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
149 GL_TEXTURE_2D, 0, 0); | |
150 } | |
151 | |
152 surface_texture_->ReleaseTexImage(); | |
153 return true; | |
90 } | 154 } |
91 | 155 |
92 bool GLImageSurfaceTexture::ScheduleOverlayPlane( | 156 bool GLImageSurfaceTexture::ScheduleOverlayPlane( |
93 gfx::AcceleratedWidget widget, | 157 gfx::AcceleratedWidget widget, |
94 int z_order, | 158 int z_order, |
95 gfx::OverlayTransform transform, | 159 gfx::OverlayTransform transform, |
96 const gfx::Rect& bounds_rect, | 160 const gfx::Rect& bounds_rect, |
97 const gfx::RectF& crop_rect) { | 161 const gfx::RectF& crop_rect) { |
98 return false; | 162 return false; |
99 } | 163 } |
100 | 164 |
101 void GLImageSurfaceTexture::OnMemoryDump( | 165 void GLImageSurfaceTexture::OnMemoryDump( |
102 base::trace_event::ProcessMemoryDump* pmd, | 166 base::trace_event::ProcessMemoryDump* pmd, |
103 uint64_t process_tracing_id, | 167 uint64_t process_tracing_id, |
104 const std::string& dump_name) { | 168 const std::string& dump_name) { |
105 // TODO(ericrk): Add OnMemoryDump for GLImages. crbug.com/514914 | 169 // TODO(ericrk): Add OnMemoryDump for GLImages. crbug.com/514914 |
106 } | 170 } |
107 | 171 |
108 } // namespace gl | 172 } // namespace gl |
OLD | NEW |