Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(782)

Side by Side Diff: compositor/xrender/xrender_visitor.cc

Issue 6793005: Add the xrender backend to the window manager. (Closed) Base URL: ssh://gitrw.chromium.org:9222/window_manager.git@master
Patch Set: Address third round of comments. Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 XRenderDrawVisitor::XRenderDrawVisitor(RealCompositor* compositor,
54 Compositor::StageActor* stage)
55 : root_window_(None),
56 back_picture_(None),
57 back_pixmap_(None),
58 stage_picture_(None),
59 compositor_(NULL),
60 xconn_(compositor->x_conn()),
61 stage_(NULL),
62 ancestor_opacity_(1.0),
63 has_fullscreen_actor_(false) {
64 // Check for the XRender extension.
65 CHECK(xconn_->RenderQueryExtension());
66
67 CHECK(AllocateXResources(stage));
68 }
69
70 XRenderDrawVisitor::~XRenderDrawVisitor() {
71 CHECK(FreeXResources());
72 }
73
74 void XRenderDrawVisitor::BindImage(const ImageContainer* container,
75 RealCompositor::ImageActor* actor) {
76 XPixmap pixmap = xconn_->CreatePixmapFromContainer(*container);
77
78 scoped_ptr<window_manager::XRenderPictureData>
79 data(new XRenderPictureData(this->xconn_));
Daniel Erat 2011/04/05 22:45:19 nit: variable name should come on same line as typ
marcheu 2011/04/06 00:26:12 Done.
80 data->Init(pixmap, kRGBAPictureBitDepth);
81 actor->set_texture_data(data.release());
82 }
83
84 void XRenderDrawVisitor::VisitStage(RealCompositor::StageActor* actor) {
85 if (!actor->IsVisible())
86 return;
87
88 stage_ = actor;
89
90 if (actor->was_resized()) {
91 CHECK(FreeXResources());
92 CHECK(AllocateXResources(actor));
93 actor->unset_was_resized();
94 }
95
96 // If we don't have a full screen actor we do a fill with the stage color.
97 if (!has_fullscreen_actor_) {
98 const Compositor::Color& color = actor->stage_color();
99 xconn_->RenderFillRectangle(back_picture_,
100 color.red,
101 color.green,
102 color.blue,
103 Point(0, 0),
104 root_geometry_.bounds.size());
105 }
106
107 #ifdef EXTRA_LOGGING
108 DLOG(INFO) << "Starting Render pass.";
109 #endif
110
111 ancestor_opacity_ = actor->opacity();
112
113 // Walk the actors and render them
114 VisitContainer(actor);
115
116 #ifdef EXTRA_LOGGING
117 DLOG(INFO) << "Ending Render pass.";
118 #endif
119
120 if (!damaged_region_.empty()) {
121 Matrix4 identity = Matrix4::identity();
122 identity[0][0] = damaged_region_.width;
123 identity[1][1] = damaged_region_.height;
124 identity[3][0] = damaged_region_.x;
125 identity[3][1] = root_geometry_.bounds.height -
126 damaged_region_.y - damaged_region_.height;
127
128 xconn_->RenderComposite(false,
129 back_picture_,
130 None,
131 stage_picture_,
132 Point(damaged_region_.x,
133 root_geometry_.bounds.height -
134 damaged_region_.y -
135 damaged_region_.height),
136 Point(0, 0),
137 identity,
138 damaged_region_.size());
139 } else {
140 Matrix4 identity = Vectormath::Aos::Matrix4::identity();
141 identity[0][0] = root_geometry_.bounds.width;
142 identity[1][1] = root_geometry_.bounds.height;
143 xconn_->RenderComposite(false,
144 back_picture_,
145 None,
146 stage_picture_,
147 Point(0, 0),
148 Point(0, 0),
149 identity,
150 root_geometry_.bounds.size());
151 }
152
153 stage_ = NULL;
154 }
155
156 void XRenderDrawVisitor::VisitContainer(RealCompositor::ContainerActor* actor) {
157 if (!actor->IsVisible())
158 return;
159
160 #ifdef EXTRA_LOGGING
161 DLOG(INFO) << "Drawing container " << actor->name() << ".";
162 DLOG(INFO) << " at: (" << actor->x() << ", " << actor->y()
163 << ", " << actor->z() << ") with scale: ("
164 << actor->scale_x() << ", " << actor->scale_y() << ") at size ("
165 << actor->width() << "x" << actor->height() << ")";
166 #endif
167 RealCompositor::ActorVector children = actor->GetChildren();
168
169 float original_opacity = ancestor_opacity_;
170 ancestor_opacity_ *= actor->opacity();
171
172 // Walk backwards so we go back to front.
173 RealCompositor::ActorVector::const_reverse_iterator iterator;
174 for (iterator = children.rbegin(); iterator != children.rend();
175 ++iterator) {
176 RealCompositor::Actor* child = *iterator;
177
178 if (child->IsVisible()) {
179 #ifdef EXTRA_LOGGING
180 DLOG(INFO) << "Drawing child " << child->name()
181 << " (visible: " << child->IsVisible()
182 << ", has_children: " << child->has_children()
183 << ", opacity: " << child->opacity()
184 << ", ancestor_opacity: " << ancestor_opacity_
185 << ", is_opaque: " << child->is_opaque() << ")";
186 #endif
187 child->Accept(this);
188 } else {
189 #ifdef EXTRA_LOGGING
190 DLOG(INFO) << "NOT drawing child " << child->name()
191 << " (visible: " << child->IsVisible()
192 << ", has_children: " << child->has_children()
193 << ", opacity: " << child->opacity()
194 << ", ancestor_opacity: " << ancestor_opacity_
195 << ", is_opaque: " << child->is_opaque() << ")";
196 #endif
197 }
198
199 // Reset ancestor opacity.
200 ancestor_opacity_ = original_opacity;
201 }
202 }
203
204 void XRenderDrawVisitor::VisitImage(RealCompositor::ImageActor* actor) {
205 if (!actor->IsVisible())
206 return;
207
208 // All ImageActors are also QuadActors, and so we let the
209 // QuadActor do all the actual drawing.
210 VisitQuad(actor);
211 }
212
213 void XRenderDrawVisitor::VisitTexturePixmap(
214 RealCompositor::TexturePixmapActor* actor) {
215 if (!actor->IsVisible())
216 return;
217
218 // Make sure we have an XRender pic for this pixmap
219 if (!actor->texture_data()) {
220 if (actor->pixmap()) {
221 scoped_ptr<window_manager::XRenderPictureData>
222 data(new XRenderPictureData(this->xconn_));
223 data->Init(actor->pixmap(),
224 actor->pixmap_is_opaque() ?
225 kRGBPictureBitDepth : kRGBAPictureBitDepth);
226 actor->set_texture_data(data.release());
227 }
228 }
229
230 // All texture pixmaps are also QuadActors, and so we let the
231 // QuadActor do all the actual drawing.
232 VisitQuad(actor);
233 }
234
235 void XRenderDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) {
236 if (!actor->IsVisible())
237 return;
238
239 #ifdef EXTRA_LOGGING
240 DLOG(INFO) << "Drawing quad " << actor->name() << ".";
241 #endif
242
243 // Calculate the vertex colors, taking into account the actor color,
244 // opacity and the dimming gradient.
245 float actor_opacity = actor->is_opaque() ?
246 1.f :
247 actor->opacity() * ancestor_opacity_;
248 float dimmed_transparency_begin = 1.f - actor->dimmed_opacity_begin();
249 float dimmed_transparency_end = 1.f - actor->dimmed_opacity_end();
250 float red = actor->color().red;
251 float green = actor->color().green;
252 float blue = actor->color().blue;
253 DCHECK_LE(actor_opacity, 1.f);
254 DCHECK_GE(actor_opacity, 0.f);
255 DCHECK_LE(dimmed_transparency_begin, 1.f);
256 DCHECK_GE(dimmed_transparency_begin, 0.f);
257 DCHECK_LE(dimmed_transparency_end, 1.f);
258 DCHECK_GE(dimmed_transparency_end, 0.f);
259 DCHECK_LE(red, 1.f);
260 DCHECK_GE(red, 0.f);
261 DCHECK_LE(green, 1.f);
262 DCHECK_GE(green, 0.f);
263 DCHECK_LE(blue, 1.f);
264 DCHECK_GE(blue, 0.f);
265
266 xconn_->RenderComposite(
267 !actor->is_opaque(),
268 static_cast<XPicture>(actor->texture_data()->texture()),
269 static_cast<XPicture>(None),
270 back_picture_,
271 Point(0, 0),
272 Point(0, 0),
273 actor->model_view(),
274 actor->GetBounds().size());
275 }
276
277 bool XRenderDrawVisitor::FreeXResources() {
278 return xconn_->FreePixmap(back_pixmap_) &&
279 xconn_->RenderFreePicture(back_picture_) &&
280 xconn_->RenderFreePicture(stage_picture_);
281 }
282
283 bool XRenderDrawVisitor::AllocateXResources(Compositor::StageActor* stage) {
284 // Find root window geometry.
285 root_window_ = stage->GetStageXWindow();
286 xconn_->GetWindowGeometry(root_window_, &root_geometry_);
287
288 // Create back pixmap.
289 back_pixmap_ =
290 xconn_->CreatePixmap(
291 root_window_,
292 root_geometry_.bounds.size(),
293 root_geometry_.depth);
294
295 // Create back picture.
296 back_picture_ = xconn_->RenderCreatePicture(back_pixmap_,
297 kRGBPictureBitDepth);
298
299 // Create stage picture.
300 stage_picture_ = xconn_->RenderCreatePicture(root_window_,
301 kRGBPictureBitDepth);
302
303 return (back_pixmap_ != None) &&
304 (back_picture_ != None) &&
305 (stage_picture_ != None);
306 }
307
308
309 } // namespace window_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698