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