ExLayer.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are
  5. * met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above
  9. * copyright notice, this list of conditions and the following
  10. * disclaimer in the documentation and/or other materials provided
  11. * with the distribution.
  12. * * Neither the name of The Linux Foundation nor the names of its
  13. * contributors may be used to endorse or promote products derived
  14. * from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  17. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  20. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  23. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  24. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  25. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  26. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include <stdlib.h>
  29. #include <stdint.h>
  30. #include <sys/types.h>
  31. #include <utils/Errors.h>
  32. #include <utils/Log.h>
  33. #include <ui/GraphicBuffer.h>
  34. #ifdef QTI_BSP
  35. #include <gralloc_priv.h>
  36. #include <qdMetaData.h>
  37. #include <hardware/display_defs.h>
  38. #endif
  39. #include "ExLayer.h"
  40. #include "RenderEngine/RenderEngine.h"
  41. namespace android {
  42. /* Calculates the aspect ratio for external display based on the video w/h */
  43. static Rect getAspectRatio(const sp<const DisplayDevice>& hw,
  44. const int& srcWidth, const int& srcHeight) {
  45. Rect outRect;
  46. int fbWidth = hw->getWidth();
  47. int fbHeight = hw->getHeight();
  48. int x , y = 0;
  49. int w = fbWidth, h = fbHeight;
  50. if (srcWidth * fbHeight > fbWidth * srcHeight) {
  51. h = fbWidth * srcHeight / srcWidth;
  52. w = fbWidth;
  53. } else if (srcWidth * fbHeight < fbWidth * srcHeight) {
  54. w = fbHeight * srcWidth / srcHeight;
  55. h = fbHeight;
  56. }
  57. x = (fbWidth - w) / 2;
  58. y = (fbHeight - h) / 2;
  59. outRect.left = x;
  60. outRect.top = y;
  61. outRect.right = x + w;
  62. outRect.bottom = y + h;
  63. return outRect;
  64. }
  65. ExLayer::ExLayer(SurfaceFlinger* flinger, const sp<Client>& client,
  66. const String8& name, uint32_t w, uint32_t h, uint32_t flags)
  67. #ifdef QTI_BSP
  68. : Layer(flinger, client, name, w, h, flags),
  69. mMeshLeftTop(Mesh::TRIANGLE_FAN, 4, 2, 2),
  70. mMeshRightBottom(Mesh::TRIANGLE_FAN, 4, 2, 2) {
  71. #else
  72. : Layer(flinger, client, name, w, h, flags) {
  73. #endif
  74. char property[PROPERTY_VALUE_MAX] = {0};
  75. mDebugLogs = false;
  76. mIsGPUAllowedForProtected = false;
  77. mIsHDMIPrimary = false;
  78. if((property_get("persist.debug.qdframework.logs", property, NULL) > 0) &&
  79. (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
  80. (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
  81. mDebugLogs = true;
  82. }
  83. ALOGD_IF(isDebug(),"Creating custom Layer %s",__FUNCTION__);
  84. if ((property_get("persist.gralloc.cp.level3", property, NULL) > 0) &&
  85. (atoi(property) == 1)) {
  86. mIsGPUAllowedForProtected = true;
  87. }
  88. if ((property_get("persist.sys.is_hdmi_primary", property, NULL) > 0) &&
  89. (atoi(property) == 1)) {
  90. mIsHDMIPrimary = true;
  91. }
  92. }
  93. ExLayer::~ExLayer() {
  94. }
  95. bool ExLayer::isExtOnly() const {
  96. const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
  97. if (activeBuffer != 0) {
  98. #ifdef QTI_BSP
  99. ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer();
  100. if(buffer) {
  101. private_handle_t* hnd = static_cast<private_handle_t*>
  102. (const_cast<native_handle_t*>(buffer->handle));
  103. /* return true if layer is EXT_ONLY */
  104. return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY));
  105. }
  106. #endif
  107. }
  108. return false;
  109. }
  110. bool ExLayer::isIntOnly() const {
  111. const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
  112. if (activeBuffer != 0) {
  113. #ifdef QTI_BSP
  114. ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer();
  115. if(buffer) {
  116. private_handle_t* hnd = static_cast<private_handle_t*>
  117. (const_cast<native_handle_t*>(buffer->handle));
  118. /* return true if layer is INT_ONLY */
  119. return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_INTERNAL_ONLY));
  120. }
  121. #endif
  122. }
  123. return false;
  124. }
  125. bool ExLayer::isSecureDisplay() const {
  126. const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
  127. if (activeBuffer != 0) {
  128. #ifdef QTI_BSP
  129. ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer();
  130. if(buffer) {
  131. private_handle_t* hnd = static_cast<private_handle_t*>
  132. (const_cast<native_handle_t*>(buffer->handle));
  133. /* return true if layer is SECURE_DISPLAY */
  134. return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
  135. }
  136. #endif
  137. }
  138. return false;
  139. }
  140. bool ExLayer::isYuvLayer() const {
  141. const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
  142. if(activeBuffer != 0) {
  143. #ifdef QTI_BSP
  144. ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer();
  145. if(buffer) {
  146. private_handle_t* hnd = static_cast<private_handle_t*>
  147. (const_cast<native_handle_t*>(buffer->handle));
  148. /* return true if layer is YUV */
  149. return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
  150. }
  151. #endif
  152. }
  153. return false;
  154. }
  155. void ExLayer::setPosition(const sp<const DisplayDevice>& hw,
  156. HWComposer::HWCLayerInterface& layer, const State& state) {
  157. /* Set dest_rect to display width and height, if external_only flag
  158. * for the layer is enabled or if its yuvLayer in extended mode.
  159. */
  160. uint32_t w = hw->getWidth();
  161. uint32_t h = hw->getHeight();
  162. bool extendedMode = ExSurfaceFlinger::isExtendedMode();
  163. if(isExtOnly()) {
  164. /* Position: fullscreen for ext_only */
  165. Rect r(0, 0, w, h);
  166. layer.setFrame(r);
  167. } else if(hw->getDisplayType() > 0 && (extendedMode && isYuvLayer())) {
  168. /* Need to position the video full screen on external with aspect ratio */
  169. Rect r = getAspectRatio(hw, state.active.w, state.active.h);
  170. layer.setFrame(r);
  171. }
  172. return;
  173. }
  174. void ExLayer::setAcquiredFenceIfBlit(int &fenceFd,
  175. HWComposer::HWCLayerInterface& layer) {
  176. #ifdef QTI_BSP
  177. if (layer.getCompositionType() == HWC_BLIT) {
  178. sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
  179. if (fence->isValid()) {
  180. fenceFd = fence->dup();
  181. if (fenceFd == -1) {
  182. ALOGW("%s: failed to dup layer fence, skipping sync: %d",
  183. __FUNCTION__,errno);
  184. }
  185. }
  186. }
  187. #else
  188. ALOGD_IF(isDebug(),"Not a BLIT Layer, compType = %d fencefd = %d",
  189. layer.getCompositionType(), fenceFd);
  190. #endif
  191. }
  192. bool ExLayer::canAllowGPUForProtected() const {
  193. if(isProtected()) {
  194. return mIsGPUAllowedForProtected;
  195. } else {
  196. return false;
  197. }
  198. }
  199. void ExLayer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
  200. const Region& /* clip */, bool useIdentityTransform) const {
  201. const State& s(getDrawingState());
  202. #if defined(QTI_BSP) && defined(SDM_TARGET)
  203. uint32_t s3d_fmt = 0;
  204. private_handle_t *pvt_handle = static_cast<private_handle_t *>
  205. (const_cast<native_handle_t*>(mActiveBuffer->handle));
  206. if (pvt_handle != NULL) {
  207. struct S3DSFRender_t s3dRender;
  208. getMetaData(pvt_handle, GET_S3D_RENDER, &s3dRender);
  209. if ((s3dRender.DisplayId == static_cast<uint32_t>(hw->getHwcDisplayId()) ||
  210. mIsHDMIPrimary) && s3dRender.GpuRender) {
  211. clearMetaData(pvt_handle, SET_S3D_RENDER);
  212. s3d_fmt = s3dRender.GpuS3dFormat;
  213. }
  214. }
  215. #endif
  216. computeGeometry(hw, mMesh, useIdentityTransform);
  217. /*
  218. * NOTE: the way we compute the texture coordinates here produces
  219. * different results than when we take the HWC path -- in the later case
  220. * the "source crop" is rounded to texel boundaries.
  221. * This can produce significantly different results when the texture
  222. * is scaled by a large amount.
  223. *
  224. * The GL code below is more logical (imho), and the difference with
  225. * HWC is due to a limitation of the HWC API to integers -- a question
  226. * is suspend is whether we should ignore this problem or revert to
  227. * GL composition when a buffer scaling is applied (maybe with some
  228. * minimal value)? Or, we could make GL behave like HWC -- but this feel
  229. * like more of a hack.
  230. */
  231. Rect win(s.active.w, s.active.h);
  232. if(!s.active.crop.isEmpty()) {
  233. win = s.active.crop;
  234. }
  235. #ifdef QTI_BSP
  236. win = s.transform.transform(win);
  237. win.intersect(hw->getViewport(), &win);
  238. win = s.transform.inverse().transform(win);
  239. win.intersect(Rect(s.active.w, s.active.h), &win);
  240. win = reduce(win, s.activeTransparentRegion);
  241. #else
  242. win = reduce(win, s.activeTransparentRegion);
  243. #endif
  244. float left = float(win.left) / float(s.active.w);
  245. float top = float(win.top) / float(s.active.h);
  246. float right = float(win.right) / float(s.active.w);
  247. float bottom = float(win.bottom) / float(s.active.h);
  248. // TODO: we probably want to generate the texture coords with the mesh
  249. // here we assume that we only have 4 vertices
  250. Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>());
  251. texCoords[0] = vec2(left, 1.0f - top);
  252. texCoords[1] = vec2(left, 1.0f - bottom);
  253. texCoords[2] = vec2(right, 1.0f - bottom);
  254. texCoords[3] = vec2(right, 1.0f - top);
  255. #if defined(QTI_BSP) && defined(SDM_TARGET)
  256. computeGeometryS3D(hw, mMesh, mMeshLeftTop, mMeshRightBottom, s3d_fmt);
  257. #endif
  258. RenderEngine& engine(mFlinger->getRenderEngine());
  259. engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
  260. #if defined(QTI_BSP) && defined(SDM_TARGET)
  261. if (s3d_fmt != HWC_S3DMODE_NONE) {
  262. engine.setScissor(0, 0, hw->getWidth(), hw->getHeight());
  263. engine.drawMesh(mMeshLeftTop);
  264. engine.drawMesh(mMeshRightBottom);
  265. } else {
  266. #endif
  267. engine.drawMesh(mMesh);
  268. #if defined(QTI_BSP) && defined(SDM_TARGET)
  269. }
  270. #endif
  271. engine.disableBlending();
  272. }
  273. #ifdef QTI_BSP
  274. void ExLayer::computeGeometryS3D(const sp<const DisplayDevice>& hw, Mesh& mesh,
  275. Mesh& meshLeftTop, Mesh &meshRightBottom, uint32_t s3d_fmt) const
  276. {
  277. Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
  278. Mesh::VertexArray<vec2> positionLeftTop(meshLeftTop.getPositionArray<vec2>());
  279. Mesh::VertexArray<vec2> positionRightBottom(meshRightBottom.getPositionArray<vec2>());
  280. Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
  281. Mesh::VertexArray<vec2> texCoordsLeftTop(meshLeftTop.getTexCoordArray<vec2>());
  282. Mesh::VertexArray<vec2> texCoordsRightBottom(meshRightBottom.getTexCoordArray<vec2>());
  283. Rect scissor = hw->getBounds();
  284. if(s3d_fmt == HWC_S3DMODE_NONE) {
  285. return;
  286. }
  287. uint32_t count = mesh.getVertexCount();
  288. while(count--) {
  289. positionLeftTop[count] = positionRightBottom[count] = position[count];
  290. texCoordsLeftTop[count] = texCoordsRightBottom[count] = texCoords[count];
  291. }
  292. switch (s3d_fmt) {
  293. case HWC_S3DMODE_LR:
  294. case HWC_S3DMODE_RL:
  295. {
  296. positionLeftTop[0].x = (position[0].x - scissor.left) / 2.0f + scissor.left;
  297. positionLeftTop[1].x = (position[1].x - scissor.left) / 2.0f + scissor.left;
  298. positionLeftTop[2].x = (position[2].x - scissor.left) / 2.0f + scissor.left;
  299. positionLeftTop[3].x = (position[3].x - scissor.left) / 2.0f + scissor.left;
  300. positionRightBottom[0].x = positionLeftTop[0].x + scissor.getWidth()/2;
  301. positionRightBottom[1].x = positionLeftTop[1].x + scissor.getWidth()/2;
  302. positionRightBottom[2].x = positionLeftTop[2].x + scissor.getWidth()/2;
  303. positionRightBottom[3].x = positionLeftTop[3].x + scissor.getWidth()/2;
  304. if(isYuvLayer()) {
  305. texCoordsLeftTop[0].x = texCoords[0].x / 2.0f;
  306. texCoordsLeftTop[1].x = texCoords[1].x / 2.0f;
  307. texCoordsLeftTop[2].x = texCoords[2].x / 2.0f;
  308. texCoordsLeftTop[3].x = texCoords[3].x / 2.0f;
  309. texCoordsRightBottom[0].x = texCoordsLeftTop[0].x + 0.5f;
  310. texCoordsRightBottom[1].x = texCoordsLeftTop[1].x + 0.5f;
  311. texCoordsRightBottom[2].x = texCoordsLeftTop[2].x + 0.5f;
  312. texCoordsRightBottom[3].x = texCoordsLeftTop[3].x + 0.5f;
  313. }
  314. break;
  315. }
  316. case HWC_S3DMODE_TB:
  317. {
  318. positionRightBottom[0].y = (position[0].y - scissor.top) / 2.0f + scissor.top;
  319. positionRightBottom[1].y = (position[1].y - scissor.top) / 2.0f + scissor.top;
  320. positionRightBottom[2].y = (position[2].y - scissor.top) / 2.0f + scissor.top;
  321. positionRightBottom[3].y = (position[3].y - scissor.top) / 2.0f + scissor.top;
  322. positionLeftTop[0].y = positionRightBottom[0].y + scissor.getHeight() / 2.0f;
  323. positionLeftTop[1].y = positionRightBottom[1].y + scissor.getHeight() / 2.0f;
  324. positionLeftTop[2].y = positionRightBottom[2].y + scissor.getHeight() / 2.0f;
  325. positionLeftTop[3].y = positionRightBottom[3].y + scissor.getHeight() / 2.0f;
  326. positionLeftTop[0].x = positionRightBottom[0].x = position[0].x;
  327. positionLeftTop[1].x = positionRightBottom[1].x = position[1].x;
  328. positionLeftTop[2].x = positionRightBottom[2].x = position[2].x;
  329. positionLeftTop[3].x = positionRightBottom[3].x = position[3].x;
  330. if(isYuvLayer()) {
  331. texCoordsRightBottom[0].y = texCoords[0].y / 2.0f;
  332. texCoordsRightBottom[1].y = texCoords[1].y / 2.0f;
  333. texCoordsRightBottom[2].y = texCoords[2].y / 2.0f;
  334. texCoordsRightBottom[3].y = texCoords[3].y / 2.0f;
  335. texCoordsLeftTop[0].y = texCoordsRightBottom[0].y + 0.5f;
  336. texCoordsLeftTop[1].y = texCoordsRightBottom[1].y + 0.5f;
  337. texCoordsLeftTop[2].y = texCoordsRightBottom[2].y + 0.5f;
  338. texCoordsLeftTop[3].y = texCoordsRightBottom[3].y + 0.5f;
  339. }
  340. break;
  341. }
  342. default:
  343. break;
  344. }
  345. }
  346. #endif
  347. }; // namespace android