blob: fee1195262db92a4213abf77406a2dc7d0edf6df [file] [log] [blame]
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -08001/* Copyright (C) 2010 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
12
13/*
14 * Contains core-side framebuffer service that sends framebuffer updates
15 * to the UI connected to the core.
16 */
17
18#include "console.h"
19#include "framebuffer.h"
20#include "android/looper.h"
21#include "android/display-core.h"
22#include "android/async-utils.h"
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -080023#include "android/protocol/fb-updates.h"
24#include "android/protocol/fb-updates-proxy.h"
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080025#include "android/utils/system.h"
26#include "android/utils/debug.h"
27
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -080028/* Descriptor for the Core-side implementation of the "framebufer" service.
29 */
30struct ProxyFramebuffer {
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080031 /* Writer used to send FB update notification messages. */
Vladimir Chtchetkine8acf4e22010-12-21 07:14:17 -080032 AsyncWriter fb_update_writer;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080033
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -080034 /* Reader used to read FB requests from the client. */
35 AsyncReader fb_req_reader;
36
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080037 /* I/O associated with this descriptor. */
Vladimir Chtchetkine8acf4e22010-12-21 07:14:17 -080038 LoopIo io;
39
40 /* Framebuffer used for this service. */
41 QFrameBuffer* fb;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080042
43 /* Looper used to communicate framebuffer updates. */
44 Looper* looper;
45
46 /* Head of the list of pending FB update notifications. */
47 struct FBUpdateNotify* fb_update_head;
48
49 /* Tail of the list of pending FB update notifications. */
50 struct FBUpdateNotify* fb_update_tail;
51
52 /* Socket used to communicate framebuffer updates. */
53 int sock;
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -080054
55 /* Framebuffer request header. */
56 FBRequestHeader fb_req_header;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080057};
58
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -080059/* Framebuffer update notification descriptor. */
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080060typedef struct FBUpdateNotify {
61 /* Links all pending FB update notifications. */
62 struct FBUpdateNotify* next_fb_update;
63
64 /* Core framebuffer instance that owns the message. */
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -080065 ProxyFramebuffer* proxy_fb;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -080066
67 /* Size of the message to transfer. */
68 size_t message_size;
69
70 /* Update message. */
71 FBUpdateMessage message;
72} FBUpdateNotify;
73
74/*
75 * Gets pointer in framebuffer's pixels for the given pixel.
76 * Param:
77 * fb Framebuffer containing pixels.
78 * x, and y identify the pixel to get pointer for.
79 * Return:
80 * Pointer in framebuffer's pixels for the given pixel.
81 */
82static const uint8_t*
83_pixel_offset(const QFrameBuffer* fb, int x, int y)
84{
85 return (const uint8_t*)fb->pixels + y * fb->pitch + x * fb->bytes_per_pixel;
86}
87
88/*
89 * Copies pixels from a framebuffer rectangle.
90 * Param:
91 * rect - Buffer where to copy pixel.
92 * fb - Framebuffer containing the rectangle to copy.
93 * x, y, w, and h - dimensions of the rectangle to copy.
94 */
95static void
96_copy_fb_rect(uint8_t* rect, const QFrameBuffer* fb, int x, int y, int w, int h)
97{
98 const uint8_t* start = _pixel_offset(fb, x, y);
99 for (; h > 0; h--) {
100 memcpy(rect, start, w * fb->bytes_per_pixel);
101 start += fb->pitch;
102 rect += w * fb->bytes_per_pixel;
103 }
104}
105
106/*
107 * Allocates and initializes framebuffer update notification descriptor.
108 * Param:
109 * ds - Display state for the framebuffer.
110 * fb Framebuffer containing pixels.
111 * x, y, w, and h identify the rectangle that is being updated.
112 * Return:
113 * Initialized framebuffer update notification descriptor.
114 */
115static FBUpdateNotify*
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800116fbupdatenotify_create(ProxyFramebuffer* proxy_fb, const QFrameBuffer* fb,
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800117 int x, int y, int w, int h)
118{
119 const size_t rect_size = w * h * fb->bytes_per_pixel;
120 FBUpdateNotify* ret = malloc(sizeof(FBUpdateNotify) + rect_size);
121
122 ret->next_fb_update = NULL;
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800123 ret->proxy_fb = proxy_fb;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800124 ret->message_size = sizeof(FBUpdateMessage) + rect_size;
125 ret->message.x = x;
126 ret->message.y = y;
127 ret->message.w = w;
128 ret->message.h = h;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800129 _copy_fb_rect(ret->message.rect, fb, x, y, w, h);
130 return ret;
131}
132
133/*
134 * Deletes FBUpdateNotify descriptor, created with fbupdatenotify_create.
135 * Param:
136 * desc - Descreptor to delete.
137 */
138static void
139fbupdatenotify_delete(FBUpdateNotify* desc)
140{
141 if (desc != NULL) {
142 free(desc);
143 }
144}
145
Vladimir Chtchetkine6ee1c4e2011-01-20 11:22:32 -0800146/* Implemented in android/console.c */
147extern void destroy_control_fb_client(void);
148
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800149/*
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800150 * Asynchronous write I/O callback launched when writing framebuffer
151 * notifications to the socket.
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800152 * Param:
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800153 * proxy_fb - ProxyFramebuffer instance.
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800154 */
155static void
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800156_proxyFb_io_write(ProxyFramebuffer* proxy_fb)
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800157{
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800158 while (proxy_fb->fb_update_head != NULL) {
159 FBUpdateNotify* current_update = proxy_fb->fb_update_head;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800160 // Lets continue writing of the current notification.
161 const AsyncStatus status =
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800162 asyncWriter_write(&proxy_fb->fb_update_writer, &proxy_fb->io);
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800163 switch (status) {
164 case ASYNC_COMPLETE:
165 // Done with the current update. Move on to the next one.
166 break;
167 case ASYNC_ERROR:
168 // Done with the current update. Move on to the next one.
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800169 loopIo_dontWantWrite(&proxy_fb->io);
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800170 break;
171
172 case ASYNC_NEED_MORE:
173 // Transfer will eventually come back into this routine.
174 return;
175 }
176
177 // Advance the list of updates
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800178 proxy_fb->fb_update_head = current_update->next_fb_update;
179 if (proxy_fb->fb_update_head == NULL) {
180 proxy_fb->fb_update_tail = NULL;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800181 }
182 fbupdatenotify_delete(current_update);
183
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800184 if (proxy_fb->fb_update_head != NULL) {
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800185 // Schedule the next one.
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800186 asyncWriter_init(&proxy_fb->fb_update_writer,
187 &proxy_fb->fb_update_head->message,
188 proxy_fb->fb_update_head->message_size,
189 &proxy_fb->io);
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800190 }
191 }
192}
193
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800194/*
195 * Asynchronous read I/O callback launched when reading framebuffer requests
196 * from the socket.
197 * Param:
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800198 * proxy_fb - ProxyFramebuffer instance.
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800199 */
200static void
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800201_proxyFb_io_read(ProxyFramebuffer* proxy_fb)
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800202{
203 // Read the request header.
204 const AsyncStatus status =
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800205 asyncReader_read(&proxy_fb->fb_req_reader, &proxy_fb->io);
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800206 switch (status) {
207 case ASYNC_COMPLETE:
208 // Request header is received
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800209 switch (proxy_fb->fb_req_header.request_type) {
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800210 case AFB_REQUEST_REFRESH:
211 // Force full screen update to be sent
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800212 proxyFb_update(proxy_fb, proxy_fb->fb,
213 0, 0, proxy_fb->fb->width,
214 proxy_fb->fb->height);
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800215 break;
216 default:
217 derror("Unknown framebuffer request %d\n",
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800218 proxy_fb->fb_req_header.request_type);
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800219 break;
220 }
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800221 proxy_fb->fb_req_header.request_type = -1;
222 asyncReader_init(&proxy_fb->fb_req_reader, &proxy_fb->fb_req_header,
223 sizeof(proxy_fb->fb_req_header), &proxy_fb->io);
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800224 break;
225 case ASYNC_ERROR:
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800226 loopIo_dontWantRead(&proxy_fb->io);
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800227 if (errno == ECONNRESET) {
228 // UI has exited. We need to destroy framebuffer service.
229 destroy_control_fb_client();
230 }
231 break;
232
233 case ASYNC_NEED_MORE:
234 // Transfer will eventually come back into this routine.
235 return;
236 }
237}
238
239/*
240 * Asynchronous I/O callback launched when writing framebuffer notifications
241 * to the socket.
242 * Param:
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800243 * opaque - ProxyFramebuffer instance.
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800244 */
245static void
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800246_proxyFb_io_fun(void* opaque, int fd, unsigned events)
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800247{
248 if (events & LOOP_IO_READ) {
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800249 _proxyFb_io_read((ProxyFramebuffer*)opaque);
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800250 } else if (events & LOOP_IO_WRITE) {
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800251 _proxyFb_io_write((ProxyFramebuffer*)opaque);
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800252 }
253}
254
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800255ProxyFramebuffer*
256proxyFb_create(int sock, const char* protocol, QFrameBuffer* fb)
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800257{
258 // At this point we're implementing the -raw protocol only.
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800259 ProxyFramebuffer* ret;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800260 ANEW0(ret);
261 ret->sock = sock;
262 ret->looper = looper_newCore();
Vladimir Chtchetkine8acf4e22010-12-21 07:14:17 -0800263 ret->fb = fb;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800264 ret->fb_update_head = NULL;
265 ret->fb_update_tail = NULL;
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800266 loopIo_init(&ret->io, ret->looper, sock, _proxyFb_io_fun, ret);
Vladimir Chtchetkineac389ae2011-01-20 14:35:55 -0800267 asyncReader_init(&ret->fb_req_reader, &ret->fb_req_header,
268 sizeof(ret->fb_req_header), &ret->io);
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800269 return ret;
270}
271
272void
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800273proxyFb_destroy(ProxyFramebuffer* proxy_fb)
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800274{
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800275 if (proxy_fb != NULL) {
276 if (proxy_fb->looper != NULL) {
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800277 // Stop all I/O that may still be going on.
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800278 loopIo_done(&proxy_fb->io);
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800279 // Delete all pending frame updates.
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800280 while (proxy_fb->fb_update_head != NULL) {
281 FBUpdateNotify* pending_update = proxy_fb->fb_update_head;
282 proxy_fb->fb_update_head = pending_update->next_fb_update;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800283 fbupdatenotify_delete(pending_update);
284 }
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800285 proxy_fb->fb_update_tail = NULL;
286 looper_free(proxy_fb->looper);
287 proxy_fb->looper = NULL;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800288 }
289 }
290}
291
292void
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800293proxyFb_update(ProxyFramebuffer* proxy_fb,
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800294 struct QFrameBuffer* fb, int x, int y, int w, int h)
295{
296 AsyncStatus status;
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800297 FBUpdateNotify* descr = fbupdatenotify_create(proxy_fb, fb, x, y, w, h);
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800298
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800299 // Lets see if we should list it behind other pending updates.
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800300 if (proxy_fb->fb_update_tail != NULL) {
301 proxy_fb->fb_update_tail->next_fb_update = descr;
302 proxy_fb->fb_update_tail = descr;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800303 return;
304 }
305
306 // We're first in the list. Just send it now.
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800307 proxy_fb->fb_update_head = proxy_fb->fb_update_tail = descr;
308 asyncWriter_init(&proxy_fb->fb_update_writer,
309 &proxy_fb->fb_update_head->message,
310 proxy_fb->fb_update_head->message_size, &proxy_fb->io);
311 status = asyncWriter_write(&proxy_fb->fb_update_writer, &proxy_fb->io);
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800312 switch (status) {
313 case ASYNC_COMPLETE:
314 fbupdatenotify_delete(descr);
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800315 proxy_fb->fb_update_head = proxy_fb->fb_update_tail = NULL;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800316 return;
317 case ASYNC_ERROR:
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800318 fbupdatenotify_delete(descr);
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800319 proxy_fb->fb_update_head = proxy_fb->fb_update_tail = NULL;
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800320 return;
321 case ASYNC_NEED_MORE:
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800322 // Update transfer will eventually complete in _proxyFb_io_fun
Vladimir Chtchetkinee95660a2010-12-20 08:28:03 -0800323 return;
324 }
325}
Vladimir Chtchetkine8acf4e22010-12-21 07:14:17 -0800326
327int
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800328proxyFb_get_bits_per_pixel(ProxyFramebuffer* proxy_fb)
Vladimir Chtchetkine8acf4e22010-12-21 07:14:17 -0800329{
Vladimir Chtchetkine94a2fba2011-01-31 10:49:06 -0800330 return (proxy_fb != NULL && proxy_fb->fb != NULL) ?
331 proxy_fb->fb->bits_per_pixel : -1;
Vladimir Chtchetkine8acf4e22010-12-21 07:14:17 -0800332}