1e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* Copyright (C) 2010 The Android Open Source Project 2e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** 3e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** This software is licensed under the terms of the GNU General Public 4e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** License version 2, as published by the Free Software Foundation, and 5e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** may be copied, distributed, and modified under those terms. 6e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** 7e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** This program is distributed in the hope that it will be useful, 8e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** but WITHOUT ANY WARRANTY; without even the implied warranty of 9e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine** GNU General Public License for more details. 11e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine*/ 12e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 13e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* 14e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Contains core-side framebuffer service that sends framebuffer updates 15e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * to the UI connected to the core. 16e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine */ 17e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 18e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "console.h" 19e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "android/looper.h" 20e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "android/display-core.h" 21e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "android/async-utils.h" 2294a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine#include "android/protocol/fb-updates.h" 2394a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine#include "android/protocol/fb-updates-proxy.h" 24e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "android/utils/system.h" 25e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "android/utils/debug.h" 26e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 2794a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine/* Descriptor for the Core-side implementation of the "framebufer" service. 2894a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine */ 2994a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkinestruct ProxyFramebuffer { 30e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Writer used to send FB update notification messages. */ 318acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine AsyncWriter fb_update_writer; 32e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 33ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine /* Reader used to read FB requests from the client. */ 34ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine AsyncReader fb_req_reader; 35ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine 36e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* I/O associated with this descriptor. */ 378acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine LoopIo io; 388acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine 397a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner /* Display state used for this service */ 407a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner DisplayState* ds; 417a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner DisplayUpdateListener* ds_listener; 42e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 43e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Looper used to communicate framebuffer updates. */ 44e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine Looper* looper; 45e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 46e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Head of the list of pending FB update notifications. */ 47e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine struct FBUpdateNotify* fb_update_head; 48e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 49e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Tail of the list of pending FB update notifications. */ 50e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine struct FBUpdateNotify* fb_update_tail; 51e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 52e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Socket used to communicate framebuffer updates. */ 53e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine int sock; 54ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine 55ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine /* Framebuffer request header. */ 56ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine FBRequestHeader fb_req_header; 57e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine}; 58e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 5994a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine/* Framebuffer update notification descriptor. */ 60e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinetypedef struct FBUpdateNotify { 61e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Links all pending FB update notifications. */ 62e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine struct FBUpdateNotify* next_fb_update; 63e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 64e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Core framebuffer instance that owns the message. */ 6594a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine ProxyFramebuffer* proxy_fb; 66e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 67e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Size of the message to transfer. */ 68e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine size_t message_size; 69e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 70e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine /* Update message. */ 71e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine FBUpdateMessage message; 72e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} FBUpdateNotify; 73e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 74e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* 75e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Gets pointer in framebuffer's pixels for the given pixel. 76e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Param: 77e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * fb Framebuffer containing pixels. 78e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * x, and y identify the pixel to get pointer for. 79e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Return: 80e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Pointer in framebuffer's pixels for the given pixel. 81e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine */ 82e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinestatic const uint8_t* 837a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner_pixel_offset(const DisplaySurface* dsu, int x, int y) 84e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 857a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner return (const uint8_t*)dsu->data + y * dsu->linesize + x * dsu->pf.bytes_per_pixel; 86e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 87e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 88e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* 89e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Copies pixels from a framebuffer rectangle. 90e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Param: 91e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * rect - Buffer where to copy pixel. 92e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * fb - Framebuffer containing the rectangle to copy. 93e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * x, y, w, and h - dimensions of the rectangle to copy. 94e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine */ 95e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinestatic void 967a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner_copy_fb_rect(uint8_t* rect, const DisplaySurface* dsu, int x, int y, int w, int h) 97e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 987a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner const uint8_t* start = _pixel_offset(dsu, x, y); 99e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine for (; h > 0; h--) { 1007a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner memcpy(rect, start, w * dsu->pf.bytes_per_pixel); 1017a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner start += dsu->linesize; 1027a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner rect += w * dsu->pf.bytes_per_pixel; 103e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 104e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 105e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 106e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* 107e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Allocates and initializes framebuffer update notification descriptor. 108e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Param: 109e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * ds - Display state for the framebuffer. 110e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * fb Framebuffer containing pixels. 111e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * x, y, w, and h identify the rectangle that is being updated. 112e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Return: 113e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Initialized framebuffer update notification descriptor. 114e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine */ 115e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinestatic FBUpdateNotify* 1167a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turnerfbupdatenotify_create(ProxyFramebuffer* proxy_fb, 117e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine int x, int y, int w, int h) 118e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 1197a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner const size_t rect_size = w * h * proxy_fb->ds->surface->pf.bytes_per_pixel; 120e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine FBUpdateNotify* ret = malloc(sizeof(FBUpdateNotify) + rect_size); 121e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 122e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->next_fb_update = NULL; 12394a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine ret->proxy_fb = proxy_fb; 124e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->message_size = sizeof(FBUpdateMessage) + rect_size; 125e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->message.x = x; 126e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->message.y = y; 127e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->message.w = w; 128e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->message.h = h; 1297a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner _copy_fb_rect(ret->message.rect, proxy_fb->ds->surface, x, y, w, h); 130e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine return ret; 131e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 132e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 133e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* 134e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Deletes FBUpdateNotify descriptor, created with fbupdatenotify_create. 135e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Param: 136e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * desc - Descreptor to delete. 137e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine */ 138e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinestatic void 139e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinefbupdatenotify_delete(FBUpdateNotify* desc) 140e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 141e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine if (desc != NULL) { 142e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine free(desc); 143e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 144e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 145e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 146e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* 147ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine * Asynchronous write I/O callback launched when writing framebuffer 148ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine * notifications to the socket. 149e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine * Param: 15094a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine * proxy_fb - ProxyFramebuffer instance. 151e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine */ 152e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinestatic void 15394a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine_proxyFb_io_write(ProxyFramebuffer* proxy_fb) 154e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 15594a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine while (proxy_fb->fb_update_head != NULL) { 15694a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine FBUpdateNotify* current_update = proxy_fb->fb_update_head; 157e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Lets continue writing of the current notification. 158e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine const AsyncStatus status = 159f9e333ade2529f257ced6bcff8e5824cb07eacf9David 'Digit' Turner asyncWriter_write(&proxy_fb->fb_update_writer); 160e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine switch (status) { 161e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine case ASYNC_COMPLETE: 162e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Done with the current update. Move on to the next one. 163e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine break; 164e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine case ASYNC_ERROR: 165e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Done with the current update. Move on to the next one. 16694a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine loopIo_dontWantWrite(&proxy_fb->io); 167e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine break; 168e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 169e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine case ASYNC_NEED_MORE: 170e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Transfer will eventually come back into this routine. 171e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine return; 172e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 173e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 174e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Advance the list of updates 17594a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_head = current_update->next_fb_update; 17694a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine if (proxy_fb->fb_update_head == NULL) { 17794a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_tail = NULL; 178e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 179e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine fbupdatenotify_delete(current_update); 180e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 18194a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine if (proxy_fb->fb_update_head != NULL) { 182e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Schedule the next one. 18394a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine asyncWriter_init(&proxy_fb->fb_update_writer, 18494a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine &proxy_fb->fb_update_head->message, 18594a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_head->message_size, 18694a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine &proxy_fb->io); 187e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 188e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 189e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 190e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 1917a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turnerstatic void proxyFb_update(void* opaque, int x, int y, int w, int h); 1927a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner 193ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine/* 194ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine * Asynchronous read I/O callback launched when reading framebuffer requests 195ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine * from the socket. 196ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine * Param: 19794a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine * proxy_fb - ProxyFramebuffer instance. 198ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine */ 199ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkinestatic void 20094a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine_proxyFb_io_read(ProxyFramebuffer* proxy_fb) 201ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine{ 202ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine // Read the request header. 2037a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner DisplaySurface* dsu; 204ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine const AsyncStatus status = 205f9e333ade2529f257ced6bcff8e5824cb07eacf9David 'Digit' Turner asyncReader_read(&proxy_fb->fb_req_reader); 206ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine switch (status) { 207ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine case ASYNC_COMPLETE: 208ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine // Request header is received 20994a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine switch (proxy_fb->fb_req_header.request_type) { 210ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine case AFB_REQUEST_REFRESH: 211ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine // Force full screen update to be sent 2127a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner dsu = proxy_fb->ds->surface; 2137a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner proxyFb_update(proxy_fb, 2147a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner 0, 0, dsu->width, dsu->height); 215ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine break; 216ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine default: 217ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine derror("Unknown framebuffer request %d\n", 21894a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_req_header.request_type); 219ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine break; 220ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine } 22194a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_req_header.request_type = -1; 22294a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine asyncReader_init(&proxy_fb->fb_req_reader, &proxy_fb->fb_req_header, 22394a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine sizeof(proxy_fb->fb_req_header), &proxy_fb->io); 224ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine break; 225ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine case ASYNC_ERROR: 22694a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine loopIo_dontWantRead(&proxy_fb->io); 227ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine if (errno == ECONNRESET) { 228ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine // UI has exited. We need to destroy framebuffer service. 2297a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner proxyFb_destroy(proxy_fb); 230ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine } 231ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine break; 232ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine 233ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine case ASYNC_NEED_MORE: 234ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine // Transfer will eventually come back into this routine. 235ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine return; 236ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine } 237ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine} 238ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine 239ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine/* 240ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine * Asynchronous I/O callback launched when writing framebuffer notifications 241ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine * to the socket. 242ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine * Param: 24394a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine * opaque - ProxyFramebuffer instance. 244ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine */ 245ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkinestatic void 24694a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine_proxyFb_io_fun(void* opaque, int fd, unsigned events) 247ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine{ 248ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine if (events & LOOP_IO_READ) { 24994a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine _proxyFb_io_read((ProxyFramebuffer*)opaque); 250ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine } else if (events & LOOP_IO_WRITE) { 25194a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine _proxyFb_io_write((ProxyFramebuffer*)opaque); 252ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine } 253ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine} 254ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine 25594a2fba98924c6684650d66409934358cb0c9d09Vladimir ChtchetkineProxyFramebuffer* 2567a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' TurnerproxyFb_create(int sock, const char* protocol) 257e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 258e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // At this point we're implementing the -raw protocol only. 25994a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine ProxyFramebuffer* ret; 2607a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner DisplayState* ds = get_displaystate(); 2617a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner DisplayUpdateListener* dul; 2627a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner 263e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ANEW0(ret); 264e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->sock = sock; 265e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->looper = looper_newCore(); 2667a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner ret->ds = ds; 2677a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner 2687a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner ANEW0(dul); 2697a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner dul->opaque = ret; 2707a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner dul->dpy_update = proxyFb_update; 2717a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner register_displayupdatelistener(ds, dul); 2727a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner ret->ds_listener = dul; 2737a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner 274e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->fb_update_head = NULL; 275e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine ret->fb_update_tail = NULL; 27694a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine loopIo_init(&ret->io, ret->looper, sock, _proxyFb_io_fun, ret); 277ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine asyncReader_init(&ret->fb_req_reader, &ret->fb_req_header, 278ac389ae4513263597dc02e4099867d5123faaa04Vladimir Chtchetkine sizeof(ret->fb_req_header), &ret->io); 279e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine return ret; 280e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 281e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 282e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinevoid 28394a2fba98924c6684650d66409934358cb0c9d09Vladimir ChtchetkineproxyFb_destroy(ProxyFramebuffer* proxy_fb) 284e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 28594a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine if (proxy_fb != NULL) { 2867a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner unregister_displayupdatelistener(proxy_fb->ds, proxy_fb->ds_listener); 28794a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine if (proxy_fb->looper != NULL) { 288e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Stop all I/O that may still be going on. 28994a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine loopIo_done(&proxy_fb->io); 290e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Delete all pending frame updates. 29194a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine while (proxy_fb->fb_update_head != NULL) { 29294a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine FBUpdateNotify* pending_update = proxy_fb->fb_update_head; 29394a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_head = pending_update->next_fb_update; 294e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine fbupdatenotify_delete(pending_update); 295e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 29694a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_tail = NULL; 29794a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine looper_free(proxy_fb->looper); 29894a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->looper = NULL; 299e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 3007a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner AFREE(proxy_fb); 301e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 302e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 303e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 3047a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turnerstatic void 3057a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' TurnerproxyFb_update(void* opaque, int x, int y, int w, int h) 306e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 3077a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner ProxyFramebuffer* proxy_fb = opaque; 308e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine AsyncStatus status; 3097a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner FBUpdateNotify* descr = fbupdatenotify_create(proxy_fb, x, y, w, h); 310e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 311e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // Lets see if we should list it behind other pending updates. 31294a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine if (proxy_fb->fb_update_tail != NULL) { 31394a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_tail->next_fb_update = descr; 31494a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_tail = descr; 315e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine return; 316e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 317e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 318e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine // We're first in the list. Just send it now. 31994a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_head = proxy_fb->fb_update_tail = descr; 32094a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine asyncWriter_init(&proxy_fb->fb_update_writer, 32194a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine &proxy_fb->fb_update_head->message, 32294a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_head->message_size, &proxy_fb->io); 323f9e333ade2529f257ced6bcff8e5824cb07eacf9David 'Digit' Turner status = asyncWriter_write(&proxy_fb->fb_update_writer); 324e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine switch (status) { 325e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine case ASYNC_COMPLETE: 326e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine fbupdatenotify_delete(descr); 32794a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_head = proxy_fb->fb_update_tail = NULL; 328e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine return; 329e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine case ASYNC_ERROR: 330e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine fbupdatenotify_delete(descr); 33194a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine proxy_fb->fb_update_head = proxy_fb->fb_update_tail = NULL; 332e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine return; 333e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine case ASYNC_NEED_MORE: 33494a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine // Update transfer will eventually complete in _proxyFb_io_fun 335e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine return; 336e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine } 337e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 3388acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine 3398acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkineint 34094a2fba98924c6684650d66409934358cb0c9d09Vladimir ChtchetkineproxyFb_get_bits_per_pixel(ProxyFramebuffer* proxy_fb) 3418acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine{ 3427a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner if (proxy_fb == NULL || proxy_fb->ds == NULL) 3437a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner return -1; 3447a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner 3457a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner return proxy_fb->ds->surface->pf.bits_per_pixel; 3468acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine} 347