| 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..22826457b381627445c5a6fb1593944ec5539e7f
 | 
| --- /dev/null
 | 
| +++ b/compositor/xrender/xrender_visitor.cc
 | 
| @@ -0,0 +1,309 @@
 | 
| +// 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>
 | 
| +
 | 
| +#include "base/basictypes.h"
 | 
| +#include "base/logging.h"
 | 
| +#include "base/scoped_ptr.h"
 | 
| +#include "window_manager/image_container.h"
 | 
| +#include "window_manager/image_enums.h"
 | 
| +#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
 | 
| +
 | 
| +namespace window_manager {
 | 
| +
 | 
| +const int kRGBPictureBitDepth = 24;
 | 
| +const int kRGBAPictureBitDepth = 32;
 | 
| +
 | 
| +class XRenderPictureData : public TextureData {
 | 
| + public:
 | 
| +  XRenderPictureData(XConnection* xconn)
 | 
| +      : pixmap_(0),
 | 
| +        xconn_(xconn) {
 | 
| +  }
 | 
| +  virtual ~XRenderPictureData() {
 | 
| +    xconn_->RenderFreePicture(texture());
 | 
| +  }
 | 
| +
 | 
| +  // Initialize our texture and make it contain the current contents of the
 | 
| +  // passed-in pixmap.  False is returned if the process fails (in
 | 
| +  // which case this object should be thrown away).
 | 
| +  bool Init(XPixmap pixmap, int bpp) {
 | 
| +    XPicture picture = xconn_->RenderCreatePicture(pixmap, bpp);
 | 
| +    set_texture(picture);
 | 
| +    return (picture != None);
 | 
| +  }
 | 
| +
 | 
| + 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)
 | 
| +    : root_window_(None),
 | 
| +      back_picture_(None),
 | 
| +      back_pixmap_(None),
 | 
| +      stage_picture_(None),
 | 
| +      compositor_(NULL),
 | 
| +      xconn_(compositor->x_conn()),
 | 
| +      stage_(NULL),
 | 
| +      ancestor_opacity_(1.0),
 | 
| +      has_fullscreen_actor_(false) {
 | 
| +  // Check for the XRender extension.
 | 
| +  CHECK(xconn_->RenderQueryExtension());
 | 
| +
 | 
| +  CHECK(AllocateXResources(stage));
 | 
| +}
 | 
| +
 | 
| +XRenderDrawVisitor::~XRenderDrawVisitor() {
 | 
| +  CHECK(FreeXResources());
 | 
| +}
 | 
| +
 | 
| +void XRenderDrawVisitor::BindImage(const ImageContainer& container,
 | 
| +                                   RealCompositor::ImageActor* actor) {
 | 
| +  XPixmap pixmap = xconn_->CreatePixmapFromContainer(container);
 | 
| +
 | 
| +  scoped_ptr<window_manager::XRenderPictureData> data(
 | 
| +      new XRenderPictureData(this->xconn_));
 | 
| +  data->Init(pixmap, kRGBAPictureBitDepth);
 | 
| +  actor->set_texture_data(data.release());
 | 
| +}
 | 
| +
 | 
| +void XRenderDrawVisitor::VisitStage(RealCompositor::StageActor* actor) {
 | 
| +  if (!actor->IsVisible())
 | 
| +    return;
 | 
| +
 | 
| +  stage_ = actor;
 | 
| +
 | 
| +  if (actor->was_resized()) {
 | 
| +    CHECK(FreeXResources());
 | 
| +    CHECK(AllocateXResources(actor));
 | 
| +    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_) {
 | 
| +    const Compositor::Color& color = actor->stage_color();
 | 
| +    xconn_->RenderFillRectangle(back_picture_,
 | 
| +                                color.red,
 | 
| +                                color.green,
 | 
| +                                color.blue,
 | 
| +                                Point(0, 0),
 | 
| +                                root_geometry_.bounds.size());
 | 
| +  }
 | 
| +
 | 
| +#ifdef EXTRA_LOGGING
 | 
| +  DLOG(INFO) << "Starting Render pass.";
 | 
| +#endif
 | 
| +
 | 
| +  ancestor_opacity_ = actor->opacity();
 | 
| +
 | 
| +  // Walk the actors and render them
 | 
| +  VisitContainer(actor);
 | 
| +
 | 
| +#ifdef EXTRA_LOGGING
 | 
| +  DLOG(INFO) << "Ending Render pass.";
 | 
| +#endif
 | 
| +
 | 
| +  if (!damaged_region_.empty()) {
 | 
| +    Matrix4 identity = 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;
 | 
| +
 | 
| +    xconn_->RenderComposite(false,
 | 
| +                            back_picture_,
 | 
| +                            None,
 | 
| +                            stage_picture_,
 | 
| +                            Point(damaged_region_.x,
 | 
| +                                  root_geometry_.bounds.height -
 | 
| +                                  damaged_region_.y -
 | 
| +                                  damaged_region_.height),
 | 
| +                            Point(0, 0),
 | 
| +                            identity,
 | 
| +                            damaged_region_.size());
 | 
| +  } else {
 | 
| +    Matrix4 identity = Vectormath::Aos::Matrix4::identity();
 | 
| +    identity[0][0] = root_geometry_.bounds.width;
 | 
| +    identity[1][1] = root_geometry_.bounds.height;
 | 
| +    xconn_->RenderComposite(false,
 | 
| +                            back_picture_,
 | 
| +                            None,
 | 
| +                            stage_picture_,
 | 
| +                            Point(0, 0),
 | 
| +                            Point(0, 0),
 | 
| +                            identity,
 | 
| +                            root_geometry_.bounds.size());
 | 
| +  }
 | 
| +
 | 
| +  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();
 | 
| +
 | 
| +  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 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 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;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void XRenderDrawVisitor::VisitImage(RealCompositor::ImageActor* actor) {
 | 
| +  if (!actor->IsVisible())
 | 
| +    return;
 | 
| +
 | 
| +  // All ImageActors are also QuadActors, and so we let the
 | 
| +  // QuadActor do all the actual drawing.
 | 
| +  VisitQuad(actor);
 | 
| +}
 | 
| +
 | 
| +void XRenderDrawVisitor::VisitTexturePixmap(
 | 
| +    RealCompositor::TexturePixmapActor* actor) {
 | 
| +  if (!actor->IsVisible())
 | 
| +    return;
 | 
| +
 | 
| +  // Make sure we have an XRender pic for this pixmap
 | 
| +  if (!actor->texture_data())  {
 | 
| +    if (actor->pixmap()) {
 | 
| +      scoped_ptr<window_manager::XRenderPictureData>
 | 
| +          data(new XRenderPictureData(this->xconn_));
 | 
| +      data->Init(actor->pixmap(),
 | 
| +                 actor->pixmap_is_opaque() ?
 | 
| +                 kRGBPictureBitDepth : kRGBAPictureBitDepth);
 | 
| +      actor->set_texture_data(data.release());
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  // All texture pixmaps are also QuadActors, and so we let the
 | 
| +  // QuadActor do all the actual drawing.
 | 
| +  VisitQuad(actor);
 | 
| +}
 | 
| +
 | 
| +void XRenderDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) {
 | 
| +  if (!actor->IsVisible())
 | 
| +    return;
 | 
| +
 | 
| +#ifdef EXTRA_LOGGING
 | 
| +  DLOG(INFO) << "Drawing quad " << actor->name() << ".";
 | 
| +#endif
 | 
| +
 | 
| +  // Calculate the vertex colors, taking into account the actor color,
 | 
| +  // opacity and the dimming gradient.
 | 
| +  float actor_opacity = actor->is_opaque() ?
 | 
| +                        1.f :
 | 
| +                        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(),
 | 
| +      static_cast<XPicture>(actor->texture_data()->texture()),
 | 
| +      static_cast<XPicture>(None),
 | 
| +      back_picture_,
 | 
| +      Point(0, 0),
 | 
| +      Point(0, 0),
 | 
| +      actor->model_view(),
 | 
| +      actor->GetBounds().size());
 | 
| +}
 | 
| +
 | 
| +bool XRenderDrawVisitor::FreeXResources() {
 | 
| +  return xconn_->FreePixmap(back_pixmap_) &&
 | 
| +         xconn_->RenderFreePicture(back_picture_) &&
 | 
| +         xconn_->RenderFreePicture(stage_picture_);
 | 
| +}
 | 
| +
 | 
| +bool XRenderDrawVisitor::AllocateXResources(Compositor::StageActor* stage) {
 | 
| +  // Find root window geometry.
 | 
| +  root_window_ = stage->GetStageXWindow();
 | 
| +  xconn_->GetWindowGeometry(root_window_, &root_geometry_);
 | 
| +
 | 
| +  // Create back pixmap.
 | 
| +  back_pixmap_ =
 | 
| +      xconn_->CreatePixmap(
 | 
| +          root_window_,
 | 
| +          root_geometry_.bounds.size(),
 | 
| +          root_geometry_.depth);
 | 
| +
 | 
| +  // Create back picture.
 | 
| +  back_picture_ = xconn_->RenderCreatePicture(back_pixmap_,
 | 
| +                                              kRGBPictureBitDepth);
 | 
| +
 | 
| +  // Create stage picture.
 | 
| +  stage_picture_ = xconn_->RenderCreatePicture(root_window_,
 | 
| +                                               kRGBPictureBitDepth);
 | 
| +
 | 
| +  return (back_pixmap_ != None) &&
 | 
| +         (back_picture_ != None) &&
 | 
| +         (stage_picture_ != None);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +}  // namespace window_manager
 | 
| 
 |