PageRenderTime 85ms CodeModel.GetById 13ms app.highlight 65ms RepoModel.GetById 1ms app.codeStats 1ms

/libgralloc/framebuffer.cpp

http://github.com/CyanogenMod/android_device_zte_blade
C++ | 857 lines | 672 code | 109 blank | 76 comment | 102 complexity | 27393ef6ca051cae7f62889eadbd0268 MD5 | raw file
  1/*
  2 * Copyright (C) 2008 The Android Open Source Project
  3 * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  4 *
  5 * Licensed under the Apache License, Version 2.0 (the "License");
  6 * you may not use this file except in compliance with the License.
  7 * You may obtain a copy of the License at
  8 *
  9 *      http://www.apache.org/licenses/LICENSE-2.0
 10 *
 11 * Unless required by applicable law or agreed to in writing, software
 12 * distributed under the License is distributed on an "AS IS" BASIS,
 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14 * See the License for the specific language governing permissions and
 15 * limitations under the License.
 16 */
 17
 18#include <sys/mman.h>
 19
 20#include <dlfcn.h>
 21
 22#include <cutils/ashmem.h>
 23#include <cutils/log.h>
 24#include <cutils/properties.h>
 25
 26#include <hardware/hardware.h>
 27#include <hardware/gralloc.h>
 28
 29#include <fcntl.h>
 30#include <errno.h>
 31#include <sys/ioctl.h>
 32#include <string.h>
 33#include <stdlib.h>
 34#include <pthread.h>
 35
 36#include <cutils/log.h>
 37#include <cutils/atomic.h>
 38
 39#include <linux/fb.h>
 40#include <linux/msm_mdp.h>
 41
 42#include <GLES/gl.h>
 43
 44#include "gralloc_priv.h"
 45#include "gr.h"
 46#ifdef NO_SURFACEFLINGER_SWAPINTERVAL
 47#include <cutils/properties.h>
 48#endif
 49
 50#if defined(HDMI_DUAL_DISPLAY)
 51#define AS_1080_RATIO_H (4.25/100)  // Default Action Safe vertical limit for 1080p
 52#define AS_1080_RATIO_W (4.25/100)  // Default Action Safe horizontal limit for 1080p
 53#define AS_720_RATIO_H (6.0/100)  // Default Action Safe vertical limit for 720p
 54#define AS_720_RATIO_W (4.25/100)  // Default Action Safe horizontal limit for 720p
 55#define AS_480_RATIO_H (8.0/100)  // Default Action Safe vertical limit for 480p
 56#define AS_480_RATIO_W (5.0/100)  // Default Action Safe horizontal limit for 480p
 57#define HEIGHT_1080P 1080
 58#define HEIGHT_720P 720
 59#define HEIGHT_480P 480
 60#define EVEN_OUT(x) if (x & 0x0001) {x--;}
 61using overlay::Overlay;
 62/** min of int a, b */
 63static inline int min(int a, int b) {
 64    return (a<b) ? a : b;
 65}
 66/** max of int a, b */
 67static inline int max(int a, int b) {
 68    return (a>b) ? a : b;
 69}
 70/** align */
 71static inline size_t ALIGN(size_t x, size_t align) {
 72    return (x + align-1) & ~(align-1);
 73}
 74#endif
 75
 76/*****************************************************************************/
 77
 78enum {
 79    MDDI_PANEL = '1',
 80    EBI2_PANEL = '2',
 81    LCDC_PANEL = '3',
 82    EXT_MDDI_PANEL = '4',
 83    TV_PANEL = '5'
 84};
 85
 86enum {
 87    PAGE_FLIP = 0x00000001,
 88    LOCKED = 0x00000002
 89};
 90
 91struct fb_context_t {
 92    framebuffer_device_t  device;
 93};
 94
 95static int neworientation;
 96/*****************************************************************************/
 97
 98static void
 99msm_copy_buffer(buffer_handle_t handle, int fd,
100                int width, int height, int format,
101                int x, int y, int w, int h);
102
103static int fb_setSwapInterval(struct framebuffer_device_t* dev,
104            int interval)
105{
106    fb_context_t* ctx = (fb_context_t*)dev;
107    private_module_t* m = reinterpret_cast<private_module_t*>(
108            dev->common.module);
109    if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
110        return -EINVAL;
111
112    m->swapInterval = interval;
113    return 0;
114}
115
116static int fb_setUpdateRect(struct framebuffer_device_t* dev,
117        int l, int t, int w, int h)
118{
119    if (((w|h) <= 0) || ((l|t)<0))
120        return -EINVAL;
121        
122    fb_context_t* ctx = (fb_context_t*)dev;
123    private_module_t* m = reinterpret_cast<private_module_t*>(
124            dev->common.module);
125    m->info.reserved[0] = 0x54445055; // "UPDT";
126    m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
127    m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
128    return 0;
129}
130
131static void *disp_loop(void *ptr)
132{
133    struct qbuf_t nxtBuf;
134    static int cur_buf=-1;
135    private_module_t *m = reinterpret_cast<private_module_t*>(ptr);
136
137    while (1) {
138        pthread_mutex_lock(&(m->qlock));
139
140        // wait (sleep) while display queue is empty;
141        if (m->disp.isEmpty()) {
142            pthread_cond_wait(&(m->qpost),&(m->qlock));
143        }
144
145        // dequeue next buff to display and lock it
146        nxtBuf = m->disp.getHeadValue();
147        m->disp.pop();
148        pthread_mutex_unlock(&(m->qlock));
149
150        // post buf out to display synchronously
151        private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>
152                                                (nxtBuf.buf);
153        const size_t offset = hnd->base - m->framebuffer->base;
154        m->info.activate = FB_ACTIVATE_VBL;
155        m->info.yoffset = offset / m->finfo.line_length;
156
157#if defined(HDMI_DUAL_DISPLAY)
158        pthread_mutex_lock(&m->overlayLock);
159        m->orientation = neworientation;
160        m->currentOffset = offset;
161        pthread_cond_signal(&(m->overlayPost));
162        pthread_mutex_unlock(&m->overlayLock);
163#endif
164        if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
165            LOGE("ERROR FBIOPUT_VSCREENINFO failed; frame not displayed");
166        }
167
168        if (cur_buf == -1) {
169            pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
170            m->avail[nxtBuf.idx].is_avail = true;
171            pthread_cond_signal(&(m->avail[nxtBuf.idx].cond));
172            pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
173        } else {
174            pthread_mutex_lock(&(m->avail[cur_buf].lock));
175            m->avail[cur_buf].is_avail = true;
176            pthread_cond_signal(&(m->avail[cur_buf].cond));
177            pthread_mutex_unlock(&(m->avail[cur_buf].lock));
178
179        }
180        cur_buf = nxtBuf.idx;
181    }
182    return NULL;
183}
184
185#if defined(HDMI_DUAL_DISPLAY)
186static void *hdmi_ui_loop(void *ptr)
187{
188    private_module_t* m = reinterpret_cast<private_module_t*>(
189            ptr);
190    while (1) {
191        pthread_mutex_lock(&m->overlayLock);
192        pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
193        if (m->exitHDMIUILoop) {
194            pthread_mutex_unlock(&m->overlayLock);
195            return NULL;
196        }
197        float asWidthRatio = m->actionsafeWidthRatio/100.0f;
198        float asHeightRatio = m->actionsafeHeightRatio/100.0f;
199
200        if (m->pobjOverlay) {
201            Overlay* pTemp = m->pobjOverlay;
202            if (!m->enableHDMIOutput)
203                pTemp->closeChannel();
204            else if (m->enableHDMIOutput && !m->videoOverlay) {
205                if (!pTemp->isChannelUP()) {
206                   int alignedW = ALIGN(m->info.xres, 32); 
207                   if (pTemp->startChannel(alignedW, m->info.yres,
208                                 m->fbFormat, 1, false, true)) {
209                        pTemp->setFd(m->framebuffer->fd);
210                        pTemp->setCrop(0, 0, m->info.xres, m->info.yres);
211                   } else
212                       pTemp->closeChannel();
213                }
214
215                if (pTemp->isChannelUP()) {
216                    int width = pTemp->getFBWidth();
217                    int height = pTemp->getFBHeight();
218                    int aswidth = width, asheight = height;
219                    int asX = 0, asY = 0; // Action safe x, y co-ordinates
220                    int fbwidth = m->info.xres, fbheight = m->info.yres;
221                    float defaultASWidthRatio = 0.0f, defaultASHeightRatio = 0.0f;
222                    if(HEIGHT_1080P == height) {
223                        defaultASHeightRatio = AS_1080_RATIO_H;
224                        defaultASWidthRatio = AS_1080_RATIO_W;
225                    } else if(HEIGHT_720P == height) {
226                        defaultASHeightRatio = AS_720_RATIO_H;
227                        defaultASWidthRatio = AS_720_RATIO_W;
228                    } else if(HEIGHT_480P == height) {
229                        defaultASHeightRatio = AS_480_RATIO_H;
230                        defaultASWidthRatio = AS_480_RATIO_W;
231                    }
232                    if(asWidthRatio <= 0.0f)
233                        asWidthRatio = defaultASWidthRatio;
234                    if(asHeightRatio <= 0.0f)
235                        asHeightRatio = defaultASHeightRatio;
236
237                    aswidth = (int)((float)width  - (float)(width * asWidthRatio));
238                    asheight = (int)((float)height  - (float)(height * asHeightRatio));
239                    asX = (width - aswidth) / 2;
240                    asY = (height - asheight) / 2;
241                    int rot = m->orientation;
242                    if (fbwidth < fbheight) {
243                         switch(rot) {
244                         // ROT_0
245                         case 0:
246                         // ROT_180
247                         case HAL_TRANSFORM_ROT_180: {
248                                aswidth = (asheight * fbwidth) / fbheight;
249                                asX = (width - aswidth) / 2;
250                                if(rot ==  HAL_TRANSFORM_ROT_180)
251                                  rot = OVERLAY_TRANSFORM_ROT_180;
252                                else
253                                  rot = 0;
254                            }
255                            break;
256                         // ROT_90
257                         case HAL_TRANSFORM_ROT_90:
258                            rot = OVERLAY_TRANSFORM_ROT_270;
259                            break;
260                         // ROT_270
261                         case HAL_TRANSFORM_ROT_270:
262                            rot = OVERLAY_TRANSFORM_ROT_90;
263                            break;
264                        }
265                    }
266                    else if (fbwidth > fbheight) {
267                         switch(rot) {
268                         // ROT_0
269                         case 0:
270                            rot = 0;
271                            break;
272                         // ROT_180
273                         case HAL_TRANSFORM_ROT_180:
274                            rot = OVERLAY_TRANSFORM_ROT_180;
275                            break;
276                         // ROT_90
277                         case HAL_TRANSFORM_ROT_90:
278                         // ROT_270
279                         case HAL_TRANSFORM_ROT_270: {
280                                //Swap width and height
281                                int t = fbwidth;
282                                fbwidth = fbheight;
283                                fbheight = t;
284                                aswidth = (asheight * fbwidth) / fbheight;
285                                asX = (width - aswidth) / 2;
286                                if(rot == HAL_TRANSFORM_ROT_90)
287                                    rot = OVERLAY_TRANSFORM_ROT_270;
288                                else
289                                    rot = OVERLAY_TRANSFORM_ROT_90;
290                            }
291                            break;
292                        }
293                    }
294                    pTemp->setParameter(OVERLAY_TRANSFORM,
295                                          rot);
296                    EVEN_OUT(asX);
297                    EVEN_OUT(asY);
298                    EVEN_OUT(aswidth);
299                    EVEN_OUT(asheight);
300                    pTemp->setPosition(asX, asY, aswidth, asheight);
301                    pTemp->queueBuffer(m->currentOffset);
302                }
303            }
304            else
305                pTemp->closeChannel();
306        }
307        pthread_mutex_unlock(&m->overlayLock);
308    }
309    return NULL;
310}
311
312static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
313{
314    private_module_t* m = reinterpret_cast<private_module_t*>(
315            dev->common.module);
316    pthread_mutex_lock(&m->overlayLock);
317    Overlay* pTemp = m->pobjOverlay;
318    if (started && pTemp) {
319        pTemp->closeChannel();
320        m->videoOverlay = true;
321        pthread_cond_signal(&(m->overlayPost));
322    }
323    else {
324        m->videoOverlay = false;
325        pthread_cond_signal(&(m->overlayPost));
326    }
327    pthread_mutex_unlock(&m->overlayLock);
328    return 0;
329}
330
331static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int enable)
332{
333    private_module_t* m = reinterpret_cast<private_module_t*>(
334            dev->common.module);
335    pthread_mutex_lock(&m->overlayLock);
336    Overlay* pTemp = m->pobjOverlay;
337    if (!enable && pTemp)
338        pTemp->closeChannel();
339    m->enableHDMIOutput = enable;
340    pthread_cond_signal(&(m->overlayPost));
341    pthread_mutex_unlock(&m->overlayLock);
342    return 0;
343}
344
345static int fb_setActionSafeWidthRatio(struct framebuffer_device_t* dev, float asWidthRatio)
346{
347    private_module_t* m = reinterpret_cast<private_module_t*>(
348            dev->common.module);
349    pthread_mutex_lock(&m->overlayLock);
350    m->actionsafeWidthRatio = asWidthRatio;
351    pthread_mutex_unlock(&m->overlayLock);
352    return 0;
353}
354
355static int fb_setActionSafeHeightRatio(struct framebuffer_device_t* dev, float asHeightRatio)
356{
357    private_module_t* m = reinterpret_cast<private_module_t*>(
358            dev->common.module);
359    pthread_mutex_lock(&m->overlayLock);
360    m->actionsafeHeightRatio = asHeightRatio;
361    pthread_mutex_unlock(&m->overlayLock);
362    return 0;
363}
364static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
365{
366    private_module_t* m = reinterpret_cast<private_module_t*>(
367            dev->common.module);
368    pthread_mutex_lock(&m->overlayLock);
369    neworientation = orientation;
370    pthread_mutex_unlock(&m->overlayLock);
371    return 0;
372}
373#endif
374
375static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
376{
377    if (private_handle_t::validate(buffer) < 0)
378        return -EINVAL;
379
380    int nxtIdx;
381    bool reuse;
382    struct qbuf_t qb;
383    fb_context_t* ctx = (fb_context_t*)dev;
384
385    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
386    private_module_t* m = reinterpret_cast<private_module_t*>(
387            dev->common.module);
388
389    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
390
391        reuse = false;
392        nxtIdx = (m->currentIdx + 1) % NUM_BUFFERS;
393
394        if (m->swapInterval == 0) {
395            // if SwapInterval = 0 and no buffers available then reuse
396            // current buf for next rendering so don't post new buffer
397            if (pthread_mutex_trylock(&(m->avail[nxtIdx].lock))) {
398                reuse = true;
399            } else {
400                if (! m->avail[nxtIdx].is_avail)
401                    reuse = true;
402                pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
403            }
404        }
405
406        if(!reuse){
407            // unlock previous ("current") Buffer and lock the new buffer
408            m->base.lock(&m->base, buffer,
409                    private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
410                    0,0, m->info.xres, m->info.yres, NULL);
411
412            // post/queue the new buffer
413            pthread_mutex_lock(&(m->avail[nxtIdx].lock));
414            m->avail[nxtIdx].is_avail = false;
415            pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
416
417            qb.idx = nxtIdx;
418            qb.buf = buffer;
419            pthread_mutex_lock(&(m->qlock));
420            m->disp.push(qb);
421            pthread_cond_signal(&(m->qpost));
422            pthread_mutex_unlock(&(m->qlock));
423
424            // LCDC: after new buffer grabbed by MDP can unlock previous
425            // (current) buffer
426            if (m->currentBuffer) {
427                if (m->swapInterval != 0) {
428                    pthread_mutex_lock(&(m->avail[m->currentIdx].lock));
429                    if (! m->avail[m->currentIdx].is_avail) {
430                        pthread_cond_wait(&(m->avail[m->currentIdx].cond),
431                                         &(m->avail[m->currentIdx].lock));
432                        m->avail[m->currentIdx].is_avail = true;
433                    }
434                    pthread_mutex_unlock(&(m->avail[m->currentIdx].lock));
435                }
436                m->base.unlock(&m->base, m->currentBuffer);
437            }
438            m->currentBuffer = buffer;
439            m->currentIdx = nxtIdx;
440        } else {
441            if (m->currentBuffer)
442                m->base.unlock(&m->base, m->currentBuffer);
443            m->base.lock(&m->base, buffer,
444                         private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
445                         0,0, m->info.xres, m->info.yres, NULL);
446            m->currentBuffer = buffer;
447        }
448
449    } else {
450        void* fb_vaddr;
451        void* buffer_vaddr;
452        
453        m->base.lock(&m->base, m->framebuffer, 
454                GRALLOC_USAGE_SW_WRITE_RARELY, 
455                0, 0, m->info.xres, m->info.yres,
456                &fb_vaddr);
457
458        m->base.lock(&m->base, buffer, 
459                GRALLOC_USAGE_SW_READ_RARELY, 
460                0, 0, m->info.xres, m->info.yres,
461                &buffer_vaddr);
462
463        //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
464
465        msm_copy_buffer(
466                m->framebuffer, m->framebuffer->fd,
467                m->info.xres, m->info.yres, m->fbFormat,
468                m->info.xoffset, m->info.yoffset,
469                m->info.width, m->info.height);
470
471        m->base.unlock(&m->base, buffer); 
472        m->base.unlock(&m->base, m->framebuffer); 
473    }
474
475    return 0;
476}
477
478static int fb_compositionComplete(struct framebuffer_device_t* dev)
479{
480    // TODO: Properly implement composition complete callback
481    glFinish();
482
483    return 0;
484}
485
486/*****************************************************************************/
487
488int mapFrameBufferLocked(struct private_module_t* module)
489{
490    // already initialized...
491    if (module->framebuffer) {
492        return 0;
493    }
494        
495    char const * const device_template[] = {
496            "/dev/graphics/fb%u",
497            "/dev/fb%u",
498            0 };
499
500    int fd = -1;
501    int i=0;
502    char name[64];
503
504    while ((fd==-1) && device_template[i]) {
505        snprintf(name, 64, device_template[i], 0);
506        fd = open(name, O_RDWR, 0);
507        i++;
508    }
509    if (fd < 0)
510        return -errno;
511
512    struct fb_fix_screeninfo finfo;
513    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
514        return -errno;
515
516    struct fb_var_screeninfo info;
517    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
518        return -errno;
519
520    info.reserved[0] = 0;
521    info.reserved[1] = 0;
522    info.reserved[2] = 0;
523    info.xoffset = 0;
524    info.yoffset = 0;
525    info.activate = FB_ACTIVATE_NOW;
526
527    /* Interpretation of offset for color fields: All offsets are from the right,
528    * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
529    * can use the offset as right argument to <<). A pixel afterwards is a bit
530    * stream and is written to video memory as that unmodified. This implies
531    * big-endian byte order if bits_per_pixel is greater than 8.
532    */
533
534    if(info.bits_per_pixel == 32) {
535	/*
536	* Explicitly request RGBA_8888
537	*/
538	info.bits_per_pixel = 32;
539	info.red.offset     = 24;
540	info.red.length     = 8;
541	info.green.offset   = 16;
542	info.green.length   = 8;
543	info.blue.offset    = 8;
544	info.blue.length    = 8;
545	info.transp.offset  = 0;
546	info.transp.length  = 8;
547
548	/* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do
549	* not use the MDP for composition (i.e. hw composition == 0), ask for
550	* RGBA instead of RGBX. */
551	char property[PROPERTY_VALUE_MAX];
552	if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
553		module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
554	else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0))
555		module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
556	else
557		module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888;
558    } else {
559	/*
560	* Explicitly request 5/6/5
561	*/
562	info.bits_per_pixel = 16;
563	info.red.offset     = 11;
564	info.red.length     = 5;
565	info.green.offset   = 5;
566	info.green.length   = 6;
567	info.blue.offset    = 0;
568	info.blue.length    = 5;
569	info.transp.offset  = 0;
570	info.transp.length  = 0;
571	module->fbFormat = HAL_PIXEL_FORMAT_RGB_565;
572    }
573    /*
574     * Request NUM_BUFFERS screens (at lest 2 for page flipping)
575     */
576    info.yres_virtual = info.yres * NUM_BUFFERS;
577
578
579    uint32_t flags = PAGE_FLIP;
580    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
581        info.yres_virtual = info.yres;
582        flags &= ~PAGE_FLIP;
583        LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
584    }
585
586    if (info.yres_virtual < info.yres * 2) {
587        // we need at least 2 for page-flipping
588        info.yres_virtual = info.yres;
589        flags &= ~PAGE_FLIP;
590        LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
591                info.yres_virtual, info.yres*2);
592    }
593
594    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
595        return -errno;
596
597    int refreshRate = 1000000000000000LLU /
598    (
599            uint64_t( info.upper_margin + info.lower_margin + info.yres )
600            * ( info.left_margin  + info.right_margin + info.xres )
601            * info.pixclock
602    );
603
604    if (refreshRate == 0) {
605        // bleagh, bad info from the driver
606        refreshRate = 60*1000;  // 60 Hz
607    }
608
609    if (int(info.width) <= 0 || int(info.height) <= 0) {
610        // the driver doesn't return that information
611        // default to 160 dpi
612        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
613        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
614    }
615
616    float xdpi = (info.xres * 25.4f) / info.width;
617    float ydpi = (info.yres * 25.4f) / info.height;
618    float fps  = refreshRate / 1000.0f;
619
620    LOGI(   "using (fd=%d)\n"
621            "id           = %s\n"
622            "xres         = %d px\n"
623            "yres         = %d px\n"
624            "xres_virtual = %d px\n"
625            "yres_virtual = %d px\n"
626            "bpp          = %d\n"
627            "r            = %2u:%u\n"
628            "g            = %2u:%u\n"
629            "b            = %2u:%u\n",
630            fd,
631            finfo.id,
632            info.xres,
633            info.yres,
634            info.xres_virtual,
635            info.yres_virtual,
636            info.bits_per_pixel,
637            info.red.offset, info.red.length,
638            info.green.offset, info.green.length,
639            info.blue.offset, info.blue.length
640    );
641
642    LOGI(   "width        = %d mm (%f dpi)\n"
643            "height       = %d mm (%f dpi)\n"
644            "refresh rate = %.2f Hz\n",
645            info.width,  xdpi,
646            info.height, ydpi,
647            fps
648    );
649
650
651    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
652        return -errno;
653
654    if (finfo.smem_len <= 0)
655        return -errno;
656
657
658    module->flags = flags;
659    module->info = info;
660    module->finfo = finfo;
661    module->xdpi = xdpi;
662    module->ydpi = ydpi;
663    module->fps = fps;
664
665#ifdef NO_SURFACEFLINGER_SWAPINTERVAL
666    char pval[PROPERTY_VALUE_MAX];
667    property_get("debug.gr.swapinterval", pval, "1");
668    module->swapInterval = atoi(pval);
669    if (module->swapInterval < private_module_t::PRIV_MIN_SWAP_INTERVAL ||
670        module->swapInterval > private_module_t::PRIV_MAX_SWAP_INTERVAL) {
671        module->swapInterval = 1;
672        LOGW("Out of range (%d to %d) value for debug.gr.swapinterval, using 1",
673             private_module_t::PRIV_MIN_SWAP_INTERVAL,
674             private_module_t::PRIV_MAX_SWAP_INTERVAL);
675    }
676
677#else
678    /* when surfaceflinger supports swapInterval then can just do this */
679    module->swapInterval = 1;
680#endif
681
682    module->currentIdx = -1;
683    pthread_cond_init(&(module->qpost), NULL);
684    pthread_mutex_init(&(module->qlock), NULL);
685    for (i = 0; i < NUM_BUFFERS; i++) {
686        pthread_mutex_init(&(module->avail[i].lock), NULL);
687        pthread_cond_init(&(module->avail[i].cond), NULL);
688        module->avail[i].is_avail = true;
689    }    
690
691    /* create display update thread */
692    pthread_t thread1;
693    if (pthread_create(&thread1, NULL, &disp_loop, (void *) module)) {
694         return -errno;
695    }
696
697    /*
698     * map the framebuffer
699     */
700
701    int err;
702    size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
703    module->framebuffer = new private_handle_t(dup(fd), fbSize,
704            private_handle_t::PRIV_FLAGS_USES_PMEM);
705
706    module->numBuffers = info.yres_virtual / info.yres;
707    module->bufferMask = 0;
708
709    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
710    if (vaddr == MAP_FAILED) {
711        LOGE("Error mapping the framebuffer (%s)", strerror(errno));
712        return -errno;
713    }
714    module->framebuffer->base = intptr_t(vaddr);
715    memset(vaddr, 0, fbSize);
716
717#if defined(HDMI_DUAL_DISPLAY)
718    /* Overlay for HDMI*/
719    pthread_mutex_init(&(module->overlayLock), NULL);
720    pthread_cond_init(&(module->overlayPost), NULL);
721    module->pobjOverlay = new Overlay();
722    module->currentOffset = 0;
723    module->exitHDMIUILoop = false;
724    pthread_t hdmiUIThread;
725    pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module);
726#endif
727
728    return 0;
729}
730
731static int mapFrameBuffer(struct private_module_t* module)
732{
733    pthread_mutex_lock(&module->lock);
734    int err = mapFrameBufferLocked(module);
735    pthread_mutex_unlock(&module->lock);
736    return err;
737}
738
739/*****************************************************************************/
740
741static int fb_close(struct hw_device_t *dev)
742{
743    fb_context_t* ctx = (fb_context_t*)dev;
744#if defined(HDMI_DUAL_DISPLAY)
745    private_module_t* m = reinterpret_cast<private_module_t*>(
746            ctx->device.common.module);
747    pthread_mutex_lock(&m->overlayLock);
748    m->exitHDMIUILoop = true;
749    pthread_cond_signal(&(m->overlayPost));
750    pthread_mutex_unlock(&m->overlayLock);
751#endif
752    if (ctx) {
753        free(ctx);
754    }
755    return 0;
756}
757
758int fb_device_open(hw_module_t const* module, const char* name,
759        hw_device_t** device)
760{
761    int status = -EINVAL;
762    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
763        alloc_device_t* gralloc_device;
764        status = gralloc_open(module, &gralloc_device);
765        if (status < 0)
766            return status;
767
768        /* initialize our state here */
769        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
770        memset(dev, 0, sizeof(*dev));
771
772        /* initialize the procs */
773        dev->device.common.tag = HARDWARE_DEVICE_TAG;
774        dev->device.common.version = 0;
775        dev->device.common.module = const_cast<hw_module_t*>(module);
776        dev->device.common.close = fb_close;
777        dev->device.setSwapInterval = fb_setSwapInterval;
778        dev->device.post            = fb_post;
779        dev->device.setUpdateRect = 0;
780        dev->device.compositionComplete = fb_compositionComplete;
781#if defined(HDMI_DUAL_DISPLAY)
782        dev->device.orientationChanged = fb_orientationChanged;
783        dev->device.videoOverlayStarted = fb_videoOverlayStarted;
784        dev->device.enableHDMIOutput = fb_enableHDMIOutput;
785        dev->device.setActionSafeWidthRatio = fb_setActionSafeWidthRatio;
786        dev->device.setActionSafeHeightRatio = fb_setActionSafeHeightRatio;
787#endif
788
789        private_module_t* m = (private_module_t*)module;
790        status = mapFrameBuffer(m);
791        if (status >= 0) {
792            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
793            const_cast<uint32_t&>(dev->device.flags) = 0;
794            const_cast<uint32_t&>(dev->device.width) = m->info.xres;
795            const_cast<uint32_t&>(dev->device.height) = m->info.yres;
796            const_cast<int&>(dev->device.stride) = stride;
797            const_cast<int&>(dev->device.format) = m->fbFormat;
798            const_cast<float&>(dev->device.xdpi) = m->xdpi;
799            const_cast<float&>(dev->device.ydpi) = m->ydpi;
800            const_cast<float&>(dev->device.fps) = m->fps;
801            const_cast<int&>(dev->device.minSwapInterval) = private_module_t::PRIV_MIN_SWAP_INTERVAL;
802            const_cast<int&>(dev->device.maxSwapInterval) = private_module_t::PRIV_MAX_SWAP_INTERVAL;
803
804            if (m->finfo.reserved[0] == 0x5444 &&
805                    m->finfo.reserved[1] == 0x5055) {
806                dev->device.setUpdateRect = fb_setUpdateRect;
807                LOGD("UPDATE_ON_DEMAND supported");
808            }
809
810            *device = &dev->device.common;
811        }
812
813        // Close the gralloc module
814        gralloc_close(gralloc_device);
815    }
816    return status;
817}
818
819/* Copy a pmem buffer to the framebuffer */
820
821static void
822msm_copy_buffer(buffer_handle_t handle, int fd,
823                int width, int height, int format,
824                int x, int y, int w, int h)
825{
826    struct {
827        unsigned int count;
828        mdp_blit_req req;
829    } blit;
830    private_handle_t *priv = (private_handle_t*) handle;
831
832    memset(&blit, 0, sizeof(blit));
833    blit.count = 1;
834
835    blit.req.flags = 0;
836    blit.req.alpha = 0xff;
837    blit.req.transp_mask = 0xffffffff;
838
839    blit.req.src.width = width;
840    blit.req.src.height = height;
841    blit.req.src.offset = 0;
842    blit.req.src.memory_id = priv->fd;
843
844    blit.req.dst.width = width;
845    blit.req.dst.height = height;
846    blit.req.dst.offset = 0;
847    blit.req.dst.memory_id = fd; 
848    blit.req.dst.format = format;
849
850    blit.req.src_rect.x = blit.req.dst_rect.x = x;
851    blit.req.src_rect.y = blit.req.dst_rect.y = y;
852    blit.req.src_rect.w = blit.req.dst_rect.w = w;
853    blit.req.src_rect.h = blit.req.dst_rect.h = h;
854
855    if (ioctl(fd, MSMFB_BLIT, &blit))
856        LOGE("MSMFB_BLIT failed = %d", -errno);
857}