1 /* Copyright (C) 2007-2008 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 #include "android/framebuffer.h"
13 #include <memory.h>
14 #include <stdlib.h>
15
16 typedef struct {
17 /* client fields, these correspond to code that waits for updates before displaying them */
18 /* at the moment, only one client is supported */
19 void* fb_opaque;
20 QFrameBufferUpdateFunc fb_update;
21 QFrameBufferRotateFunc fb_rotate;
22 QFrameBufferPollFunc fb_poll;
23 QFrameBufferDoneFunc fb_done;
24
25 void* pr_opaque;
26 QFrameBufferCheckUpdateFunc pr_check;
27 QFrameBufferInvalidateFunc pr_invalidate;
28 QFrameBufferDetachFunc pr_detach;
29
30 } QFrameBufferExtra;
31
32
33 static int
_get_pitch(int width,QFrameBufferFormat format)34 _get_pitch( int width, QFrameBufferFormat format )
35 {
36
37 switch (format) {
38 case QFRAME_BUFFER_RGB565:
39 return width*2;
40 case QFRAME_BUFFER_RGBX_8888:
41 return width*4;
42 default:
43 return -1;
44 }
45 }
46
47 static int
_get_bits_per_pixel(QFrameBufferFormat format)48 _get_bits_per_pixel(QFrameBufferFormat format)
49 {
50
51 switch (format) {
52 case QFRAME_BUFFER_RGB565:
53 return 16;
54 case QFRAME_BUFFER_RGBX_8888:
55 return 32;
56 default:
57 return -1;
58 }
59 }
60
61 static int
_get_bytes_per_pixel(QFrameBufferFormat format)62 _get_bytes_per_pixel(QFrameBufferFormat format)
63 {
64
65 switch (format) {
66 case QFRAME_BUFFER_RGB565:
67 return 2;
68 case QFRAME_BUFFER_RGBX_8888:
69 return 4;
70 default:
71 return -1;
72 }
73 }
74
75 int
qframebuffer_init(QFrameBuffer * qfbuff,int width,int height,int rotation,QFrameBufferFormat format)76 qframebuffer_init( QFrameBuffer* qfbuff,
77 int width,
78 int height,
79 int rotation,
80 QFrameBufferFormat format )
81 {
82 int pitch, bytes_per_pixel, bits_per_pixel;
83
84 rotation &= 3;
85
86 if (!qfbuff || width < 0 || height < 0)
87 return -1;
88
89 pitch = _get_pitch( width, format );
90 if (pitch < 0)
91 return -1;
92
93 bits_per_pixel = _get_bits_per_pixel(format);
94 if (bits_per_pixel < 0)
95 return -1;
96
97 bytes_per_pixel = _get_bytes_per_pixel(format);
98 if (bytes_per_pixel < 0)
99 return -1;
100
101 memset( qfbuff, 0, sizeof(*qfbuff) );
102
103 qfbuff->extra = calloc( 1, sizeof(QFrameBufferExtra) );
104 if (qfbuff->extra == NULL)
105 return -1;
106
107 qfbuff->pixels = calloc( pitch, height );
108 if (qfbuff->pixels == NULL && (height > 0 && pitch > 0)) {
109 free( qfbuff->extra );
110 return -1;
111 }
112
113 qfbuff->width = width;
114 qfbuff->height = height;
115 qfbuff->pitch = pitch;
116 qfbuff->format = format;
117 qfbuff->bits_per_pixel = bits_per_pixel;
118 qfbuff->bytes_per_pixel = bytes_per_pixel;
119
120 qframebuffer_set_dpi( qfbuff, DEFAULT_FRAMEBUFFER_DPI, DEFAULT_FRAMEBUFFER_DPI );
121 return 0;
122 }
123
124
125 void
qframebuffer_set_dpi(QFrameBuffer * qfbuff,int x_dpi,int y_dpi)126 qframebuffer_set_dpi( QFrameBuffer* qfbuff,
127 int x_dpi,
128 int y_dpi )
129 {
130 /* dpi = dots / inch
131 ** inch = dots / dpi
132 ** mm / 25.4 = dots / dpi
133 ** mm = (dots * 25.4)/dpi
134 */
135 qfbuff->phys_width_mm = (int)(0.5 + 25.4 * qfbuff->width / x_dpi);
136 qfbuff->phys_height_mm = (int)(0.5 + 25.4 * qfbuff->height / y_dpi);
137 }
138
139 /* alternative to qframebuffer_set_dpi where one can set the physical dimensions directly */
140 /* in millimeters. for the record 1 inch = 25.4 mm */
141 void
qframebuffer_set_mm(QFrameBuffer * qfbuff,int width_mm,int height_mm)142 qframebuffer_set_mm( QFrameBuffer* qfbuff,
143 int width_mm,
144 int height_mm )
145 {
146 qfbuff->phys_width_mm = width_mm;
147 qfbuff->phys_height_mm = height_mm;
148 }
149
150 void
qframebuffer_update(QFrameBuffer * qfbuff,int x,int y,int w,int h)151 qframebuffer_update( QFrameBuffer* qfbuff, int x, int y, int w, int h )
152 {
153 QFrameBufferExtra* extra = qfbuff->extra;
154
155 if (extra->fb_update)
156 extra->fb_update( extra->fb_opaque, x, y, w, h );
157 }
158
159
160 void
qframebuffer_add_client(QFrameBuffer * qfbuff,void * fb_opaque,QFrameBufferUpdateFunc fb_update,QFrameBufferRotateFunc fb_rotate,QFrameBufferPollFunc fb_poll,QFrameBufferDoneFunc fb_done)161 qframebuffer_add_client( QFrameBuffer* qfbuff,
162 void* fb_opaque,
163 QFrameBufferUpdateFunc fb_update,
164 QFrameBufferRotateFunc fb_rotate,
165 QFrameBufferPollFunc fb_poll,
166 QFrameBufferDoneFunc fb_done )
167 {
168 QFrameBufferExtra* extra = qfbuff->extra;
169
170 extra->fb_opaque = fb_opaque;
171 extra->fb_update = fb_update;
172 extra->fb_rotate = fb_rotate;
173 extra->fb_poll = fb_poll;
174 extra->fb_done = fb_done;
175 }
176
177 void
qframebuffer_set_producer(QFrameBuffer * qfbuff,void * opaque,QFrameBufferCheckUpdateFunc pr_check,QFrameBufferInvalidateFunc pr_invalidate,QFrameBufferDetachFunc pr_detach)178 qframebuffer_set_producer( QFrameBuffer* qfbuff,
179 void* opaque,
180 QFrameBufferCheckUpdateFunc pr_check,
181 QFrameBufferInvalidateFunc pr_invalidate,
182 QFrameBufferDetachFunc pr_detach )
183 {
184 QFrameBufferExtra* extra = qfbuff->extra;
185
186 extra->pr_opaque = opaque;
187 extra->pr_check = pr_check;
188 extra->pr_invalidate = pr_invalidate;
189 extra->pr_detach = pr_detach;
190 }
191
192
193 void
qframebuffer_rotate(QFrameBuffer * qfbuff,int rotation)194 qframebuffer_rotate( QFrameBuffer* qfbuff, int rotation )
195 {
196 QFrameBufferExtra* extra = qfbuff->extra;
197
198 if ((rotation ^ qfbuff->rotation) & 1) {
199 /* swap width and height if new rotation requires it */
200 int temp = qfbuff->width;
201 qfbuff->width = qfbuff->height;
202 qfbuff->height = temp;
203 qfbuff->pitch = _get_pitch( qfbuff->width, qfbuff->format );
204
205 temp = qfbuff->phys_width_mm;
206 qfbuff->phys_width_mm = qfbuff->phys_height_mm;
207 qfbuff->phys_height_mm = temp;
208 }
209 qfbuff->rotation = rotation;
210
211 if (extra->fb_rotate)
212 extra->fb_rotate( extra->fb_opaque, rotation );
213 }
214
215 void
qframebuffer_poll(QFrameBuffer * qfbuff)216 qframebuffer_poll( QFrameBuffer* qfbuff )
217 {
218 QFrameBufferExtra* extra = qfbuff->extra;
219
220 if (extra && extra->fb_poll)
221 extra->fb_poll( extra->fb_opaque );
222 }
223
224
225 extern void
qframebuffer_done(QFrameBuffer * qfbuff)226 qframebuffer_done( QFrameBuffer* qfbuff )
227 {
228 QFrameBufferExtra* extra = qfbuff->extra;
229
230 if (extra) {
231 if (extra->pr_detach)
232 extra->pr_detach( extra->pr_opaque );
233
234 if (extra->fb_done)
235 extra->fb_done( extra->fb_opaque );
236 }
237
238 free( qfbuff->pixels );
239 free( qfbuff->extra );
240 memset( qfbuff, 0, sizeof(*qfbuff) );
241 }
242
243
244 #define MAX_FRAME_BUFFERS 8
245
246 static QFrameBuffer* framebuffer_fifo[ MAX_FRAME_BUFFERS ];
247 static int framebuffer_fifo_rpos;
248 static int framebuffer_fifo_count;
249
250 void
qframebuffer_fifo_add(QFrameBuffer * qfbuff)251 qframebuffer_fifo_add( QFrameBuffer* qfbuff )
252 {
253 if (framebuffer_fifo_count >= MAX_FRAME_BUFFERS)
254 return;
255
256 framebuffer_fifo[ framebuffer_fifo_count++ ] = qfbuff;
257 }
258
259
260 QFrameBuffer*
qframebuffer_fifo_get(void)261 qframebuffer_fifo_get( void )
262 {
263 if (framebuffer_fifo_rpos >= framebuffer_fifo_count)
264 return NULL;
265
266 return framebuffer_fifo[ framebuffer_fifo_rpos++ ];
267 }
268
269
270 void
qframebuffer_check_updates(void)271 qframebuffer_check_updates( void )
272 {
273 int nn;
274 for (nn = 0; nn < framebuffer_fifo_count; nn++) {
275 QFrameBuffer* q = framebuffer_fifo[nn];
276 QFrameBufferExtra* extra = q->extra;
277
278 if (extra->pr_check)
279 extra->pr_check( extra->pr_opaque );
280 }
281 }
282
283 void
qframebuffer_pulse(void)284 qframebuffer_pulse( void )
285 {
286 int nn;
287 for (nn = 0; nn < framebuffer_fifo_count; nn++) {
288 qframebuffer_poll(framebuffer_fifo[nn]);
289 }
290 }
291
292 void
qframebuffer_invalidate_all(void)293 qframebuffer_invalidate_all( void )
294 {
295 int nn;
296 for (nn = 0; nn < framebuffer_fifo_count; nn++) {
297 QFrameBuffer* q = framebuffer_fifo[nn];
298 QFrameBufferExtra* extra = q->extra;
299
300 if (extra->pr_invalidate)
301 extra->pr_invalidate( extra->pr_opaque );
302 }
303 }
304