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 <HwcTrace.h>
17 #include <Hwcomposer.h>
18 #include <BufferManager.h>
19 #include <anniedale/AnnRGBPlane.h>
20 #include <tangier/TngGrallocBuffer.h>
21 #include <common/PixelFormat.h>
22 
23 namespace android {
24 namespace intel {
25 
AnnRGBPlane(int index,int type,int disp)26 AnnRGBPlane::AnnRGBPlane(int index, int type, int disp)
27     : DisplayPlane(index, type, disp)
28 {
29     CTRACE();
30     memset(&mContext, 0, sizeof(mContext));
31 }
32 
~AnnRGBPlane()33 AnnRGBPlane::~AnnRGBPlane()
34 {
35     CTRACE();
36 }
37 
enable()38 bool AnnRGBPlane::enable()
39 {
40     return enablePlane(true);
41 }
42 
disable()43 bool AnnRGBPlane::disable()
44 {
45     return enablePlane(false);
46 }
47 
getContext() const48 void* AnnRGBPlane::getContext() const
49 {
50     CTRACE();
51     return (void *)&mContext;
52 }
53 
setZOrderConfig(ZOrderConfig & config,void * nativeConfig)54 void AnnRGBPlane::setZOrderConfig(ZOrderConfig& config, void *nativeConfig)
55 {
56     CTRACE();
57 }
58 
setDataBuffer(buffer_handle_t handle)59 bool AnnRGBPlane::setDataBuffer(buffer_handle_t handle)
60 {
61     if (!handle) {
62         setFramebufferTarget(handle);
63         return true;
64     }
65 
66     TngGrallocBuffer tmpBuf(handle);
67     uint32_t usage;
68     bool ret;
69 
70     ATRACE("handle = %#x", handle);
71 
72     usage = tmpBuf.getUsage();
73     if (GRALLOC_USAGE_HW_FB & usage) {
74         setFramebufferTarget(handle);
75         return true;
76     }
77 
78     // use primary as a sprite
79     ret = DisplayPlane::setDataBuffer(handle);
80     if (ret == false) {
81         ETRACE("failed to set data buffer");
82         return ret;
83     }
84 
85     return true;
86 }
87 
setDataBuffer(BufferMapper & mapper)88 bool AnnRGBPlane::setDataBuffer(BufferMapper& mapper)
89 {
90     int bpp;
91     int srcX, srcY, srcW, srcH;
92     int dstX, dstY, dstW, dstH;
93     uint32_t spriteFormat;
94     uint32_t stride;
95     uint32_t linoff;
96     uint32_t planeAlpha;
97     drmModeModeInfoPtr mode = &mModeInfo;
98 
99     CTRACE();
100 
101     // setup plane position
102     dstX = mPosition.x;
103     dstY = mPosition.y;
104     dstW = mPosition.w;
105     dstH = mPosition.h;
106 
107     checkPosition(dstX, dstY, dstW, dstH);
108 
109     // setup plane format
110     if (!PixelFormat::convertFormat(mapper.getFormat(), spriteFormat, bpp)) {
111         ETRACE("unsupported format %#x", mapper.getFormat());
112         return false;
113     }
114 
115     // setup stride and source buffer crop
116     srcX = mapper.getCrop().x;
117     srcY = mapper.getCrop().y;
118     srcW = mapper.getWidth();
119     srcH = mapper.getHeight();
120     stride = mapper.getStride().rgb.stride;
121 
122     if (mPanelOrientation == PANEL_ORIENTATION_180)
123         linoff = srcY * stride + srcX * bpp + (mapper.getCrop().h  - 1) * stride + (mapper.getCrop().w - 1) * bpp;
124     else
125         linoff = srcY * stride + srcX * bpp;
126 
127     // unlikely happen, but still we need make sure linoff is valid
128     if (linoff > (stride * mapper.getHeight())) {
129         ETRACE("invalid source crop");
130         return false;
131     }
132 
133     // update context
134     if (mType == PLANE_SPRITE)
135         mContext.type = DC_SPRITE_PLANE;
136     else
137         mContext.type = DC_PRIMARY_PLANE;
138 
139     // setup plane alpha
140     if (0 < mPlaneAlpha && mPlaneAlpha < 0xff) {
141        planeAlpha = mPlaneAlpha | 0x80000000;
142     } else {
143        // disable plane alpha to offload HW
144        planeAlpha = 0xff;
145     }
146 
147     mContext.ctx.sp_ctx.index = mIndex;
148     mContext.ctx.sp_ctx.pipe = mDevice;
149     mContext.ctx.sp_ctx.cntr = spriteFormat | 0x80000000;
150     mContext.ctx.sp_ctx.linoff = linoff;
151     mContext.ctx.sp_ctx.stride = stride;
152 
153     // turn off premultipled alpha blending for HWC_BLENDING_COVERAGE
154     if (mBlending == HWC_BLENDING_COVERAGE) {
155         mContext.ctx.sp_ctx.cntr |= (0x1 << 23);
156     }
157 
158     if (mPanelOrientation == PANEL_ORIENTATION_180)
159         mContext.ctx.sp_ctx.cntr |= (0x1 << 15);
160 
161     if (mapper.isCompression()) {
162         mContext.ctx.sp_ctx.stride = align_to(srcW, 32) * 4;
163         mContext.ctx.sp_ctx.linoff = (align_to(srcW, 32) * srcH / 64) - 1;
164         mContext.ctx.sp_ctx.tileoff = (srcY & 0xfff) << 16 | (srcX & 0xfff);
165         mContext.ctx.sp_ctx.cntr |= (0x1 << 11);
166     }
167 
168     mContext.ctx.sp_ctx.surf = mapper.getGttOffsetInPage(0) << 12;
169     mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);
170 
171     if (mPanelOrientation == PANEL_ORIENTATION_180) {
172         if (mode->vdisplay && mode->hdisplay)
173             mContext.ctx.sp_ctx.pos = ((mode->vdisplay - dstY - dstH) & 0xfff) << 16 | ((mode->hdisplay - dstX - dstW) & 0xfff);
174         else
175             mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff);
176     } else {
177         mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff);
178     }
179 
180     mContext.ctx.sp_ctx.size =
181         ((dstH - 1) & 0xfff) << 16 | ((dstW - 1) & 0xfff);
182     mContext.ctx.sp_ctx.contalpa = planeAlpha;
183     mContext.ctx.sp_ctx.update_mask = SPRITE_UPDATE_ALL;
184 
185     VTRACE("type = %d, index = %d, cntr = %#x, linoff = %#x, stride = %#x,"
186           "surf = %#x, pos = %#x, size = %#x, contalpa = %#x", mType, mIndex,
187           mContext.ctx.sp_ctx.cntr,
188           mContext.ctx.sp_ctx.linoff,
189           mContext.ctx.sp_ctx.stride,
190           mContext.ctx.sp_ctx.surf,
191           mContext.ctx.sp_ctx.pos,
192           mContext.ctx.sp_ctx.size,
193           mContext.ctx.sp_ctx.contalpa);
194     return true;
195 }
196 
enablePlane(bool enabled)197 bool AnnRGBPlane::enablePlane(bool enabled)
198 {
199     RETURN_FALSE_IF_NOT_INIT();
200 
201     struct drm_psb_register_rw_arg arg;
202     memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
203     if (enabled) {
204         arg.plane_enable_mask = 1;
205     } else {
206         arg.plane_disable_mask = 1;
207     }
208 
209     if (mType == PLANE_SPRITE)
210         arg.plane.type = DC_SPRITE_PLANE;
211     else
212         arg.plane.type = DC_PRIMARY_PLANE;
213 
214     arg.plane.index = mIndex;
215     arg.plane.ctx = 0;
216 
217     // issue ioctl
218     Drm *drm = Hwcomposer::getInstance().getDrm();
219     bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
220     if (ret == false) {
221         WTRACE("plane enabling (%d) failed with error code %d", enabled, ret);
222         return false;
223     }
224 
225     return true;
226 }
227 
isDisabled()228 bool AnnRGBPlane::isDisabled()
229 {
230     RETURN_FALSE_IF_NOT_INIT();
231 
232     struct drm_psb_register_rw_arg arg;
233     memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
234 
235     if (mType == PLANE_SPRITE)
236         arg.plane.type = DC_SPRITE_PLANE;
237     else
238         arg.plane.type = DC_PRIMARY_PLANE;
239 
240     arg.get_plane_state_mask = 1;
241     arg.plane.index = mIndex;
242     arg.plane.ctx = 0;
243 
244     // issue ioctl
245     Drm *drm = Hwcomposer::getInstance().getDrm();
246     bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
247     if (ret == false) {
248         WTRACE("plane state query failed with error code %d", ret);
249         return false;
250     }
251 
252     return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
253 }
254 
postFlip()255 void AnnRGBPlane::postFlip()
256 {
257     // prevent mUpdateMasks from being reset
258     // skipping flip may cause flicking
259 }
260 
setFramebufferTarget(buffer_handle_t handle)261 void AnnRGBPlane::setFramebufferTarget(buffer_handle_t handle)
262 {
263     uint32_t stride;
264     uint32_t planeAlpha;
265 
266     CTRACE();
267 
268     // do not need to update the buffer handle
269     if (mCurrentDataBuffer != handle)
270         mUpdateMasks |= PLANE_BUFFER_CHANGED;
271     else
272         mUpdateMasks &= ~PLANE_BUFFER_CHANGED;
273 
274     // if no update then do Not need set data buffer
275     if (!mUpdateMasks)
276         return;
277 
278     // don't need to map data buffer for primary plane
279     if (mType == PLANE_SPRITE)
280         mContext.type = DC_SPRITE_PLANE;
281     else
282         mContext.type = DC_PRIMARY_PLANE;
283 
284     stride = align_to((4 * align_to(mPosition.w, 32)), 64);
285 
286     if (0 < mPlaneAlpha && mPlaneAlpha < 0xff) {
287        planeAlpha = mPlaneAlpha | 0x80000000;
288     } else {
289        // disable plane alpha to offload HW
290        planeAlpha = 0xff;
291     }
292 
293     // FIXME: use sprite context for sprite plane
294     mContext.ctx.prim_ctx.update_mask = SPRITE_UPDATE_ALL;
295     mContext.ctx.prim_ctx.index = mIndex;
296     mContext.ctx.prim_ctx.pipe = mDevice;
297 
298     if (mPanelOrientation == PANEL_ORIENTATION_180)
299         mContext.ctx.prim_ctx.linoff = (mPosition.h  - 1) * stride + (mPosition.w - 1) * 4;
300     else
301         mContext.ctx.prim_ctx.linoff = 0;
302 
303     mContext.ctx.prim_ctx.stride = stride;
304     mContext.ctx.prim_ctx.tileoff = 0;
305     mContext.ctx.prim_ctx.pos = 0;
306     mContext.ctx.prim_ctx.size =
307         ((mPosition.h - 1) & 0xfff) << 16 | ((mPosition.w - 1) & 0xfff);
308     mContext.ctx.prim_ctx.surf = 0;
309     mContext.ctx.prim_ctx.contalpa = planeAlpha;
310     mContext.ctx.prim_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888;
311     mContext.ctx.prim_ctx.cntr |= 0x80000000;
312 
313     // turn off premultipled alpha blending for HWC_BLENDING_COVERAGE
314     if (mBlending == HWC_BLENDING_COVERAGE) {
315         mContext.ctx.prim_ctx.cntr |= (0x1 << 23);
316     }
317 
318     if (mPanelOrientation == PANEL_ORIENTATION_180)
319         mContext.ctx.prim_ctx.cntr |= (0x1 << 15);
320 
321     VTRACE("type = %d, index = %d, cntr = %#x, linoff = %#x, stride = %#x,"
322           "surf = %#x, pos = %#x, size = %#x, contalpa = %#x", mType, mIndex,
323           mContext.ctx.prim_ctx.cntr,
324           mContext.ctx.prim_ctx.linoff,
325           mContext.ctx.prim_ctx.stride,
326           mContext.ctx.prim_ctx.surf,
327           mContext.ctx.prim_ctx.pos,
328           mContext.ctx.prim_ctx.size,
329           mContext.ctx.sp_ctx.contalpa);
330 
331     mCurrentDataBuffer = handle;
332 }
333 
334 } // namespace intel
335 } // namespace android
336