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 "window_manager/image_container.h" | |
| 12 #include "window_manager/image_enums.h" | |
| 13 #include "window_manager/util.h" | |
| 14 #include "window_manager/x11/x_connection.h" | |
| 15 | |
| 16 | |
| 17 #ifndef COMPOSITOR_XRENDER | |
| 18 #error Need COMPOSITOR_XRENDER defined to compile this file | |
| 19 #endif | |
| 20 | |
| 21 namespace window_manager { | |
| 22 | |
| 23 const int kRGBPictureBitDepth = 24; | |
| 24 const int kRGBAPictureBitDepth = 32; | |
| 25 | |
| 26 class XRenderPictureData : public TextureData { | |
| 27 public: | |
| 28 XRenderPictureData(XRenderDrawVisitor* visitor) { | |
| 29 pixmap_ = 0; | |
|
Daniel Erat
2011/04/04 21:16:35
move these to an initialization list?
XRenderPict
marcheu
2011/04/05 00:23:40
Done.
| |
| 30 set_texture(0); | |
| 31 xconn_ = visitor->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 r = xconn_->RenderCreatePicture(pixmap, bpp); | |
|
Daniel Erat
2011/04/04 21:16:35
nit: s/r/picture/
marcheu
2011/04/05 00:23:40
Done.
| |
| 42 set_texture(r); | |
| 43 return (r != 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 | |
| 54 XRenderDrawVisitor::XRenderDrawVisitor(RealCompositor* compositor, | |
| 55 Compositor::StageActor* stage) { | |
| 56 xconn_ = compositor->x_conn(); | |
|
Daniel Erat
2011/04/04 21:16:35
nit: move this to an initialization list. i'd als
marcheu
2011/04/05 00:23:40
Done.
| |
| 57 | |
| 58 // Check for the XRender extension. | |
| 59 CHECK(xconn_->RenderQueryExtension()); | |
| 60 | |
| 61 // Find root window geometry. | |
| 62 root_window = stage->GetStageXWindow(); | |
| 63 xconn_->GetWindowGeometry(root_window, &root_geometry); | |
| 64 | |
| 65 // Create back pixmap. | |
| 66 back_pixmap_ = | |
| 67 xconn_->CreatePixmap( | |
| 68 root_window, | |
| 69 Size(root_geometry.bounds.width, root_geometry.bounds.height), | |
|
Daniel Erat
2011/04/04 21:16:35
nit: root_geometry.bounds.size()
marcheu
2011/04/05 00:23:40
Done.
| |
| 70 root_geometry.depth); | |
| 71 | |
| 72 // Create back picture. | |
| 73 back_picture_ = xconn_->RenderCreatePicture(back_pixmap_, | |
| 74 kRGBPictureBitDepth); | |
| 75 | |
| 76 // Create stage picture. | |
| 77 stage_picture_ = xconn_->RenderCreatePicture(root_window, | |
| 78 kRGBPictureBitDepth); | |
| 79 } | |
| 80 | |
| 81 XRenderDrawVisitor::~XRenderDrawVisitor() { | |
| 82 } | |
| 83 | |
| 84 void XRenderDrawVisitor::BindImage(const ImageContainer* container, | |
| 85 RealCompositor::ImageActor* actor) { | |
| 86 XPixmap pixmap = xconn_->CreatePixmapFromContainer(container); | |
| 87 | |
| 88 XRenderPictureData* data = new XRenderPictureData(this); | |
|
Daniel Erat
2011/04/04 21:16:35
mind using scoped_ptr here and then data.release()
marcheu
2011/04/05 00:23:40
Done.
| |
| 89 data->Init(pixmap, kRGBAPictureBitDepth); | |
| 90 actor->set_texture_data(data); | |
| 91 } | |
| 92 | |
| 93 void XRenderDrawVisitor::VisitImage(RealCompositor::ImageActor* actor) { | |
| 94 if (!actor->IsVisible()) | |
| 95 return; | |
| 96 | |
| 97 // All ImageActors are also QuadActors, and so we let the | |
| 98 // QuadActor do all the actual drawing. | |
| 99 VisitQuad(actor); | |
| 100 } | |
| 101 | |
| 102 void XRenderDrawVisitor::VisitTexturePixmap( | |
| 103 RealCompositor::TexturePixmapActor* actor) { | |
| 104 if (!actor->IsVisible()) | |
| 105 return; | |
| 106 | |
| 107 // Make sure we have an XRender pic for this pixmap | |
| 108 if (!actor->texture_data()) { | |
| 109 if (actor->pixmap()) { | |
| 110 XRenderPictureData* data = new XRenderPictureData(this); | |
|
Daniel Erat
2011/04/04 21:16:35
scoped_ptr here too please
marcheu
2011/04/05 00:23:40
Done.
| |
| 111 data->Init(actor->pixmap(), | |
| 112 actor->pixmap_is_opaque() ? | |
| 113 kRGBPictureBitDepth : kRGBAPictureBitDepth); | |
| 114 actor->set_texture_data(data); | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 // All texture pixmaps are also QuadActors, and so we let the | |
| 119 // QuadActor do all the actual drawing. | |
| 120 VisitQuad(actor); | |
| 121 } | |
| 122 | |
| 123 void XRenderDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { | |
| 124 if (!actor->IsVisible()) | |
| 125 return; | |
| 126 | |
| 127 #ifdef EXTRA_LOGGING | |
| 128 DLOG(INFO) << "Drawing quad " << actor->name() << "."; | |
| 129 #endif | |
| 130 | |
| 131 // Calculate the vertex colors, taking into account the actor color, | |
| 132 // opacity and the dimming gradient. | |
| 133 float actor_opacity = actor->is_opaque() ? | |
| 134 1.f : | |
| 135 actor->opacity() * ancestor_opacity_; | |
| 136 float dimmed_transparency_begin = 1.f - actor->dimmed_opacity_begin(); | |
| 137 float dimmed_transparency_end = 1.f - actor->dimmed_opacity_end(); | |
| 138 float red = actor->color().red; | |
| 139 float green = actor->color().green; | |
| 140 float blue = actor->color().blue; | |
| 141 DCHECK_LE(actor_opacity, 1.f); | |
| 142 DCHECK_GE(actor_opacity, 0.f); | |
| 143 DCHECK_LE(dimmed_transparency_begin, 1.f); | |
| 144 DCHECK_GE(dimmed_transparency_begin, 0.f); | |
| 145 DCHECK_LE(dimmed_transparency_end, 1.f); | |
| 146 DCHECK_GE(dimmed_transparency_end, 0.f); | |
| 147 DCHECK_LE(red, 1.f); | |
| 148 DCHECK_GE(red, 0.f); | |
| 149 DCHECK_LE(green, 1.f); | |
| 150 DCHECK_GE(green, 0.f); | |
| 151 DCHECK_LE(blue, 1.f); | |
| 152 DCHECK_GE(blue, 0.f); | |
| 153 | |
| 154 xconn_->RenderComposite( | |
| 155 !actor->is_opaque(), | |
| 156 static_cast<XPicture>(actor->texture_data()->texture()), | |
| 157 static_cast<XPicture>(None), | |
| 158 back_picture_, | |
| 159 Point(0, 0), | |
| 160 Point(0, 0), | |
| 161 actor->model_view(), | |
| 162 actor->GetBounds().size()); | |
| 163 } | |
| 164 | |
| 165 void XRenderDrawVisitor::VisitStage(RealCompositor::StageActor* actor) { | |
| 166 if (!actor->IsVisible()) | |
| 167 return; | |
| 168 | |
| 169 stage_ = actor; | |
| 170 | |
| 171 if (actor->was_resized()) | |
|
Daniel Erat
2011/04/04 21:16:35
don't you need to throw out your pictures and pixm
marcheu
2011/04/05 00:23:40
Done.
| |
| 172 actor->unset_was_resized(); | |
| 173 | |
| 174 // If we don't have a full screen actor we do a fill with the stage color. | |
| 175 if (!has_fullscreen_actor_) { | |
| 176 const Compositor::Color& color = actor->stage_color(); | |
| 177 xconn_->RenderFillRectangle(back_picture_, | |
| 178 color.red, | |
| 179 color.green, | |
| 180 color.blue, | |
| 181 Point(0, 0), | |
| 182 root_geometry.bounds.size()); | |
| 183 } | |
| 184 | |
| 185 #ifdef EXTRA_LOGGING | |
| 186 DLOG(INFO) << "Starting Render pass."; | |
| 187 #endif | |
| 188 | |
| 189 ancestor_opacity_ = actor->opacity(); | |
| 190 | |
| 191 // Walk the actors and render them | |
| 192 VisitContainer(actor); | |
| 193 | |
| 194 #ifdef EXTRA_LOGGING | |
| 195 DLOG(INFO) << "Ending Render pass."; | |
| 196 #endif | |
| 197 | |
| 198 if (!damaged_region_.empty()) { | |
| 199 Matrix4 identity = Vectormath::Aos::Matrix4::identity(); | |
|
Daniel Erat
2011/04/04 21:16:35
you can just use "Matrix4::identity()" here, right
marcheu
2011/04/05 00:23:40
Done.
| |
| 200 identity[0][0] = damaged_region_.width; | |
| 201 identity[1][1] = damaged_region_.height; | |
| 202 identity[3][0] = damaged_region_.x; | |
| 203 identity[3][1] = root_geometry.bounds.height - | |
| 204 damaged_region_.y - damaged_region_.height; | |
| 205 | |
| 206 xconn_->RenderComposite(false, | |
| 207 back_picture_, | |
| 208 None, | |
| 209 stage_picture_, | |
| 210 Point(damaged_region_.x, | |
| 211 root_geometry.bounds.height - | |
| 212 damaged_region_.y - | |
| 213 damaged_region_.height), | |
| 214 Point(0, 0), | |
| 215 identity, | |
| 216 damaged_region_.size()); | |
| 217 } else { | |
| 218 Matrix4 identity = Vectormath::Aos::Matrix4::identity(); | |
| 219 identity[0][0] = root_geometry.bounds.width; | |
| 220 identity[1][1] = root_geometry.bounds.height; | |
| 221 xconn_->RenderComposite(false, | |
| 222 back_picture_, | |
| 223 None, | |
| 224 stage_picture_, | |
| 225 Point(0, 0), | |
| 226 Point(0, 0), | |
| 227 identity, | |
| 228 root_geometry.bounds.size()); | |
| 229 } | |
| 230 | |
| 231 stage_ = NULL; | |
| 232 } | |
| 233 | |
| 234 void XRenderDrawVisitor::VisitContainer(RealCompositor::ContainerActor* actor) { | |
| 235 if (!actor->IsVisible()) | |
| 236 return; | |
| 237 | |
| 238 #ifdef EXTRA_LOGGING | |
| 239 DLOG(INFO) << "Drawing container " << actor->name() << "."; | |
| 240 DLOG(INFO) << " at: (" << actor->x() << ", " << actor->y() | |
| 241 << ", " << actor->z() << ") with scale: (" | |
| 242 << actor->scale_x() << ", " << actor->scale_y() << ") at size (" | |
| 243 << actor->width() << "x" << actor->height() << ")"; | |
| 244 #endif | |
| 245 RealCompositor::ActorVector children = actor->GetChildren(); | |
| 246 | |
| 247 float original_opacity = ancestor_opacity_; | |
| 248 ancestor_opacity_ *= actor->opacity(); | |
| 249 | |
| 250 // Walk backwards so we go back to front. | |
| 251 RealCompositor::ActorVector::const_reverse_iterator iterator; | |
| 252 for (iterator = children.rbegin(); iterator != children.rend(); | |
| 253 ++iterator) { | |
| 254 RealCompositor::Actor* child = *iterator; | |
| 255 | |
| 256 if (child->IsVisible()) { | |
| 257 #ifdef EXTRA_LOGGING | |
| 258 DLOG(INFO) << "Drawing transparent child " << child->name() | |
|
Daniel Erat
2011/04/04 21:16:35
nit: transparent/opaque here and in the next log s
marcheu
2011/04/05 00:23:40
Done.
| |
| 259 << " (visible: " << child->IsVisible() | |
| 260 << ", has_children: " << child->has_children() | |
| 261 << ", opacity: " << child->opacity() | |
| 262 << ", ancestor_opacity: " << ancestor_opacity_ | |
| 263 << ", is_opaque: " << child->is_opaque() << ")"; | |
| 264 #endif | |
| 265 child->Accept(this); | |
| 266 } else { | |
| 267 #ifdef EXTRA_LOGGING | |
| 268 DLOG(INFO) << "NOT drawing opaque child " << child->name() | |
| 269 << " (visible: " << child->IsVisible() | |
| 270 << ", has_children: " << child->has_children() | |
| 271 << ", opacity: " << child->opacity() | |
| 272 << ", ancestor_opacity: " << ancestor_opacity_ | |
| 273 << ", is_opaque: " << child->is_opaque() << ")"; | |
| 274 #endif | |
| 275 } | |
| 276 | |
| 277 // Reset ancestor opacity. | |
| 278 ancestor_opacity_ = original_opacity; | |
| 279 } | |
| 280 } | |
| 281 | |
| 282 } // namespace window_manager | |
| OLD | NEW |