1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
/**
* @file
*
* @section DESCRIPTION
* Buffer is the heart of the (virtual) frame buffer memory management routines. It implements a "buffer" as defined by nitpicker; we consider this as more-or-less synonymous with a virtualized frame buffer. It is based upon the original nitpicker buffer code with all of the CORBA calls removed. This file is fairly stable and is not modified often. It does support the following interfaces:
*
* buffer *lookup_buffer()
* int nitpicker_import_buffer()
* void nitpicker_remove_buffer()
* void nitpicker_refresh()
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h> /* for POSIX shared memory objects */
#include <sys/mman.h> /* for POSIX shared memory objects */
#include <errno.h> /* for errno */
#include <fcntl.h> /* for O_RDWR */
#include <limits.h>
#include "view.h"
#include "client.h"
#include "display.h"
static int
buffer_position_background(struct buffer *b)
{
DFBRectangle bpos, spos;
int guest_width, guest_height;
guest_width = display_get_width();
guest_height = display_get_height();
bpos.x = 0;
bpos.y = 0;
bpos.w = b->desc.width;
bpos.h = b->desc.height;
b->xoff = (bpos.w >= guest_width) ? 0 : (guest_width - bpos.w) / 2;
b->yoff = (bpos.h >= guest_height) ? 0 : (guest_height - bpos.h) / 2;
spos.x = b->xoff;
spos.y = b->yoff;
spos.w = bpos.w;
spos.h = bpos.h;
return view_set_viewport(b->bg_view, &bpos, &spos, 1);
}
static void
buffer_free(struct buffer *b)
{
/* remove buffer from its client list */
LIST_REMOVE(b, client_next);
/* free resources */
b->bsurface->Release(b->bsurface);
free(b);
}
/*** LOOK UP BUFFER STRUCT BY CLIENT ID AND BUFFER ID ***/
struct buffer *
lookup_buffer(int domid, int buf_id)
{
struct client *c = client_lookup(domid);
struct buffer *b;
LIST_FOREACH(b, &c->buffers, client_next)
if (b->id == buf_id)
return b;
return NULL;
}
/*** INTERFACE: IMPORT NEW BUFFER INTO NITPICKER ***/
struct buffer *
buffer_new(struct client *c, const DFBSurfaceDescription *desc, unsigned int flags)
{
struct buffer *b;
IDirectFBSurface *surf;
struct view *v;
if (c->num_buffers >= c->max_buffers)
return NULL; /* NITPICKER_ERR_OUT_OF_BUFS */
/* create DirectFB surface */
if (dfb->CreateSurface(dfb, desc, &surf) != DFB_OK)
return NULL;
/* get memory for the buffer header */
b = calloc(1, sizeof(struct buffer));
if (!b)
return NULL;
TAILQ_INIT(&b->views);
b->id = c->num_buffers;
b->client = c;
b->state = STATE_ALLOCATED;
b->flags = flags;
memcpy(&b->desc, desc, sizeof(DFBSurfaceDescription));
b->bsurface = surf;
/* bump client view count */
c->num_buffers++;
/* add buffer to the client's buffer list */
LIST_INSERT_HEAD(&c->buffers, b, client_next);
/* create background view for this buffer */
v = view_new(b->client, b, 0, VIEW_FLAGS_BACKGROUND);
if (!v) {
buffer_free(b);
return NULL;
}
b->bg_view = v;
buffer_position_background(b);
/* notify display subsystem */
if (display_buffer_new(b) < 0) {
view_remove(v);
buffer_free(b);
return NULL;
}
return b;
}
int
buffer_resize(struct buffer *b, const DFBSurfaceDescription *desc)
{
struct view *v;
IDirectFBSurface *oldsurf, *newsurf;
/* create new DirectFB surface */
if (dfb->CreateSurface(dfb, desc, &newsurf) != DFB_OK)
return -1;
memcpy(&b->desc, desc, sizeof(DFBSurfaceDescription));
oldsurf = b->bsurface;
b->bsurface = newsurf;
/* go through all the views and change over to the new surface */
TAILQ_FOREACH(v, &b->views, buffer_next)
view_update_surface(v);
/* re-center the background view on the screen */
buffer_position_background(b);
/* free old surface */
oldsurf->Release(oldsurf);
return 0;
}
/*** INTERFACE: REMOVE BUFFER FROM NITPICKER ***/
void
buffer_remove(struct buffer *b) {
/* close all views */
while (!TAILQ_EMPTY(&b->views))
view_remove(TAILQ_FIRST(&b->views));
/* call display hook */
display_buffer_remove(b);
/* release resources */
buffer_free(b);
}
/*** INTERFACE: REFRESH BUFFER AREA ***/
void
buffer_refresh(struct buffer *b, int x, int y, int w, int h)
{
int x1, y1, x2, y2;
struct view *v;
/* for all views at this buffer */
TAILQ_FOREACH(v, &b->views, buffer_next) {
/* calculate intersection of refresh area and view area */
x1 = MAX(x, v->bpos.x);
y1 = MAX(y, v->bpos.y);
x2 = MIN(x + w, v->bpos.x + v->bpos.w);
y2 = MIN(y + h, v->bpos.y + v->bpos.h);
/* redraw intersection */
if ((x1 <= x2) && (y1 <= y2))
view_refresh(v);
}
}
|