Home | History | Annotate | Download | only in hwc
      1 /*
      2  * Copyright (C) Texas Instruments - http://www.ti.com/
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <errno.h>
     19 #include <time.h>
     20 #include <assert.h>
     21 #include <strings.h>
     22 #include <dlfcn.h>
     23 
     24 #include <fcntl.h>
     25 #include <sys/mman.h>
     26 #include <linux/fb.h>
     27 #include <linux/bltsville.h>
     28 #include <video/dsscomp.h>
     29 #include <video/omap_hwc.h>
     30 
     31 #ifndef RGZ_TEST_INTEGRATION
     32 #include <cutils/log.h>
     33 #include <cutils/properties.h>
     34 #include <hardware/hwcomposer.h>
     35 #include "hal_public.h"
     36 #else
     37 #include "hwcomposer.h"
     38 #include "buffer_handle.h"
     39 #define ALIGN(x,a) (((x) + (a) - 1L) & ~((a) - 1L))
     40 #define HW_ALIGN   32
     41 #endif
     42 
     43 #include "rgz_2d.h"
     44 
     45 #ifdef RGZ_TEST_INTEGRATION
     46 extern void BVDump(const char* prefix, const char* tab, const struct bvbltparams* parms);
     47 #define BVDUMP(p,t,parms) BVDump(p, t, parms)
     48 #define HANDLE_TO_BUFFER(h) handle_to_buffer(h)
     49 #define HANDLE_TO_STRIDE(h) handle_to_stride(h)
     50 #else
     51 static int rgz_handle_to_stride(IMG_native_handle_t *h);
     52 #define BVDUMP(p,t,parms)
     53 #define HANDLE_TO_BUFFER(h) NULL
     54 /* Needs to be meaningful for TILER & GFX buffers and NV12 */
     55 #define HANDLE_TO_STRIDE(h) rgz_handle_to_stride(h)
     56 #endif
     57 #define DSTSTRIDE(dstgeom) dstgeom->virtstride
     58 
     59 /* Borrowed macros from hwc.c vvv - consider sharing later */
     60 #define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } )
     61 #define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } )
     62 #define swap(a, b) do { typeof(a) __a = (a); (a) = (b); (b) = __a; } while (0)
     63 
     64 #define WIDTH(rect) ((rect).right - (rect).left)
     65 #define HEIGHT(rect) ((rect).bottom - (rect).top)
     66 
     67 #define is_RGB(format) ((format) == HAL_PIXEL_FORMAT_BGRA_8888 || (format) == HAL_PIXEL_FORMAT_RGB_565 || (format) == HAL_PIXEL_FORMAT_BGRX_8888)
     68 #define is_BGR(format) ((format) == HAL_PIXEL_FORMAT_RGBX_8888 || (format) == HAL_PIXEL_FORMAT_RGBA_8888)
     69 #define is_NV12(format) ((format) == HAL_PIXEL_FORMAT_TI_NV12 || (format) == HAL_PIXEL_FORMAT_TI_NV12_PADDED)
     70 
     71 #define HAL_PIXEL_FORMAT_BGRX_8888 0x1FF
     72 #define HAL_PIXEL_FORMAT_TI_NV12 0x100
     73 #define HAL_PIXEL_FORMAT_TI_NV12_PADDED 0x101
     74 /* Borrowed macros from hwc.c ^^^ */
     75 #define is_OPAQUE(format) ((format) == HAL_PIXEL_FORMAT_RGB_565 || (format) == HAL_PIXEL_FORMAT_RGBX_8888 || (format) == HAL_PIXEL_FORMAT_BGRX_8888)
     76 
     77 /* OUTP the means for grabbing diagnostic data */
     78 #ifndef RGZ_TEST_INTEGRATION
     79 #define OUTP ALOGI
     80 #define OUTE ALOGE
     81 #else
     82 #define OUTP(...) { printf(__VA_ARGS__); printf("\n"); fflush(stdout); }
     83 #define OUTE OUTP
     84 #define ALOGD_IF(debug, ...) { if (debug) OUTP(__VA_ARGS__); }
     85 #endif
     86 
     87 #define IS_BVCMD(params) (params->op == RGZ_OUT_BVCMD_REGION || params->op == RGZ_OUT_BVCMD_PAINT)
     88 
     89 /* Number of framebuffers to track */
     90 #define RGZ_NUM_FB 2
     91 
     92 struct rgz_blts {
     93     struct rgz_blt_entry bvcmds[RGZ_MAX_BLITS];
     94     int idx;
     95 };
     96 
     97 
     98 static int rgz_hwc_layer_blit(rgz_out_params_t *params, rgz_layer_t *rgz_layer);
     99 static void rgz_blts_init(struct rgz_blts *blts);
    100 static void rgz_blts_free(struct rgz_blts *blts);
    101 static struct rgz_blt_entry* rgz_blts_get(struct rgz_blts *blts, rgz_out_params_t *params);
    102 static int rgz_blts_bvdirect(rgz_t* rgz, struct rgz_blts *blts, rgz_out_params_t *params);
    103 static void rgz_get_src_rect(hwc_layer_1_t* layer, blit_rect_t *subregion_rect, blit_rect_t *res_rect);
    104 static int hal_to_ocd(int color);
    105 static int rgz_get_orientation(unsigned int transform);
    106 static int rgz_get_flip_flags(unsigned int transform, int use_src2_flags);
    107 static int rgz_hwc_scaled(hwc_layer_1_t *layer);
    108 
    109 int debug = 0;
    110 struct rgz_blts blts;
    111 /* Represents a screen sized background layer */
    112 static hwc_layer_1_t bg_layer;
    113 
    114 static void svgout_header(int htmlw, int htmlh, int coordw, int coordh)
    115 {
    116     OUTP("<svg xmlns=\"http://www.w3.org/2000/svg\""
    117          "width=\"%d\" height=\"%d\""
    118          "viewBox=\"0 0 %d %d\">",
    119         htmlw, htmlh, coordw, coordh);
    120 }
    121 
    122 static void svgout_footer(void)
    123 {
    124     OUTP("</svg>");
    125 }
    126 
    127 static void svgout_rect(blit_rect_t *r, char *color, char *text)
    128 {
    129     OUTP("<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" fill=\"%s\" "
    130          "fill-opacity=\"%f\" stroke=\"black\" stroke-width=\"1\" />",
    131          r->left, r->top, r->right - r->left, r->bottom - r->top, color, 1.0f);
    132 
    133     if (!text)
    134         return;
    135 
    136     OUTP("<text x=\"%d\" y=\"%d\" style=\"font-size:30\" fill=\"black\">%s"
    137          "</text>",
    138          r->left, r->top + 40, text);
    139 }
    140 
    141 static int empty_rect(blit_rect_t *r)
    142 {
    143     return !r->left && !r->top && !r->right && !r->bottom;
    144 }
    145 
    146 static int get_top_rect(blit_hregion_t *hregion, int subregion, blit_rect_t **routp)
    147 {
    148     int l = hregion->nlayers - 1;
    149     do {
    150         *routp = &hregion->blitrects[l][subregion];
    151         if (!empty_rect(*routp))
    152             break;
    153     }
    154     while (--l >= 0);
    155     return l;
    156 }
    157 
    158 /*
    159  * The idea here is that we walk the layers from front to back and count the
    160  * number of layers in the hregion until the first layer which doesn't require
    161  * blending.
    162  */
    163 static int get_layer_ops(blit_hregion_t *hregion, int subregion, int *bottom)
    164 {
    165     int l = hregion->nlayers - 1;
    166     int ops = 0;
    167     *bottom = -1;
    168     do {
    169         if (!empty_rect(&hregion->blitrects[l][subregion])) {
    170             ops++;
    171             *bottom = l;
    172             hwc_layer_1_t *layer = hregion->rgz_layers[l]->hwc_layer;
    173             IMG_native_handle_t *h = (IMG_native_handle_t *)layer->handle;
    174             if ((layer->blending != HWC_BLENDING_PREMULT) || is_OPAQUE(h->iFormat))
    175                 break;
    176         }
    177     }
    178     while (--l >= 0);
    179     return ops;
    180 }
    181 
    182 static int get_layer_ops_next(blit_hregion_t *hregion, int subregion, int l)
    183 {
    184     while (++l < hregion->nlayers) {
    185         if (!empty_rect(&hregion->blitrects[l][subregion]))
    186             return l;
    187     }
    188     return -1;
    189 }
    190 
    191 static int svgout_intersects_display(blit_rect_t *a, int dispw, int disph)
    192 {
    193     return ((a->bottom > 0) && (a->top < disph) &&
    194             (a->right > 0) && (a->left < dispw));
    195 }
    196 
    197 static void svgout_hregion(blit_hregion_t *hregion, int dispw, int disph)
    198 {
    199     char *colors[] = {"red", "orange", "yellow", "green", "blue", "indigo", "violet", NULL};
    200     int b;
    201     for (b = 0; b < hregion->nsubregions; b++) {
    202         blit_rect_t *rect;
    203         (void)get_top_rect(hregion, b, &rect);
    204         /* Only generate SVG for subregions intersecting the displayed area */
    205         if (!svgout_intersects_display(rect, dispw, disph))
    206             continue;
    207         svgout_rect(rect, colors[b % 7], NULL);
    208     }
    209 }
    210 
    211 static void rgz_out_svg(rgz_t *rgz, rgz_out_params_t *params)
    212 {
    213     if (!rgz || !(rgz->state & RGZ_REGION_DATA)) {
    214         OUTE("rgz_out_svg invoked with bad state");
    215         return;
    216     }
    217     blit_hregion_t *hregions = rgz->hregions;
    218     svgout_header(params->data.svg.htmlw, params->data.svg.htmlh,
    219                   params->data.svg.dispw, params->data.svg.disph);
    220     int i;
    221     for (i = 0; i < rgz->nhregions; i++) {
    222 
    223         OUTP("<!-- hregion %d (subcount %d)-->", i, hregions[i].nsubregions);
    224         svgout_hregion(&hregions[i], params->data.svg.dispw,
    225                        params->data.svg.disph);
    226     }
    227     svgout_footer();
    228 }
    229 
    230 /* XXX duplicate of hwc.c version */
    231 static void dump_layer(hwc_layer_1_t const* l, int iserr)
    232 {
    233 #define FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \
    234                 (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \
    235                 (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \
    236                 (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \
    237                 (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \
    238                 (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??")
    239 
    240     OUTE("%stype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
    241             iserr ? ">>  " : "    ",
    242             l->compositionType, l->flags, l->handle, l->transform, l->blending,
    243             l->sourceCrop.left,
    244             l->sourceCrop.top,
    245             l->sourceCrop.right,
    246             l->sourceCrop.bottom,
    247             l->displayFrame.left,
    248             l->displayFrame.top,
    249             l->displayFrame.right,
    250             l->displayFrame.bottom);
    251     if (l->handle) {
    252         IMG_native_handle_t *h = (IMG_native_handle_t *)l->handle;
    253         OUTE("%s%d*%d(%s)",
    254             iserr ? ">>  " : "    ",
    255             h->iWidth, h->iHeight, FMT(h->iFormat));
    256         OUTE("hndl %p", l->handle);
    257     }
    258 }
    259 
    260 static void dump_all(rgz_layer_t *rgz_layers, unsigned int layerno, unsigned int errlayer)
    261 {
    262     unsigned int i;
    263     for (i = 0; i < layerno; i++) {
    264         hwc_layer_1_t *l = rgz_layers[i].hwc_layer;
    265         OUTE("Layer %d", i);
    266         dump_layer(l, errlayer == i);
    267     }
    268 }
    269 
    270 static int rgz_out_bvdirect_paint(rgz_t *rgz, rgz_out_params_t *params)
    271 {
    272     int rv = 0;
    273     unsigned int i;
    274     (void)rgz;
    275 
    276     rgz_blts_init(&blts);
    277 
    278     /* Begin from index 1 to remove the background layer from the output */
    279     for (i = 1; i < rgz->rgz_layerno; i++) {
    280         rv = rgz_hwc_layer_blit(params, &rgz->rgz_layers[i]);
    281         if (rv) {
    282             OUTE("bvdirect_paint: error in layer %d: %d", i, rv);
    283             dump_all(rgz->rgz_layers, rgz->rgz_layerno, i);
    284             rgz_blts_free(&blts);
    285             return rv;
    286         }
    287     }
    288     rgz_blts_bvdirect(rgz, &blts, params);
    289     rgz_blts_free(&blts);
    290     return rv;
    291 }
    292 
    293 static void rgz_set_async(struct rgz_blt_entry *e, int async)
    294 {
    295     e->bp.flags = async ? e->bp.flags | BVFLAG_ASYNC : e->bp.flags & ~BVFLAG_ASYNC;
    296 }
    297 
    298 static void rgz_get_screen_info(rgz_out_params_t *params, struct bvsurfgeom **screen_geom)
    299 {
    300     *screen_geom = params->data.bvc.dstgeom;
    301 }
    302 
    303 static int rgz_is_blending_disabled(rgz_out_params_t *params)
    304 {
    305     return params->data.bvc.noblend;
    306 }
    307 
    308 static void rgz_get_displayframe_rect(hwc_layer_1_t *layer, blit_rect_t *res_rect)
    309 {
    310     res_rect->left = layer->displayFrame.left;
    311     res_rect->top = layer->displayFrame.top;
    312     res_rect->bottom = layer->displayFrame.bottom;
    313     res_rect->right = layer->displayFrame.right;
    314 }
    315 
    316 static void rgz_set_dst_data(rgz_out_params_t *params, blit_rect_t *subregion_rect,
    317     struct rgz_blt_entry* e)
    318 {
    319     struct bvsurfgeom *screen_geom;
    320     rgz_get_screen_info(params, &screen_geom);
    321 
    322     /* omaplfb is in charge of assigning the correct dstdesc in the kernel */
    323     e->dstgeom.structsize = sizeof(struct bvsurfgeom);
    324     e->dstgeom.format = screen_geom->format;
    325     e->dstgeom.width = screen_geom->width;
    326     e->dstgeom.height = screen_geom->height;
    327     e->dstgeom.orientation = screen_geom->orientation;
    328     e->dstgeom.virtstride = DSTSTRIDE(screen_geom);
    329 
    330     e->bp.dstrect.left = subregion_rect->left;
    331     e->bp.dstrect.top = subregion_rect->top;
    332     e->bp.dstrect.width = WIDTH(*subregion_rect);
    333     e->bp.dstrect.height = HEIGHT(*subregion_rect);
    334 }
    335 
    336 static void rgz_set_src_data(rgz_out_params_t *params, rgz_layer_t *rgz_layer,
    337     blit_rect_t *subregion_rect, struct rgz_blt_entry* e, int is_src2)
    338 {
    339     hwc_layer_1_t *hwc_layer = rgz_layer->hwc_layer;
    340     struct bvbuffdesc *srcdesc = is_src2 ? &e->src2desc : &e->src1desc;
    341     struct bvsurfgeom *srcgeom = is_src2 ? &e->src2geom : &e->src1geom;
    342     struct bvrect *srcrect = is_src2 ? &e->bp.src2rect : &e->bp.src1rect;
    343     IMG_native_handle_t *handle = (IMG_native_handle_t *)hwc_layer->handle;
    344 
    345     srcdesc->structsize = sizeof(struct bvbuffdesc);
    346     srcdesc->length = handle->iHeight * HANDLE_TO_STRIDE(handle);
    347     srcdesc->auxptr = (void*)rgz_layer->buffidx;
    348     srcgeom->structsize = sizeof(struct bvsurfgeom);
    349     srcgeom->format = hal_to_ocd(handle->iFormat);
    350     srcgeom->width = handle->iWidth;
    351     srcgeom->height = handle->iHeight;
    352     srcgeom->orientation = rgz_get_orientation(hwc_layer->transform);
    353     srcgeom->virtstride = HANDLE_TO_STRIDE(handle);
    354     if (hwc_layer->transform & HAL_TRANSFORM_ROT_90)
    355         swap(srcgeom->width, srcgeom->height);
    356 
    357     /* Find out what portion of the src we want to use for the blit */
    358     blit_rect_t res_rect;
    359     rgz_get_src_rect(hwc_layer, subregion_rect, &res_rect);
    360     srcrect->left = res_rect.left;
    361     srcrect->top = res_rect.top;
    362     srcrect->width = WIDTH(res_rect);
    363     srcrect->height = HEIGHT(res_rect);
    364 }
    365 
    366 /*
    367  * Set the clipping rectangle, if part of the subregion rectangle is outside
    368  * the boundaries of the destination, remove only the out-of-bounds area
    369  */
    370 static void rgz_set_clip_rect(rgz_out_params_t *params, blit_rect_t *subregion_rect,
    371     struct rgz_blt_entry* e)
    372 {
    373     struct bvsurfgeom *screen_geom;
    374     rgz_get_screen_info(params, &screen_geom);
    375 
    376     blit_rect_t clip_rect;
    377     clip_rect.left = max(0, subregion_rect->left);
    378     clip_rect.top = max(0, subregion_rect->top);
    379     clip_rect.bottom = min(screen_geom->height, subregion_rect->bottom);
    380     clip_rect.right = min(screen_geom->width, subregion_rect->right);
    381 
    382     e->bp.cliprect.left = clip_rect.left;
    383     e->bp.cliprect.top = clip_rect.top;
    384     e->bp.cliprect.width = WIDTH(clip_rect);
    385     e->bp.cliprect.height = HEIGHT(clip_rect);
    386 }
    387 
    388 /*
    389  * Configures blit entry to set src2 is the same as the destination
    390  */
    391 static void rgz_set_src2_is_dst(rgz_out_params_t *params, struct rgz_blt_entry* e)
    392 {
    393     /* omaplfb is in charge of assigning the correct src2desc in the kernel */
    394     e->src2geom = e->dstgeom;
    395     e->src2desc.structsize = sizeof(struct bvbuffdesc);
    396     e->src2desc.auxptr = (void*)HWC_BLT_DESC_FB_FN(0);
    397     e->bp.src2rect = e->bp.dstrect;
    398 }
    399 
    400 /*
    401  * Configure the scaling mode according to the layer format
    402  */
    403 static void rgz_cfg_scale_mode(struct rgz_blt_entry* e, hwc_layer_1_t *layer)
    404 {
    405     /*
    406      * TODO: Revisit scaling mode assignment later, output between GPU and GC320
    407      * seem different
    408      */
    409     IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
    410     e->bp.scalemode = is_NV12(handle->iFormat) ? BVSCALE_9x9_TAP : BVSCALE_BILINEAR;
    411 }
    412 
    413 /*
    414  * Copies src1 into the framebuffer
    415  */
    416 static struct rgz_blt_entry* rgz_hwc_subregion_copy(rgz_out_params_t *params,
    417     blit_rect_t *subregion_rect, rgz_layer_t *rgz_src1)
    418 {
    419     struct rgz_blt_entry* e = rgz_blts_get(&blts, params);
    420     hwc_layer_1_t *hwc_src1 = rgz_src1->hwc_layer;
    421     e->bp.structsize = sizeof(struct bvbltparams);
    422     e->bp.op.rop = 0xCCCC; /* SRCCOPY */
    423     e->bp.flags = BVFLAG_CLIP | BVFLAG_ROP;
    424     e->bp.flags |= rgz_get_flip_flags(hwc_src1->transform, 0);
    425     rgz_set_async(e, 1);
    426 
    427     blit_rect_t tmp_rect;
    428     if (rgz_hwc_scaled(hwc_src1)) {
    429         rgz_get_displayframe_rect(hwc_src1, &tmp_rect);
    430         rgz_cfg_scale_mode(e, hwc_src1);
    431     } else
    432         tmp_rect = *subregion_rect;
    433 
    434     rgz_set_src_data(params, rgz_src1, &tmp_rect, e, 0);
    435     rgz_set_dst_data(params, &tmp_rect, e);
    436     rgz_set_clip_rect(params, subregion_rect, e);
    437 
    438     if((e->src1geom.format == OCDFMT_BGR124) ||
    439        (e->src1geom.format == OCDFMT_RGB124) ||
    440        (e->src1geom.format == OCDFMT_RGB16))
    441         e->dstgeom.format = OCDFMT_BGR124;
    442 
    443     return e;
    444 }
    445 
    446 /*
    447  * Blends two layers and write the result in the framebuffer, src1 must be the
    448  * top most layer while src2 is the one behind. If src2 is NULL means src1 will
    449  * be blended with the current content of the framebuffer.
    450  */
    451 static struct rgz_blt_entry* rgz_hwc_subregion_blend(rgz_out_params_t *params,
    452     blit_rect_t *subregion_rect, rgz_layer_t *rgz_src1, rgz_layer_t *rgz_src2)
    453 {
    454     struct rgz_blt_entry* e = rgz_blts_get(&blts, params);
    455     hwc_layer_1_t *hwc_src1 = rgz_src1->hwc_layer;
    456     e->bp.structsize = sizeof(struct bvbltparams);
    457     e->bp.op.blend = BVBLEND_SRC1OVER;
    458     e->bp.flags = BVFLAG_CLIP | BVFLAG_BLEND;
    459     e->bp.flags |= rgz_get_flip_flags(hwc_src1->transform, 0);
    460     rgz_set_async(e, 1);
    461 
    462     blit_rect_t tmp_rect;
    463     if (rgz_hwc_scaled(hwc_src1)) {
    464         rgz_get_displayframe_rect(hwc_src1, &tmp_rect);
    465         rgz_cfg_scale_mode(e, hwc_src1);
    466     } else
    467         tmp_rect = *subregion_rect;
    468 
    469     rgz_set_src_data(params, rgz_src1, &tmp_rect, e, 0);
    470     rgz_set_dst_data(params, &tmp_rect, e);
    471     rgz_set_clip_rect(params, subregion_rect, e);
    472 
    473     if (rgz_src2) {
    474         /*
    475          * NOTE: Due to an API limitation it's not possible to blend src1 and
    476          * src2 if both have scaling, hence only src1 is used for now
    477          */
    478         hwc_layer_1_t *hwc_src2 = rgz_src2->hwc_layer;
    479         if (rgz_hwc_scaled(hwc_src2))
    480             OUTE("src2 layer %p has scaling, this is not supported", hwc_src2);
    481         e->bp.flags |= rgz_get_flip_flags(hwc_src2->transform, 1);
    482         rgz_set_src_data(params, rgz_src2, subregion_rect, e, 1);
    483     } else
    484         rgz_set_src2_is_dst(params, e);
    485 
    486     return e;
    487 }
    488 
    489 /*
    490  * Clear the destination buffer, if rect is NULL means the whole screen, rect
    491  * cannot be outside the boundaries of the screen
    492  */
    493 static void rgz_out_clrdst(rgz_out_params_t *params, blit_rect_t *rect)
    494 {
    495     struct rgz_blt_entry* e = rgz_blts_get(&blts, params);
    496     e->bp.structsize = sizeof(struct bvbltparams);
    497     e->bp.op.rop = 0xCCCC; /* SRCCOPY */
    498     e->bp.flags = BVFLAG_CLIP | BVFLAG_ROP;
    499     rgz_set_async(e, 1);
    500 
    501     struct bvsurfgeom *screen_geom;
    502     rgz_get_screen_info(params, &screen_geom);
    503 
    504     e->src1desc.structsize = sizeof(struct bvbuffdesc);
    505     e->src1desc.length = 4; /* 1 pixel, 32bpp */
    506     /*
    507      * With the HWC we don't bother having a buffer for the fill we'll get the
    508      * OMAPLFB to fixup the src1desc and stride if the auxiliary pointer is -1
    509      */
    510     e->src1desc.auxptr = (void*)-1;
    511     e->src1geom.structsize = sizeof(struct bvsurfgeom);
    512     e->src1geom.format = OCDFMT_RGBA24;
    513     e->bp.src1rect.left = e->bp.src1rect.top = e->src1geom.orientation = 0;
    514     e->src1geom.height = e->src1geom.width = e->bp.src1rect.height = e->bp.src1rect.width = 1;
    515 
    516     blit_rect_t clear_rect;
    517     if (rect) {
    518         clear_rect.left = rect->left;
    519         clear_rect.top = rect->top;
    520         clear_rect.right = rect->right;
    521         clear_rect.bottom = rect->bottom;
    522     } else {
    523         clear_rect.left = clear_rect.top = 0;
    524         clear_rect.right = screen_geom->width;
    525         clear_rect.bottom = screen_geom->height;
    526     }
    527 
    528     rgz_set_dst_data(params, &clear_rect, e);
    529     rgz_set_clip_rect(params, &clear_rect, e);
    530 }
    531 
    532 static int rgz_out_bvcmd_paint(rgz_t *rgz, rgz_out_params_t *params)
    533 {
    534     int rv = 0;
    535     params->data.bvc.out_blits = 0;
    536     params->data.bvc.out_nhndls = 0;
    537     rgz_blts_init(&blts);
    538     rgz_out_clrdst(params, NULL);
    539 
    540     unsigned int i, j;
    541 
    542     /* Begin from index 1 to remove the background layer from the output */
    543     for (i = 1, j = 0; i < rgz->rgz_layerno; i++) {
    544         rgz_layer_t *rgz_layer = &rgz->rgz_layers[i];
    545         hwc_layer_1_t *l = rgz_layer->hwc_layer;
    546 
    547         //OUTP("blitting meminfo %d", rgz->rgz_layers[i].buffidx);
    548 
    549         /*
    550          * See if it is needed to put transparent pixels where this layer
    551          * is located in the screen
    552          */
    553         if (rgz_layer->buffidx == -1) {
    554             struct bvsurfgeom *scrgeom = params->data.bvc.dstgeom;
    555             blit_rect_t srcregion;
    556             srcregion.left = max(0, l->displayFrame.left);
    557             srcregion.top = max(0, l->displayFrame.top);
    558             srcregion.bottom = min(scrgeom->height, l->displayFrame.bottom);
    559             srcregion.right = min(scrgeom->width, l->displayFrame.right);
    560             rgz_out_clrdst(params, &srcregion);
    561             continue;
    562         }
    563 
    564         rv = rgz_hwc_layer_blit(params, rgz_layer);
    565         if (rv) {
    566             OUTE("bvcmd_paint: error in layer %d: %d", i, rv);
    567             dump_all(rgz->rgz_layers, rgz->rgz_layerno, i);
    568             rgz_blts_free(&blts);
    569             return rv;
    570         }
    571         params->data.bvc.out_hndls[j++] = l->handle;
    572         params->data.bvc.out_nhndls++;
    573     }
    574 
    575     /* Last blit is made sync to act like a fence for the previous async blits */
    576     struct rgz_blt_entry* e = &blts.bvcmds[blts.idx-1];
    577     rgz_set_async(e, 0);
    578 
    579     /* FIXME: we want to be able to call rgz_blts_free and populate the actual
    580      * composition data structure ourselves */
    581     params->data.bvc.cmdp = blts.bvcmds;
    582     params->data.bvc.cmdlen = blts.idx;
    583 
    584     if (params->data.bvc.out_blits >= RGZ_MAX_BLITS) {
    585         rv = -1;
    586     // rgz_blts_free(&blts); // FIXME
    587     }
    588     return rv;
    589 }
    590 
    591 static float getscalew(hwc_layer_1_t *layer)
    592 {
    593     int w = WIDTH(layer->sourceCrop);
    594     int h = HEIGHT(layer->sourceCrop);
    595 
    596     if (layer->transform & HWC_TRANSFORM_ROT_90)
    597         swap(w, h);
    598 
    599     return ((float)WIDTH(layer->displayFrame)) / (float)w;
    600 }
    601 
    602 static float getscaleh(hwc_layer_1_t *layer)
    603 {
    604     int w = WIDTH(layer->sourceCrop);
    605     int h = HEIGHT(layer->sourceCrop);
    606 
    607     if (layer->transform & HWC_TRANSFORM_ROT_90)
    608         swap(w, h);
    609 
    610     return ((float)HEIGHT(layer->displayFrame)) / (float)h;
    611 }
    612 
    613 static int rgz_bswap(int *a, int *b)
    614 {
    615     if (*a > *b) {
    616         int tmp = *b;
    617         *b = *a;
    618         *a = tmp;
    619         return 1;
    620     }
    621     return 0;
    622 }
    623 
    624 /*
    625  * Simple bubble sort on an array
    626  */
    627 static void rgz_bsort(int *a, int len)
    628 {
    629     int i, s;
    630 
    631     do {
    632         s=0;
    633         for (i=0; i+1<len; i++) {
    634             if (rgz_bswap(&a[i], &a[i+1]))
    635                 s = 1;
    636         }
    637     } while (s);
    638 }
    639 
    640 /*
    641  * Leave only unique numbers in a sorted array
    642  */
    643 static int rgz_bunique(int *a, int len)
    644 {
    645     int unique = 1;
    646     int base = 0;
    647     while (base + 1 < len) {
    648         if (a[base] == a[base + 1]) {
    649             int skip = 1;
    650             while (base + skip < len && a[base] == a[base + skip])
    651                 skip++;
    652             if (base + skip == len)
    653                 break;
    654             int i;
    655             for (i = 0; i < skip - 1; i++)
    656                 a[base + 1 + i] = a[base + skip];
    657         }
    658         unique++;
    659         base++;
    660     }
    661     return unique;
    662 }
    663 
    664 static int rgz_hwc_layer_sortbyy(rgz_layer_t *ra, int rsz, int *out, int *width, int screen_height)
    665 {
    666     int outsz = 0;
    667     int i;
    668     *width = 0;
    669     for (i = 0; i < rsz; i++) {
    670         hwc_layer_1_t *layer = ra[i].hwc_layer;
    671         /* Maintain regions inside display boundaries */
    672         int top = layer->displayFrame.top;
    673         int bottom = layer->displayFrame.bottom;
    674         out[outsz++] = max(0, top);
    675         out[outsz++] = min(bottom, screen_height);
    676         int right = layer->displayFrame.right;
    677         *width = *width > right ? *width : right;
    678     }
    679     rgz_bsort(out, outsz);
    680     return outsz;
    681 }
    682 
    683 static int rgz_hwc_intersects(blit_rect_t *a, hwc_rect_t *b)
    684 {
    685     return ((a->bottom > b->top) && (a->top < b->bottom) &&
    686             (a->right > b->left) && (a->left < b->right));
    687 }
    688 
    689 static void rgz_gen_blitregions(blit_hregion_t *hregion, int screen_width)
    690 {
    691 /*
    692  * 1. Get the offsets (left/right positions) of each layer within the
    693  *    hregion. Assume that layers describe the bounds of the hregion.
    694  * 2. We should then be able to generate an array of rects
    695  * 3. Each layer will have a different z-order, for each z-order
    696  *    find the intersection. Some intersections will be empty.
    697  */
    698 
    699     int offsets[RGZ_SUBREGIONMAX];
    700     int noffsets=0;
    701     int l, r;
    702     for (l = 0; l < hregion->nlayers; l++) {
    703         hwc_layer_1_t *layer = hregion->rgz_layers[l]->hwc_layer;
    704         /* Make sure the subregion is not outside the boundaries of the screen */
    705         int left = layer->displayFrame.left;
    706         int right = layer->displayFrame.right;
    707         offsets[noffsets++] = max(0, left);
    708         offsets[noffsets++] = min(right, screen_width);
    709     }
    710     rgz_bsort(offsets, noffsets);
    711     noffsets = rgz_bunique(offsets, noffsets);
    712     hregion->nsubregions = noffsets - 1;
    713     bzero(hregion->blitrects, sizeof(hregion->blitrects));
    714     for (r = 0; r + 1 < noffsets; r++) {
    715         blit_rect_t subregion;
    716         subregion.top = hregion->rect.top;
    717         subregion.bottom = hregion->rect.bottom;
    718         subregion.left = offsets[r];
    719         subregion.right = offsets[r+1];
    720 
    721         ALOGD_IF(debug, "                sub l %d r %d",
    722             subregion.left, subregion.right);
    723         for (l = 0; l < hregion->nlayers; l++) {
    724             hwc_layer_1_t *layer = hregion->rgz_layers[l]->hwc_layer;
    725             if (rgz_hwc_intersects(&subregion, &layer->displayFrame)) {
    726 
    727                 hregion->blitrects[l][r] = subregion;
    728 
    729                 ALOGD_IF(debug, "hregion->blitrects[%d][%d] (%d %d %d %d)", l, r,
    730                         hregion->blitrects[l][r].left,
    731                         hregion->blitrects[l][r].top,
    732                         hregion->blitrects[l][r].right,
    733                         hregion->blitrects[l][r].bottom);
    734             }
    735         }
    736     }
    737 }
    738 
    739 static int rgz_hwc_scaled(hwc_layer_1_t *layer)
    740 {
    741     int w = WIDTH(layer->sourceCrop);
    742     int h = HEIGHT(layer->sourceCrop);
    743 
    744     if (layer->transform & HWC_TRANSFORM_ROT_90)
    745         swap(w, h);
    746 
    747     return WIDTH(layer->displayFrame) != w || HEIGHT(layer->displayFrame) != h;
    748 }
    749 
    750 static int rgz_in_valid_hwc_layer(hwc_layer_1_t *layer)
    751 {
    752     IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
    753     if ((layer->flags & HWC_SKIP_LAYER) || !handle)
    754         return 0;
    755 
    756     if (is_NV12(handle->iFormat))
    757         return handle->iFormat == HAL_PIXEL_FORMAT_TI_NV12;
    758 
    759     /* FIXME: The following must be removed when GC supports vertical/horizontal
    760      * buffer flips, please note having a FLIP_H and FLIP_V means 180 rotation
    761      * which is supported indeed
    762      */
    763     if (layer->transform) {
    764         int is_flipped = !!(layer->transform & HWC_TRANSFORM_FLIP_H) ^ !!(layer->transform & HWC_TRANSFORM_FLIP_V);
    765         if (is_flipped) {
    766             ALOGE("Layer %p is flipped %d", layer, layer->transform);
    767             return 0;
    768         }
    769     }
    770 
    771     switch(handle->iFormat) {
    772     case HAL_PIXEL_FORMAT_BGRX_8888:
    773     case HAL_PIXEL_FORMAT_RGBX_8888:
    774     case HAL_PIXEL_FORMAT_RGB_565:
    775     case HAL_PIXEL_FORMAT_RGBA_8888:
    776     case HAL_PIXEL_FORMAT_BGRA_8888:
    777         break;
    778     default:
    779         return 0;
    780     }
    781     return 1;
    782 }
    783 
    784 /* Reset dirty region data and state */
    785 static void rgz_delete_region_data(rgz_t *rgz){
    786     if (!rgz)
    787         return;
    788     if (rgz->hregions)
    789         free(rgz->hregions);
    790     rgz->hregions = NULL;
    791     rgz->nhregions = 0;
    792     rgz->state &= ~RGZ_REGION_DATA;
    793 }
    794 
    795 static void rgz_handle_dirty_region(rgz_t *rgz, int reset_counters)
    796 {
    797     unsigned int i;
    798     for (i = 0; i < rgz->rgz_layerno; i++) {
    799         rgz_layer_t *rgz_layer = &rgz->rgz_layers[i];
    800         void *new_handle;
    801 
    802         /*
    803          * We don't care about the handle for background and layers with the
    804          * clear fb hint, but we want to maintain a layer state for dirty
    805          * region handling.
    806          */
    807         if (i == 0 || rgz_layer->buffidx == -1)
    808             new_handle = (void*)0x1;
    809         else
    810             new_handle = (void*)rgz_layer->hwc_layer->handle;
    811 
    812         if (reset_counters || new_handle != rgz_layer->dirty_hndl) {
    813             rgz_layer->dirty_count = RGZ_NUM_FB;
    814             rgz_layer->dirty_hndl = new_handle;
    815         } else
    816             rgz_layer->dirty_count -= rgz_layer->dirty_count ? 1 : 0;
    817 
    818     }
    819 }
    820 
    821 static int rgz_in_hwccheck(rgz_in_params_t *p, rgz_t *rgz)
    822 {
    823     hwc_layer_1_t *layers = p->data.hwc.layers;
    824     int layerno = p->data.hwc.layerno;
    825 
    826     rgz->state &= ~RGZ_STATE_INIT;
    827 
    828     if (!layers)
    829         return -1;
    830 
    831     /* For debugging */
    832     //dump_all(layers, layerno, 0);
    833 
    834     /*
    835      * Store buffer index to be sent in the HWC Post2 list. Any overlay
    836      * meminfos must come first
    837      */
    838     int l, memidx = 0;
    839     for (l = 0; l < layerno; l++) {
    840         /*
    841          * Workaround: If a NV12 layer is present in the list, don't even try
    842          * to blit. There is a performance degradation while playing video and
    843          * using GC at the same time.
    844          */
    845         IMG_native_handle_t *handle = (IMG_native_handle_t *)layers[l].handle;
    846         if (!(layers[l].flags & HWC_SKIP_LAYER) && handle && is_NV12(handle->iFormat))
    847             return -1;
    848 
    849         if (layers[l].compositionType == HWC_OVERLAY)
    850             memidx++;
    851     }
    852 
    853     int possible_blit = 0, candidates = 0;
    854 
    855     /*
    856      * Insert the background layer at the beginning of the list, maintain a
    857      * state for dirty region handling
    858      */
    859     rgz_layer_t *rgz_layer = &rgz->rgz_layers[0];
    860     rgz_layer->hwc_layer = &bg_layer;
    861 
    862     for (l = 0; l < layerno; l++) {
    863         if (layers[l].compositionType == HWC_FRAMEBUFFER) {
    864             candidates++;
    865             if (rgz_in_valid_hwc_layer(&layers[l]) &&
    866                     possible_blit < RGZ_INPUT_MAXLAYERS) {
    867                 rgz_layer_t *rgz_layer = &rgz->rgz_layers[possible_blit+1];
    868                 rgz_layer->hwc_layer = &layers[l];
    869                 rgz_layer->buffidx = memidx++;
    870                 possible_blit++;
    871             }
    872             continue;
    873         }
    874 
    875         if (layers[l].hints & HWC_HINT_CLEAR_FB) {
    876             candidates++;
    877             if (possible_blit < RGZ_INPUT_MAXLAYERS) {
    878                 /*
    879                  * Use only the layer rectangle as an input to regionize when the clear
    880                  * fb hint is present, mark this layer to identify it.
    881                  */
    882                 rgz_layer_t *rgz_layer = &rgz->rgz_layers[possible_blit+1];
    883                 rgz_layer->buffidx = -1;
    884                 rgz_layer->hwc_layer = &layers[l];
    885                 possible_blit++;
    886             }
    887         }
    888     }
    889 
    890     if (!possible_blit || possible_blit != candidates) {
    891         return -1;
    892     }
    893 
    894     unsigned int blit_layers = possible_blit + 1; /* Account for background layer */
    895     int reset_dirty_counters = rgz->rgz_layerno != blit_layers ? 1 : 0;
    896     /*
    897      * The layers we are going to blit differ in number from the previous frame,
    898      * we can't trust anymore the region data, calculate it again
    899      */
    900     if (reset_dirty_counters)
    901         rgz_delete_region_data(rgz);
    902 
    903     rgz->state |= RGZ_STATE_INIT;
    904     rgz->rgz_layerno = blit_layers;
    905 
    906     rgz_handle_dirty_region(rgz, reset_dirty_counters);
    907 
    908     return RGZ_ALL;
    909 }
    910 
    911 static int rgz_in_hwc(rgz_in_params_t *p, rgz_t *rgz)
    912 {
    913     int yentries[RGZ_SUBREGIONMAX];
    914     int dispw;  /* widest layer */
    915     int screen_width = p->data.hwc.dstgeom->width;
    916     int screen_height = p->data.hwc.dstgeom->height;
    917 
    918     if (!(rgz->state & RGZ_STATE_INIT)) {
    919         OUTE("rgz_process started with bad state");
    920         return -1;
    921     }
    922 
    923     /* If there is already region data avoid parsing it again */
    924     if (rgz->state & RGZ_REGION_DATA) {
    925         return 0;
    926     }
    927 
    928     int layerno = rgz->rgz_layerno;
    929 
    930     /* Find the horizontal regions */
    931     rgz_layer_t *rgz_layers = rgz->rgz_layers;
    932     int ylen = rgz_hwc_layer_sortbyy(rgz_layers, layerno, yentries, &dispw, screen_height);
    933 
    934     ylen = rgz_bunique(yentries, ylen);
    935 
    936     /* at this point we have an array of horizontal regions */
    937     rgz->nhregions = ylen - 1;
    938 
    939     blit_hregion_t *hregions = calloc(rgz->nhregions, sizeof(blit_hregion_t));
    940     if (!hregions) {
    941         OUTE("Unable to allocate memory for hregions");
    942         return -1;
    943     }
    944     rgz->hregions = hregions;
    945 
    946     ALOGD_IF(debug, "Allocated %d regions (sz = %d), layerno = %d", rgz->nhregions, rgz->nhregions * sizeof(blit_hregion_t), layerno);
    947     int i, j;
    948     for (i = 0; i < rgz->nhregions; i++) {
    949         hregions[i].rect.top = yentries[i];
    950         hregions[i].rect.bottom = yentries[i+1];
    951         /* Avoid hregions outside the display boundaries */
    952         hregions[i].rect.left = 0;
    953         hregions[i].rect.right = dispw > screen_width ? screen_width : dispw;
    954         hregions[i].nlayers = 0;
    955         for (j = 0; j < layerno; j++) {
    956             hwc_layer_1_t *layer = rgz_layers[j].hwc_layer;
    957             if (rgz_hwc_intersects(&hregions[i].rect, &layer->displayFrame)) {
    958                 int l = hregions[i].nlayers++;
    959                 hregions[i].rgz_layers[l] = &rgz_layers[j];
    960             }
    961         }
    962     }
    963 
    964     /* Calculate blit regions */
    965     for (i = 0; i < rgz->nhregions; i++) {
    966         rgz_gen_blitregions(&hregions[i], screen_width);
    967         ALOGD_IF(debug, "hregion %3d: nsubregions %d", i, hregions[i].nsubregions);
    968         ALOGD_IF(debug, "           : %d to %d: ",
    969             hregions[i].rect.top, hregions[i].rect.bottom);
    970         for (j = 0; j < hregions[i].nlayers; j++)
    971             ALOGD_IF(debug, "              %p ", hregions[i].rgz_layers[j]->hwc_layer);
    972     }
    973     rgz->state |= RGZ_REGION_DATA;
    974     return 0;
    975 }
    976 
    977 /*
    978  * generate a human readable description of the layer
    979  *
    980  * idx, flags, fmt, type, sleft, stop, sright, sbot, dleft, dtop, \
    981  * dright, dbot, rot, flip, blending, scalew, scaleh, visrects
    982  *
    983  */
    984 static void rgz_print_layer(hwc_layer_1_t *l, int idx, int csv)
    985 {
    986     char big_log[1024];
    987     int e = sizeof(big_log);
    988     char *end = big_log + e;
    989     e -= snprintf(end - e, e, "<!-- LAYER-DAT: %d", idx);
    990 
    991 
    992     e -= snprintf(end - e, e, "%s %p", csv ? "," : " hndl:",
    993             l->handle ? l->handle : NULL);
    994 
    995     e -= snprintf(end - e, e, "%s %s", csv ? "," : " flags:",
    996         l->flags & HWC_SKIP_LAYER ? "skip" : "none");
    997 
    998     IMG_native_handle_t *handle = (IMG_native_handle_t *)l->handle;
    999     if (handle) {
   1000         e -= snprintf(end - e, e, "%s", csv ? ", " : " fmt: ");
   1001         switch(handle->iFormat) {
   1002         case HAL_PIXEL_FORMAT_BGRA_8888:
   1003             e -= snprintf(end - e, e, "bgra"); break;
   1004         case HAL_PIXEL_FORMAT_RGB_565:
   1005             e -= snprintf(end - e, e, "rgb565"); break;
   1006         case HAL_PIXEL_FORMAT_BGRX_8888:
   1007             e -= snprintf(end - e, e, "bgrx"); break;
   1008         case HAL_PIXEL_FORMAT_RGBX_8888:
   1009             e -= snprintf(end - e, e, "rgbx"); break;
   1010         case HAL_PIXEL_FORMAT_RGBA_8888:
   1011             e -= snprintf(end - e, e, "rgba"); break;
   1012         case HAL_PIXEL_FORMAT_TI_NV12:
   1013         case HAL_PIXEL_FORMAT_TI_NV12_PADDED:
   1014             e -= snprintf(end - e, e, "nv12"); break;
   1015         default:
   1016             e -= snprintf(end - e, e, "unknown");
   1017         }
   1018         e -= snprintf(end - e, e, "%s", csv ? ", " : " type: ");
   1019         if (handle->usage & GRALLOC_USAGE_HW_RENDER)
   1020             e -= snprintf(end - e, e, "hw");
   1021         else if (handle->usage & GRALLOC_USAGE_SW_READ_MASK ||
   1022                  handle->usage & GRALLOC_USAGE_SW_WRITE_MASK)
   1023             e -= snprintf(end - e, e, "sw");
   1024         else
   1025             e -= snprintf(end - e, e, "unknown");
   1026     } else {
   1027         e -= snprintf(end - e, e, csv ? ", unknown" : " fmt: unknown");
   1028         e -= snprintf(end - e, e, csv ? ", na" : " type: na");
   1029     }
   1030     e -= snprintf(end - e, e, csv ? ", %d, %d, %d, %d" : " src: %d %d %d %d",
   1031         l->sourceCrop.left, l->sourceCrop.top, l->sourceCrop.right,
   1032         l->sourceCrop.bottom);
   1033     e -= snprintf(end - e, e, csv ? ", %d, %d, %d, %d" : " disp: %d %d %d %d",
   1034         l->displayFrame.left, l->displayFrame.top,
   1035         l->displayFrame.right, l->displayFrame.bottom);
   1036 
   1037     e -= snprintf(end - e, e, "%s %s", csv ? "," : " rot:",
   1038         l->transform & HWC_TRANSFORM_ROT_90 ? "90" :
   1039             l->transform & HWC_TRANSFORM_ROT_180 ? "180" :
   1040             l->transform & HWC_TRANSFORM_ROT_270 ? "270" : "none");
   1041 
   1042     char flip[5] = "";
   1043     strcat(flip, l->transform & HWC_TRANSFORM_FLIP_H ? "H" : "");
   1044     strcat(flip, l->transform & HWC_TRANSFORM_FLIP_V ? "V" : "");
   1045     if (!(l->transform & (HWC_TRANSFORM_FLIP_V|HWC_TRANSFORM_FLIP_H)))
   1046         strcpy(flip, "none");
   1047     e -= snprintf(end - e, e, "%s %s", csv ? "," : " flip:", flip);
   1048 
   1049     e -= snprintf(end - e, e, "%s %s", csv ? "," : " blending:",
   1050         l->blending == HWC_BLENDING_NONE ? "none" :
   1051         l->blending == HWC_BLENDING_PREMULT ? "premult" :
   1052         l->blending == HWC_BLENDING_COVERAGE ? "coverage" : "invalid");
   1053 
   1054     e -= snprintf(end - e, e, "%s %1.3f", csv ? "," : " scalew:", getscalew(l));
   1055     e -= snprintf(end - e, e, "%s %1.3f", csv ? "," : " scaleh:", getscaleh(l));
   1056 
   1057     e -= snprintf(end - e, e, "%s %d", csv ? "," : " visrect:",
   1058         l->visibleRegionScreen.numRects);
   1059 
   1060     if (!csv) {
   1061         e -= snprintf(end - e, e, " -->");
   1062         OUTP("%s", big_log);
   1063 
   1064         size_t i = 0;
   1065         for (; i < l->visibleRegionScreen.numRects; i++) {
   1066             hwc_rect_t const *r = &l->visibleRegionScreen.rects[i];
   1067             OUTP("<!-- LAYER-VIS: %d: rect: %d %d %d %d -->",
   1068                     i, r->left, r->top, r->right, r->bottom);
   1069         }
   1070     } else {
   1071         size_t i = 0;
   1072         for (; i < l->visibleRegionScreen.numRects; i++) {
   1073             hwc_rect_t const *r = &l->visibleRegionScreen.rects[i];
   1074             e -= snprintf(end - e, e, ", %d, %d, %d, %d",
   1075                     r->left, r->top, r->right, r->bottom);
   1076         }
   1077         e -= snprintf(end - e, e, " -->");
   1078         OUTP("%s", big_log);
   1079     }
   1080 }
   1081 
   1082 static void rgz_print_layers(hwc_display_contents_1_t* list, int csv)
   1083 {
   1084     size_t i;
   1085     for (i = 0; i < list->numHwLayers; i++) {
   1086         hwc_layer_1_t *l = &list->hwLayers[i];
   1087         rgz_print_layer(l, i, csv);
   1088     }
   1089 }
   1090 
   1091 static int hal_to_ocd(int color)
   1092 {
   1093     switch(color) {
   1094     case HAL_PIXEL_FORMAT_BGRA_8888:
   1095         return OCDFMT_BGRA24;
   1096     case HAL_PIXEL_FORMAT_BGRX_8888:
   1097         return OCDFMT_BGR124;
   1098     case HAL_PIXEL_FORMAT_RGB_565:
   1099         return OCDFMT_RGB16;
   1100     case HAL_PIXEL_FORMAT_RGBA_8888:
   1101         return OCDFMT_RGBA24;
   1102     case HAL_PIXEL_FORMAT_RGBX_8888:
   1103         return OCDFMT_RGB124;
   1104     case HAL_PIXEL_FORMAT_TI_NV12:
   1105         return OCDFMT_NV12;
   1106     case HAL_PIXEL_FORMAT_YV12:
   1107         return OCDFMT_YV12;
   1108     default:
   1109         return OCDFMT_UNKNOWN;
   1110     }
   1111 }
   1112 
   1113 /*
   1114  * The loadbltsville fn is only needed for testing, the bltsville shared
   1115  * libraries aren't planned to be used directly in production code here
   1116  */
   1117 static BVFN_MAP bv_map;
   1118 static BVFN_BLT bv_blt;
   1119 static BVFN_UNMAP bv_unmap;
   1120 #ifndef RGZ_TEST_INTEGRATION
   1121 gralloc_module_t const *gralloc;
   1122 #endif
   1123 #define BLTSVILLELIB "libbltsville_cpu.so"
   1124 
   1125 #ifdef RGZ_TEST_INTEGRATION
   1126 static int loadbltsville(void)
   1127 {
   1128     void *hndl = dlopen(BLTSVILLELIB, RTLD_LOCAL | RTLD_LAZY);
   1129     if (!hndl) {
   1130         OUTE("Loading bltsville failed");
   1131         return -1;
   1132     }
   1133     bv_map = (BVFN_MAP)dlsym(hndl, "bv_map");
   1134     bv_blt = (BVFN_BLT)dlsym(hndl, "bv_blt");
   1135     bv_unmap = (BVFN_UNMAP)dlsym(hndl, "bv_unmap");
   1136     if(!bv_blt || !bv_map || !bv_unmap) {
   1137         OUTE("Missing bltsville fn %p %p %p", bv_map, bv_blt, bv_unmap);
   1138         return -1;
   1139     }
   1140     OUTP("Loaded %s", BLTSVILLELIB);
   1141 
   1142 #ifndef RGZ_TEST_INTEGRATION
   1143     hw_module_t const* module;
   1144     int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
   1145     if (err != 0) {
   1146         OUTE("Loading gralloc failed");
   1147         return -1;
   1148     }
   1149     gralloc = (gralloc_module_t const *)module;
   1150 #endif
   1151     return 0;
   1152 }
   1153 #else
   1154 static int loadbltsville(void) {
   1155     return 0;
   1156 }
   1157 #endif
   1158 
   1159 #ifndef RGZ_TEST_INTEGRATION
   1160 static int rgz_handle_to_stride(IMG_native_handle_t *h)
   1161 {
   1162     int bpp = is_NV12(h->iFormat) ? 0 : (h->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4);
   1163     int stride = ALIGN(h->iWidth, HW_ALIGN) * bpp;
   1164     return stride;
   1165 }
   1166 
   1167 #endif
   1168 
   1169 extern void BVDump(const char* prefix, const char* tab, const struct bvbltparams* parms);
   1170 
   1171 static int rgz_get_orientation(unsigned int transform)
   1172 {
   1173     int orientation = 0;
   1174     if ((transform & HWC_TRANSFORM_FLIP_H) && (transform & HWC_TRANSFORM_FLIP_V))
   1175         orientation += 180;
   1176     if (transform & HWC_TRANSFORM_ROT_90)
   1177         orientation += 90;
   1178 
   1179     return orientation;
   1180 }
   1181 
   1182 static int rgz_get_flip_flags(unsigned int transform, int use_src2_flags)
   1183 {
   1184     /*
   1185      * If vertical and horizontal flip flags are set it means a 180 rotation
   1186      * (with no flip) is intended for the layer, so we return 0 in that case.
   1187      */
   1188     int flip_flags = 0;
   1189     if (transform & HWC_TRANSFORM_FLIP_H)
   1190         flip_flags |= (use_src2_flags ? BVFLAG_HORZ_FLIP_SRC2 : BVFLAG_HORZ_FLIP_SRC1);
   1191     if (transform & HWC_TRANSFORM_FLIP_V)
   1192         flip_flags = flip_flags ? 0 : flip_flags | (use_src2_flags ? BVFLAG_VERT_FLIP_SRC2 : BVFLAG_VERT_FLIP_SRC1);
   1193     return flip_flags;
   1194 }
   1195 
   1196 static int rgz_hwc_layer_blit(rgz_out_params_t *params, rgz_layer_t *rgz_layer)
   1197 {
   1198     static int loaded = 0;
   1199     if (!loaded)
   1200         loaded = loadbltsville() ? : 1; /* attempt load once */
   1201 
   1202     hwc_layer_1_t* layer = rgz_layer->hwc_layer;
   1203     blit_rect_t srcregion;
   1204     rgz_get_displayframe_rect(layer, &srcregion);
   1205 
   1206     int noblend = rgz_is_blending_disabled(params);
   1207     if (!noblend && layer->blending == HWC_BLENDING_PREMULT)
   1208         rgz_hwc_subregion_blend(params, &srcregion, rgz_layer, NULL);
   1209     else
   1210         rgz_hwc_subregion_copy(params, &srcregion, rgz_layer);
   1211 
   1212     return 0;
   1213 }
   1214 
   1215 /*
   1216  * Calculate the src rectangle on the basis of the layer display, source crop
   1217  * and subregion rectangles. Additionally any rotation will be taken in
   1218  * account. The resulting rectangle is written in res_rect.
   1219  */
   1220 static void rgz_get_src_rect(hwc_layer_1_t* layer, blit_rect_t *subregion_rect, blit_rect_t *res_rect)
   1221 {
   1222     IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle;
   1223     int res_left = 0;
   1224     int res_top = 0;
   1225     int delta_left;
   1226     int delta_top;
   1227     int res_width;
   1228     int res_height;
   1229 
   1230     /*
   1231      * If the layer is scaled we use the whole cropping rectangle from the
   1232      * source and just move the clipping rectangle for the region we want to
   1233      * blit, this is done to prevent any artifacts when blitting subregions of
   1234      * a scaled layer. If there is a transform, adjust the width and height
   1235      * accordingly to match the rotated buffer geometry.
   1236      */
   1237     if (rgz_hwc_scaled(layer)) {
   1238         delta_top = 0;
   1239         delta_left = 0;
   1240         res_width = WIDTH(layer->sourceCrop);
   1241         res_height = HEIGHT(layer->sourceCrop);
   1242         if (layer->transform & HAL_TRANSFORM_ROT_90)
   1243             swap(res_width , res_height);
   1244     } else {
   1245         delta_top = subregion_rect->top - layer->displayFrame.top;
   1246         delta_left = subregion_rect->left - layer->displayFrame.left;
   1247         res_width = WIDTH(*subregion_rect);
   1248         res_height = HEIGHT(*subregion_rect);
   1249     }
   1250 
   1251     /*
   1252      * Calculate the top, left offset from the source cropping rectangle
   1253      * depending on the rotation
   1254      */
   1255     switch(layer->transform) {
   1256         case 0:
   1257             res_left = layer->sourceCrop.left + delta_left;
   1258             res_top = layer->sourceCrop.top + delta_top;
   1259             break;
   1260         case HAL_TRANSFORM_ROT_90:
   1261             res_left = handle->iHeight - layer->sourceCrop.bottom + delta_left;
   1262             res_top = layer->sourceCrop.left + delta_top;
   1263             break;
   1264         case HAL_TRANSFORM_ROT_180:
   1265             res_left = handle->iWidth - layer->sourceCrop.right + delta_left;
   1266             res_top = handle->iHeight - layer->sourceCrop.bottom + delta_top;
   1267             break;
   1268         case HAL_TRANSFORM_ROT_270:
   1269             res_left = layer->sourceCrop.top + delta_left;
   1270             res_top = handle->iWidth - layer->sourceCrop.right + delta_top;
   1271             break;
   1272         default:
   1273             OUTE("Invalid transform value %d", layer->transform);
   1274     }
   1275 
   1276     /* Resulting rectangle has the subregion dimensions */
   1277     res_rect->left = res_left;
   1278     res_rect->top = res_top;
   1279     res_rect->right = res_left + res_width;
   1280     res_rect->bottom = res_top + res_height;
   1281 }
   1282 
   1283 static void rgz_batch_entry(struct rgz_blt_entry* e, unsigned int flag, unsigned int set)
   1284 {
   1285     e->bp.flags &= ~BVFLAG_BATCH_MASK;
   1286     e->bp.flags |= flag;
   1287     e->bp.batchflags |= set;
   1288 }
   1289 
   1290 static int rgz_hwc_subregion_blit(blit_hregion_t *hregion, int sidx, rgz_out_params_t *params)
   1291 {
   1292     static int loaded = 0;
   1293     if (!loaded)
   1294         loaded = loadbltsville() ? : 1; /* attempt load once */
   1295 
   1296     int lix;
   1297     int ldepth = get_layer_ops(hregion, sidx, &lix);
   1298     if (ldepth == 0) {
   1299         /* Impossible, there are no layers in this region even if the
   1300          * background is covering the whole screen
   1301          */
   1302         OUTE("hregion %p subregion %d doesn't have any ops", hregion, sidx);
   1303         return -1;
   1304     }
   1305 
   1306     /* Determine if this region is dirty */
   1307     int dirty = 0, dirtylix = lix;
   1308     while (dirtylix != -1) {
   1309         rgz_layer_t *rgz_layer = hregion->rgz_layers[dirtylix];
   1310         if (rgz_layer->dirty_count){
   1311             /* One of the layers is dirty, we need to generate blits for this subregion */
   1312             dirty = 1;
   1313             break;
   1314         }
   1315         dirtylix = get_layer_ops_next(hregion, sidx, dirtylix);
   1316     }
   1317 
   1318     if (!dirty)
   1319         return 0;
   1320 
   1321     /* Check if the bottom layer is the background */
   1322     if (hregion->rgz_layers[lix]->hwc_layer == &bg_layer) {
   1323         if (ldepth == 1) {
   1324             /* Background layer is the only operation, clear subregion */
   1325             rgz_out_clrdst(params, &hregion->blitrects[lix][sidx]);
   1326             return 0;
   1327         } else {
   1328             /* No need to generate blits with background layer if there is
   1329              * another layer on top of it, discard it
   1330              */
   1331             ldepth--;
   1332             lix = get_layer_ops_next(hregion, sidx, lix);
   1333         }
   1334     }
   1335 
   1336     /*
   1337      * See if the depth most layer needs to be ignored. If this layer is the
   1338      * only operation, we need to clear this subregion.
   1339      */
   1340     if (hregion->rgz_layers[lix]->buffidx == -1) {
   1341         ldepth--;
   1342         if (!ldepth) {
   1343             rgz_out_clrdst(params, &hregion->blitrects[lix][sidx]);
   1344             return 0;
   1345         }
   1346         lix = get_layer_ops_next(hregion, sidx, lix);
   1347     }
   1348 
   1349     int noblend = rgz_is_blending_disabled(params);
   1350 
   1351     if (!noblend && ldepth > 1) { /* BLEND */
   1352         blit_rect_t *rect = &hregion->blitrects[lix][sidx];
   1353         struct rgz_blt_entry* e;
   1354 
   1355         int s2lix = lix;
   1356         lix = get_layer_ops_next(hregion, sidx, lix);
   1357 
   1358         /*
   1359          * We save a read and a write from the FB if we blend the bottom
   1360          * two layers, we can do this only if both layers are not scaled
   1361          */
   1362         int first_batchflags = 0;
   1363         if (!rgz_hwc_scaled(hregion->rgz_layers[lix]->hwc_layer) &&
   1364             !rgz_hwc_scaled(hregion->rgz_layers[s2lix]->hwc_layer)) {
   1365             e = rgz_hwc_subregion_blend(params, rect, hregion->rgz_layers[lix],
   1366                 hregion->rgz_layers[s2lix]);
   1367             first_batchflags |= BVBATCH_SRC2;
   1368         } else {
   1369             /* Return index to the first operation and make a copy of the first layer */
   1370             lix = s2lix;
   1371             e = rgz_hwc_subregion_copy(params, rect, hregion->rgz_layers[lix]);
   1372             first_batchflags |= BVBATCH_OP | BVBATCH_SRC2;
   1373         }
   1374         rgz_batch_entry(e, BVFLAG_BATCH_BEGIN, 0);
   1375 
   1376         /* Rest of layers blended with FB */
   1377         int first = 1;
   1378         while((lix = get_layer_ops_next(hregion, sidx, lix)) != -1) {
   1379             int batchflags = 0;
   1380             e = rgz_hwc_subregion_blend(params, rect, hregion->rgz_layers[lix], NULL);
   1381             if (first) {
   1382                 first = 0;
   1383                 batchflags |= first_batchflags;
   1384             }
   1385             /*
   1386              * TODO: This will work when scaling is introduced, however we need
   1387              * to think on a better way to optimize this.
   1388              */
   1389             batchflags |= BVBATCH_SRC1 | BVBATCH_SRC1RECT_ORIGIN| BVBATCH_SRC1RECT_SIZE |
   1390                 BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE | BVBATCH_SRC2RECT_ORIGIN |
   1391                 BVBATCH_SRC2RECT_SIZE | BVBATCH_SCALE;
   1392             rgz_batch_entry(e, BVFLAG_BATCH_CONTINUE, batchflags);
   1393         }
   1394 
   1395         if (e->bp.flags & BVFLAG_BATCH_BEGIN)
   1396             rgz_batch_entry(e, 0, 0);
   1397         else
   1398             rgz_batch_entry(e, BVFLAG_BATCH_END, 0);
   1399 
   1400     } else { /* COPY */
   1401         blit_rect_t *rect = &hregion->blitrects[lix][sidx];
   1402         if (noblend)    /* get_layer_ops() doesn't understand this so get the top */
   1403             lix = get_top_rect(hregion, sidx, &rect);
   1404         rgz_hwc_subregion_copy(params, rect, hregion->rgz_layers[lix]);
   1405     }
   1406     return 0;
   1407 }
   1408 
   1409 struct bvbuffdesc gscrndesc = {
   1410     .structsize = sizeof(struct bvbuffdesc), .length = 0,
   1411     .auxptr = MAP_FAILED
   1412 };
   1413 struct bvsurfgeom gscrngeom = {
   1414     .structsize = sizeof(struct bvsurfgeom), .format = OCDFMT_UNKNOWN
   1415 };
   1416 
   1417 static void rgz_blts_init(struct rgz_blts *blts)
   1418 {
   1419     bzero(blts, sizeof(*blts));
   1420 }
   1421 
   1422 static void rgz_blts_free(struct rgz_blts *blts)
   1423 {
   1424     /* TODO ??? maybe we should dynamically allocate this */
   1425     rgz_blts_init(blts);
   1426 }
   1427 
   1428 static struct rgz_blt_entry* rgz_blts_get(struct rgz_blts *blts, rgz_out_params_t *params)
   1429 {
   1430     struct rgz_blt_entry *ne;
   1431     if (blts->idx < RGZ_MAX_BLITS) {
   1432         ne = &blts->bvcmds[blts->idx++];
   1433         if (IS_BVCMD(params))
   1434             params->data.bvc.out_blits++;
   1435     } else {
   1436         OUTE("!!! BIG PROBLEM !!! run out of blit entries");
   1437         ne = &blts->bvcmds[blts->idx - 1]; /* Return last slot */
   1438     }
   1439     return ne;
   1440 }
   1441 
   1442 static int rgz_blts_bvdirect(rgz_t *rgz, struct rgz_blts *blts, rgz_out_params_t *params)
   1443 {
   1444     struct bvbatch *batch = NULL;
   1445     int rv = -1;
   1446     int idx = 0;
   1447 
   1448     while (idx < blts->idx) {
   1449         struct rgz_blt_entry *e = &blts->bvcmds[idx];
   1450         if (e->bp.flags & BVFLAG_BATCH_MASK)
   1451             e->bp.batch = batch;
   1452         rv = bv_blt(&e->bp);
   1453         if (rv) {
   1454             OUTE("BV_BLT failed: %d", rv);
   1455             BVDUMP("bv_blt:", "  ", &e->bp);
   1456             return -1;
   1457         }
   1458         if (e->bp.flags & BVFLAG_BATCH_BEGIN)
   1459             batch = e->bp.batch;
   1460         idx++;
   1461     }
   1462     return rv;
   1463 }
   1464 
   1465 static int rgz_out_region(rgz_t *rgz, rgz_out_params_t *params)
   1466 {
   1467     if (!(rgz->state & RGZ_REGION_DATA)) {
   1468         OUTE("rgz_out_region invoked with bad state");
   1469         return -1;
   1470     }
   1471 
   1472     rgz_blts_init(&blts);
   1473     ALOGD_IF(debug, "rgz_out_region:");
   1474 
   1475     if (IS_BVCMD(params))
   1476         params->data.bvc.out_blits = 0;
   1477 
   1478     int i;
   1479     for (i = 0; i < rgz->nhregions; i++) {
   1480         blit_hregion_t *hregion = &rgz->hregions[i];
   1481         int s;
   1482         ALOGD_IF(debug, "h[%d] nsubregions = %d", i, hregion->nsubregions);
   1483         if (hregion->nlayers == 0) {
   1484             /* Impossible, there are no layers in this region even if the
   1485              * background is covering the whole screen
   1486              */
   1487             OUTE("hregion %p doesn't have any ops", hregion);
   1488             return -1;
   1489         }
   1490         for (s = 0; s < hregion->nsubregions; s++) {
   1491             ALOGD_IF(debug, "h[%d] -> [%d]", i, s);
   1492             if (rgz_hwc_subregion_blit(hregion, s, params))
   1493                 return -1;
   1494         }
   1495     }
   1496 
   1497     int rv = 0;
   1498 
   1499     if (IS_BVCMD(params)) {
   1500         unsigned int j;
   1501         params->data.bvc.out_nhndls = 0;
   1502         /* Begin from index 1 to remove the background layer from the output */
   1503         for (j = 1, i = 0; j < rgz->rgz_layerno; j++) {
   1504             rgz_layer_t *rgz_layer = &rgz->rgz_layers[j];
   1505             /* We don't need the handles for layers marked as -1 */
   1506             if (rgz_layer->buffidx == -1)
   1507                 continue;
   1508             hwc_layer_1_t *layer = rgz_layer->hwc_layer;
   1509             params->data.bvc.out_hndls[i++] = layer->handle;
   1510             params->data.bvc.out_nhndls++;
   1511         }
   1512 
   1513         if (blts.idx > 0) {
   1514             /* Last blit is made sync to act like a fence for the previous async blits */
   1515             struct rgz_blt_entry* e = &blts.bvcmds[blts.idx-1];
   1516             rgz_set_async(e, 0);
   1517         }
   1518 
   1519         /* FIXME: we want to be able to call rgz_blts_free and populate the actual
   1520          * composition data structure ourselves */
   1521         params->data.bvc.cmdp = blts.bvcmds;
   1522         params->data.bvc.cmdlen = blts.idx;
   1523         if (params->data.bvc.out_blits >= RGZ_MAX_BLITS)
   1524             rv = -1;
   1525         //rgz_blts_free(&blts);
   1526     } else {
   1527         rv = rgz_blts_bvdirect(rgz, &blts, params);
   1528         rgz_blts_free(&blts);
   1529     }
   1530 
   1531     return rv;
   1532 }
   1533 
   1534 void rgz_profile_hwc(hwc_display_contents_1_t* list, int dispw, int disph)
   1535 {
   1536     if (!list)  /* A NULL composition list can occur */
   1537         return;
   1538 
   1539 #ifndef RGZ_TEST_INTEGRATION
   1540     static char regiondump2[PROPERTY_VALUE_MAX] = "";
   1541     char regiondump[PROPERTY_VALUE_MAX];
   1542     property_get("debug.2dhwc.region", regiondump, "0");
   1543     int dumpregions = strncmp(regiondump, regiondump2, PROPERTY_VALUE_MAX);
   1544     if (dumpregions)
   1545         strncpy(regiondump2, regiondump, PROPERTY_VALUE_MAX);
   1546     else {
   1547         dumpregions = !strncmp(regiondump, "all", PROPERTY_VALUE_MAX) &&
   1548                       (list->flags & HWC_GEOMETRY_CHANGED);
   1549         static int iteration = 0;
   1550         if (dumpregions)
   1551             sprintf(regiondump, "iteration %d", iteration++);
   1552     }
   1553 
   1554     char dumplayerdata[PROPERTY_VALUE_MAX];
   1555     /* 0 - off, 1 - human readable, 2 - CSV */
   1556     property_get("debug.2dhwc.dumplayers", dumplayerdata, "0");
   1557     int dumplayers = atoi(dumplayerdata);
   1558 #else
   1559     char regiondump[] = "";
   1560     int dumplayers = 1;
   1561     int dumpregions = 0;
   1562 #endif
   1563     if (dumplayers && (list->flags & HWC_GEOMETRY_CHANGED)) {
   1564         OUTP("<!-- BEGUN-LAYER-DUMP: %d -->", list->numHwLayers);
   1565         rgz_print_layers(list, dumplayers == 1 ? 0 : 1);
   1566         OUTP("<!-- ENDED-LAYER-DUMP -->");
   1567     }
   1568 
   1569     if(!dumpregions)
   1570         return;
   1571 
   1572     rgz_t rgz;
   1573     rgz_in_params_t ip = { .data = { .hwc = {
   1574                            .layers = list->hwLayers,
   1575                            .layerno = list->numHwLayers } } };
   1576     ip.op = RGZ_IN_HWCCHK;
   1577     if (rgz_in(&ip, &rgz) == RGZ_ALL) {
   1578         ip.op = RGZ_IN_HWC;
   1579         if (rgz_in(&ip, &rgz) == RGZ_ALL) {
   1580             OUTP("<!-- BEGUN-SVG-DUMP: %s -->", regiondump);
   1581             OUTP("<b>%s</b>", regiondump);
   1582             rgz_out_params_t op = {
   1583                 .op = RGZ_OUT_SVG,
   1584                 .data = {
   1585                     .svg = {
   1586                         .dispw = dispw, .disph = disph,
   1587                         .htmlw = 450, .htmlh = 800
   1588                     }
   1589                 },
   1590             };
   1591             rgz_out(&rgz, &op);
   1592             OUTP("<!-- ENDED-SVG-DUMP -->");
   1593         }
   1594     }
   1595     rgz_release(&rgz);
   1596 }
   1597 
   1598 int rgz_get_screengeometry(int fd, struct bvsurfgeom *geom, int fmt)
   1599 {
   1600     /* Populate Bltsville destination buffer information with framebuffer data */
   1601     struct fb_fix_screeninfo fb_fixinfo;
   1602     struct fb_var_screeninfo fb_varinfo;
   1603 
   1604     ALOGI("Attempting to get framebuffer device info.");
   1605     if(ioctl(fd, FBIOGET_FSCREENINFO, &fb_fixinfo)) {
   1606         OUTE("Error getting fb_fixinfo");
   1607         return -EINVAL;
   1608     }
   1609 
   1610     if(ioctl(fd, FBIOGET_VSCREENINFO, &fb_varinfo)) {
   1611         ALOGE("Error gettting fb_varinfo");
   1612         return -EINVAL;
   1613     }
   1614 
   1615     bzero(&bg_layer, sizeof(bg_layer));
   1616     bg_layer.displayFrame.left = bg_layer.displayFrame.top = 0;
   1617     bg_layer.displayFrame.right = fb_varinfo.xres;
   1618     bg_layer.displayFrame.bottom = fb_varinfo.yres;
   1619 
   1620     bzero(geom, sizeof(*geom));
   1621     geom->structsize = sizeof(*geom);
   1622     geom->width = fb_varinfo.xres;
   1623     geom->height = fb_varinfo.yres;
   1624     geom->virtstride = fb_fixinfo.line_length;
   1625     geom->format = hal_to_ocd(fmt);
   1626     /* Always set to 0, src buffers will contain rotation values as needed */
   1627     geom->orientation = 0;
   1628     return 0;
   1629 }
   1630 
   1631 int rgz_in(rgz_in_params_t *p, rgz_t *rgz)
   1632 {
   1633     int rv = -1;
   1634     switch (p->op) {
   1635     case RGZ_IN_HWC:
   1636         rv = rgz_in_hwccheck(p, rgz);
   1637         if (rv == RGZ_ALL)
   1638             rv = rgz_in_hwc(p, rgz) ? 0 : RGZ_ALL;
   1639         break;
   1640     case RGZ_IN_HWCCHK:
   1641         bzero(rgz, sizeof(rgz_t));
   1642         rv = rgz_in_hwccheck(p, rgz);
   1643         break;
   1644     default:
   1645         return -1;
   1646     }
   1647     return rv;
   1648 }
   1649 
   1650 void rgz_release(rgz_t *rgz)
   1651 {
   1652     if (!rgz)
   1653         return;
   1654     if (rgz->hregions)
   1655         free(rgz->hregions);
   1656     bzero(rgz, sizeof(*rgz));
   1657 }
   1658 
   1659 int rgz_out(rgz_t *rgz, rgz_out_params_t *params)
   1660 {
   1661     switch (params->op) {
   1662     case RGZ_OUT_SVG:
   1663         rgz_out_svg(rgz, params);
   1664         return 0;
   1665     case RGZ_OUT_BVDIRECT_PAINT:
   1666         return rgz_out_bvdirect_paint(rgz, params);
   1667     case RGZ_OUT_BVCMD_PAINT:
   1668         return rgz_out_bvcmd_paint(rgz, params);
   1669     case RGZ_OUT_BVDIRECT_REGION:
   1670     case RGZ_OUT_BVCMD_REGION:
   1671         return rgz_out_region(rgz, params);
   1672     default:
   1673         return -1;
   1674     }
   1675 }
   1676