Home | History | Annotate | Download | only in qemu
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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*
    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
    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
    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