Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "window_manager/compositor/xrender/xrender_visitor.h" | |
| 6 | |
| 7 #include <X11/extensions/Xrender.h> | |
| 8 | |
| 9 #include "base/basictypes.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/scoped_ptr.h" | |
| 12 #include "window_manager/image_container.h" | |
| 13 #include "window_manager/image_enums.h" | |
| 14 #include "window_manager/util.h" | |
| 15 #include "window_manager/x11/x_connection.h" | |
| 16 | |
| 17 | |
| 18 #ifndef COMPOSITOR_XRENDER | |
| 19 #error Need COMPOSITOR_XRENDER defined to compile this file | |
| 20 #endif | |
| 21 | |
| 22 namespace window_manager { | |
| 23 | |
| 24 const int kRGBPictureBitDepth = 24; | |
| 25 const int kRGBAPictureBitDepth = 32; | |
| 26 | |
| 27 class XRenderPictureData : public TextureData { | |
| 28 public: | |
| 29 XRenderPictureData(XConnection* xconn) | |
| 30 : pixmap_(0), | |
| 31 xconn_(xconn) { | |
| 32 } | |
| 33 virtual ~XRenderPictureData() { | |
| 34 xconn_->RenderFreePicture(texture()); | |
| 35 } | |
| 36 | |
| 37 // Initialize our texture and make it contain the current contents of the | |
| 38 // passed-in pixmap. False is returned if the process fails (in | |
| 39 // which case this object should be thrown away). | |
| 40 bool Init(XPixmap pixmap, int bpp) { | |
| 41 XPicture picture = xconn_->RenderCreatePicture(pixmap, bpp); | |
| 42 set_texture(picture); | |
| 43 return (picture != None); | |
| 44 } | |
| 45 | |
| 46 private: | |
| 47 // The actor's X pixmap. Ownership of the pixmap remains with the caller. | |
| 48 XPixmap pixmap_; | |
| 49 | |
| 50 XConnection* xconn_; // Not owned. | |
| 51 }; | |
| 52 | |
| 53 bool XRenderDrawVisitor::FreeXResources() { | |
|
Daniel Erat
2011/04/05 01:35:06
move this and AllocateXResources() down. the meth
marcheu
2011/04/05 02:07:42
Done.
| |
| 54 return xconn_->FreePixmap(back_pixmap_) && | |
| 55 xconn_->RenderFreePicture(back_picture_) && | |
|
Daniel Erat
2011/04/05 01:35:06
fix indenting: line this up with the xconn_ on the
marcheu
2011/04/05 02:07:42
Done.
| |
| 56 xconn_->RenderFreePicture(stage_picture_); | |
| 57 } | |
| 58 | |
| 59 bool XRenderDrawVisitor::AllocateXResources(Compositor::StageActor* stage) { | |
| 60 // Find root window geometry. | |
| 61 root_window_ = stage->GetStageXWindow(); | |
| 62 xconn_->GetWindowGeometry(root_window_, &root_geometry_); | |
| 63 | |
| 64 // Create back pixmap. | |
| 65 back_pixmap_ = | |
| 66 xconn_->CreatePixmap( | |
| 67 root_window_, | |
| 68 root_geometry_.bounds.size(), | |
| 69 root_geometry_.depth); | |
| 70 | |
| 71 // Create back picture. | |
| 72 back_picture_ = xconn_->RenderCreatePicture(back_pixmap_, | |
| 73 kRGBPictureBitDepth); | |
| 74 | |
| 75 // Create stage picture. | |
| 76 stage_picture_ = xconn_->RenderCreatePicture(root_window_, | |
| 77 kRGBPictureBitDepth); | |
| 78 | |
| 79 return (back_pixmap_ != None) && | |
| 80 (back_picture_ != None) && | |
| 81 (stage_picture_ != None); | |
| 82 } | |
| 83 | |
| 84 | |
| 85 XRenderDrawVisitor::XRenderDrawVisitor(RealCompositor* compositor, | |
| 86 Compositor::StageActor* stage) | |
| 87 : root_window_(None), | |
| 88 root_geometry_(), | |
|
Daniel Erat
2011/04/05 01:35:06
nit: no need to list objects with reasonable defau
marcheu
2011/04/05 02:07:42
Done.
| |
| 89 back_picture_(None), | |
| 90 back_pixmap_(None), | |
| 91 stage_picture_(None), | |
| 92 compositor_(NULL), | |
| 93 xconn_(compositor->x_conn()), | |
| 94 stage_(NULL), | |
| 95 ancestor_opacity_(1.0), | |
| 96 has_fullscreen_actor_(false) { | |
| 97 // Check for the XRender extension. | |
| 98 CHECK(xconn_->RenderQueryExtension()); | |
| 99 | |
| 100 CHECK(AllocateXResources(stage)); | |
| 101 } | |
| 102 | |
| 103 XRenderDrawVisitor::~XRenderDrawVisitor() { | |
|
Daniel Erat
2011/04/05 01:35:06
call FreeXResources() here
marcheu
2011/04/05 02:07:42
Done.
| |
| 104 } | |
| 105 | |
| 106 void XRenderDrawVisitor::BindImage(const ImageContainer* container, | |
| 107 RealCompositor::ImageActor* actor) { | |
| 108 XPixmap pixmap = xconn_->CreatePixmapFromContainer(*container); | |
| 109 | |
| 110 scoped_ptr<window_manager::XRenderPictureData> | |
| 111 data(new XRenderPictureData(this->xconn_)); | |
| 112 data->Init(pixmap, kRGBAPictureBitDepth); | |
| 113 actor->set_texture_data(data.release()); | |
| 114 } | |
| 115 | |
| 116 void XRenderDrawVisitor::VisitImage(RealCompositor::ImageActor* actor) { | |
| 117 if (!actor->IsVisible()) | |
| 118 return; | |
| 119 | |
| 120 // All ImageActors are also QuadActors, and so we let the | |
| 121 // QuadActor do all the actual drawing. | |
| 122 VisitQuad(actor); | |
| 123 } | |
| 124 | |
| 125 void XRenderDrawVisitor::VisitTexturePixmap( | |
| 126 RealCompositor::TexturePixmapActor* actor) { | |
| 127 if (!actor->IsVisible()) | |
| 128 return; | |
| 129 | |
| 130 // Make sure we have an XRender pic for this pixmap | |
| 131 if (!actor->texture_data()) { | |
| 132 if (actor->pixmap()) { | |
| 133 scoped_ptr<window_manager::XRenderPictureData> | |
| 134 data(new XRenderPictureData(this->xconn_)); | |
| 135 data->Init(actor->pixmap(), | |
| 136 actor->pixmap_is_opaque() ? | |
| 137 kRGBPictureBitDepth : kRGBAPictureBitDepth); | |
| 138 actor->set_texture_data(data.release()); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 // All texture pixmaps are also QuadActors, and so we let the | |
| 143 // QuadActor do all the actual drawing. | |
| 144 VisitQuad(actor); | |
| 145 } | |
| 146 | |
| 147 void XRenderDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { | |
| 148 if (!actor->IsVisible()) | |
| 149 return; | |
| 150 | |
| 151 #ifdef EXTRA_LOGGING | |
| 152 DLOG(INFO) << "Drawing quad " << actor->name() << "."; | |
| 153 #endif | |
| 154 | |
| 155 // Calculate the vertex colors, taking into account the actor color, | |
| 156 // opacity and the dimming gradient. | |
| 157 float actor_opacity = actor->is_opaque() ? | |
| 158 1.f : | |
| 159 actor->opacity() * ancestor_opacity_; | |
| 160 float dimmed_transparency_begin = 1.f - actor->dimmed_opacity_begin(); | |
| 161 float dimmed_transparency_end = 1.f - actor->dimmed_opacity_end(); | |
| 162 float red = actor->color().red; | |
| 163 float green = actor->color().green; | |
| 164 float blue = actor->color().blue; | |
| 165 DCHECK_LE(actor_opacity, 1.f); | |
| 166 DCHECK_GE(actor_opacity, 0.f); | |
| 167 DCHECK_LE(dimmed_transparency_begin, 1.f); | |
| 168 DCHECK_GE(dimmed_transparency_begin, 0.f); | |
| 169 DCHECK_LE(dimmed_transparency_end, 1.f); | |
| 170 DCHECK_GE(dimmed_transparency_end, 0.f); | |
| 171 DCHECK_LE(red, 1.f); | |
| 172 DCHECK_GE(red, 0.f); | |
| 173 DCHECK_LE(green, 1.f); | |
| 174 DCHECK_GE(green, 0.f); | |
| 175 DCHECK_LE(blue, 1.f); | |
| 176 DCHECK_GE(blue, 0.f); | |
| 177 | |
| 178 xconn_->RenderComposite( | |
| 179 !actor->is_opaque(), | |
| 180 static_cast<XPicture>(actor->texture_data()->texture()), | |
| 181 static_cast<XPicture>(None), | |
| 182 back_picture_, | |
| 183 Point(0, 0), | |
| 184 Point(0, 0), | |
| 185 actor->model_view(), | |
| 186 actor->GetBounds().size()); | |
| 187 } | |
| 188 | |
| 189 void XRenderDrawVisitor::VisitStage(RealCompositor::StageActor* actor) { | |
| 190 if (!actor->IsVisible()) | |
| 191 return; | |
| 192 | |
| 193 stage_ = actor; | |
| 194 | |
| 195 if (actor->was_resized()) { | |
| 196 CHECK(FreeXResources()); | |
| 197 CHECK(AllocateXResources(actor)); | |
| 198 actor->unset_was_resized(); | |
| 199 } | |
| 200 | |
| 201 // If we don't have a full screen actor we do a fill with the stage color. | |
| 202 if (!has_fullscreen_actor_) { | |
| 203 const Compositor::Color& color = actor->stage_color(); | |
| 204 xconn_->RenderFillRectangle(back_picture_, | |
| 205 color.red, | |
| 206 color.green, | |
| 207 color.blue, | |
| 208 Point(0, 0), | |
| 209 root_geometry_.bounds.size()); | |
| 210 } | |
| 211 | |
| 212 #ifdef EXTRA_LOGGING | |
| 213 DLOG(INFO) << "Starting Render pass."; | |
| 214 #endif | |
| 215 | |
| 216 ancestor_opacity_ = actor->opacity(); | |
| 217 | |
| 218 // Walk the actors and render them | |
| 219 VisitContainer(actor); | |
| 220 | |
| 221 #ifdef EXTRA_LOGGING | |
| 222 DLOG(INFO) << "Ending Render pass."; | |
| 223 #endif | |
| 224 | |
| 225 if (!damaged_region_.empty()) { | |
| 226 Matrix4 identity = Matrix4::identity(); | |
| 227 identity[0][0] = damaged_region_.width; | |
| 228 identity[1][1] = damaged_region_.height; | |
| 229 identity[3][0] = damaged_region_.x; | |
| 230 identity[3][1] = root_geometry_.bounds.height - | |
| 231 damaged_region_.y - damaged_region_.height; | |
| 232 | |
| 233 xconn_->RenderComposite(false, | |
| 234 back_picture_, | |
| 235 None, | |
| 236 stage_picture_, | |
| 237 Point(damaged_region_.x, | |
| 238 root_geometry_.bounds.height - | |
| 239 damaged_region_.y - | |
| 240 damaged_region_.height), | |
| 241 Point(0, 0), | |
| 242 identity, | |
| 243 damaged_region_.size()); | |
| 244 } else { | |
| 245 Matrix4 identity = Vectormath::Aos::Matrix4::identity(); | |
| 246 identity[0][0] = root_geometry_.bounds.width; | |
| 247 identity[1][1] = root_geometry_.bounds.height; | |
| 248 xconn_->RenderComposite(false, | |
| 249 back_picture_, | |
| 250 None, | |
| 251 stage_picture_, | |
| 252 Point(0, 0), | |
| 253 Point(0, 0), | |
| 254 identity, | |
| 255 root_geometry_.bounds.size()); | |
| 256 } | |
| 257 | |
| 258 stage_ = NULL; | |
| 259 } | |
| 260 | |
| 261 void XRenderDrawVisitor::VisitContainer(RealCompositor::ContainerActor* actor) { | |
| 262 if (!actor->IsVisible()) | |
| 263 return; | |
| 264 | |
| 265 #ifdef EXTRA_LOGGING | |
| 266 DLOG(INFO) << "Drawing container " << actor->name() << "."; | |
| 267 DLOG(INFO) << " at: (" << actor->x() << ", " << actor->y() | |
| 268 << ", " << actor->z() << ") with scale: (" | |
| 269 << actor->scale_x() << ", " << actor->scale_y() << ") at size (" | |
| 270 << actor->width() << "x" << actor->height() << ")"; | |
| 271 #endif | |
| 272 RealCompositor::ActorVector children = actor->GetChildren(); | |
| 273 | |
| 274 float original_opacity = ancestor_opacity_; | |
| 275 ancestor_opacity_ *= actor->opacity(); | |
| 276 | |
| 277 // Walk backwards so we go back to front. | |
| 278 RealCompositor::ActorVector::const_reverse_iterator iterator; | |
| 279 for (iterator = children.rbegin(); iterator != children.rend(); | |
| 280 ++iterator) { | |
| 281 RealCompositor::Actor* child = *iterator; | |
| 282 | |
| 283 if (child->IsVisible()) { | |
| 284 #ifdef EXTRA_LOGGING | |
| 285 DLOG(INFO) << "Drawing child " << child->name() | |
| 286 << " (visible: " << child->IsVisible() | |
| 287 << ", has_children: " << child->has_children() | |
| 288 << ", opacity: " << child->opacity() | |
| 289 << ", ancestor_opacity: " << ancestor_opacity_ | |
| 290 << ", is_opaque: " << child->is_opaque() << ")"; | |
| 291 #endif | |
| 292 child->Accept(this); | |
| 293 } else { | |
| 294 #ifdef EXTRA_LOGGING | |
| 295 DLOG(INFO) << "NOT drawing child " << child->name() | |
| 296 << " (visible: " << child->IsVisible() | |
| 297 << ", has_children: " << child->has_children() | |
| 298 << ", opacity: " << child->opacity() | |
| 299 << ", ancestor_opacity: " << ancestor_opacity_ | |
| 300 << ", is_opaque: " << child->is_opaque() << ")"; | |
| 301 #endif | |
| 302 } | |
| 303 | |
| 304 // Reset ancestor opacity. | |
| 305 ancestor_opacity_ = original_opacity; | |
| 306 } | |
| 307 } | |
| 308 | |
| 309 } // namespace window_manager | |
| OLD | NEW |