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

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 first 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 "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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698