You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
11 KiB
357 lines
11 KiB
/*
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
* Copyright (C)2012-2013, The Linux Foundation. All rights reserved.
|
|
*
|
|
* Not a Contribution, Apache license notifications and license are retained
|
|
* for attribution purposes only.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef HWC_UTILS_H
|
|
#define HWC_UTILS_H
|
|
|
|
#define HWC_REMOVE_DEPRECATED_VERSIONS 1
|
|
#include <fcntl.h>
|
|
#include <hardware/hwcomposer.h>
|
|
#include <gr.h>
|
|
#include <gralloc_priv.h>
|
|
#include <utils/String8.h>
|
|
#include <linux/fb.h>
|
|
#include "qdMetaData.h"
|
|
#include <overlayUtils.h>
|
|
#include <cutils/sockets.h>
|
|
|
|
#define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1))
|
|
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
|
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
|
#define MAX_NUM_APP_LAYERS 32
|
|
#define MAX_DISPLAY_DIM 2048
|
|
|
|
// For support of virtual displays
|
|
#define MAX_DISPLAYS (HWC_NUM_DISPLAY_TYPES)
|
|
#define DAEMON_SOCKET "pps"
|
|
//Fwrd decls
|
|
struct hwc_context_t;
|
|
|
|
namespace ovutils = overlay::utils;
|
|
|
|
namespace overlay {
|
|
class Overlay;
|
|
class Rotator;
|
|
class RotMgr;
|
|
}
|
|
|
|
namespace qhwc {
|
|
//fwrd decl
|
|
class QueuedBufferStore;
|
|
class ExternalDisplay;
|
|
class IFBUpdate;
|
|
class IVideoOverlay;
|
|
class MDPComp;
|
|
class CopyBit;
|
|
|
|
|
|
struct MDPInfo {
|
|
int version;
|
|
char panel;
|
|
bool hasOverlay;
|
|
};
|
|
|
|
struct DisplayAttributes {
|
|
uint32_t vsync_period; //nanos
|
|
uint32_t xres;
|
|
uint32_t yres;
|
|
uint32_t stride;
|
|
float xdpi;
|
|
float ydpi;
|
|
int fd;
|
|
bool connected; //Applies only to pluggable disp.
|
|
//Connected does not mean it ready to use.
|
|
//It should be active also. (UNBLANKED)
|
|
bool isActive;
|
|
// In pause state, composition is bypassed
|
|
// used for WFD displays only
|
|
bool isPause;
|
|
};
|
|
|
|
struct ListStats {
|
|
int numAppLayers; //Total - 1, excluding FB layer.
|
|
int skipCount;
|
|
int fbLayerIndex; //Always last for now. = numAppLayers
|
|
//Video specific
|
|
int yuvCount;
|
|
int yuvIndices[MAX_NUM_APP_LAYERS];
|
|
bool needsAlphaScale;
|
|
bool preMultipliedAlpha;
|
|
bool planeAlpha;
|
|
};
|
|
|
|
struct LayerProp {
|
|
uint32_t mFlags; //qcom specific layer flags
|
|
LayerProp():mFlags(0) {};
|
|
};
|
|
|
|
struct VsyncState {
|
|
bool enable;
|
|
bool fakevsync;
|
|
};
|
|
|
|
struct CablProp {
|
|
bool enabled;
|
|
bool start;
|
|
bool videoOnly;
|
|
//daemon_socket for connection to pp-daemon
|
|
int daemon_socket;
|
|
};
|
|
|
|
// LayerProp::flag values
|
|
enum {
|
|
HWC_MDPCOMP = 0x00000001,
|
|
HWC_COPYBIT = 0x00000002,
|
|
};
|
|
|
|
class LayerRotMap {
|
|
public:
|
|
LayerRotMap() { reset(); }
|
|
enum { MAX_SESS = 3 };
|
|
void add(hwc_layer_1_t* layer, overlay::Rotator *rot);
|
|
void reset();
|
|
uint32_t getCount() const;
|
|
hwc_layer_1_t* getLayer(uint32_t index) const;
|
|
overlay::Rotator* getRot(uint32_t index) const;
|
|
void setReleaseFd(const int& fence);
|
|
private:
|
|
hwc_layer_1_t* mLayer[MAX_SESS];
|
|
overlay::Rotator* mRot[MAX_SESS];
|
|
uint32_t mCount;
|
|
};
|
|
|
|
inline uint32_t LayerRotMap::getCount() const {
|
|
return mCount;
|
|
}
|
|
|
|
inline hwc_layer_1_t* LayerRotMap::getLayer(uint32_t index) const {
|
|
if(index >= mCount) return NULL;
|
|
return mLayer[index];
|
|
}
|
|
|
|
inline overlay::Rotator* LayerRotMap::getRot(uint32_t index) const {
|
|
if(index >= mCount) return NULL;
|
|
return mRot[index];
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Utility functions - implemented in hwc_utils.cpp
|
|
void dumpLayer(hwc_layer_1_t const* l);
|
|
void setListStats(hwc_context_t *ctx, const hwc_display_contents_1_t *list,
|
|
int dpy);
|
|
void initContext(hwc_context_t *ctx);
|
|
void closeContext(hwc_context_t *ctx);
|
|
//Crops source buffer against destination and FB boundaries
|
|
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
|
|
const hwc_rect_t& scissor, int orient);
|
|
void getNonWormholeRegion(hwc_display_contents_1_t* list,
|
|
hwc_rect_t& nwr);
|
|
bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer);
|
|
bool isSecureModePolicy(int mdpVersion);
|
|
bool isExternalActive(hwc_context_t* ctx);
|
|
bool needsScaling(hwc_layer_1_t const* layer);
|
|
bool isAlphaPresent(hwc_layer_1_t const* layer);
|
|
bool setupBasePipe(hwc_context_t *ctx);
|
|
int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable);
|
|
int getBlending(int blending);
|
|
|
|
//Helper function to dump logs
|
|
void dumpsys_log(android::String8& buf, const char* fmt, ...);
|
|
|
|
/* Calculates the destination position based on the action safe rectangle */
|
|
void getActionSafePosition(hwc_context_t *ctx, int dpy, uint32_t& x,
|
|
uint32_t& y, uint32_t& w, uint32_t& h);
|
|
|
|
//Close acquireFenceFds of all layers of incoming list
|
|
void closeAcquireFds(hwc_display_contents_1_t* list);
|
|
|
|
//Sync point impl.
|
|
int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
|
|
int fd);
|
|
|
|
//Trims a layer's source crop which is outside of screen boundary.
|
|
void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
|
|
hwc_rect_t& crop, hwc_rect_t& dst);
|
|
|
|
//Sets appropriate mdp flags for a layer.
|
|
void setMdpFlags(hwc_layer_1_t *layer,
|
|
ovutils::eMdpFlags &mdpFlags,
|
|
int rotDownscale = 0);
|
|
|
|
//Routine to configure low resolution panels (<= 2048 width)
|
|
int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
|
|
ovutils::eMdpFlags& mdpFlags, const ovutils::eZorder& z,
|
|
const ovutils::eIsFg& isFg, const ovutils::eDest& dest,
|
|
overlay::Rotator **rot);
|
|
|
|
//Routine to configure high resolution panels (> 2048 width)
|
|
int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
|
|
ovutils::eMdpFlags& mdpFlags, const ovutils::eZorder& z,
|
|
const ovutils::eIsFg& isFg, const ovutils::eDest& lDest,
|
|
const ovutils::eDest& rDest, overlay::Rotator **rot);
|
|
|
|
// Inline utility functions
|
|
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
|
|
return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
|
|
}
|
|
|
|
// Returns true if the buffer is yuv
|
|
static inline bool isYuvBuffer(const private_handle_t* hnd) {
|
|
return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
|
|
}
|
|
|
|
// Returns true if the buffer is secure
|
|
static inline bool isSecureBuffer(const private_handle_t* hnd) {
|
|
return (hnd && (private_handle_t::PRIV_FLAGS_SECURE_BUFFER & hnd->flags));
|
|
}
|
|
//Return true if buffer is marked locked
|
|
static inline bool isBufferLocked(const private_handle_t* hnd) {
|
|
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
|
|
}
|
|
|
|
//Return true if buffer is for external display only
|
|
static inline bool isExtOnly(const private_handle_t* hnd) {
|
|
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY));
|
|
}
|
|
|
|
//Return true if buffer is for external display only with a BLOCK flag.
|
|
static inline bool isExtBlock(const private_handle_t* hnd) {
|
|
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK));
|
|
}
|
|
|
|
//Return true if buffer is for external display only with a Close Caption flag.
|
|
static inline bool isExtCC(const private_handle_t* hnd) {
|
|
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_CC));
|
|
}
|
|
|
|
static inline int getWidth(const private_handle_t* hnd) {
|
|
if(isYuvBuffer(hnd)) {
|
|
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
|
|
if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
|
|
return metadata->bufferDim.sliceWidth;
|
|
}
|
|
}
|
|
return hnd->width;
|
|
}
|
|
|
|
static inline int getHeight(const private_handle_t* hnd) {
|
|
if(isYuvBuffer(hnd)) {
|
|
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
|
|
if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
|
|
return metadata->bufferDim.sliceHeight;
|
|
}
|
|
}
|
|
return hnd->height;
|
|
}
|
|
|
|
template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
|
|
template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
|
|
|
|
// Initialize uevent thread
|
|
void init_uevent_thread(hwc_context_t* ctx);
|
|
// Initialize vsync thread
|
|
void init_vsync_thread(hwc_context_t* ctx);
|
|
|
|
inline void getLayerResolution(const hwc_layer_1_t* layer,
|
|
int& width, int& height) {
|
|
hwc_rect_t displayFrame = layer->displayFrame;
|
|
width = displayFrame.right - displayFrame.left;
|
|
height = displayFrame.bottom - displayFrame.top;
|
|
}
|
|
|
|
static inline int openFb(int dpy) {
|
|
int fd = -1;
|
|
const char *devtmpl = "/dev/graphics/fb%u";
|
|
char name[64] = {0};
|
|
snprintf(name, 64, devtmpl, dpy);
|
|
fd = open(name, O_RDWR);
|
|
return fd;
|
|
}
|
|
|
|
template <class T>
|
|
inline void swap(T& a, T& b) {
|
|
T tmp = a;
|
|
a = b;
|
|
b = tmp;
|
|
}
|
|
|
|
}; //qhwc namespace
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// HWC context
|
|
// This structure contains overall state
|
|
struct hwc_context_t {
|
|
hwc_composer_device_1_t device;
|
|
const hwc_procs_t* proc;
|
|
|
|
//CopyBit objects
|
|
qhwc::CopyBit *mCopyBit[MAX_DISPLAYS];
|
|
|
|
//Overlay object - NULL for non overlay devices
|
|
overlay::Overlay *mOverlay;
|
|
//Holds a few rot objects
|
|
overlay::RotMgr *mRotMgr;
|
|
|
|
//Primary and external FB updater
|
|
qhwc::IFBUpdate *mFBUpdate[MAX_DISPLAYS];
|
|
// External display related information
|
|
qhwc::ExternalDisplay *mExtDisplay;
|
|
qhwc::MDPInfo mMDP;
|
|
qhwc::VsyncState vstate;
|
|
qhwc::DisplayAttributes dpyAttr[MAX_DISPLAYS];
|
|
qhwc::ListStats listStats[MAX_DISPLAYS];
|
|
qhwc::LayerProp *layerProp[MAX_DISPLAYS];
|
|
qhwc::LayerRotMap *mLayerRotMap[MAX_DISPLAYS];
|
|
qhwc::MDPComp *mMDPComp[MAX_DISPLAYS];
|
|
qhwc::CablProp mCablProp;
|
|
overlay::utils::Whf mPrevWHF[MAX_DISPLAYS];
|
|
|
|
//Securing in progress indicator
|
|
bool mSecuring;
|
|
//External Display configuring progress indicator
|
|
bool mExtDispConfiguring;
|
|
//Display in secure mode indicator
|
|
bool mSecureMode;
|
|
//Lock to prevent set from being called while blanking
|
|
mutable Locker mBlankLock;
|
|
//Lock to protect set when detaching external disp
|
|
mutable Locker mExtSetLock;
|
|
//DMA used for rotator
|
|
bool mDMAInUse;
|
|
//MDP rotater needed
|
|
bool mNeedsRotator;
|
|
//Check if base pipe is set up
|
|
bool mBasePipeSetup;
|
|
//Flags the transition of a video session
|
|
bool mVideoTransFlag;
|
|
};
|
|
|
|
namespace qhwc {
|
|
static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) {
|
|
return ctx->listStats[dpy].skipCount;
|
|
}
|
|
|
|
static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) {
|
|
return ctx->listStats[dpy].yuvCount;
|
|
}
|
|
};
|
|
|
|
#endif //HWC_UTILS_H
|