hwc: vpuclient: vpuClient implementation

Vpuclient is the client side for VFM in hwc. It follows the
similar pattern of prepare and draw. It has 2 step prepare
including: setVpuSession and prepare. The setVpuSession function
passes all the layers from the SF list to VFM, which marks
the layers that it can support. After this, the layer
allocation/configuration is done, and finally in prepare the
allocated pipes are passed down to VFM. The draw function
passes the handle to the VFM to draw the video layer.

Change-Id: I5d8795de35ed98716f7fa4cd48506b488cb3cb5d
This commit is contained in:
Zohaib Alam
2013-09-28 03:38:20 -04:00
parent ac06730570
commit 1bb656178e
8 changed files with 1084 additions and 89 deletions

View File

@@ -36,8 +36,7 @@ ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
common_flags += -DMDSS_TARGET common_flags += -DMDSS_TARGET
endif endif
ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true) ifeq ($(call is-board-platform-in-list, mpq8092), true)
#XXX: Replace with check from MDP when available
common_flags += -DVPU_TARGET common_flags += -DVPU_TARGET
endif endif

View File

@@ -25,10 +25,8 @@ LOCAL_SRC_FILES := hwc.cpp \
hwc_dump_layers.cpp \ hwc_dump_layers.cpp \
hwc_ad.cpp \ hwc_ad.cpp \
hwc_virtual.cpp hwc_virtual.cpp
ifeq ($(call is-board-platform-in-list, mpq8092), true)
ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
LOCAL_SRC_FILES += hwc_vpuclient.cpp LOCAL_SRC_FILES += hwc_vpuclient.cpp
endif endif
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View File

@@ -180,6 +180,7 @@ static int hwc_prepare_primary(hwc_composer_device_1 *dev,
ATRACE_CALL(); ATRACE_CALL();
hwc_context_t* ctx = (hwc_context_t*)(dev); hwc_context_t* ctx = (hwc_context_t*)(dev);
const int dpy = HWC_DISPLAY_PRIMARY; const int dpy = HWC_DISPLAY_PRIMARY;
bool fbComp = false;
if (LIKELY(list && list->numHwLayers > 1) && if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive) { ctx->dpyAttr[dpy].isActive) {
@@ -188,13 +189,19 @@ static int hwc_prepare_primary(hwc_composer_device_1 *dev,
reset_layer_prop(ctx, dpy, list->numHwLayers - 1); reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
setListStats(ctx, list, dpy); setListStats(ctx, list, dpy);
if (ctx->mVPUClient == NULL)
fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
#ifdef VPU_TARGET #ifdef VPU_TARGET
ctx->mVPUClient->prepare(ctx, list); else
fbComp = (ctx->mVPUClient->prepare(ctx, dpy, list) < 0);
#endif #endif
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
if (fbComp) {
const int fbZ = 0; const int fbZ = 0;
ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ); ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
} }
if (ctx->mMDP.version < qdutils::MDP_V4_0) { if (ctx->mMDP.version < qdutils::MDP_V4_0) {
if(ctx->mCopyBit[dpy]) if(ctx->mCopyBit[dpy])
ctx->mCopyBit[dpy]->prepare(ctx, list, dpy); ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
@@ -487,13 +494,15 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
if(ctx->mHwcDebug[dpy]) if(ctx->mHwcDebug[dpy])
ctx->mHwcDebug[dpy]->dumpLayers(list); ctx->mHwcDebug[dpy]->dumpLayers(list);
if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { if (ctx->mVPUClient != NULL) {
#ifdef VPU_TARGET
ctx->mVPUClient->predraw(ctx, dpy, list);
#endif
}
else if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
ALOGE("%s: MDPComp draw failed", __FUNCTION__); ALOGE("%s: MDPComp draw failed", __FUNCTION__);
ret = -1; ret = -1;
} }
#ifdef VPU_TARGET
ctx->mVPUClient->draw(ctx, list);
#endif
//TODO We dont check for SKIP flag on this layer because we need PAN //TODO We dont check for SKIP flag on this layer because we need PAN
//always. Last layer is always FB //always. Last layer is always FB
@@ -514,6 +523,11 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
ret = -1; ret = -1;
} }
#ifdef VPU_TARGET
if (ctx->mVPUClient != NULL)
ctx->mVPUClient->draw(ctx, dpy, list);
#endif
} }
closeAcquireFds(list); closeAcquireFds(list);

View File

@@ -31,6 +31,7 @@
#include <IQService.h> #include <IQService.h>
#include <hwc_utils.h> #include <hwc_utils.h>
#include <hwc_vpuclient.h> #include <hwc_vpuclient.h>
#include <mdp_version.h>
#define QCLIENT_DEBUG 0 #define QCLIENT_DEBUG 0
@@ -94,16 +95,19 @@ static android::status_t screenRefresh(hwc_context_t *ctx) {
return result; return result;
} }
#ifdef VPU_TARGET
static android::status_t vpuCommand(hwc_context_t *ctx, static android::status_t vpuCommand(hwc_context_t *ctx,
uint32_t command, uint32_t command,
const Parcel* inParcel, const Parcel* inParcel,
Parcel* outParcel) { Parcel* outParcel) {
status_t result = NO_INIT; status_t result = NO_INIT;
#ifdef VPU_TARGET #ifdef QCOM_BSP
result = ctx->mVPUClient->processCommand(command, inParcel, outParcel); if(qdutils::MDPVersion::getInstance().is8092())
result = ctx->mVPUClient->processCommand(command, inParcel, outParcel);
#endif #endif
return result; return result;
} }
#endif
static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) { static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
ctx->mExtOrientation = orientation; ctx->mExtOrientation = orientation;
@@ -181,10 +185,12 @@ status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) { Parcel* outParcel) {
status_t ret = NO_ERROR; status_t ret = NO_ERROR;
#ifdef VPU_TARGET
if (command > IQService::VPU_COMMAND_LIST_START && if (command > IQService::VPU_COMMAND_LIST_START &&
command < IQService::VPU_COMMAND_LIST_END) { command < IQService::VPU_COMMAND_LIST_END) {
return vpuCommand(mHwcContext, command, inParcel, outParcel); return vpuCommand(mHwcContext, command, inParcel, outParcel);
} }
#endif
switch(command) { switch(command) {
case IQService::SECURING: case IQService::SECURING:

View File

@@ -232,8 +232,11 @@ void initContext(hwc_context_t *ctx)
// Initialize device orientation to its default orientation // Initialize device orientation to its default orientation
ctx->deviceOrientation = 0; ctx->deviceOrientation = 0;
ctx->mBufferMirrorMode = false; ctx->mBufferMirrorMode = false;
ctx->mVPUClient = NULL;
#ifdef VPU_TARGET #ifdef VPU_TARGET
ctx->mVPUClient = new VPUClient(); if(qdutils::MDPVersion::getInstance().is8092())
ctx->mVPUClient = new VPUClient(ctx);
#endif #endif
ALOGI("Initializing Qualcomm Hardware Composer"); ALOGI("Initializing Qualcomm Hardware Composer");
@@ -270,9 +273,8 @@ void closeContext(hwc_context_t *ctx)
} }
#ifdef VPU_TARGET #ifdef VPU_TARGET
if(ctx->mVPUClient) { if(ctx->mVPUClient != NULL)
delete ctx->mVPUClient; delete ctx->mVPUClient;
}
#endif #endif
for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) { for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
@@ -1302,6 +1304,7 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
dpy, list->numHwLayers); dpy, list->numHwLayers);
} }
LayerProp *layerProp = ctx->layerProp[dpy];
for(uint32_t i = 0; i < list->numHwLayers; i++) { for(uint32_t i = 0; i < list->numHwLayers; i++) {
if(list->hwLayers[i].compositionType == HWC_OVERLAY || if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
list->hwLayers[i].compositionType == HWC_BLIT || list->hwLayers[i].compositionType == HWC_BLIT ||
@@ -1313,8 +1316,10 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
// Release all the app layer fds immediately, // Release all the app layer fds immediately,
// if animation is in progress. // if animation is in progress.
list->hwLayers[i].releaseFenceFd = -1; list->hwLayers[i].releaseFenceFd = -1;
} else if(list->hwLayers[i].releaseFenceFd < 0) { } else if(list->hwLayers[i].releaseFenceFd < 0 &&
//If rotator has not already populated this field. !(layerProp[i].mFlags & HWC_VPUCOMP)) {
//If rotator has not already populated this field
// & if it's a not VPU layer
list->hwLayers[i].releaseFenceFd = dup(releaseFd); list->hwLayers[i].releaseFenceFd = dup(releaseFd);
} }
} }
@@ -1361,8 +1366,10 @@ void setMdpFlags(hwc_layer_1_t *layer,
ovutils::setMdpFlags(mdpFlags, ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_SECURE_OVERLAY_SESSION); ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
} }
// in mpq, deinterlacing is done in vpu
if(metadata && (metadata->operation & PP_PARAM_INTERLACED) && if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
metadata->interlaced) { metadata->interlaced &&
(!qdutils::MDPVersion::getInstance().is8092())) {
ovutils::setMdpFlags(mdpFlags, ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_DEINTERLACE); ovutils::OV_MDP_DEINTERLACE);
} }
@@ -1549,6 +1556,17 @@ int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
int rotFlags = ovutils::ROT_FLAGS_NONE; int rotFlags = ovutils::ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd)); uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size); Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
LayerProp *layerProp = ctx->layerProp[dpy];
#ifdef VPU_TARGET
if(ctx->mVPUClient != NULL &&
ctx->mVPUClient->supportedVPULayer(dpy, layer)) {
whf.format = getMdpFormat(
ctx->mVPUClient->getLayerFormat(dpy, layer));
whf.w = ctx->mVPUClient->getWidth(dpy, layer);
whf.h = ctx->mVPUClient->getHeight(dpy, layer);
}
#endif
// Handle R/B swap // Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) { if (layer->flags & HWC_FORMAT_RB_SWAP) {
@@ -1656,6 +1674,17 @@ int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
int rotFlags = ROT_FLAGS_NONE; int rotFlags = ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd)); uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size); Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
LayerProp *layerProp = ctx->layerProp[dpy];
#ifdef VPU_TARGET
if(ctx->mVPUClient != NULL &&
ctx->mVPUClient->supportedVPULayer(dpy, layer)) {
whf.format = getMdpFormat(
ctx->mVPUClient->getLayerFormat(dpy, layer));
whf.w = ctx->mVPUClient->getWidth(dpy, layer);
whf.h = ctx->mVPUClient->getHeight(dpy, layer);
}
#endif
// Handle R/B swap // Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) { if (layer->flags & HWC_FORMAT_RB_SWAP) {

View File

@@ -145,6 +145,7 @@ struct BwcPM {
enum { enum {
HWC_MDPCOMP = 0x00000001, HWC_MDPCOMP = 0x00000001,
HWC_COPYBIT = 0x00000002, HWC_COPYBIT = 0x00000002,
HWC_VPUCOMP = 0x00000004,
}; };
// HAL specific features // HAL specific features

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013 The Linux Foundation. All rights reserved. * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@@ -31,13 +31,20 @@
#define HWC_VPU_H #define HWC_VPU_H
#include <sys/types.h> #include <sys/types.h>
#include "hwc_utils.h"
#define MAX_PIPES_PER_LAYER 2
//Forward declarations //Forward declarations
struct hwc_display_contents_1; struct hwc_display_contents_1;
typedef struct hwc_display_contents_1 hwc_display_contents_1_t; typedef struct hwc_display_contents_1 hwc_display_contents_1_t;
struct hwc_layer_1;
typedef struct hwc_layer_1 hwc_layer_1_t;
struct hwc_context_t; struct hwc_context_t;
namespace vpu { namespace vpu {
class VPU; class VPU;
struct LayerList;
}; };
namespace android { namespace android {
class Parcel; class Parcel;
@@ -47,21 +54,91 @@ namespace qhwc {
class VPUClient { class VPUClient {
public: public:
VPUClient(); VPUClient(hwc_context_t *ctx);
~VPUClient(); ~VPUClient();
int prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list); int setupVpuSession(hwc_context_t *ctx, int display,
hwc_display_contents_1_t* list);
int draw(hwc_context_t *ctx, hwc_display_contents_1_t* list); int prepare(hwc_context_t *ctx, int display,
hwc_display_contents_1_t* list);
int predraw(hwc_context_t *ctx, int display,
hwc_display_contents_1_t* list);
int draw(hwc_context_t *ctx, int display,
hwc_display_contents_1_t* list);
int processCommand(uint32_t command, int processCommand(uint32_t command,
const android::Parcel* inParcel, android::Parcel* outParcel); const android::Parcel* inParcel, android::Parcel* outParcel);
int getLayerFormat(int dpy, hwc_layer_1_t *layer);
int getWidth(int dpy, hwc_layer_1_t *layer);
int getHeight(int dpy, hwc_layer_1_t *layer);
bool supportedVPULayer(int dpy, hwc_layer_1_t *layer);
private: private:
vpu::VPU *mVPU; vpu::VPU *mVPU;
void* mVPULib; void* mVPULib;
/* VpuLayerProp struct:
* This struct corresponds to only one layer
* pipeCount: number of pipes required for a layer
* pipeID[]: pipe ids corresponding to the layer
*/
struct VpuLayerProp {
int format;
int width;
int height;
int pipeCount;
bool vpuLayer;
bool firstBuffer;
hwc_frect_t sourceCropf;
hwc_layer_1_t *layer;
int pipeID[MAX_PIPES_PER_LAYER];
int dest[MAX_PIPES_PER_LAYER];
};
int mNumVpuLayers; /* total num of vpu supported layers */
int mGpuFallback; /* all layers are not supported by vpu */
VpuLayerProp mProp[HWC_NUM_DISPLAY_TYPES][MAX_NUM_APP_LAYERS];
int mDebugLogs;
private_handle_t *mHnd[HWC_NUM_DISPLAY_TYPES][MAX_NUM_APP_LAYERS];
vpu::LayerList *vList[HWC_NUM_DISPLAY_TYPES];
/* Private debug functions */
int32_t isDebug() { return (mDebugLogs >= 1); }
int32_t isDebug2() { return (mDebugLogs >= 2); }
/* Private Get/Set functions */
int getLayerIdx(int dpy, hwc_layer_1_t *layer);
void getPipeId(VpuLayerProp* prop, int &pipe);
void getPipeId(VpuLayerProp* prop, int &lPipe, int &rPipe);
int getDest(VpuLayerProp* prop, int pipenum);
void setPipeCount(VpuLayerProp* prop, int count);
void setPipeId(VpuLayerProp* prop, int lPipeId, int rPipeId);
void setPipeId(VpuLayerProp* prop, int pipeId);
void setDest(VpuLayerProp* prop, int lDest, int rDest);
void setDest(VpuLayerProp* prop, int dest);
/* Private implementations */
bool supportedVPULayer(VpuLayerProp* prop);
bool allocResLayerPipes(hwc_context_t* ctx, int dpy,
hwc_display_contents_1_t* list);
bool allocLayerPipes(hwc_context_t* ctx, int dpy,
hwc_display_contents_1_t* list);
bool allocResLayerPipesSplit(hwc_context_t* ctx, int dpy,
hwc_display_contents_1_t* list);
bool allocLayerPipesSplit(hwc_context_t* ctx, int dpy,
hwc_display_contents_1_t* list);
bool configureLayers(hwc_context_t* ctx, int dpy,
hwc_display_contents_1_t* list);
bool configureLayersSplit(hwc_context_t* ctx, int dpy,
hwc_display_contents_1_t* list);
void setMDPCompLayerFlags(hwc_context_t *ctx, int dpy,
hwc_display_contents_1_t* list);
bool drawDummyLayers(hwc_context_t* ctx, int dpy,
hwc_display_contents_1_t* list);
bool queueHandle(hwc_context_t* ctx, VpuLayerProp* prop,
private_handle_t* hnd);
bool queueHandleSplit(hwc_context_t* ctx, VpuLayerProp* prop,
private_handle_t* hnd);
}; // class VPU }; // class VPU
}; // namespace qhwc }; // namespace qhwc
#endif /* end of include guard: HWC_VPU_H */ #endif /* end of include guard: HWC_VPU_H */