From 537364c7229cb7d5d63b4683a34e47db6aa013bd Mon Sep 17 00:00:00 2001 From: feifanz Date: Wed, 27 Apr 2016 12:23:28 +0800 Subject: SF: Add support to draw S3D framebuffer target Add support to draw S3D framebuffer target in case HWC driver can not handle due to resource or capability issue. Change-Id: I536fa4a03e246d51891045b692d5dc5be88f2adf CRs-fixed: 999055 --- .../surfaceflinger/ExSurfaceFlinger/ExLayer.cpp | 184 ++++++++++++++++++++- 1 file changed, 183 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp') diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExLayer.cpp index fa45579..5df34ed 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 -- cgit v1.1