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