• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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