• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
svgout_header(int htmlw,int htmlh,int coordw,int coordh)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 
svgout_footer(void)122 static void svgout_footer(void)
123 {
124     OUTP("</svg>");
125 }
126 
svgout_rect(blit_rect_t * r,char * color,char * text)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 
empty_rect(blit_rect_t * r)141 static int empty_rect(blit_rect_t *r)
142 {
143     return !r->left && !r->top && !r->right && !r->bottom;
144 }
145 
get_top_rect(blit_hregion_t * hregion,int subregion,blit_rect_t ** routp)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  */
get_layer_ops(blit_hregion_t * hregion,int subregion,int * bottom)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 
get_layer_ops_next(blit_hregion_t * hregion,int subregion,int l)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 
svgout_intersects_display(blit_rect_t * a,int dispw,int disph)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 
svgout_hregion(blit_hregion_t * hregion,int dispw,int disph)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 
rgz_out_svg(rgz_t * rgz,rgz_out_params_t * params)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 */
dump_layer(hwc_layer_1_t const * l,int iserr)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 
dump_all(rgz_layer_t * rgz_layers,unsigned int layerno,unsigned int errlayer)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 
rgz_out_bvdirect_paint(rgz_t * rgz,rgz_out_params_t * params)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 
rgz_set_async(struct rgz_blt_entry * e,int async)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 
rgz_get_screen_info(rgz_out_params_t * params,struct bvsurfgeom ** screen_geom)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 
rgz_is_blending_disabled(rgz_out_params_t * params)303 static int rgz_is_blending_disabled(rgz_out_params_t *params)
304 {
305     return params->data.bvc.noblend;
306 }
307 
rgz_get_displayframe_rect(hwc_layer_1_t * layer,blit_rect_t * res_rect)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 
rgz_set_dst_data(rgz_out_params_t * params,blit_rect_t * subregion_rect,struct rgz_blt_entry * e)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 
rgz_set_src_data(rgz_out_params_t * params,rgz_layer_t * rgz_layer,blit_rect_t * subregion_rect,struct rgz_blt_entry * e,int is_src2)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  */
rgz_set_clip_rect(rgz_out_params_t * params,blit_rect_t * subregion_rect,struct rgz_blt_entry * e)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  */
rgz_set_src2_is_dst(rgz_out_params_t * params,struct rgz_blt_entry * e)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  */
rgz_cfg_scale_mode(struct rgz_blt_entry * e,hwc_layer_1_t * layer)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  */
rgz_hwc_subregion_copy(rgz_out_params_t * params,blit_rect_t * subregion_rect,rgz_layer_t * rgz_src1)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  */
rgz_hwc_subregion_blend(rgz_out_params_t * params,blit_rect_t * subregion_rect,rgz_layer_t * rgz_src1,rgz_layer_t * rgz_src2)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  */
rgz_out_clrdst(rgz_out_params_t * params,blit_rect_t * rect)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 
rgz_out_bvcmd_paint(rgz_t * rgz,rgz_out_params_t * params)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 
getscalew(hwc_layer_1_t * layer)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 
getscaleh(hwc_layer_1_t * layer)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 
rgz_bswap(int * a,int * b)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  */
rgz_bsort(int * a,int len)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  */
rgz_bunique(int * a,int len)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 
rgz_hwc_layer_sortbyy(rgz_layer_t * ra,int rsz,int * out,int * width,int screen_height)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 
rgz_hwc_intersects(blit_rect_t * a,hwc_rect_t * b)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 
rgz_gen_blitregions(blit_hregion_t * hregion,int screen_width)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 
rgz_hwc_scaled(hwc_layer_1_t * layer)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 
rgz_in_valid_hwc_layer(hwc_layer_1_t * layer)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 */
rgz_delete_region_data(rgz_t * rgz)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 
rgz_handle_dirty_region(rgz_t * rgz,int reset_counters)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 
rgz_in_hwccheck(rgz_in_params_t * p,rgz_t * rgz)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 
rgz_in_hwc(rgz_in_params_t * p,rgz_t * rgz)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  */
rgz_print_layer(hwc_layer_1_t * l,int idx,int csv)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 
rgz_print_layers(hwc_display_contents_1_t * list,int csv)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 
hal_to_ocd(int color)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
loadbltsville(void)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
loadbltsville(void)1154 static int loadbltsville(void) {
1155     return 0;
1156 }
1157 #endif
1158 
1159 #ifndef RGZ_TEST_INTEGRATION
rgz_handle_to_stride(IMG_native_handle_t * h)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 
rgz_get_orientation(unsigned int transform)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 
rgz_get_flip_flags(unsigned int transform,int use_src2_flags)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 
rgz_hwc_layer_blit(rgz_out_params_t * params,rgz_layer_t * rgz_layer)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  */
rgz_get_src_rect(hwc_layer_1_t * layer,blit_rect_t * subregion_rect,blit_rect_t * res_rect)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 
rgz_batch_entry(struct rgz_blt_entry * e,unsigned int flag,unsigned int set)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 
rgz_hwc_subregion_blit(blit_hregion_t * hregion,int sidx,rgz_out_params_t * params)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 
rgz_blts_init(struct rgz_blts * blts)1417 static void rgz_blts_init(struct rgz_blts *blts)
1418 {
1419     bzero(blts, sizeof(*blts));
1420 }
1421 
rgz_blts_free(struct rgz_blts * blts)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 
rgz_blts_get(struct rgz_blts * blts,rgz_out_params_t * params)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 
rgz_blts_bvdirect(rgz_t * rgz,struct rgz_blts * blts,rgz_out_params_t * params)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 
rgz_out_region(rgz_t * rgz,rgz_out_params_t * params)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 
rgz_profile_hwc(hwc_display_contents_1_t * list,int dispw,int disph)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 
rgz_get_screengeometry(int fd,struct bvsurfgeom * geom,int fmt)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 
rgz_in(rgz_in_params_t * p,rgz_t * rgz)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 
rgz_release(rgz_t * rgz)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 
rgz_out(rgz_t * rgz,rgz_out_params_t * params)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