Index: gles/opengles_visitor.cc |
diff --git a/gles/opengles_visitor.cc b/gles/opengles_visitor.cc |
index 3f3f2be2bcd62db498f332c3272f57acf026fa22..cd3a462c60a0d82b3185d652e18e39e4bfd5e07d 100644 |
--- a/gles/opengles_visitor.cc |
+++ b/gles/opengles_visitor.cc |
@@ -33,6 +33,63 @@ |
namespace window_manager { |
+// Base for rendering passes. |
+class BasePass : virtual public RealCompositor::ActorVisitor { |
+ public: |
+ explicit BasePass(const OpenGlesDrawVisitor* gles_visitor) |
+ : gles_visitor_(gles_visitor) {} |
+ virtual ~BasePass() {} |
+ virtual void VisitActor(RealCompositor::Actor* actor) {} |
+ virtual void VisitContainer(RealCompositor::ContainerActor* actor) = 0; |
+ virtual void VisitTexturePixmap(RealCompositor::TexturePixmapActor* actor); |
+ virtual void VisitQuad(RealCompositor::QuadActor* actor) = 0; |
+ virtual void VisitImage(RealCompositor::ImageActor* actor) { |
+ VisitQuad(actor); |
+ } |
+ |
+ protected: |
+ const OpenGlesDrawVisitor* gles_visitor() const { return gles_visitor_; } |
+ |
+ private: |
+ const OpenGlesDrawVisitor* gles_visitor_; // Not owned. |
+ |
+ DISALLOW_COPY_AND_ASSIGN(BasePass); |
+}; |
+ |
+// Back to front pass with blending on. |
+class TransparentPass : public BasePass { |
+ public: |
+ explicit TransparentPass(const OpenGlesDrawVisitor* gles_visitor) |
+ : BasePass(gles_visitor) {} |
+ virtual ~TransparentPass() {} |
+ virtual void VisitStage(RealCompositor::StageActor* actor); |
+ virtual void VisitContainer(RealCompositor::ContainerActor* actor); |
+ virtual void VisitQuad(RealCompositor::QuadActor* actor) { |
+ gles_visitor()->DrawQuad(actor, ancestor_opacity_); |
+ } |
+ |
+ private: |
+ // Cumulative opacity of the ancestors |
+ float ancestor_opacity_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TransparentPass); |
+}; |
+ |
+// Front to back pass with blending off. |
+class OpaquePass : public BasePass { |
+ public: |
+ explicit OpaquePass(const OpenGlesDrawVisitor* gles_visitor) |
+ : BasePass(gles_visitor) {} |
+ virtual ~OpaquePass() {} |
+ virtual void VisitContainer(RealCompositor::ContainerActor* actor); |
+ virtual void VisitQuad(RealCompositor::QuadActor* actor) { |
+ gles_visitor()->DrawQuad(actor, 1.f); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(OpaquePass); |
+}; |
+ |
OpenGlesDrawVisitor::OpenGlesDrawVisitor(Gles2Interface* gl, |
RealCompositor* compositor, |
Compositor::StageActor* stage) |
@@ -99,6 +156,10 @@ OpenGlesDrawVisitor::OpenGlesDrawVisitor(Gles2Interface* gl, |
1.f, 1.f, |
}; |
gl_->BufferData(GL_ARRAY_BUFFER, sizeof(kQuad), kQuad, GL_STATIC_DRAW); |
+ |
+ // Unchanging state |
+ gl_->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
+ gl_->Enable(GL_DEPTH_TEST); |
} |
OpenGlesDrawVisitor::~OpenGlesDrawVisitor() { |
@@ -186,48 +247,57 @@ void OpenGlesDrawVisitor::VisitStage(RealCompositor::StageActor* actor) { |
gl_->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
projection_ = actor->projection(); |
- ancestor_opacity_ = actor->opacity(); |
- // Back to front rendering |
- // TODO: Switch to two pass Z-buffered rendering |
- gl_->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
- gl_->Enable(GL_BLEND); |
+ // Front to back opaque rendering pass |
+ OpaquePass opaque_pass(this); |
+ actor->Accept(&opaque_pass); |
- // Back to front rendering |
- const RealCompositor::ActorVector children = actor->GetChildren(); |
- for (RealCompositor::ActorVector::const_reverse_iterator i = |
- children.rbegin(); i != children.rend(); ++i) { |
- (*i)->Accept(this); |
- } |
+ // Back to front rendering transparent pass |
+ gl_->Enable(GL_BLEND); |
+ gl_->DepthMask(GL_FALSE); |
+ TransparentPass transparent_pass(this); |
+ actor->Accept(&transparent_pass); |
+ gl_->DepthMask(GL_TRUE); |
+ gl_->Disable(GL_BLEND); |
gl_->EglSwapBuffers(egl_display_, egl_surface_); |
} |
-void OpenGlesDrawVisitor::VisitTexturePixmap( |
- RealCompositor::TexturePixmapActor* actor) { |
- if (!actor->IsVisible()) |
+void OpenGlesDrawVisitor::CreateTextureData( |
+ RealCompositor::TexturePixmapActor* actor) const { |
+ OpenGlesEglImageData image_data(gl_); |
+ |
+ if (!image_data.Bind(actor)) |
return; |
- if (!actor->texture_data()) { |
- OpenGlesEglImageData image_data(gl_); |
+ OpenGlesTextureData* texture = new OpenGlesTextureData(gl_); |
+ image_data.BindTexture(texture, !actor->pixmap_is_opaque()); |
+ actor->set_texture_data(texture); |
+} |
- if (!image_data.Bind(actor)) |
- return; |
+void BasePass::VisitTexturePixmap( |
+ RealCompositor::TexturePixmapActor* actor) { |
+ if (!actor->IsVisible()) |
+ return; |
- OpenGlesTextureData* texture = new OpenGlesTextureData(gl_); |
- image_data.BindTexture(texture, !actor->pixmap_is_opaque()); |
- actor->set_texture_data(texture); |
- } |
+ if (!actor->texture_data()) |
+ gles_visitor_->CreateTextureData(actor); |
VisitQuad(actor); |
} |
-void OpenGlesDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
+void TransparentPass::VisitStage(RealCompositor::StageActor* actor) { |
+ ancestor_opacity_ = actor->opacity(); |
+ VisitContainer(actor); |
+} |
+ |
+void OpenGlesDrawVisitor::DrawQuad(RealCompositor::QuadActor* actor, |
+ float ancestor_opacity) const { |
if (!actor->IsVisible()) |
return; |
// This must live until after the draw call, so it's at the top level |
- scoped_array<float> colors; |
+ GLfloat colors[4 * 4]; |
// mvp matrix |
Matrix4 mvp = projection_ * actor->model_view(); |
@@ -250,7 +320,7 @@ void OpenGlesDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
gl_->Uniform1i(tex_color_shader_->SamplerLocation(), 0); |
gl_->Uniform4f(tex_color_shader_->ColorLocation(), actor->color().red, |
actor->color().green, actor->color().blue, |
- actor->opacity() * ancestor_opacity_); |
+ actor->opacity() * ancestor_opacity); |
gl_->BindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object_); |
gl_->VertexAttribPointer(tex_color_shader_->PosLocation(), |
@@ -266,7 +336,7 @@ void OpenGlesDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
gl_->Uniform4f(no_alpha_color_shader_->ColorLocation(), |
actor->color().red, actor->color().green, |
actor->color().blue, |
- actor->opacity() * ancestor_opacity_); |
+ actor->opacity() * ancestor_opacity); |
gl_->BindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object_); |
gl_->VertexAttribPointer(no_alpha_color_shader_->PosLocation(), |
@@ -276,31 +346,31 @@ void OpenGlesDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
no_alpha_color_shader_->EnableVertexAttribs(); |
} |
} else { |
- const float actor_opacity = actor->opacity() * ancestor_opacity_; |
+ const float actor_opacity = actor->opacity() * ancestor_opacity; |
const float dimmed_transparency_begin = 1.f - actor->dimmed_opacity_begin(); |
const float dimmed_transparency_end = 1.f - actor->dimmed_opacity_end(); |
// TODO: Consider managing a ring buffer in a VBO ourselves. Could be |
// better performance depending on driver quality. |
- colors_[ 0] = dimmed_transparency_begin * actor->color().red; |
- colors_[ 1] = dimmed_transparency_begin * actor->color().green; |
- colors_[ 2] = dimmed_transparency_begin * actor->color().blue; |
- colors_[ 3] = actor_opacity; |
- |
- colors_[ 4] = dimmed_transparency_begin * actor->color().red; |
- colors_[ 5] = dimmed_transparency_begin * actor->color().green; |
- colors_[ 6] = dimmed_transparency_begin * actor->color().blue; |
- colors_[ 7] = actor_opacity; |
- |
- colors_[ 8] = dimmed_transparency_end * actor->color().red; |
- colors_[ 9] = dimmed_transparency_end * actor->color().green; |
- colors_[10] = dimmed_transparency_end * actor->color().blue; |
- colors_[11] = actor_opacity; |
- |
- colors_[12] = dimmed_transparency_end * actor->color().red; |
- colors_[13] = dimmed_transparency_end * actor->color().green; |
- colors_[14] = dimmed_transparency_end * actor->color().blue; |
- colors_[15] = actor_opacity; |
+ colors[ 0] = dimmed_transparency_begin * actor->color().red; |
+ colors[ 1] = dimmed_transparency_begin * actor->color().green; |
+ colors[ 2] = dimmed_transparency_begin * actor->color().blue; |
+ colors[ 3] = actor_opacity; |
+ |
+ colors[ 4] = dimmed_transparency_begin * actor->color().red; |
+ colors[ 5] = dimmed_transparency_begin * actor->color().green; |
+ colors[ 6] = dimmed_transparency_begin * actor->color().blue; |
+ colors[ 7] = actor_opacity; |
+ |
+ colors[ 8] = dimmed_transparency_end * actor->color().red; |
+ colors[ 9] = dimmed_transparency_end * actor->color().green; |
+ colors[10] = dimmed_transparency_end * actor->color().blue; |
+ colors[11] = actor_opacity; |
+ |
+ colors[12] = dimmed_transparency_end * actor->color().red; |
+ colors[13] = dimmed_transparency_end * actor->color().green; |
+ colors[14] = dimmed_transparency_end * actor->color().blue; |
+ colors[15] = actor_opacity; |
if (texture_has_alpha) { |
gl_->UseProgram(tex_shade_shader_->program()); |
@@ -314,7 +384,7 @@ void OpenGlesDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
2, GL_FLOAT, GL_FALSE, 0, 0); |
gl_->BindBuffer(GL_ARRAY_BUFFER, 0); |
gl_->VertexAttribPointer(tex_shade_shader_->ColorInLocation(), |
- 4, GL_FLOAT, GL_FALSE, 0, colors_); |
+ 4, GL_FLOAT, GL_FALSE, 0, colors); |
tex_shade_shader_->EnableVertexAttribs(); |
} else { |
gl_->UseProgram(no_alpha_shade_shader_->program()); |
@@ -328,7 +398,7 @@ void OpenGlesDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
2, GL_FLOAT, GL_FALSE, 0, 0); |
gl_->BindBuffer(GL_ARRAY_BUFFER, 0); |
gl_->VertexAttribPointer(no_alpha_shade_shader_->ColorInLocation(), |
- 4, GL_FLOAT, GL_FALSE, 0, colors_); |
+ 4, GL_FLOAT, GL_FALSE, 0, colors); |
no_alpha_shade_shader_->EnableVertexAttribs(); |
} |
} |
@@ -337,7 +407,7 @@ void OpenGlesDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
gl_->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
} |
-void OpenGlesDrawVisitor::VisitContainer( |
+void TransparentPass::VisitContainer( |
RealCompositor::ContainerActor* actor) { |
if (!actor->IsVisible()) |
return; |
@@ -351,13 +421,31 @@ void OpenGlesDrawVisitor::VisitContainer( |
const RealCompositor::ActorVector children = actor->GetChildren(); |
for (RealCompositor::ActorVector::const_reverse_iterator i = |
children.rbegin(); i != children.rend(); ++i) { |
- (*i)->Accept(this); |
+ if (ancestor_opacity_ <= 0.999f || (*i)->has_children() || |
+ !(*i)->is_opaque()) |
+ (*i)->Accept(this); |
} |
// Reset opacity. |
ancestor_opacity_ = original_opacity; |
} |
+void OpaquePass::VisitContainer( |
+ RealCompositor::ContainerActor* actor) { |
+ if (!actor->IsVisible()) |
+ return; |
+ |
+ LOG(INFO) << "Visit container: " << actor->name(); |
+ |
+ // Front to back rendering |
+ const RealCompositor::ActorVector children = actor->GetChildren(); |
+ for (RealCompositor::ActorVector::const_iterator i = children.begin(); |
+ i != children.end(); ++i) { |
+ if ((*i)->is_opaque()) |
+ (*i)->Accept(this); |
+ } |
+} |
+ |
OpenGlesTextureData::OpenGlesTextureData(Gles2Interface* gl) |
: gl_(gl) {} |