diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 6a9008385..4a6d32044 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -120,6 +120,7 @@ ifeq ($(TARGET_USES_QCOM_BSP), true) LOCAL_C_INCLUDES += $(call project-path-for,qcom-display)/libgralloc LOCAL_C_INCLUDES += $(call project-path-for,qcom-display)/libqdutils LOCAL_SHARED_LIBRARIES += libqdutils + LOCAL_SHARED_LIBRARIES += libqdMetaData LOCAL_CFLAGS += -DQTI_BSP LOCAL_SRC_FILES += \ ExSurfaceFlinger/ExLayer.cpp \ diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 9bdb7dea6..efdcd03a3 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -306,6 +306,7 @@ public: }; friend class VSyncThread; + friend class ExHWComposer; // for debugging ---------------------------------------------------------- void dump(String8& out) const; diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.cpp index 2b4109877..6b228ed85 100644 --- a/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.cpp +++ b/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.cpp @@ -31,6 +31,8 @@ #include "ExHWComposer.h" #ifdef QTI_BSP #include +#include +#include #endif namespace android { @@ -74,4 +76,25 @@ bool ExHWComposer::isCompositionTypeBlit(const int32_t compType) const { return false; } +#ifdef QTI_BSP +uint32_t ExHWComposer::getS3DFlag(int disp) const { + const DisplayData& disp_data(mDisplayData[disp]); + + for (size_t i=0 ; inumHwLayers-1; i++) { + const hwc_layer_1_t &l = disp_data.list->hwLayers[i]; + private_handle_t *pvt_handle = static_cast + (const_cast(l.handle)); + + if (pvt_handle != NULL) { + struct S3DSFRender_t s3dRender; + getMetaData(pvt_handle, GET_S3D_RENDER, &s3dRender); + if (s3dRender.DisplayId == static_cast(disp) && s3dRender.GpuRender) { + return s3dRender.GpuS3dFormat; + } + } + } + return 0; +} +#endif + }; // namespace android diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.h b/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.h index 2016ff063..06ee32b89 100644 --- a/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.h +++ b/services/surfaceflinger/ExSurfaceFlinger/ExHWComposer.h @@ -43,6 +43,10 @@ public: virtual ~ExHWComposer(); +#ifdef QTI_BSP + uint32_t getS3DFlag(int disp) const; +#endif + protected: bool mVDSEnabled; inline bool isVDSEnabled() const { return mVDSEnabled; }; diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp index fa4557909..5df34edf6 100644 --- a/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp +++ b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp @@ -36,10 +36,12 @@ #include #ifdef QTI_BSP #include +#include #include #endif #include "ExLayer.h" +#include "RenderEngine/RenderEngine.h" namespace android { @@ -70,12 +72,18 @@ static Rect getAspectRatio(const sp& hw, ExLayer::ExLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags) +#ifdef QTI_BSP + : Layer(flinger, client, name, w, h, flags), + mMeshLeftTop(Mesh::TRIANGLE_FAN, 4, 2, 2), + mMeshRightBottom(Mesh::TRIANGLE_FAN, 4, 2, 2) { +#else : Layer(flinger, client, name, w, h, flags) { - +#endif char property[PROPERTY_VALUE_MAX] = {0}; mDebugLogs = false; mIsGPUAllowedForProtected = false; + mIsHDMIPrimary = false; if((property_get("persist.debug.qdframework.logs", property, NULL) > 0) && (!strncmp(property, "1", PROPERTY_VALUE_MAX ) || (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) { @@ -88,6 +96,12 @@ ExLayer::ExLayer(SurfaceFlinger* flinger, const sp& client, (atoi(property) == 1)) { mIsGPUAllowedForProtected = true; } + + if ((property_get("persist.sys.is_hdmi_primary", property, NULL) > 0) && + (atoi(property) == 1)) { + mIsHDMIPrimary = true; + } + } ExLayer::~ExLayer() { @@ -204,4 +218,172 @@ bool ExLayer::canAllowGPUForProtected() const { } } +void ExLayer::drawWithOpenGL(const sp& hw, + const Region& /* clip */, bool useIdentityTransform) const { + const State& s(getDrawingState()); +#ifdef QTI_BSP + uint32_t s3d_fmt = 0; + private_handle_t *pvt_handle = static_cast + (const_cast(mActiveBuffer->handle)); + if (pvt_handle != NULL) { + struct S3DSFRender_t s3dRender; + getMetaData(pvt_handle, GET_S3D_RENDER, &s3dRender); + + if ((s3dRender.DisplayId == static_cast(hw->getHwcDisplayId()) || + mIsHDMIPrimary) && s3dRender.GpuRender) { + clearMetaData(pvt_handle, SET_S3D_RENDER); + s3d_fmt = s3dRender.GpuS3dFormat; + } + } +#endif + computeGeometry(hw, mMesh, useIdentityTransform); + + /* + * NOTE: the way we compute the texture coordinates here produces + * different results than when we take the HWC path -- in the later case + * the "source crop" is rounded to texel boundaries. + * This can produce significantly different results when the texture + * is scaled by a large amount. + * + * The GL code below is more logical (imho), and the difference with + * HWC is due to a limitation of the HWC API to integers -- a question + * is suspend is whether we should ignore this problem or revert to + * GL composition when a buffer scaling is applied (maybe with some + * minimal value)? Or, we could make GL behave like HWC -- but this feel + * like more of a hack. + */ + Rect win(s.active.w, s.active.h); + if(!s.active.crop.isEmpty()) { + win = s.active.crop; + } +#ifdef QTI_BSP + win = s.transform.transform(win); + win.intersect(hw->getViewport(), &win); + win = s.transform.inverse().transform(win); + win.intersect(Rect(s.active.w, s.active.h), &win); + win = reduce(win, s.activeTransparentRegion); +#else + win = reduce(win, s.activeTransparentRegion); +#endif + float left = float(win.left) / float(s.active.w); + float top = float(win.top) / float(s.active.h); + float right = float(win.right) / float(s.active.w); + float bottom = float(win.bottom) / float(s.active.h); + + // TODO: we probably want to generate the texture coords with the mesh + // here we assume that we only have 4 vertices + Mesh::VertexArray texCoords(mMesh.getTexCoordArray()); + texCoords[0] = vec2(left, 1.0f - top); + texCoords[1] = vec2(left, 1.0f - bottom); + texCoords[2] = vec2(right, 1.0f - bottom); + texCoords[3] = vec2(right, 1.0f - top); + +#ifdef QTI_BSP + computeGeometryS3D(hw, mMesh, mMeshLeftTop, mMeshRightBottom, s3d_fmt); +#endif + + RenderEngine& engine(mFlinger->getRenderEngine()); + engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha); + +#ifdef QTI_BSP + if (s3d_fmt != HWC_S3DMODE_NONE) { + engine.setScissor(0, 0, hw->getWidth(), hw->getHeight()); + engine.drawMesh(mMeshLeftTop); + engine.drawMesh(mMeshRightBottom); + } else { +#endif + engine.drawMesh(mMesh); +#ifdef QTI_BSP + } +#endif + + engine.disableBlending(); +} + +#ifdef QTI_BSP +void ExLayer::computeGeometryS3D(const sp& hw, Mesh& mesh, + Mesh& meshLeftTop, Mesh &meshRightBottom, uint32_t s3d_fmt) const +{ + Mesh::VertexArray position(mesh.getPositionArray()); + Mesh::VertexArray positionLeftTop(meshLeftTop.getPositionArray()); + Mesh::VertexArray positionRightBottom(meshRightBottom.getPositionArray()); + Mesh::VertexArray texCoords(mesh.getTexCoordArray()); + Mesh::VertexArray texCoordsLeftTop(meshLeftTop.getTexCoordArray()); + Mesh::VertexArray texCoordsRightBottom(meshRightBottom.getTexCoordArray()); + + Rect scissor = hw->getBounds(); + + if(s3d_fmt == HWC_S3DMODE_NONE) { + return; + } + + uint32_t count = mesh.getVertexCount(); + while(count--) { + positionLeftTop[count] = positionRightBottom[count] = position[count]; + texCoordsLeftTop[count] = texCoordsRightBottom[count] = texCoords[count]; + } + + switch (s3d_fmt) { + case HWC_S3DMODE_LR: + case HWC_S3DMODE_RL: + { + positionLeftTop[0].x = (position[0].x - scissor.left) / 2.0f + scissor.left; + positionLeftTop[1].x = (position[1].x - scissor.left) / 2.0f + scissor.left; + positionLeftTop[2].x = (position[2].x - scissor.left) / 2.0f + scissor.left; + positionLeftTop[3].x = (position[3].x - scissor.left) / 2.0f + scissor.left; + + positionRightBottom[0].x = positionLeftTop[0].x + scissor.getWidth()/2; + positionRightBottom[1].x = positionLeftTop[1].x + scissor.getWidth()/2; + positionRightBottom[2].x = positionLeftTop[2].x + scissor.getWidth()/2; + positionRightBottom[3].x = positionLeftTop[3].x + scissor.getWidth()/2; + + if(isYuvLayer()) { + texCoordsLeftTop[0].x = texCoords[0].x / 2.0f; + texCoordsLeftTop[1].x = texCoords[1].x / 2.0f; + texCoordsLeftTop[2].x = texCoords[2].x / 2.0f; + texCoordsLeftTop[3].x = texCoords[3].x / 2.0f; + + texCoordsRightBottom[0].x = texCoordsLeftTop[0].x + 0.5f; + texCoordsRightBottom[1].x = texCoordsLeftTop[1].x + 0.5f; + texCoordsRightBottom[2].x = texCoordsLeftTop[2].x + 0.5f; + texCoordsRightBottom[3].x = texCoordsLeftTop[3].x + 0.5f; + } + break; + } + case HWC_S3DMODE_TB: + { + positionRightBottom[0].y = (position[0].y - scissor.top) / 2.0f + scissor.top; + positionRightBottom[1].y = (position[1].y - scissor.top) / 2.0f + scissor.top; + positionRightBottom[2].y = (position[2].y - scissor.top) / 2.0f + scissor.top; + positionRightBottom[3].y = (position[3].y - scissor.top) / 2.0f + scissor.top; + + positionLeftTop[0].y = positionRightBottom[0].y + scissor.getHeight() / 2.0f; + positionLeftTop[1].y = positionRightBottom[1].y + scissor.getHeight() / 2.0f; + positionLeftTop[2].y = positionRightBottom[2].y + scissor.getHeight() / 2.0f; + positionLeftTop[3].y = positionRightBottom[3].y + scissor.getHeight() / 2.0f; + + positionLeftTop[0].x = positionRightBottom[0].x = position[0].x; + positionLeftTop[1].x = positionRightBottom[1].x = position[1].x; + positionLeftTop[2].x = positionRightBottom[2].x = position[2].x; + positionLeftTop[3].x = positionRightBottom[3].x = position[3].x; + + if(isYuvLayer()) { + texCoordsRightBottom[0].y = texCoords[0].y / 2.0f; + texCoordsRightBottom[1].y = texCoords[1].y / 2.0f; + texCoordsRightBottom[2].y = texCoords[2].y / 2.0f; + texCoordsRightBottom[3].y = texCoords[3].y / 2.0f; + + texCoordsLeftTop[0].y = texCoordsRightBottom[0].y + 0.5f; + texCoordsLeftTop[1].y = texCoordsRightBottom[1].y + 0.5f; + texCoordsLeftTop[2].y = texCoordsRightBottom[2].y + 0.5f; + texCoordsLeftTop[3].y = texCoordsRightBottom[3].y + 0.5f; + } + break; + } + default: + break; + } +} +#endif + }; // namespace android diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExLayer.h b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.h index 01c74a810..9d22b5f52 100644 --- a/services/surfaceflinger/ExSurfaceFlinger/ExLayer.h +++ b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.h @@ -43,6 +43,22 @@ class ExSurfaceFlinger; class ExLayer : public Layer { public: +#ifdef QTI_BSP + enum { + /* + * HWC S3D_MODE is set by HWC driver to indicate that HWC driver can not support + * S3D standalone, need surfaceflinger help to draw layers twice to construct + * S3D framebuffer target. + */ + HWC_S3DMODE_NONE = 0x00000000, + HWC_S3DMODE_LR = 0x00000001, + HWC_S3DMODE_RL = 0x00000002, + HWC_S3DMODE_TB = 0x00000003, + HWC_S3DMODE_FP = 0x00000004, + HWC_S3DMODE_MAX = 0x00000005, + }; +#endif + ExLayer(SurfaceFlinger* flinger, const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags); virtual ~ExLayer(); @@ -57,11 +73,27 @@ public: HWComposer::HWCLayerInterface& layer); virtual bool canAllowGPUForProtected() const; +#ifdef QTI_BSP + virtual void computeGeometryS3D(const sp& hw, Mesh& mesh, + Mesh& meshLeftTop, Mesh &meshRightBottom, uint32_t s3d_fmt) const; +#endif protected: bool mDebugLogs; bool isDebug() { return mDebugLogs; } bool mIsGPUAllowedForProtected; + bool mIsHDMIPrimary; + +private: +#ifdef QTI_BSP + // The mesh used to draw the layer in GLES composition mode for s3d left/top + mutable Mesh mMeshLeftTop; + // The mesh used to draw the layer in GLES composition mode for s3d right/bottom + mutable Mesh mMeshRightBottom; + + virtual void drawWithOpenGL(const sp& hw, const Region& clip, + bool useIdentityTransform) const; }; +#endif }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 02d6f1639..0d6ec41ee 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -162,8 +162,13 @@ public: uint32_t getTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags); +#ifdef QTI_BSP + virtual void computeGeometry(const sp& hw, Mesh& mesh, + bool useIdentityTransform) const; +#else void computeGeometry(const sp& hw, Mesh& mesh, bool useIdentityTransform) const; +#endif Rect computeBounds(const Region& activeTransparentRegion) const; Rect computeBounds() const; @@ -392,9 +397,14 @@ private: // drawing void clearWithOpenGL(const sp& hw, const Region& clip, float r, float g, float b, float alpha) const; +#ifdef QTI_BSP + virtual void drawWithOpenGL(const sp& hw, const Region& clip, + bool useIdentityTransform) const; +#else void drawWithOpenGL(const sp& hw, const Region& clip, bool useIdentityTransform) const; +#endif // Temporary - Used only for LEGACY camera mode. uint32_t getProducerStickyTransform() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 97d3163eb..693e9d90f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -74,6 +74,7 @@ #include "DisplayHardware/FramebufferSurface.h" #include "DisplayHardware/HWComposer.h" +#include "ExSurfaceFlinger/ExHWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" #include "Effects/Daltonizer.h" @@ -2003,7 +2004,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const } // Never touch the framebuffer if we don't have any framebuffer layers +#ifdef QTI_BSP + const bool hasHwcComposition = hwc.hasHwcComposition(id) | + (reinterpret_cast(&hwc))->getS3DFlag(id); +#else const bool hasHwcComposition = hwc.hasHwcComposition(id); +#endif if (hasHwcComposition) { // when using overlays, we assume a fully transparent framebuffer // NOTE: we could reduce how much we need to clear, for instance diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 20d65c1ae..2003d6efa 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -146,6 +146,9 @@ private: friend class DisplayEventConnection; friend class Layer; friend class LayerDim; +#ifdef QTI_BSP + friend class ExLayer; +#endif friend class MonitoredProducer; friend class LayerBlur;