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