1 /*
2 // Copyright (c) 2014 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #include <math.h>
17 #include <HwcTrace.h>
18 #include <Drm.h>
19 #include <Hwcomposer.h>
20 #include <tangier/TngOverlayPlane.h>
21 #include <tangier/TngGrallocBuffer.h>
22
23 namespace android {
24 namespace intel {
25
TngOverlayPlane(int index,int disp)26 TngOverlayPlane::TngOverlayPlane(int index, int disp)
27 : OverlayPlaneBase(index, disp),
28 mRotationBufProvider(NULL)
29 {
30 CTRACE();
31
32 memset(&mContext, 0, sizeof(mContext));
33 }
34
~TngOverlayPlane()35 TngOverlayPlane::~TngOverlayPlane()
36 {
37 CTRACE();
38 }
39
flip(void * ctx)40 bool TngOverlayPlane::flip(void *ctx)
41 {
42 RETURN_FALSE_IF_NOT_INIT();
43
44 if (!DisplayPlane::flip(ctx))
45 return false;
46
47 mContext.type = DC_OVERLAY_PLANE;
48 mContext.ctx.ov_ctx.ovadd = 0x0;
49 mContext.ctx.ov_ctx.ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
50 mContext.ctx.ov_ctx.index = mIndex;
51 mContext.ctx.ov_ctx.pipe = mDevice;
52 mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
53 mContext.ctx.ov_ctx.ovadd |= 0x1;
54
55 // move to next back buffer
56 //mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT;
57
58 VTRACE("ovadd = %#x, index = %d, device = %d",
59 mContext.ctx.ov_ctx.ovadd,
60 mIndex,
61 mDevice);
62
63 return true;
64 }
65
reset()66 bool TngOverlayPlane::reset()
67 {
68 OverlayPlaneBase::reset();
69 if (mRotationBufProvider)
70 mRotationBufProvider->reset();
71 return true;
72 }
73
getContext() const74 void* TngOverlayPlane::getContext() const
75 {
76 CTRACE();
77 return (void *)&mContext;
78 }
79
setDataBuffer(BufferMapper & mapper)80 bool TngOverlayPlane::setDataBuffer(BufferMapper& mapper)
81 {
82 if (OverlayPlaneBase::setDataBuffer(mapper) == false) {
83 return false;
84 }
85
86 if (mIsProtectedBuffer) {
87 // Bit 0: Decryption request, only allowed to change on a synchronous flip
88 // This request will be qualified with the separate decryption enable bit for OV
89 mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1;
90 mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1;
91 }
92
93 mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);
94 return true;
95 }
96
initialize(uint32_t bufferCount)97 bool TngOverlayPlane::initialize(uint32_t bufferCount)
98 {
99 if (!OverlayPlaneBase::initialize(bufferCount)) {
100 ETRACE("failed to initialize OverlayPlaneBase");
101 return false;
102 }
103
104 // setup rotation buffer
105 mRotationBufProvider = new RotationBufferProvider(mWsbm);
106 if (!mRotationBufProvider || !mRotationBufProvider->initialize()) {
107 DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider");
108 }
109 return true;
110 }
111
deinitialize()112 void TngOverlayPlane::deinitialize()
113 {
114 DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
115 OverlayPlaneBase::deinitialize();
116 }
117
rotatedBufferReady(BufferMapper & mapper,BufferMapper * & rotatedMapper)118 bool TngOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
119 {
120 struct VideoPayloadBuffer *payload;
121 VideoPayloadBuffer buffer_info;
122 uint32_t format;
123 // only NV12_VED has rotated buffer
124 format = mapper.getFormat();
125
126 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
127 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled &&
128 format != HAL_PIXEL_FORMAT_NV12) {
129 ETRACE("Invalid video format %#x", format);
130 return false;
131 }
132
133 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
134
135 if (payload == NULL && format == HAL_PIXEL_FORMAT_NV12) {
136 // need to populate buffer_info
137 void *p = mapper.getCpuAddress(SUB_BUFFER0);
138 if (!p) {
139 ETRACE("failed to get buffer user pointer");
140 return false;
141 }
142
143 bool ret = mRotationBufProvider->prepareBufferInfo(mapper.getWidth(),
144 mapper.getHeight(),
145 mapper.getStride().yuv.yStride,
146 &buffer_info, p);
147 if (ret == false) {
148 ETRACE("failed to prepare buffer info");
149 return false;
150 }
151 payload = &buffer_info;
152 }
153
154 // check payload
155 if (!payload) {
156 ETRACE("no payload found");
157 return false;
158 }
159
160 if (payload->force_output_method == FORCE_OUTPUT_GPU) {
161 ETRACE("Output method is not supported!");
162 return false;
163 }
164
165 if (payload->client_transform != mTransform ||
166 mBobDeinterlace) {
167 payload->hwc_timestamp = systemTime();
168 payload->layer_transform = mTransform;
169 if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
170 ETRACE("failed to setup rotation buffer");
171 return false;
172 }
173 }
174
175 rotatedMapper = getTTMMapper(mapper, payload);
176
177 return true;
178 }
179
flush(uint32_t flags)180 bool TngOverlayPlane::flush(uint32_t flags)
181 {
182 RETURN_FALSE_IF_NOT_INIT();
183 ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
184
185 if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE))
186 return false;
187
188 struct drm_psb_register_rw_arg arg;
189 memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
190
191 if (flags & PLANE_DISABLE)
192 arg.plane_disable_mask = 1;
193 else if (flags & PLANE_ENABLE)
194 arg.plane_enable_mask = 1;
195
196 arg.plane.type = DC_OVERLAY_PLANE;
197 arg.plane.index = mIndex;
198 arg.plane.ctx = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
199 // pipe select
200 arg.plane.ctx |= mPipeConfig;
201
202 if (flags & PLANE_DISABLE) {
203 DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
204 }
205
206 // issue ioctl
207 Drm *drm = Hwcomposer::getInstance().getDrm();
208 bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
209 if (ret == false) {
210 WTRACE("overlay update failed with error code %d", ret);
211 return false;
212 }
213
214 return true;
215 }
216
217 } // namespace intel
218 } // namespace android
219