• 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 "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     QFrameBufferDoneFunc         fb_done;
23 
24     void*                        pr_opaque;
25     QFrameBufferCheckUpdateFunc  pr_check;
26     QFrameBufferInvalidateFunc   pr_invalidate;
27     QFrameBufferDetachFunc       pr_detach;
28 
29 } QFrameBufferExtra;
30 
31 
32 static int
_get_pitch(int width,QFrameBufferFormat format)33 _get_pitch( int  width, QFrameBufferFormat  format )
34 {
35 
36     switch (format) {
37         case QFRAME_BUFFER_RGB565:
38             return width*2;
39         default:
40             return -1;
41     }
42 }
43 
44 
45 int
qframebuffer_init(QFrameBuffer * qfbuff,int width,int height,int rotation,QFrameBufferFormat format)46 qframebuffer_init( QFrameBuffer*       qfbuff,
47                    int                 width,
48                    int                 height,
49                    int                 rotation,
50                    QFrameBufferFormat  format )
51 {
52     int   pitch;
53 
54     rotation &= 3;
55 
56     if (!qfbuff || width < 0 || height < 0)
57         return -1;
58 
59     pitch = _get_pitch( width, format );
60     if (pitch < 0)
61         return -1;
62 
63     memset( qfbuff, 0, sizeof(*qfbuff) );
64 
65     qfbuff->extra = calloc( 1, sizeof(QFrameBufferExtra) );
66     if (qfbuff->extra == NULL)
67         return -1;
68 
69     qfbuff->pixels = calloc( pitch, height );
70     if (qfbuff->pixels == NULL && (height > 0 && pitch > 0)) {
71         free( qfbuff->extra );
72         return -1;
73     }
74 
75     qfbuff->width  = width;
76     qfbuff->height = height;
77     qfbuff->pitch  = pitch;
78     qfbuff->format = format;
79 
80     qframebuffer_set_dpi( qfbuff, DEFAULT_FRAMEBUFFER_DPI, DEFAULT_FRAMEBUFFER_DPI );
81     return 0;
82 }
83 
84 
85 void
qframebuffer_set_dpi(QFrameBuffer * qfbuff,int x_dpi,int y_dpi)86 qframebuffer_set_dpi( QFrameBuffer*   qfbuff,
87                       int             x_dpi,
88                       int             y_dpi )
89 {
90     /* dpi = dots / inch
91     ** inch = dots / dpi
92     ** mm / 25.4 = dots / dpi
93     ** mm = (dots * 25.4)/dpi
94     */
95     qfbuff->phys_width_mm  = (int)(0.5 + 25.4 * qfbuff->width  / x_dpi);
96     qfbuff->phys_height_mm = (int)(0.5 + 25.4 * qfbuff->height / y_dpi);
97 }
98 
99 /* alternative to qframebuffer_set_dpi where one can set the physical dimensions directly */
100 /* in millimeters. for the record 1 inch = 25.4 mm */
101 void
qframebuffer_set_mm(QFrameBuffer * qfbuff,int width_mm,int height_mm)102 qframebuffer_set_mm( QFrameBuffer*   qfbuff,
103                      int             width_mm,
104                      int             height_mm )
105 {
106     qfbuff->phys_width_mm  = width_mm;
107     qfbuff->phys_height_mm = height_mm;
108 }
109 
110 void
qframebuffer_update(QFrameBuffer * qfbuff,int x,int y,int w,int h)111 qframebuffer_update( QFrameBuffer*  qfbuff, int  x, int  y, int  w, int  h )
112 {
113     QFrameBufferExtra*  extra = qfbuff->extra;
114 
115     if (extra->fb_update)
116         extra->fb_update( extra->fb_opaque, x, y, w, h );
117 }
118 
119 
120 void
qframebuffer_add_client(QFrameBuffer * qfbuff,void * fb_opaque,QFrameBufferUpdateFunc fb_update,QFrameBufferRotateFunc fb_rotate,QFrameBufferDoneFunc fb_done)121 qframebuffer_add_client( QFrameBuffer*           qfbuff,
122                          void*                   fb_opaque,
123                          QFrameBufferUpdateFunc  fb_update,
124                          QFrameBufferRotateFunc  fb_rotate,
125                          QFrameBufferDoneFunc    fb_done )
126 {
127     QFrameBufferExtra*  extra = qfbuff->extra;
128 
129     extra->fb_opaque = fb_opaque;
130     extra->fb_update = fb_update;
131     extra->fb_rotate = fb_rotate;
132     extra->fb_done   = fb_done;
133 }
134 
135 void
qframebuffer_set_producer(QFrameBuffer * qfbuff,void * opaque,QFrameBufferCheckUpdateFunc pr_check,QFrameBufferInvalidateFunc pr_invalidate,QFrameBufferDetachFunc pr_detach)136 qframebuffer_set_producer( QFrameBuffer*                qfbuff,
137                            void*                        opaque,
138                            QFrameBufferCheckUpdateFunc  pr_check,
139                            QFrameBufferInvalidateFunc   pr_invalidate,
140                            QFrameBufferDetachFunc       pr_detach )
141 {
142     QFrameBufferExtra*  extra = qfbuff->extra;
143 
144     extra->pr_opaque     = opaque;
145     extra->pr_check      = pr_check;
146     extra->pr_invalidate = pr_invalidate;
147     extra->pr_detach     = pr_detach;
148 }
149 
150 
151 void
qframebuffer_rotate(QFrameBuffer * qfbuff,int rotation)152 qframebuffer_rotate( QFrameBuffer*  qfbuff, int  rotation )
153 {
154     QFrameBufferExtra*  extra = qfbuff->extra;
155 
156     if ((rotation ^ qfbuff->rotation) & 1) {
157         /* swap width and height if new rotation requires it */
158         int  temp = qfbuff->width;
159         qfbuff->width  = qfbuff->height;
160         qfbuff->height = temp;
161         qfbuff->pitch  = _get_pitch( qfbuff->width, qfbuff->format );
162 
163         temp = qfbuff->phys_width_mm;
164         qfbuff->phys_width_mm  = qfbuff->phys_height_mm;
165         qfbuff->phys_height_mm = temp;
166     }
167     qfbuff->rotation = rotation;
168 
169     if (extra->fb_rotate)
170         extra->fb_rotate( extra->fb_opaque, rotation );
171 }
172 
173 
174 extern void
qframebuffer_done(QFrameBuffer * qfbuff)175 qframebuffer_done( QFrameBuffer*   qfbuff )
176 {
177     QFrameBufferExtra*  extra = qfbuff->extra;
178 
179     if (extra) {
180         if (extra->pr_detach)
181             extra->pr_detach( extra->pr_opaque );
182 
183         if (extra->fb_done)
184             extra->fb_done( extra->fb_opaque );
185     }
186 
187     free( qfbuff->pixels );
188     free( qfbuff->extra );
189     memset( qfbuff, 0, sizeof(*qfbuff) );
190 }
191 
192 
193 #define  MAX_FRAME_BUFFERS  8
194 
195 static QFrameBuffer* framebuffer_fifo[ MAX_FRAME_BUFFERS ];
196 static int           framebuffer_fifo_rpos;
197 static int           framebuffer_fifo_count;
198 
199 void
qframebuffer_fifo_add(QFrameBuffer * qfbuff)200 qframebuffer_fifo_add( QFrameBuffer*  qfbuff )
201 {
202     if (framebuffer_fifo_count >= MAX_FRAME_BUFFERS)
203         return;
204 
205     framebuffer_fifo[ framebuffer_fifo_count++ ] = qfbuff;
206 }
207 
208 
209 QFrameBuffer*
qframebuffer_fifo_get(void)210 qframebuffer_fifo_get( void )
211 {
212     if (framebuffer_fifo_rpos >= framebuffer_fifo_count)
213         return NULL;
214 
215     return framebuffer_fifo[ framebuffer_fifo_rpos++ ];
216 }
217 
218 
219 void
qframebuffer_check_updates(void)220 qframebuffer_check_updates( void )
221 {
222     int  nn;
223     for (nn = 0; nn < framebuffer_fifo_count; nn++) {
224         QFrameBuffer*       q     = framebuffer_fifo[nn];
225         QFrameBufferExtra*  extra = q->extra;
226 
227         if (extra->pr_check)
228             extra->pr_check( extra->pr_opaque );
229     }
230 }
231 
232 void
qframebuffer_invalidate_all(void)233 qframebuffer_invalidate_all( void )
234 {
235     int  nn;
236     for (nn = 0; nn < framebuffer_fifo_count; nn++) {
237         QFrameBuffer*       q     = framebuffer_fifo[nn];
238         QFrameBufferExtra*  extra = q->extra;
239 
240         if (extra->pr_invalidate)
241             extra->pr_invalidate( extra->pr_opaque );
242     }
243 }
244