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