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