/* XXX duplicate of hwc.c version */
static void dump_layer(hwc_layer_1_t const* l, int iserr)
{
#define FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \
                (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \
                (f) == HAL_PIXEL_FORMAT_RGBX_8888 ? "xBGR32" : \
                (f) == HAL_PIXEL_FORMAT_BGRA_8888 ? "ARGB32" : \
                (f) == HAL_PIXEL_FORMAT_RGBA_8888 ? "ABGR32" : \
                (f) == HAL_PIXEL_FORMAT_RGB_565 ? "RGB565" : "??")

    OUTE("%stype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
            iserr ? ">>  " : "    ",
            l->compositionType, l->flags, l->handle, l->transform, l->blending,
            l->sourceCrop.left,
            l->sourceCrop.top,
            l->sourceCrop.right,
            l->sourceCrop.bottom,
            l->displayFrame.left,
            l->displayFrame.top,
            l->displayFrame.right,
            l->displayFrame.bottom);
    if (l->handle) {
        IMG_native_handle_t *h = (IMG_native_handle_t *)l->handle;
        OUTE("%s%d*%d(%s)",
            iserr ? ">>  " : "    ",
            h->iWidth, h->iHeight, FMT(h->iFormat));
    }
}
static int loadbltsville(void)
{
    void *hndl = dlopen(BLTSVILLELIB, RTLD_LOCAL | RTLD_LAZY);
    if (!hndl) {
        OUTE("Loading bltsville failed");
        return -1;
    }
    bv_map = (BVFN_MAP)dlsym(hndl, "bv_map");
    bv_blt = (BVFN_BLT)dlsym(hndl, "bv_blt");
    bv_unmap = (BVFN_UNMAP)dlsym(hndl, "bv_unmap");
    if(!bv_blt || !bv_map || !bv_unmap) {
        OUTE("Missing bltsville fn %p %p %p", bv_map, bv_blt, bv_unmap);
        return -1;
    }
    OUTP("Loaded %s", BLTSVILLELIB);

#ifndef RGZ_TEST_INTEGRATION
    hw_module_t const* module;
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    if (err != 0) {
        OUTE("Loading gralloc failed");
        return -1;
    }
    gralloc = (gralloc_module_t const *)module;
#endif
    return 0;
}
static int rgz_out_bvcmd_paint(rgz_t *rgz, rgz_out_params_t *params)
{
    int rv = 0;
    unsigned int i;
    (void)rgz;

    rgz_blts_init(&blts);

    if (params->data.bvc.clrdst) {
        rgz_out_clrdst(rgz, params);
    }

    for (i = 0; i < rgz->layerno; i++) {
        hwc_layer_1_t *l = &rgz->layers[i];
        if (l->compositionType != HWC_OVERLAY)
            continue;

        rv = rgz_hwc_layer_blit(l, NULL,
                                params->data.bvc.dstgeom,
                                params->data.bvc.noblend,
                                rgz->layersbuf[i]);
        if (rv) {
            OUTE("bvcmd_paint: error in layer %d: %d", i, rv);
            dump_all(rgz->layers, rgz->layerno, i);
            rgz_blts_free(&blts);
            return rv;
        }
    }

    params->data.bvc.cmdp = blts.bvcmds;
    params->data.bvc.cmdlen = blts.idx;

    //rgz_blts_free(&blts);
    return rv;
}
static int rgz_out_bvdirect_paint(rgz_t *rgz, rgz_out_params_t *params)
{
    int rv = 0;
    unsigned int i;
    (void)rgz;

    rgz_blts_init(&blts);

    for (i = 0; i < rgz->layerno; i++) {
        hwc_layer_1_t *l = &rgz->layers[i];
        if (l->compositionType != HWC_OVERLAY)
            continue;

        rv = rgz_hwc_layer_blit(l, params->data.bv.dstdesc,
                                params->data.bv.dstgeom,
                                params->data.bv.noblend,
				-1);
        if (rv) {
            OUTE("bvdirect_paint: error in layer %d: %d", i, rv);
            dump_all(rgz->layers, rgz->layerno, i);
            rgz_blts_free(&blts);
            return rv;
        }
    }
    rgz_blts_bvdirect(rgz, &blts, params);
    rgz_blts_free(&blts);
    return rv;
}
static void dump_all(hwc_layer_1_t *layers, unsigned int layerno, unsigned int errlayer)
{
    unsigned int i;
    for (i = 0; i < layerno; i++) {
        hwc_layer_1_t *l = &layers[i];
        OUTE("Layer %d", i);
        dump_layer(l, errlayer == i);
    }
}
static struct rgz_blt_entry* rgz_blts_get(struct rgz_blts *blts)
{
    struct rgz_blt_entry *ne;
    if (blts->idx < (RGZ_MAXLAYERS * RGZ_SUBREGIONMAX)) {
        ne = &blts->bvcmds[blts->idx++];
    } else {
        OUTE("!!! BIG PROBLEM !!! run out of blit entries");
        ne = &blts->bvcmds[blts->idx - 1]; /* Return last slot */
    }
    return ne;
}
static void rgz_out_svg(rgz_t *rgz, rgz_out_params_t *params)
{
    if (!rgz || !(rgz->state & RGZ_REGION_DATA)) {
        OUTE("rgz_out_svg invoked with bad state");
        return;
    }
    blit_hregion_t *hregions = rgz->hregions;
    svgout_header(params->data.svg.htmlw, params->data.svg.htmlh,
                  params->data.svg.dispw, params->data.svg.disph);
    int i;
    for (i = 0; i < rgz->nhregions; i++) {

        OUTP("<!-- hregion %d (subcount %d)-->", i, hregions[i].nsubregions);
        svgout_hregion(&hregions[i], params->data.svg.dispw,
                       params->data.svg.disph);
    }
    svgout_footer();
}
static int rgz_blts_bvdirect(rgz_t *rgz, struct rgz_blts *blts, rgz_out_params_t *params)
{
    struct bvbatch *batch = NULL;
    int rv = -1;
    int idx = 0;

    while (idx < blts->idx) {
        struct rgz_blt_entry *e = &blts->bvcmds[idx];
        if (e->bp.flags & BVFLAG_BATCH_MASK)
            e->bp.batch = batch;
        rv = bv_blt(&e->bp);
        if (rv) {
            OUTE("BV_BLT failed: %d", rv);
            BVDUMP("bv_blt:", "  ", &e->bp);
            dump_all(rgz->layers, rgz->layerno, -1);
            return -1;
        }
        if (e->bp.flags & BVFLAG_BATCH_BEGIN)
            batch = e->bp.batch;
        idx++;
    }
    return rv;
}
static int rgz_out_region(rgz_t *rgz, rgz_out_params_t *params, int bvdirect)
{
    if (!(rgz->state & RGZ_REGION_DATA)) {
        OUTE("rgz_out_region invoked with bad state");
        return -1;
    }

    rgz_blts_init(&blts);
    ALOGD_IF(debug, "rgz_out_region:");

    int i;
    for (i = 0; i < rgz->nhregions; i++) {
        struct bvbuffdesc *dstdesc = params->data.bv.dstdesc;
        struct bvsurfgeom *dstgeom = params->data.bv.dstgeom;
        blit_hregion_t *hregion = &rgz->hregions[i];
        int s;
        ALOGD_IF(debug, "h[%d] nsubregions = %d", i, hregion->nsubregions);
        if (hregion->nlayers == 0)
            continue;
        for (s = 0; s < hregion->nsubregions; s++) {
            ALOGD_IF(debug, "h[%d] -> [%d]", i, s);
            rgz_hwc_subregion_blit(hregion, s, dstdesc, dstgeom, params->data.bv.noblend);
        }
    }

    int rv = 0;
    if (bvdirect){
        rv = rgz_blts_bvdirect(rgz, &blts, params);
    } else {
        params->data.bvc.cmdp = blts.bvcmds;
        params->data.bvc.cmdlen = blts.idx;
    }

    //rgz_blts_free(&blts);
    return rv;
}
static int rgz_in_hwc(rgz_in_params_t *p, rgz_t *rgz)
{
    int yentries[RGZ_SUBREGIONMAX];
    int dispw;  /* widest layer */

    if (rgz->state != RGZ_STATE_INIT) {
        OUTE("rgz_process started with bad state");
        return -1;
    }
    int layerno = p->data.hwc.layerno;
    int l;
    for (l = 0; l < layerno; l++) {
        if ((rgz->dirtyhndl[l] != p->data.hwc.layers[l].handle) ||
            (p->data.hwc.flags & HWC_GEOMETRY_CHANGED)) {
            rgz->dirtyhndl[l] = (void*)p->data.hwc.layers[l].handle;
            rgz->dirtyno[l] = RGZ_NUM_FB;
        }
    }
    if (p->data.hwc.flags & HWC_GEOMETRY_CHANGED) {
        for (; l < RGZ_MAXLAYERS; l++) {
            rgz->dirtyhndl[l] = NULL;
            rgz->dirtyno[l] = 0;
        }
    }

    /* Find the horizontal regions */
    hwc_layer_1_t *layers = p->data.hwc.layers;
    int ylen = rgz_hwc_layer_sortbyy(layers, layerno, yentries, &dispw);

    ylen = rgz_bunique(yentries, ylen);

    /* at this point we have an array of horizontal regions */
    rgz->nhregions = ylen - 1;

    blit_hregion_t *hregions = calloc(rgz->nhregions, sizeof(blit_hregion_t));
    if (!hregions)
        return -1;
    rgz->hregions = hregions;

    ALOGD_IF(debug, "Allocated %d regions (sz = %d), layerno = %d", rgz->nhregions, rgz->nhregions * sizeof(blit_hregion_t), layerno);
    int i, j;
    for (i = 0; i < rgz->nhregions; i++) {
        hregions[i].rect.top = yentries[i];
        hregions[i].rect.bottom = yentries[i+1];
        hregions[i].rect.left = 0;
        hregions[i].rect.right = dispw;
        hregions[i].nlayers = 0;
        for (j = 0; j < layerno; j++) {
            if (rgz_hwc_intersects(&hregions[i].rect, &layers[j].displayFrame)) {
                int l = hregions[i].nlayers++;
                hregions[i].layers[l] = &layers[j];
            }
        }
    }

    /* Calculate blit regions */
    for (i = 0; i < rgz->nhregions; i++) {
        rgz_gen_blitregions(&hregions[i]);
        ALOGD_IF(debug, "hregion %3d: nsubregions %d", i, hregions[i].nsubregions);
        ALOGD_IF(debug, "           : %d to %d: ",
            hregions[i].rect.top, hregions[i].rect.bottom);
        for (j = 0; j < hregions[i].nlayers; j++)
            ALOGD_IF(debug, "              %p ", hregions[i].layers[j]);
    }
    rgz->state |= RGZ_REGION_DATA;
    return 0;
}
void
makeSquareGrid(int dim1, int dim2, int connect_corners, int partial, edgefn ef)
{
    int i, j, tl, hd;

    for (i = 0; i < dim1; i++)
	for (j = 0; j < dim2; j++) {
	    // write the neighbors of the node i*dim2+j+1
	    tl = i * dim2 + j + 1;
	    if (j > 0
		&& (!partial || j <= 2 * dim2 / 6 || j > 4 * dim2 / 6
		    || i <= 2 * dim1 / 6 || i > 4 * dim1 / 6)) {
		OUTE(i * dim2 + j);
	    }
	    if (j < dim2 - 1
		&& (!partial || j < 2 * dim2 / 6 || j >= 4 * dim2 / 6
		    || i <= 2 * dim1 / 6 || i > 4 * dim1 / 6)) {
		OUTE(i * dim2 + j + 2);
	    }
	    if (i > 0) {
		OUTE((i - 1) * dim2 + j + 1);
	    }
	    if (i < dim1 - 1) {
		OUTE((i + 1) * dim2 + j + 1);
	    }
	    if (connect_corners == 1) {
		if (i == 0 && j == 0) {	// upper left
		    OUTE((dim1 - 1) * dim2 + dim2);
		} else if (i == (dim1 - 1) && j == 0) {	// lower left
		    OUTE(dim2);
		} else if (i == 0 && j == (dim2 - 1)) {	// upper right
		    OUTE((dim1 - 1) * dim2 + 1);
		} else if (i == (dim1 - 1) && j == (dim2 - 1)) {	// lower right
		    OUTE(1);
		}
	    } else if (connect_corners == 2) {
		if (i == 0 && j == 0) {	// upper left
		    OUTE(dim2);
		} else if (i == (dim1 - 1) && j == 0) {	// lower left
		    OUTE((dim1 - 1) * dim2 + dim2);
		} else if (i == 0 && j == (dim2 - 1)) {	// upper right
		    OUTE(1);
		} else if (i == (dim1 - 1) && j == (dim2 - 1)) {	// lower right
		    OUTE((dim1 - 1) * dim2 + 1);
		}
	    }
	}
}