blob: 6904efceea48cae7896d8051bdc67aa1dc4ee2cf [file] [log] [blame]
Naseer Ahmed58780b92013-07-29 17:41:40 -04001/*
Zohaib Alam1bb65612013-09-28 03:38:20 -04002 * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation. nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. INNO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER INCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING INANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
Naseer Ahmed58780b92013-07-29 17:41:40 -040029
30#include <dlfcn.h>
31#include "hwc_vpuclient.h"
Naseer Ahmed4957c522013-11-12 18:07:15 -050032#include <binder/Parcel.h>
Zohaib Alam1bb65612013-09-28 03:38:20 -040033#include "hwc_fbupdate.h"
34#include <vpu/vpu.h>
Naseer Ahmed58780b92013-07-29 17:41:40 -040035
36using namespace vpu;
Naseer Ahmed4957c522013-11-12 18:07:15 -050037using namespace android;
Zohaib Alam1bb65612013-09-28 03:38:20 -040038using namespace overlay::utils;
39namespace ovutils = overlay::utils;
40
Naseer Ahmed58780b92013-07-29 17:41:40 -040041namespace qhwc {
42
Zohaib Alam1bb65612013-09-28 03:38:20 -040043VPUClient::VPUClient(hwc_context_t *ctx)
Naseer Ahmed58780b92013-07-29 17:41:40 -040044{
45 mVPULib = dlopen("libvpu.so", RTLD_NOW);
Zohaib Alam1bb65612013-09-28 03:38:20 -040046 VPU* (*getObject)();
47
48 mVPU = NULL;
49 if (mVPULib == NULL) {
50 ALOGE("%s: Cannot open libvpu.so object", __FUNCTION__);
51 return;
52 }
53
54 *(void **) &getObject = dlsym(mVPULib, "getObject");
55 if (getObject) {
56 mVPU = getObject();
57 ALOGI("Initializing VPU client..");
58
59 // calling vpu init
60 if (mVPU->init() == NO_ERROR) {
61 // passing display attributes to libvpu
62 ALOGD_IF(isDebug(), "%s: VFM init successful!", __FUNCTION__);
63
64 DispAttr_t attr;
65 attr.width = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
66 attr.height = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
67 attr.fp100s = (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period) ?
68 1000000000/(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period/100):0;
69 mVPU->setDisplayAttr((DISPLAY_ID)HWC_DISPLAY_PRIMARY, attr);
70
71 ALOGD_IF(isDebug(),"%s: Display attr: width:%d height:%d fp100s:%d",
72 __FUNCTION__, attr.width, attr.height, attr.fp100s);
73
74 // memsetting the pipe structure to 0
75 memset(mProp, 0, sizeof(mProp));
76
77 mDebugLogs = 0;
78 // enable logs
79 char property[PROPERTY_VALUE_MAX];
80 if ( property_get("debug.vpuclient.logs", property, NULL) > 0 )
81 mDebugLogs = atoi(property);
82
83 // allocating memory for LayerList
84 for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; ++i)
85 vList[i] = (LayerList*) malloc(sizeof(LayerList));
86 }
87 else {
88 ALOGE("Error: VPU init failed!");
89 mVPU = NULL;
90 }
91 }
Naseer Ahmed58780b92013-07-29 17:41:40 -040092}
93
94VPUClient::~VPUClient()
95{
Zohaib Alam1bb65612013-09-28 03:38:20 -040096 // freeing LayerList
97 for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; ++i) {
98 if (vList[i])
99 free(vList[i]);
100 }
101
Naseer Ahmed58780b92013-07-29 17:41:40 -0400102 void (*destroy) (VPU*);
103 *(void **) &destroy = dlsym(mVPULib, "deleteObject");
104 dlclose(mVPULib);
105}
106
Zohaib Alam1bb65612013-09-28 03:38:20 -0400107void setLayer(hwc_layer_1_t *layer, Layer *vLayer)
Naseer Ahmed58780b92013-07-29 17:41:40 -0400108{
Zohaib Alam1bb65612013-09-28 03:38:20 -0400109 // setting handle info in vLayer
110 vLayer->handle = (private_handle_t *)(layer->handle);
111
112 if (vLayer->handle) {
113 vLayer->srcStride.width = getWidth(vLayer->handle);
114 vLayer->srcStride.height = getHeight(vLayer->handle);
115 }
116
117 // setting source crop
118 hwc_rect_t sourceRect = integerizeSourceCrop(layer->sourceCropf);
119 vLayer->srcRect.left = sourceRect.left;
120 vLayer->srcRect.top = sourceRect.top;
121 vLayer->srcRect.right = sourceRect.right;
122 vLayer->srcRect.bottom = sourceRect.bottom;
123
124 // setting destination crop
125 vLayer->tgtRect.left = layer->displayFrame.left;
126 vLayer->tgtRect.top = layer->displayFrame.top;
127 vLayer->tgtRect.right = layer->displayFrame.right;
128 vLayer->tgtRect.bottom = layer->displayFrame.bottom;
129
130 if (layer->flags & HWC_GEOMETRY_CHANGED)
131 vLayer->inFlags |= GEOMETRY_CHANGED;
132
133 vLayer->acquireFenceFd = layer->acquireFenceFd;
134
135 if (layer->compositionType == HWC_FRAMEBUFFER_TARGET || isSkipLayer(layer))
136 vLayer->inFlags |= SKIP_LAYER;
Naseer Ahmed58780b92013-07-29 17:41:40 -0400137}
138
Zohaib Alam1bb65612013-09-28 03:38:20 -0400139int VPUClient::setupVpuSession(hwc_context_t *ctx, int display,
140 hwc_display_contents_1_t* list)
141{
142 memset(vList[display], 0, sizeof(LayerList));
143 memset(mProp, 0, sizeof(mProp));
144 mNumVpuLayers = 0;
145
146 // setting up the layer
147 LayerList *vpuList = vList[display];
148 vpuList->numLayers = list->numHwLayers;
149 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
150 hwc_layer_1_t *layer = &list->hwLayers[i];
151 Layer *vLayer = &vpuList->layers[i];
152 VpuLayerProp* prop = &mProp[display][i];
153
154 // Storing the sourceCropf, as it's going to be changed for overlay Set
155 // will be restored after overlay set in prepare.
156 prop->sourceCropf = layer->sourceCropf;
157
158 // filling up the vpu list
159 setLayer(layer, vLayer);
160 ALOGD_IF(isDebug2(), "%s:Done setting lyr:%d for VFM", __FUNCTION__, i);
161 }
162
163 if (mVPU->setupVpuSession((DISPLAY_ID)display, vpuList) != NO_ERROR) {
164 //error in vpu prepare
165 ALOGE("%s: ERROR in VPU::setupVpuSession", __FUNCTION__);
166 return -1;
167 }
168 ALOGD_IF(isDebug2(), "%s: Done VFM: setupVpuSession", __FUNCTION__);
169
170 mGpuFallback = true;
171 LayerProp *layerProp = ctx->layerProp[display];
172 // check if the pipeID is already set for this layer, then will need to
173 // ensure that it is reserved in overlay
174 for (unsigned int i=0; i<(vpuList->numLayers); ++i) {
175 hwc_layer_1_t *layer = &list->hwLayers[i];
176 Layer *vLayer = &vpuList->layers[i];
177 VpuLayerProp* prop = &mProp[display][i];
178
179 if (vLayer->outFlags & VPU_LAYER) {
180 ALOGD_IF(isDebug(), "%s: VPU supported layer:%d", __FUNCTION__, i);
181
182 mNumVpuLayers++;
183 mGpuFallback = false;
184 // Reserving the pipe used in last iteration for the same layer
185 if ((vLayer->outFlags & RESERVE_PREV_PIPES) &&
186 vLayer->sDestPipes.numPipes > 0) {
187 prop->pipeCount = vLayer->sDestPipes.numPipes;
188 if (prop->pipeCount == 1) {
189 setPipeId(prop, vLayer->sDestPipes.pipe[0]);
190 ALOGD_IF(isDebug(), "%s: VPU: Reserved pipe:%d",
191 __FUNCTION__, prop->pipeID[0]);
192 }
193 else if (prop->pipeCount == 2) {
194 setPipeId(prop, vLayer->sDestPipes.pipe[0],
195 vLayer->sDestPipes.pipe[1]);
196 ALOGD_IF(isDebug(), "%s: VPU: Reserved lpipe:%d, rpipe:%d",
197 __FUNCTION__, prop->pipeID[0], prop->pipeID[1]);
198 }
199 else {
200 ALOGE("%s: Invalid pipeCount for resevation", __FUNCTION__);
201 }
202 }
203 else {
204 ALOGD_IF(isDebug(), "%s: 1st vid frame for VPU", __FUNCTION__);
205 prop->firstBuffer = true;
206 }
207
208 // marking the layer pipes for vpu.
209 prop->vpuLayer = true;
210 prop->layer = layer;
211 layer->flags |= HWC_VPU_PIPE;
212
213 // getting image width and height
214 prop->width = layer->displayFrame.right - layer->displayFrame.left;
215 prop->height = layer->displayFrame.bottom - layer->displayFrame.top;
216
217 //setting source crop = dest crop (only for layers drawn by vpu,
218 // since we know it will be scaled up/down by vpu)
219 layer->sourceCropf.left = 0.0;
220 layer->sourceCropf.top = 0.0;
221 layer->sourceCropf.right = (float) prop->width;
222 layer->sourceCropf.bottom = (float) prop->height;
223
224 // setting the flag so that mdpComp wont recognize it as the MDPCOMP
225 layerProp[i].mFlags |= HWC_VPUCOMP;
226
227 // TODO: need to get the proper solution for color fill
228
229 // storing locally the vpu supported format from VFM
230 prop->format = vLayer->vpuOutPixFmt;
231 ALOGD_IF(isDebug(), "%s: MDP: sourceCropf: w:%d h:%d format:%d",
232 __FUNCTION__, prop->width, prop->height, prop->format);
233 }
234 }
235 return 0;
236}
237
238bool VPUClient::allocResLayerPipes(hwc_context_t* ctx, int dpy,
239 hwc_display_contents_1_t* list)
240{
241 overlay::Overlay& ov = *ctx->mOverlay;
242 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
243 int pipeid = -1;
244 VpuLayerProp* prop = &mProp[dpy][i];
245
246 // checking if there is already a reserved pipe for this layer
247 // then use the same allocated pipe for this layer
248 getPipeId(prop, pipeid);
249
250 if (pipeid != -1) {
251 // there is a reserved pipe for this layer.
252 ovutils::eDest dest = ov.reservePipe(pipeid);
253 if (dest == ovutils::OV_INVALID) {
254 ALOGE("%s: Unable to get reserved pipe: layer#%d",
255 __FUNCTION__, i);
256 return false;
257 }
258
259 // setting dest locally
260 setDest(prop, dest);
261 ALOGD_IF(isDebug(), "%s: Reserving pipe:%d, dest:%d ", __FUNCTION__,
262 pipeid, dest);
263 }
264 else {
265 ALOGD_IF(isDebug2(), "%s: No reserved pipe for layer:%d",
266 __FUNCTION__, i);
267 }
268 }
269 return true;
270}
271
272bool VPUClient::allocLayerPipes(hwc_context_t* ctx, int dpy,
273 hwc_display_contents_1_t* list)
274{
275 // checking if the pipes are reserved for any layer,
276 // if yes, then updating the index of the pipes
277 if (!allocResLayerPipes(ctx, dpy, list)) {
278 ALOGE("%s: Reserved pipe alloc failed", __FUNCTION__);
279 return false;
280 }
281
282 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
283 hwc_layer_1_t* layer = &list->hwLayers[i];
284 private_handle_t *hnd = (private_handle_t *)layer->handle;
285 VpuLayerProp* prop = &mProp[dpy][i];
286 int pipe = -1;
287 overlay::Overlay& ov = *ctx->mOverlay;
288
289 // only care about the layers supported by VPU
290 if (!prop->vpuLayer)
291 continue;
292
293 // continue if this layer has reserved pipe
294 getPipeId(prop, pipe);
295 if (pipe != -1)
296 continue;
297
298 ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
299 overlay::Overlay::MIXER_DEFAULT);
300 if (dest == ovutils::OV_INVALID) {
301 ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
302 return false;
303 }
304
305 // setting dest locally
306 setDest(prop, dest);
307 ALOGD_IF(isDebug(), "%s: Newly allocated pipe_dest:%d", __FUNCTION__,
308 dest);
309 }
310 return true;
311}
312
313bool VPUClient::allocResLayerPipesSplit(hwc_context_t* ctx, int dpy,
314 hwc_display_contents_1_t* list)
315{
316 overlay::Overlay& ov = *ctx->mOverlay;
317 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
318 int lpipeid = -1;
319 int rpipeid = -1;
320 VpuLayerProp* prop = &mProp[dpy][i];
321
322 // checking if there is already a reserved pipe for this layer
323 // then use the same allocated pipe for this layer
324 getPipeId(prop, lpipeid, rpipeid);
325
326 if (lpipeid != -1 && rpipeid != -1) {
327 ovutils::eDest ldest = ov.reservePipe(lpipeid);
328 if (ldest == ovutils::OV_INVALID) {
329 ALOGD_IF(isDebug(), "%s: Unable to get reserved pipe-lsplit: "
330 "layer#%d", __FUNCTION__, i);
331 return false;
332 }
333
334 ovutils::eDest rdest = ov.reservePipe(rpipeid);
335 if (rdest == ovutils::OV_INVALID) {
336 ALOGD_IF(isDebug(), "%s: Unable to get reserved pipe-rsplit: "
337 "layer#%d", __FUNCTION__, i);
338 return false;
339 }
340
341 setDest(prop, ldest, rdest);
342 ALOGD_IF(isDebug(), "%s: Reserve lpipe:%d, ldest:%d, rpipe:%d, "
343 "rdest:%d", __FUNCTION__, lpipeid, ldest, rpipeid, rdest);
344 }
345 else if (lpipeid != -1 || rpipeid != -1) {
346 ALOGE("%s: Bug: only one pipe reserved!", __FUNCTION__);
347 return false;
348 }
349 }
350 return true;
351}
352
353bool VPUClient::allocLayerPipesSplit(hwc_context_t* ctx, int dpy,
354 hwc_display_contents_1_t* list)
355{
356 // checking if the pipes are reserved for any layer,
357 // if yes, then updating the index of the pipes
358 if (!allocResLayerPipesSplit(ctx, dpy, list)) {
359 ALOGE("%s: Reserved pipe alloc failed", __FUNCTION__);
360 return false;
361 }
362
363 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
364 hwc_layer_1_t* layer = &list->hwLayers[i];
365 private_handle_t *hnd = (private_handle_t *)layer->handle;
366 VpuLayerProp* prop = &mProp[dpy][i];
367 int lpipe, rpipe;
368 overlay::Overlay& ov = *ctx->mOverlay;
369
370 // only care about the layers supported by VPU
371 if (!prop->vpuLayer)
372 continue;
373
374 // only care about the layers supported by VPU
375 getPipeId(prop, lpipe, rpipe);
376 if (lpipe != -1 && rpipe != -1)
377 continue;
378
379 ovutils::eDest ldest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
380 overlay::Overlay::MIXER_LEFT);
381 if (ldest == ovutils::OV_INVALID) {
382 ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
383 return false;
384 }
385
386 ovutils::eDest rdest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
387 overlay::Overlay::MIXER_RIGHT);
388 if (rdest == ovutils::OV_INVALID) {
389 ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
390 return false;
391 }
392
393 // setting dests locally
394 setDest(prop, ldest, rdest);
395 ALOGD_IF(isDebug(), "%s: Newly allocated ldest:%d rdest:%d",
396 __FUNCTION__, ldest, rdest);
397 }
398 return true;
399}
400
401bool VPUClient::configureLayers(hwc_context_t* ctx, int dpy,
402 hwc_display_contents_1_t* list)
403{
404 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
405 VpuLayerProp* prop = &mProp[dpy][i];
406 hwc_layer_1_t* layer = &list->hwLayers[i];
407
408 if (!prop->vpuLayer)
409 continue;
410
411 eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
412 eZorder zOrder = static_cast<eZorder>(i);
413 eIsFg isFg = IS_FG_OFF;
414 setPipeCount(prop, 1);
415 eDest dest = (eDest) getDest(prop, 0);
416
417 ALOGD_IF(isDebug(),"%s: configuring: layer:%p z_order:%d dest_pipe:%d",
418 __FUNCTION__, layer, zOrder, dest);
419
420 if (configureNonSplit(ctx, layer, dpy, mdpFlags, zOrder, isFg,
421 dest, NULL)) {
422 ALOGE("%s: Failed to configure overlay for layer %d",
423 __FUNCTION__, i);
424 return false;
425 }
426 ALOGD_IF(isDebug2(), "%s: layer:%d configured!", __FUNCTION__, i);
427
428 // Pipe is successfully allocated for this layer; retrieving it from
429 // overlay
430 int pipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 0));
431 setPipeId(prop, pipeId);
432
433 ALOGD_IF(isDebug(), "%s: allocated pipe:%d layer:%d", __FUNCTION__,
434 pipeId, i);
435 }
436 return true;
437}
438
439bool VPUClient::configureLayersSplit(hwc_context_t* ctx, int dpy,
440 hwc_display_contents_1_t* list)
441{
442 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
443 VpuLayerProp* prop = &mProp[dpy][i];
444 hwc_layer_1_t* layer = &list->hwLayers[i];
445
446 if (!prop->vpuLayer)
447 continue;
448
449 eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
450 eZorder zOrder = static_cast<eZorder>(i);
451 eIsFg isFg = IS_FG_OFF;
452 setPipeCount(prop, 2);
453 eDest ldest = (eDest) getDest(prop, 0);
454 eDest rdest = (eDest) getDest(prop, 1);
455
456 ALOGD_IF(isDebug(),"%s: configuring: layer:%p z_order:%d dest_pipeL:%d"
457 "dest_pipeR:%d",__FUNCTION__, layer, zOrder, ldest, rdest);
458
459 if (configureSplit(ctx, layer, dpy, mdpFlags, zOrder, isFg, ldest,
460 rdest, NULL)) {
461 ALOGE("%s: Failed to configure overlay for layer %d",
462 __FUNCTION__, i);
463 return false;
464 }
465 ALOGD_IF(isDebug2(), "%s: layer:%d configured!", __FUNCTION__, i);
466
467 // Pipe is successfully allocated for this layer; retrieving it from
468 // overlay
469 int lpipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 0));
470 int rpipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 1));
471 setPipeId(prop, lpipeId, rpipeId);
472
473 ALOGD_IF(isDebug(), "%s: allocated l-pipe:%d - r-pipe:%d for layer:%d",
474 __FUNCTION__, lpipeId, rpipeId, i);
475 }
476 return true;
477}
478
479void VPUClient::setMDPCompLayerFlags(hwc_context_t *ctx, int dpy,
480 hwc_display_contents_1_t* list)
481{
482 LayerProp *layerProp = ctx->layerProp[dpy];
483
484 // disableGpu only disables gpu for video layer. The expected behavior is to
485 // show a blank screen in case VPU doesnt support a video layer, and gpu
486 // fallback is disabled by the user.
487 bool disableGpu = false;
488 char property[PROPERTY_VALUE_MAX];
489 if ((property_get("persist.hwc.noGpuFallback", property, NULL) > 0) &&
490 (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
491 (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
492 ALOGD_IF(isDebug(), "%s: GPU fallback is disabled through prop",
493 __FUNCTION__);
494 disableGpu = true;
495 }
496
497 // no layers are supported by vpu
498 if (mGpuFallback && !disableGpu) {
499 ALOGD_IF(isDebug(), "%s: No VPU supported layers - Falling back to GPU",
500 __FUNCTION__);
501 return;
502 }
503
504 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
505 hwc_layer_1_t* layer = &(list->hwLayers[i]);
506 VpuLayerProp* prop = &mProp[dpy][i];
507 private_handle_t *hnd = (private_handle_t *)layer->handle;
508
509 // mark vpu layers as HWC_OVERLAY, and those video layers that
510 // are not supported by vpu and gpu fallback is disabled by the
511 // user.
512 if (prop->vpuLayer || (isYuvBuffer(hnd) && disableGpu)) {
513 layer->compositionType = HWC_OVERLAY;
514 layer->hints |= HWC_HINT_CLEAR_FB;
515 ALOGD_IF(isDebug(), "%s: Marking layer:%d as overlay",
516 __FUNCTION__, i);
517 }
518 }
519}
520
521int VPUClient::prepare(hwc_context_t *ctx, int display,
522 hwc_display_contents_1_t* list)
523{
524 if (!mVPU) {
525 return -1;
526 }
527
528 const int numLayers = ctx->listStats[display].numAppLayers;
529 //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
530 //do not cache the information for next draw cycle.
531 if (numLayers > MAX_NUM_APP_LAYERS) {
532 ALOGE("%s: Number of App layers exceeded the limit ",__FUNCTION__);
533 return -1;
534 }
535
536 if (setupVpuSession(ctx, display, list)) {
537 ALOGD_IF(isDebug(), "%s: Vpu session setup failed! ",__FUNCTION__);
538 return -1;
539 }
540
541 LayerProp *layerProp = ctx->layerProp[display];
542 bool isSplit = isDisplaySplit(ctx, display);
543 ALOGD_IF(isDebug2(), "%s: Split Pipe:%d ", __FUNCTION__,
544 isSplit ? 1 : 0);
545
546 // setting up the layer
547 LayerList *vpuList = vList[display];
548 vpuList->numLayers = list->numHwLayers;
549
550 // Prepare FB Update at z-0
551 if (numLayers > mNumVpuLayers) {
552 if (!ctx->mFBUpdate[display]->prepare(ctx, list, mNumVpuLayers)) {
553 ALOGD_IF(isDebug(), "%s configure framebuffer failed",
554 __FUNCTION__);
555 return -1;
556 }
557 }
558
559 // Allocate pipe for layers
560 if (!isSplit ? !allocLayerPipes(ctx, display, list) :
561 !allocLayerPipesSplit(ctx, display, list)) {
562 ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
563 return -1;
564 }
565
566 // Configure layers
567 if (!isSplit ? !configureLayers(ctx, display, list) :
568 !configureLayersSplit(ctx, display, list)) {
569 ALOGD_IF(isDebug(), "%s: Unable to configure MDP pipes", __FUNCTION__);
570 return -1;
571 }
572
573 // Set layer flags for MDP/VPU composition
574 setMDPCompLayerFlags(ctx, display, list);
575
576 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
577 VpuLayerProp* prop = &mProp[display][i];
578
579 if (!prop->vpuLayer)
580 continue;
581
582 hwc_layer_1_t *layer = &list->hwLayers[i];
583 Layer *vLayer = &vpuList->layers[i];
584
585 // re-storing the sourceCropf, as it was changed in setVpuSession for
586 // overlay set
587 layer->sourceCropf = prop->sourceCropf;
588
589 // updating the pipe info inside vfm list
590 if ( prop->pipeCount > 0 && prop->pipeCount <= MAX_PIPES_PER_LAYER ) {
591 vLayer->sDestPipes.numPipes = prop->pipeCount;
592
593 for (int j=0; j < prop->pipeCount; ++j) {
594 // Setting pipe for VPU
595 vLayer->sDestPipes.pipe[j] = prop->pipeID[j];
596 }
597 }
598 }
599
600 if (mVPU->prepare((DISPLAY_ID)display, vpuList) != NO_ERROR) {
601 //error in vpu prepare
602 ALOGE("%s: ERROR in VPU::prepare", __func__);
603 return -1;
604 }
605 return 0;
606}
607
608bool VPUClient::queueHandle(hwc_context_t* ctx, VpuLayerProp* prop,
609 private_handle_t* hnd)
610{
611 overlay::Overlay& ov = *ctx->mOverlay;
612 ovutils::eDest dest = (eDest) getDest(prop, 0);
613
614 int fd = hnd->fd;
615 uint32_t offset = hnd->offset;
616
617 if (dest != ovutils::OV_INVALID) {
618 if (!ov.queueBuffer(fd, offset, dest)) {
619 ALOGE("%s: queueBuffer failed", __FUNCTION__);
620 return false;
621 }
622 else {
623 ALOGD_IF(isDebug(), "%s: Queue handle successful: hnd:0x%x "
624 "dest:%d", __FUNCTION__, (unsigned int) hnd, dest);
625 }
626 }
627 else {
628 ALOGE("%s: Invalid Dest: dest:%d", __FUNCTION__, dest);
629 return false;
630 }
631 return true;
632}
633
634bool VPUClient::queueHandleSplit(hwc_context_t* ctx, VpuLayerProp* prop,
635 private_handle_t* hnd)
636{
637 overlay::Overlay& ov = *ctx->mOverlay;
638 ovutils::eDest ldest = (eDest) getDest(prop, 0);
639 ovutils::eDest rdest = (eDest) getDest(prop, 1);
640
641 int fd = hnd->fd;
642 uint32_t offset = hnd->offset;
643
644 // play left mixer
645 if (ldest != ovutils::OV_INVALID) {
646 ALOGD_IF(isDebug(), "%s: Queuing left mixer", __FUNCTION__);
647 if (!ov.queueBuffer(fd, offset, ldest)) {
648 ALOGE("%s: queueBuffer failed for left mixer ", __FUNCTION__);
649 return false;
650 }
651 else {
652 ALOGD_IF(isDebug(), "%s: Queue left-handle successful: hnd:0x%x "
653 "ldest:%d", __FUNCTION__, (unsigned int) hnd, ldest);
654 }
655 }
656 else {
657 ALOGE("%s: Invalid l-Split Dest", __FUNCTION__);
658 return false;
659 }
660
661 // play right mixer
662 if (rdest != ovutils::OV_INVALID) {
663 ALOGD_IF(isDebug(), "%s: Queuing right mixer", __FUNCTION__);
664 if (!ov.queueBuffer(fd, offset, rdest)) {
665 ALOGE("%s: queueBuffer failed for right mixer ", __FUNCTION__);
666 return false;
667 }
668 else {
669 ALOGD_IF(isDebug(), "%s: Queue right-handle successful: hnd:0x%x "
670 "rdest:%d", __FUNCTION__, (unsigned int) hnd, rdest);
671 }
672 }
673 else {
674 ALOGE("%s: Invalid r-Split Dest", __FUNCTION__);
675 return false;
676 }
677 return true;
678}
679
680bool VPUClient::drawDummyLayers(hwc_context_t* ctx, int dpy,
681 hwc_display_contents_1_t* list)
Naseer Ahmed58780b92013-07-29 17:41:40 -0400682{
683 int err = 0;
Zohaib Alam1bb65612013-09-28 03:38:20 -0400684 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
685 VpuLayerProp* prop = &mProp[dpy][i];
686
687 if (!prop->vpuLayer)
688 continue;
689
690 // displaying blank screen for the first frame
691 if (prop->firstBuffer) {
692 ALOGD_IF(isDebug(), "%s: Displaying first (blank) frame",
693 __FUNCTION__);
694 prop->firstBuffer = false;
695
696 if (mHnd[dpy][i] != NULL)
697 free_buffer(mHnd[dpy][i]);
698
699 // TO-FIX: out dummy buffer is currently allocated based on
700 // RGB888 format
701 err = alloc_buffer(&mHnd[dpy][i], prop->width, prop->height,
702 HAL_PIXEL_FORMAT_RGB_888, GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
703 if (err == -1) {
704 ALOGE("%s: Dummy buffer allocation failed!", __FUNCTION__);
705 return false;
706 }
707
708 private_handle_t* hnd = mHnd[dpy][i];
709 if (prop->format == HAL_PIXEL_FORMAT_RGB_888) {
710 ALOGD_IF(isDebug(), "%s: Format: RGB888", __FUNCTION__);
711 memset((void*)hnd->base, 0x0, hnd->size);
712 }
713 else if (prop->format ==
714 HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED) {
715 ALOGD_IF(isDebug(), "%s: Format: 10BIT_BWC", __FUNCTION__);
716 memset((void*)hnd->base, 0xaa, hnd->size);
717 }
718 else {
719 ALOGE("%s: Error! Wrong VPU out format - layer:%d",
720 __FUNCTION__, i);
721 return false;
722 }
723
724 bool isSplit = isDisplaySplit(ctx, dpy);
725 if (!isSplit ? !queueHandle(ctx, prop, hnd) :
726 !queueHandleSplit(ctx, prop, hnd)) {
727 ALOGD_IF(isDebug(), "%s: Error in queue handle: layer:%d",
728 __FUNCTION__, i);
729 return false;
730 }
731 else {
732 ALOGD_IF(isDebug(), "%s: queue handle successful: hnd:0x%x "
733 "layer:%d", __FUNCTION__, (unsigned int) hnd, i);
734 }
735 }
736 }
737 return true;
738}
739
740int VPUClient::predraw(hwc_context_t *ctx, int display,
741 hwc_display_contents_1_t* list)
742{
743 if (!mVPU) {
744 return -1;
745 }
746
747 if (!ctx || !list) {
748 ALOGE("%s: invalid contxt or list",__FUNCTION__);
749 return -1;
750 }
751
752 if (ctx->listStats[display].numAppLayers > MAX_NUM_APP_LAYERS) {
753 ALOGE("%s: Exceeding max layer count", __FUNCTION__);
754 return -1;
755 }
756
757 // Although all the video layers are composed through VPU, but still need to
758 // queue the first buffer (blank screen) to mdp in order to initialize the
759 // settings
760 if (!drawDummyLayers(ctx, display, list)) {
761 ALOGE("%s: Failed to draw the first layer through overlay",
762 __FUNCTION__);
763 return -1;
764 }
765 return 0;
766}
767
768int VPUClient::draw(hwc_context_t *ctx, int display,
769 hwc_display_contents_1_t* list)
770{
771 if (!mVPU) {
772 return -1;
773 }
774
775 LayerList *vpuList = vList[display];
776 vpuList->numLayers = list->numHwLayers;
777
778 for (unsigned int i=0; i<(list->numHwLayers); ++i) {
779 hwc_layer_1_t *layer = &list->hwLayers[i];
780 Layer *vLayer = &vpuList->layers[i];
781
782 // setting layer info again for the update content.
783 setLayer(layer, vLayer);
784 }
785
786 // queuing the buffer to VPU
787 if (mVPU->draw((DISPLAY_ID)display, vpuList) != NO_ERROR) {
788 //error in vpu draw
789 ALOGE("%s: ERROR in VPU::draw", __func__);
790 return -1;
791 }
792
793 ALOGD_IF(isDebug2(), "%s: Done VFM draw", __FUNCTION__);
794
795 LayerProp *layerProp = ctx->layerProp[display];
796 // setting releaseFenceFd for the vpu layer
797 for (unsigned int i=0; i<(vpuList->numLayers); ++i) {
798
799 VpuLayerProp* prop = &mProp[display][i];
800 if (!prop->vpuLayer)
801 continue;
802
803 hwc_layer_1_t *layer = &list->hwLayers[i];
804 Layer *vLayer = &vpuList->layers[i];
805
806 // TODO: Fix properly once the releaseFenceFd is implemented
807 layer->releaseFenceFd = vLayer->releaseFenceFd;
808 ALOGD_IF(isDebug(), "%s: releaseFd:%d for layer:%d", __FUNCTION__,
809 layer->releaseFenceFd, i);
810 }
811 return 0;
812}
813
814int VPUClient::getLayerIdx(int dpy, hwc_layer_1_t *layer)
815{
816 for (int i=0; i < MAX_NUM_APP_LAYERS; ++i) {
817 VpuLayerProp* prop = &mProp[dpy][i];
818
819 if (!prop->vpuLayer)
820 continue;
821
822 if (prop->layer == layer) {
823 ALOGD_IF(isDebug2(), "%s: OUT - dpy:%d", __FUNCTION__, dpy);
824 return i;
825 }
826 }
827 return -1;
828}
829
830int VPUClient::getLayerFormat(int dpy, hwc_layer_1_t *layer)
831{
832 if (!mVPU) {
833 return -1;
834 }
835
836 int idx = -1;
837 if ((idx = getLayerIdx(dpy, layer)) == -1) {
838 ALOGE("%s: Layer not found!", __FUNCTION__);
839 return -1;
840 }
841
842 VpuLayerProp* prop = &mProp[dpy][idx];
843 ALOGD_IF(isDebug(), "%s: layer:%d format:0x%x", __FUNCTION__, idx,
844 (unsigned int) prop->format);
845
846 return prop->format;
847}
848
849int VPUClient::getWidth(int dpy, hwc_layer_1_t *layer)
850{
851 if (!mVPU) {
852 return -1;
853 }
854
855 int idx = -1;
856 if ((idx = getLayerIdx(dpy, layer)) == -1) {
857 ALOGE("%s: Layer not found!", __FUNCTION__);
858 return -1;
859 }
860
861 VpuLayerProp* prop = &mProp[dpy][idx];
862 ALOGD_IF(isDebug(), "%s: layer:%d width:%d", __FUNCTION__, idx,
863 prop->width);
864
865 return prop->width;
866}
867
868int VPUClient::getHeight(int dpy, hwc_layer_1_t *layer)
869{
870 if (!mVPU) {
871 return -1;
872 }
873
874 int idx = -1;
875 if ((idx = getLayerIdx(dpy, layer)) == -1) {
876 ALOGE("%s: Layer not found!", __FUNCTION__);
877 return -1;
878 }
879
880 VpuLayerProp* prop = &mProp[dpy][idx];
881 ALOGD_IF(isDebug(), "%s: layer:%d height:%d", __FUNCTION__, idx,
882 prop->height);
883
884 return prop->height;
885}
886
887// TODO: getter function has side-effect. Need to cleanup
888void VPUClient::getPipeId(VpuLayerProp* prop, int &pipe)
889{
890 pipe = (prop->pipeCount == 1) ? (prop->pipeID[0]) : -1;
891}
892
893void VPUClient::getPipeId(VpuLayerProp* prop, int &lPipe, int &rPipe)
894{
895 lPipe = (prop->pipeCount == 2) ? (prop->pipeID[0]) : -1;
896 rPipe = (prop->pipeCount == 2) ? (prop->pipeID[1]) : -1;
897}
898
899int VPUClient::getDest(VpuLayerProp* prop, int pipenum)
900{
901 return (prop->pipeCount > 0) ? (prop->dest[pipenum]) : -1;
902}
903
904void VPUClient::setPipeCount(VpuLayerProp* prop, int count)
905{
906 prop->pipeCount = count;
907}
908
909void VPUClient::setPipeId(VpuLayerProp* prop, int lPipeId, int rPipeId)
910{
911 prop->pipeCount = 2;
912 prop->pipeID[0] = lPipeId;
913 prop->pipeID[1] = rPipeId;
914}
915
916void VPUClient::setPipeId(VpuLayerProp* prop, int pipeId)
917{
918 prop->pipeCount = 1;
919 prop->pipeID[0] = pipeId;
920}
921
922void VPUClient::setDest(VpuLayerProp* prop, int lDest, int rDest)
923{
924 prop->dest[0] = lDest;
925 prop->dest[1] = rDest;
926}
927
928void VPUClient::setDest(VpuLayerProp* prop, int dest)
929{
930 prop->dest[0] = dest;
931}
932
933bool VPUClient::supportedVPULayer(VpuLayerProp* prop)
934{
935 if (!prop->vpuLayer)
936 return false;
937
938 return true;
939}
940
941bool VPUClient::supportedVPULayer(int dpy, hwc_layer_1_t *layer)
942{
943 if (!mVPU) {
944 return false;
945 }
946
947 int idx = -1;
948 if ((idx = getLayerIdx(dpy, layer)) == -1) {
949 ALOGD_IF(isDebug(), "%s: Layer not found!", __FUNCTION__);
950 return false;
951 }
952 return true;
Naseer Ahmed58780b92013-07-29 17:41:40 -0400953}
954
Naseer Ahmed4957c522013-11-12 18:07:15 -0500955int VPUClient::processCommand(uint32_t command,
Zohaib Alam1bb65612013-09-28 03:38:20 -0400956 const Parcel* inParcel, Parcel* outParcel)
Naseer Ahmed58780b92013-07-29 17:41:40 -0400957{
Zohaib Alam1bb65612013-09-28 03:38:20 -0400958 if (!mVPU)
Naseer Ahmed58780b92013-07-29 17:41:40 -0400959 return 0;
Zohaib Alam1bb65612013-09-28 03:38:20 -0400960
961 return mVPU->processCommand(command, inParcel, outParcel);
Naseer Ahmed58780b92013-07-29 17:41:40 -0400962}
963
964}; // namespace qhwc