Chromium Code Reviews| Index: compositor/xrender/xrender_visitor.cc |
| diff --git a/compositor/xrender/xrender_visitor.cc b/compositor/xrender/xrender_visitor.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..563453a7b4e88ea769d9687d5f98c2dabb1cfb7d |
| --- /dev/null |
| +++ b/compositor/xrender/xrender_visitor.cc |
| @@ -0,0 +1,307 @@ |
| +// Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "window_manager/compositor/xrender/xrender_visitor.h" |
| + |
| +#include <X11/extensions/Xrender.h> |
|
Daniel Erat
2011/04/02 14:54:36
nit: move this down just under where the gflags.h
marcheu
2011/04/04 19:55:58
Done.
|
| + |
| +#include <sys/time.h> |
|
Daniel Erat
2011/04/02 14:54:36
i don't think you need this include, algorithm, ct
marcheu
2011/04/04 19:55:58
Done.
|
| + |
| +#include <algorithm> |
| +#include <ctime> |
| +#include <string> |
| + |
| +#include <gflags/gflags.h> |
| + |
| +#include "base/basictypes.h" |
| +#include "base/logging.h" |
| +#include "window_manager/image_container.h" |
| +#include "window_manager/image_enums.h" |
| +#include "window_manager/profiler.h" |
|
Daniel Erat
2011/04/02 14:54:36
if you didn't use the profiling code while develop
marcheu
2011/04/04 19:55:58
Done.
|
| +#include "window_manager/util.h" |
| +#include "window_manager/x11/x_connection.h" |
| + |
| + |
| +#ifndef COMPOSITOR_XRENDER |
| +#error Need COMPOSITOR_XRENDER defined to compile this file |
| +#endif |
| + |
| +using window_manager::util::XidStr; |
|
Daniel Erat
2011/04/02 14:54:36
delete this; you don't use it
marcheu
2011/04/04 19:55:58
Done.
|
| + |
| +namespace window_manager { |
| + |
| +class XRenderPictureData : public TextureData { |
| + public: |
| + XRenderPictureData(XRenderDrawVisitor* visitor) { |
| + pixmap_ = 0; |
| + set_texture(0); |
| + xconn_ = visitor->xconn(); |
| + } |
| + virtual ~XRenderPictureData() { |
| + xconn_->RenderFreePicture (texture()); |
|
Daniel Erat
2011/04/02 14:54:36
delete space between method name and paren
marcheu
2011/04/04 19:55:58
Done.
|
| + } |
| + |
| + // Initialize our texture and make it contain the current contents of the |
| + // passed-in actor's pixmap. False is returned if the process fails (in |
|
Daniel Erat
2011/04/02 14:54:36
this comment is obsolete; no actor is being passed
marcheu
2011/04/04 19:55:58
Done.
|
| + // which case this object should be thrown away). |
| + bool Init(XPixmap pixmap, int bpp) { |
| + set_texture( xconn_->RenderCreatePicture(pixmap, bpp) ); |
|
Daniel Erat
2011/04/02 14:54:36
no spaces around function args
marcheu
2011/04/04 19:55:58
Done.
|
| + return true; |
| + } |
| + |
| + private: |
| + // The actor's X pixmap. Ownership of the pixmap remains with the caller. |
| + XPixmap pixmap_; |
| + |
| + XConnection* xconn_; // Not owned. |
| +}; |
| + |
| + |
| +XRenderDrawVisitor::XRenderDrawVisitor(RealCompositor* compositor, |
| + Compositor::StageActor* stage) { |
|
Daniel Erat
2011/04/02 14:54:36
make left edges of parameters line up
marcheu
2011/04/04 19:55:58
Done.
|
| + xconn_ = compositor->x_conn(); |
| + |
| + // check for the XRender extension |
|
Daniel Erat
2011/04/02 14:54:36
nit: fix capitalization and punctuation of this co
marcheu
2011/04/04 19:55:58
Done.
|
| + if (!xconn_->RenderQueryExtension ()) { |
|
Daniel Erat
2011/04/02 14:54:36
no space between method name and paren
you should
marcheu
2011/04/04 19:55:58
Done.
|
| + LOG(ERROR) << "No render extension"; |
| + } |
| + |
| + // find default depth |
| + root_window = stage->GetStageXWindow(); |
| + xconn_->GetWindowGeometry(root_window, &root_geometry); |
| + |
| + // create back pixmap |
| + backPixmap = xconn_->CreatePixmap (root_window, |
|
Daniel Erat
2011/04/02 14:54:36
fix style:
- no space between method name and pare
marcheu
2011/04/04 19:55:58
Done.
|
| + Size(root_geometry.bounds.width, root_geometry.bounds.height), |
| + root_geometry.depth); |
| + backPicture = xconn_->RenderCreatePicture(backPixmap, 24); |
|
Daniel Erat
2011/04/02 14:54:36
pull the "24" to a const at the top of the file
marcheu
2011/04/04 19:55:58
Done.
|
| + // create stage pixmap |
| + stagePicture = xconn_->RenderCreatePicture(root_window, 24); |
| +} |
| + |
| +XRenderDrawVisitor::~XRenderDrawVisitor() { |
| +} |
| + |
| +void XRenderDrawVisitor::BindImage(const ImageContainer* container, |
| + RealCompositor::ImageActor* actor) { |
|
Daniel Erat
2011/04/02 14:54:36
align with param on previous line
marcheu
2011/04/04 19:55:58
Done.
|
| + XPixmap pixmap = xconn_->CreatePixmapFromData( (char*)container->data(), |
|
Daniel Erat
2011/04/02 14:54:36
fix indenting
marcheu
2011/04/04 19:55:58
Done.
|
| + Size(container->width(), container->height())); |
|
Daniel Erat
2011/04/02 14:54:36
i added an Actor::GetBounds() method, so you shoul
marcheu
2011/04/04 19:55:58
ImageContainer is not an actor, so I added a GetSi
|
| + |
| + XRenderPictureData* data = new XRenderPictureData(this); |
| + data->Init(pixmap, 32); |
| + actor->set_texture_data(data); |
| +} |
| + |
| +void XRenderDrawVisitor::VisitImage(RealCompositor::ImageActor* actor) { |
| + if (!actor->IsVisible()) |
| + return; |
| + |
| + PROFILER_MARKER_BEGIN(VisitImage); |
| + |
| + // All ImageActors are also QuadActors, and so we let the |
| + // QuadActor do all the actual drawing. |
| + VisitQuad(actor); |
| + PROFILER_MARKER_END(VisitImage); |
| +} |
| + |
| +void XRenderDrawVisitor::VisitTexturePixmap( |
| + RealCompositor::TexturePixmapActor* actor) { |
| + if (!actor->IsVisible()) |
| + return; |
| + |
| + PROFILER_MARKER_BEGIN(VisitTexturePixmap); |
| + |
| + // Make sure we have an XRender pic for this pixmap |
| + if (!actor->texture_data()) { |
| + if (actor->pixmap()) { |
| + XRenderPictureData* data = new XRenderPictureData(this); |
| + data->Init(actor->pixmap(), actor->pixmap_is_opaque() ? 24:32); |
|
Daniel Erat
2011/04/02 14:54:36
fix spacing: only one space after comma, and add s
marcheu
2011/04/04 19:55:58
Done.
|
| + actor->set_texture_data(data); |
| + } |
| + } |
| + |
| + // All texture pixmaps are also QuadActors, and so we let the |
| + // QuadActor do all the actual drawing. |
| + VisitQuad(actor); |
| + PROFILER_MARKER_END(VisitTexturePixmap); |
| +} |
| + |
| +void XRenderDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
| + if (!actor->IsVisible()) |
| + return; |
| + |
| +#ifdef EXTRA_LOGGING |
| + DLOG(INFO) << "Drawing quad " << actor->name() << "."; |
| +#endif |
| + PROFILER_DYNAMIC_MARKER_BEGIN(actor->name().c_str()); |
| + |
| + // Calculate the vertex colors, taking into account the actor color, |
| + // opacity and the dimming gradient. |
| + float actor_opacity = actor->is_opaque() ? 1.0f : |
|
Daniel Erat
2011/04/02 14:54:36
nit: move "1.0f :" to its own line
marcheu
2011/04/04 19:55:58
Done.
|
| + actor->opacity() * ancestor_opacity_; |
| + float dimmed_transparency_begin = 1.f - actor->dimmed_opacity_begin(); |
| + float dimmed_transparency_end = 1.f - actor->dimmed_opacity_end(); |
| + float red = actor->color().red; |
| + float green = actor->color().green; |
| + float blue = actor->color().blue; |
| + DCHECK_LE(actor_opacity, 1.f); |
| + DCHECK_GE(actor_opacity, 0.f); |
| + DCHECK_LE(dimmed_transparency_begin, 1.f); |
| + DCHECK_GE(dimmed_transparency_begin, 0.f); |
| + DCHECK_LE(dimmed_transparency_end, 1.f); |
| + DCHECK_GE(dimmed_transparency_end, 0.f); |
| + DCHECK_LE(red, 1.f); |
| + DCHECK_GE(red, 0.f); |
| + DCHECK_LE(green, 1.f); |
| + DCHECK_GE(green, 0.f); |
| + DCHECK_LE(blue, 1.f); |
| + DCHECK_GE(blue, 0.f); |
| + |
| + xconn_->RenderComposite (!actor->is_opaque(), |
|
Daniel Erat
2011/04/02 14:54:36
remove space before paren
marcheu
2011/04/04 19:55:58
Done.
|
| + (XPicture)actor->texture_data()->texture(), |
|
Daniel Erat
2011/04/02 14:54:36
use c++ style casts (static_cast<XPicture>(...))
marcheu
2011/04/04 19:55:58
Done.
|
| + (XPicture)None, backPicture, |
|
Daniel Erat
2011/04/02 14:54:36
one arg per line except for stuff like x, y and wi
marcheu
2011/04/04 19:55:58
Done.
|
| + Point(0, 0), |
| + Point(0, 0), |
| + actor->model_view(), |
| + Size(actor->width(), actor->height()) |
|
Daniel Erat
2011/04/02 14:54:36
GetBounds().size()
marcheu
2011/04/04 19:55:58
Done.
|
| + ); |
|
Daniel Erat
2011/04/02 14:54:36
move to end of previous line
marcheu
2011/04/04 19:55:58
Done.
|
| + |
| + PROFILER_DYNAMIC_MARKER_END(); |
| +} |
| + |
| + |
| +void XRenderDrawVisitor::VisitStage(RealCompositor::StageActor* actor) { |
| + if (!actor->IsVisible()) return; |
|
Daniel Erat
2011/04/02 14:54:36
move 'return' to its own line
marcheu
2011/04/04 19:55:58
Done.
|
| + |
| + PROFILER_MARKER_BEGIN(VisitStage); |
| + stage_ = actor; |
| + |
| + if (actor->was_resized()) { |
|
Daniel Erat
2011/04/02 14:54:36
chrome style is to not use curly braces for ifs wi
marcheu
2011/04/04 19:55:58
Done.
|
| + actor->unset_was_resized(); |
| + } |
| + |
| + // If we don't have a full screen actor we do a fill with the stage color. |
| + if (!has_fullscreen_actor_) |
| + { |
|
Daniel Erat
2011/04/02 14:54:36
move '{' to end of previous line
marcheu
2011/04/04 19:55:58
Done.
|
| + const Compositor::Color& color = actor->stage_color(); |
| + xconn_->RenderFillRectangle(backPicture, color.red, color.green, color.blue, |
| + Point(0, 0), |
|
Daniel Erat
2011/04/02 14:54:36
fix indenting
marcheu
2011/04/04 19:55:58
Done.
|
| + Size(root_geometry.bounds.width, root_geometry.bounds.height) |
|
Daniel Erat
2011/04/02 14:54:36
root_geometry.bounds.size()
marcheu
2011/04/04 19:55:58
Done.
|
| + ); |
|
Daniel Erat
2011/04/02 14:54:36
move to end of previous line
marcheu
2011/04/04 19:55:58
Done.
|
| + } |
| + |
| +#ifdef EXTRA_LOGGING |
| + DLOG(INFO) << "Starting Render pass."; |
| +#endif |
| + |
| + ancestor_opacity_ = actor->opacity(); |
| + |
| + // Walk the actors and render them |
| + PROFILER_MARKER_BEGIN(Render_Pass); |
| + VisitContainer(actor); |
| + PROFILER_MARKER_END(Render_Pass); |
| + |
| +#ifdef EXTRA_LOGGING |
| + DLOG(INFO) << "Ending Render pass."; |
| +#endif |
| + |
| + PROFILER_MARKER_BEGIN(Swap_Buffer); |
| + if ( !damaged_region_.empty() ) { |
|
Daniel Erat
2011/04/02 14:54:36
remove extra spaces
marcheu
2011/04/04 19:55:58
Done.
|
| + Matrix4 identity = Vectormath::Aos::Matrix4::identity(); |
| + identity[0][0] = damaged_region_.width; |
| + identity[1][1] = damaged_region_.height; |
| + identity[3][0] = damaged_region_.x; |
| + identity[3][1] = root_geometry.bounds.height |
| + - damaged_region_.y - damaged_region_.height; |
|
Daniel Erat
2011/04/02 14:54:36
move initial '-' to end of previous line
marcheu
2011/04/04 19:55:58
Done.
|
| + xconn_->RenderComposite (false, |
| + backPicture, |
|
Daniel Erat
2011/04/02 14:54:36
fix indenting
marcheu
2011/04/04 19:55:58
Done.
|
| + None, |
| + stagePicture, |
| + Point(damaged_region_.x, |
| + root_geometry.bounds.height |
|
Daniel Erat
2011/04/02 14:54:36
fix indenting
marcheu
2011/04/04 19:55:58
Done.
|
| + - damaged_region_.y |
|
Daniel Erat
2011/04/02 14:54:36
put operators at end of lines instead of beginning
marcheu
2011/04/04 19:55:58
Done.
|
| + - damaged_region_.height), |
| + Point(0, 0), |
| + identity, |
| + Size(damaged_region_.width, damaged_region_.height) |
|
Daniel Erat
2011/04/02 14:54:36
damaged_region_.size()
marcheu
2011/04/04 19:55:58
Done.
|
| + ); |
|
Daniel Erat
2011/04/02 14:54:36
move to end of previous line
marcheu
2011/04/04 19:55:58
Done.
|
| + } |
| + else |
| + { |
|
Daniel Erat
2011/04/02 14:54:36
move to end of previous line
marcheu
2011/04/04 19:55:58
Done.
|
| + Matrix4 identity = Vectormath::Aos::Matrix4::identity(); |
| + identity[0][0] = root_geometry.bounds.width; |
| + identity[1][1] = root_geometry.bounds.height; |
| + xconn_->RenderComposite (false, |
| + backPicture, |
|
Daniel Erat
2011/04/02 14:54:36
fix indenting
marcheu
2011/04/04 19:55:58
Done.
|
| + None, |
| + stagePicture, |
| + Point(0, 0), |
| + Point(0, 0), |
| + identity, |
| + Size(root_geometry.bounds.width, root_geometry.bounds.height) |
|
Daniel Erat
2011/04/02 14:54:36
size()
marcheu
2011/04/04 19:55:58
Done.
|
| + ); |
|
Daniel Erat
2011/04/02 14:54:36
you get the idea
marcheu
2011/04/04 19:55:58
Done.
|
| + } |
| + |
| + PROFILER_MARKER_END(Swap_Buffer); |
| + ++num_frames_drawn_; |
| + |
| + PROFILER_MARKER_END(VisitStage); |
| + // The profiler is flushed explicitly every 100 frames, or flushed |
| + // implicitly when the internal buffer is full. |
| + if (num_frames_drawn_ % 100 == 0) |
| + PROFILER_FLUSH(); |
| + stage_ = NULL; |
| +} |
| + |
| +void XRenderDrawVisitor::VisitContainer(RealCompositor::ContainerActor* actor) { |
| + if (!actor->IsVisible()) |
| + return; |
| + |
| +#ifdef EXTRA_LOGGING |
| + DLOG(INFO) << "Drawing container " << actor->name() << "."; |
| + DLOG(INFO) << " at: (" << actor->x() << ", " << actor->y() |
| + << ", " << actor->z() << ") with scale: (" |
| + << actor->scale_x() << ", " << actor->scale_y() << ") at size (" |
| + << actor->width() << "x" << actor->height() << ")"; |
| +#endif |
| + RealCompositor::ActorVector children = actor->GetChildren(); |
| + |
| + { |
|
Daniel Erat
2011/04/02 14:54:36
this should be indented one more space, but do you
marcheu
2011/04/04 19:55:58
Done.
|
| + float original_opacity = ancestor_opacity_; |
| + ancestor_opacity_ *= actor->opacity(); |
| + |
| + // Walk backwards so we go back to front. |
| + RealCompositor::ActorVector::const_reverse_iterator iterator; |
| + for (iterator = children.rbegin(); iterator != children.rend(); |
| + ++iterator) { |
| + RealCompositor::Actor* child = *iterator; |
| + |
| + if (child->IsVisible()) { |
| +#ifdef EXTRA_LOGGING |
| + DLOG(INFO) << "Drawing transparent child " << child->name() |
| + << " (visible: " << child->IsVisible() |
| + << ", has_children: " << child->has_children() |
| + << ", opacity: " << child->opacity() |
| + << ", ancestor_opacity: " << ancestor_opacity_ |
| + << ", is_opaque: " << child->is_opaque() << ")"; |
| +#endif |
| + child->Accept(this); |
| + } else { |
| +#ifdef EXTRA_LOGGING |
| + DLOG(INFO) << "NOT drawing opaque child " << child->name() |
| + << " (visible: " << child->IsVisible() |
| + << ", has_children: " << child->has_children() |
| + << ", opacity: " << child->opacity() |
| + << ", ancestor_opacity: " << ancestor_opacity_ |
| + << ", is_opaque: " << child->is_opaque() << ")"; |
| +#endif |
| + } |
| + } |
| + |
| + // Reset ancestor opacity. |
| + ancestor_opacity_ = original_opacity; |
| + } |
| +} |
| + |
| +} // namespace window_manager |