OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/client/x11_view.h" | 5 #include "remoting/client/x11_view.h" |
6 | 6 |
7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
8 #include <X11/Xutil.h> | 8 #include <X11/Xutil.h> |
9 #include <X11/extensions/Xrender.h> | 9 #include <X11/extensions/Xrender.h> |
10 #include <X11/extensions/Xcomposite.h> | 10 #include <X11/extensions/Xcomposite.h> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "remoting/base/decoder_verbatim.h" | |
14 #include "remoting/base/decoder_zlib.h" | 13 #include "remoting/base/decoder_zlib.h" |
15 | 14 |
16 namespace remoting { | 15 namespace remoting { |
17 | 16 |
18 X11View::X11View() | 17 X11View::X11View() |
19 : display_(NULL), | 18 : display_(NULL), |
20 window_(0), | 19 window_(0), |
21 width_(0), | |
22 height_(0), | |
23 picture_(0) { | 20 picture_(0) { |
24 } | 21 } |
25 | 22 |
26 X11View::X11View(Display* display, XID window, int width, int height) | |
27 : display_(display), | |
28 window_(window), | |
29 width_(width), | |
30 height_(height), | |
31 picture_(0) { | |
32 media::VideoFrame::CreateFrame(media::VideoFrame::RGB32, width_, height_, | |
33 base::TimeDelta(), base::TimeDelta(), &frame_); | |
34 DCHECK(frame_); | |
35 } | |
36 | |
37 X11View::~X11View() { | 23 X11View::~X11View() { |
38 DCHECK(!display_); | 24 DCHECK(!display_); |
39 DCHECK(!window_); | 25 DCHECK(!window_); |
40 } | 26 } |
41 | 27 |
42 bool X11View::Initialize() { | 28 bool X11View::Initialize() { |
43 display_ = XOpenDisplay(NULL); | 29 display_ = XOpenDisplay(NULL); |
44 if (!display_) { | 30 if (!display_) { |
45 return false; | 31 return false; |
46 } | 32 } |
(...skipping 20 matching lines...) Expand all Loading... |
67 // Shutdown the window system. | 53 // Shutdown the window system. |
68 XDestroyWindow(display_, window_); | 54 XDestroyWindow(display_, window_); |
69 XCloseDisplay(display_); | 55 XCloseDisplay(display_); |
70 } | 56 } |
71 display_ = NULL; | 57 display_ = NULL; |
72 window_ = 0; | 58 window_ = 0; |
73 } | 59 } |
74 | 60 |
75 void X11View::Paint() { | 61 void X11View::Paint() { |
76 // Don't bother attempting to paint if the display hasn't been set up. | 62 // Don't bother attempting to paint if the display hasn't been set up. |
77 if (!display_ || !window_ || !height_ || !width_ || !frame_) { | 63 if (!display_ || !window_ || !frame_height_ || !frame_width_ || !frame_) { |
78 return; | 64 return; |
79 } | 65 } |
80 | 66 |
81 // TODO(hclam): Paint only the updated regions. | 67 // TODO(hclam): Paint only the updated regions. |
82 all_update_rects_.clear(); | 68 all_update_rects_.clear(); |
83 | 69 |
84 // If we have not initialized the render target then do it now. | 70 // If we have not initialized the render target then do it now. |
85 if (!picture_) | 71 if (!picture_) |
86 InitPaintTarget(); | 72 InitPaintTarget(); |
87 | 73 |
88 // Upload the image to a pixmap. And then create a picture from the pixmap | 74 // Upload the image to a pixmap. And then create a picture from the pixmap |
89 // and composite the picture over the picture representing the window. | 75 // and composite the picture over the picture representing the window. |
90 | 76 |
91 // Creates a XImage. | 77 // Creates a XImage. |
92 XImage image; | 78 XImage image; |
93 memset(&image, 0, sizeof(image)); | 79 memset(&image, 0, sizeof(image)); |
94 image.width = width_; | 80 image.width = frame_width_; |
95 image.height = height_; | 81 image.height = frame_height_; |
96 image.depth = 32; | 82 image.depth = 32; |
97 image.bits_per_pixel = 32; | 83 image.bits_per_pixel = 32; |
98 image.format = ZPixmap; | 84 image.format = ZPixmap; |
99 image.byte_order = LSBFirst; | 85 image.byte_order = LSBFirst; |
100 image.bitmap_unit = 8; | 86 image.bitmap_unit = 8; |
101 image.bitmap_bit_order = LSBFirst; | 87 image.bitmap_bit_order = LSBFirst; |
102 image.bytes_per_line = frame_->stride(media::VideoFrame::kRGBPlane); | 88 image.bytes_per_line = frame_->stride(media::VideoFrame::kRGBPlane); |
103 image.red_mask = 0xff; | 89 image.red_mask = 0xff; |
104 image.green_mask = 0xff00; | 90 image.green_mask = 0xff00; |
105 image.blue_mask = 0xff0000; | 91 image.blue_mask = 0xff0000; |
106 image.data = reinterpret_cast<char*>( | 92 image.data = reinterpret_cast<char*>( |
107 frame_->data(media::VideoFrame::kRGBPlane)); | 93 frame_->data(media::VideoFrame::kRGBPlane)); |
108 | 94 |
109 // Creates a pixmap and uploads from the XImage. | 95 // Creates a pixmap and uploads from the XImage. |
110 unsigned long pixmap = XCreatePixmap(display_, window_, width_, height_, 32); | 96 unsigned long pixmap = XCreatePixmap(display_, window_, |
| 97 frame_width_, frame_height_, 32); |
111 | 98 |
112 GC gc = XCreateGC(display_, pixmap, 0, NULL); | 99 GC gc = XCreateGC(display_, pixmap, 0, NULL); |
113 XPutImage(display_, pixmap, gc, &image, 0, 0, 0, 0, width_, height_); | 100 XPutImage(display_, pixmap, gc, &image, 0, 0, 0, 0, |
| 101 frame_width_, frame_height_); |
114 XFreeGC(display_, gc); | 102 XFreeGC(display_, gc); |
115 | 103 |
116 // Creates the picture representing the pixmap. | 104 // Creates the picture representing the pixmap. |
117 XID picture = XRenderCreatePicture( | 105 XID picture = XRenderCreatePicture( |
118 display_, pixmap, | 106 display_, pixmap, |
119 XRenderFindStandardFormat(display_, PictStandardARGB32), | 107 XRenderFindStandardFormat(display_, PictStandardARGB32), |
120 0, NULL); | 108 0, NULL); |
121 | 109 |
122 // Composite the picture over the picture representing the window. | 110 // Composite the picture over the picture representing the window. |
123 XRenderComposite(display_, PictOpSrc, picture, 0, | 111 XRenderComposite(display_, PictOpSrc, picture, 0, |
124 picture_, 0, 0, 0, 0, 0, 0, | 112 picture_, 0, 0, 0, 0, 0, 0, |
125 width_, height_); | 113 frame_width_, frame_height_); |
126 | 114 |
127 XRenderFreePicture(display_, picture); | 115 XRenderFreePicture(display_, picture); |
128 XFreePixmap(display_, pixmap); | 116 XFreePixmap(display_, pixmap); |
129 } | 117 } |
130 | 118 |
131 void X11View::SetSolidFill(uint32 color) { | 119 void X11View::SetSolidFill(uint32 color) { |
132 // TODO(garykac): Implement. | 120 // TODO(garykac): Implement. |
133 // NOTIMPLEMENTED(); | 121 // NOTIMPLEMENTED(); |
134 } | 122 } |
135 | 123 |
136 void X11View::UnsetSolidFill() { | 124 void X11View::UnsetSolidFill() { |
137 // TODO(garykac): Implement. | 125 // TODO(garykac): Implement. |
138 // NOTIMPLEMENTED(); | 126 // NOTIMPLEMENTED(); |
139 } | 127 } |
140 | 128 |
141 void X11View::SetViewport(int x, int y, int width, int height) { | 129 void X11View::SetViewport(int x, int y, int width, int height) { |
142 // TODO(garykac): Implement. | 130 // TODO(garykac): Implement. |
143 // NOTIMPLEMENTED(); | 131 // NOTIMPLEMENTED(); |
144 } | 132 } |
145 | 133 |
146 void X11View::SetHostScreenSize(int width, int height) { | 134 void X11View::SetHostScreenSize(int width, int height) { |
147 width_ = width; | 135 frame_width_ = width; |
148 height_ = height; | 136 frame_height_ = height; |
149 XResizeWindow(display_, window_, width_, height_); | 137 frame_ = NULL; |
150 media::VideoFrame::CreateFrame(media::VideoFrame::RGB32, width_, height_, | 138 |
151 base::TimeDelta(), base::TimeDelta(), &frame_); | 139 XResizeWindow(display_, window_, frame_width_, frame_height_); |
152 } | 140 } |
153 | 141 |
154 void X11View::InitPaintTarget() { | 142 void X11View::InitPaintTarget() { |
155 // Testing XRender support. | 143 // Testing XRender support. |
156 int dummy; | 144 int dummy; |
157 bool xrender_support = XRenderQueryExtension(display_, &dummy, &dummy); | 145 bool xrender_support = XRenderQueryExtension(display_, &dummy, &dummy); |
158 CHECK(xrender_support) << "XRender is not supported!"; | 146 CHECK(xrender_support) << "XRender is not supported!"; |
159 | 147 |
160 XWindowAttributes attr; | 148 XWindowAttributes attr; |
161 XGetWindowAttributes(display_, window_, &attr); | 149 XGetWindowAttributes(display_, window_, &attr); |
162 | 150 |
163 XRenderPictFormat* pictformat = XRenderFindVisualFormat( | 151 XRenderPictFormat* pictformat = XRenderFindVisualFormat( |
164 display_, | 152 display_, |
165 attr.visual); | 153 attr.visual); |
166 CHECK(pictformat) << "XRENDER does not support default visual"; | 154 CHECK(pictformat) << "XRENDER does not support default visual"; |
167 | 155 |
168 picture_ = XRenderCreatePicture(display_, window_, pictformat, 0, NULL); | 156 picture_ = XRenderCreatePicture(display_, window_, pictformat, 0, NULL); |
169 CHECK(picture_) << "Backing picture not created"; | 157 CHECK(picture_) << "Backing picture not created"; |
170 } | 158 } |
171 | 159 |
172 void X11View::HandleBeginUpdateStream(HostMessage* msg) { | 160 void X11View::HandleBeginUpdateStream(HostMessage* msg) { |
173 scoped_ptr<HostMessage> deleter(msg); | 161 scoped_ptr<HostMessage> deleter(msg); |
174 | 162 |
175 // TODO(hclam): Use the information from the message to create the decoder. | 163 // Make sure the |frame_| is initialized. |
176 // We lazily construct the decoder. | 164 if (!frame_) { |
177 if (!decoder_.get()) { | 165 media::VideoFrame::CreateFrame(media::VideoFrame::RGB32, |
178 decoder_.reset(new DecoderZlib()); | 166 frame_width_, frame_height_, |
| 167 base::TimeDelta(), base::TimeDelta(), |
| 168 &frame_); |
| 169 CHECK(frame_); |
179 } | 170 } |
180 | |
181 // Tell the decoder to do start decoding. | |
182 decoder_->BeginDecode(frame_, &update_rects_, | |
183 NewRunnableMethod(this, &X11View::OnPartialDecodeDone), | |
184 NewRunnableMethod(this, &X11View::OnDecodeDone)); | |
185 } | 171 } |
186 | 172 |
187 void X11View::HandleUpdateStreamPacket(HostMessage* msg) { | 173 void X11View::HandleUpdateStreamPacket(HostMessage* msg) { |
188 decoder_->PartialDecode(msg); | 174 // Lazily initialize the decoder. |
| 175 SetupDecoder(msg->update_stream_packet().begin_rect().encoding()); |
| 176 if (!decoder_->IsStarted()) { |
| 177 BeginDecoding(NewRunnableMethod(this, &X11View::OnPartialDecodeDone), |
| 178 NewRunnableMethod(this, &X11View::OnDecodeDone)); |
| 179 } |
| 180 |
| 181 Decode(msg); |
189 } | 182 } |
190 | 183 |
191 void X11View::HandleEndUpdateStream(HostMessage* msg) { | 184 void X11View::HandleEndUpdateStream(HostMessage* msg) { |
192 scoped_ptr<HostMessage> deleter(msg); | 185 scoped_ptr<HostMessage> deleter(msg); |
193 decoder_->EndDecode(); | 186 EndDecoding(); |
194 } | 187 } |
195 | 188 |
196 void X11View::OnPartialDecodeDone() { | 189 void X11View::OnPartialDecodeDone() { |
197 // Decoder has produced some output so schedule a paint. We'll get a Paint() | 190 // Decoder has produced some output so schedule a paint. We'll get a Paint() |
198 // call in the near future. Note that we can get UpdateStreamPacket during | 191 // call in the near future. Note that we can get UpdateStreamPacket during |
199 // this short period of time and we will perform decode again and the | 192 // this short period of time and we will perform decode again and the |
200 // information in updated rects will be lost. | 193 // information in updated rects will be lost. |
201 // There are several ways to solve this problem. | 194 // There are several ways to solve this problem. |
202 // 1. Merge the updated rects and perform one paint. | 195 // 1. Merge the updated rects and perform one paint. |
203 // 2. Queue the updated rects and perform two paints. | 196 // 2. Queue the updated rects and perform two paints. |
(...skipping 10 matching lines...) Expand all Loading... |
214 XEvent event; | 207 XEvent event; |
215 event.type = Expose; | 208 event.type = Expose; |
216 XSendEvent(display_, static_cast<int>(window_), true, ExposureMask, &event); | 209 XSendEvent(display_, static_cast<int>(window_), true, ExposureMask, &event); |
217 } | 210 } |
218 | 211 |
219 void X11View::OnDecodeDone() { | 212 void X11View::OnDecodeDone() { |
220 // Since we do synchronous decoding here there's nothing in this method. | 213 // Since we do synchronous decoding here there's nothing in this method. |
221 } | 214 } |
222 | 215 |
223 } // namespace remoting | 216 } // namespace remoting |
OLD | NEW |