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 <common/utils/HwcTrace.h>
17 #include <Hwcomposer.h>
18 #include <BufferManager.h>
19 #include <ips/anniedale/AnnRGBPlane.h>
20 #include <ips/tangier/TngGrallocBuffer.h>
21 #include <ips/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 
reset()48 bool AnnRGBPlane::reset()
49 {
50     while (!mScalingBufferMap.isEmpty()) {
51         uint32_t handle = mScalingBufferMap.valueAt(0);
52         Hwcomposer::getInstance().getBufferManager()->freeGrallocBuffer(handle);
53         mScalingBufferMap.removeItemsAt(0);
54     }
55 
56     return DisplayPlane::reset();
57 }
58 
flip(void *)59 bool AnnRGBPlane::flip(void*)
60 {
61     if (mForceScaling) {
62         BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
63         if (!bm->blitGrallocBuffer(mScalingSource, mScalingTarget, mDisplayCrop, 0)) {
64             ELOGTRACE("Failed to blit RGB buffer.");
65             return false;
66         }
67     }
68 
69     return true;
70 }
71 
getContext() const72 void* AnnRGBPlane::getContext() const
73 {
74     CTRACE();
75     return (void *)&mContext;
76 }
77 
setZOrderConfig(ZOrderConfig &,void *)78 void AnnRGBPlane::setZOrderConfig(ZOrderConfig& /* config */, void * /* nativeConfig */)
79 {
80     CTRACE();
81 }
82 
setDataBuffer(uint32_t handle)83 bool AnnRGBPlane::setDataBuffer(uint32_t handle)
84 {
85     if (!handle) {
86         if (!mForceScaling) {
87             setFramebufferTarget(handle);
88             return true;
89         } else {
90             ELOGTRACE("Invalid handle while scaling is required.");
91             return false;
92         }
93     }
94 
95     if (mForceScaling) {
96         BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
97         ssize_t index = mScalingBufferMap.indexOfKey(handle);
98         if (index < 0) {
99             mScalingTarget = bm->allocGrallocBuffer(
100                     mDisplayWidth,
101                     mDisplayHeight,
102                     HAL_PIXEL_FORMAT_RGBA_8888,
103                     GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE);
104             if (!mScalingTarget) {
105                 ELOGTRACE("Failed to allocate gralloc buffer.");
106                 return false;
107             }
108 
109             if (mScalingBufferMap.size() >= MAX_SCALING_BUF_COUNT) {
110                 while (!mScalingBufferMap.isEmpty()) {
111                     uint32_t handle = mScalingBufferMap.valueAt(0);
112                     bm->freeGrallocBuffer(handle);
113                     mScalingBufferMap.removeItemsAt(0);
114                 }
115             }
116 
117             mScalingBufferMap.add(handle, mScalingTarget);
118         } else {
119             mScalingTarget = mScalingBufferMap.valueAt(index);
120         }
121         mScalingSource = handle;
122         handle = mScalingTarget;
123     }
124 
125     TngGrallocBuffer tmpBuf(handle);
126     uint32_t usage;
127     bool ret;
128 
129     ALOGTRACE("handle = %#x", handle);
130 
131     usage = tmpBuf.getUsage();
132     if (GRALLOC_USAGE_HW_FB & usage) {
133         setFramebufferTarget(handle);
134         return true;
135     }
136 
137     // use primary as a sprite
138     ret = DisplayPlane::setDataBuffer(handle);
139     if (ret == false) {
140         ELOGTRACE("failed to set data buffer");
141         return ret;
142     }
143 
144     return true;
145 }
146 
setDataBuffer(BufferMapper & mapper)147 bool AnnRGBPlane::setDataBuffer(BufferMapper& mapper)
148 {
149     int bpp;
150     int srcX, srcY, srcW, srcH;
151     int dstX, dstY, dstW, dstH;
152     uint32_t spriteFormat;
153     uint32_t stride;
154     uint32_t linoff;
155     uint32_t planeAlpha;
156     drmModeModeInfoPtr mode = &mModeInfo;
157 
158     CTRACE();
159 
160     // setup plane position
161     dstX = mPosition.x;
162     dstY = mPosition.y;
163     dstW = mPosition.w;
164     dstH = mPosition.h;
165 
166     checkPosition(dstX, dstY, dstW, dstH);
167 
168     // setup plane format
169     if (!PixelFormat::convertFormat(mapper.getFormat(), spriteFormat, bpp)) {
170         ELOGTRACE("unsupported format %#x", mapper.getFormat());
171         return false;
172     }
173 
174     // setup stride and source buffer crop
175     srcX = mapper.getCrop().x;
176     srcY = mapper.getCrop().y;
177     srcW = mapper.getWidth();
178     srcH = mapper.getHeight();
179     stride = mapper.getStride().rgb.stride;
180 
181     if (mPanelOrientation == PANEL_ORIENTATION_180)
182         linoff = srcY * stride + srcX * bpp + (mapper.getCrop().h  - 1) * stride + (mapper.getCrop().w - 1) * bpp;
183     else
184         linoff = srcY * stride + srcX * bpp;
185 
186     // unlikely happen, but still we need make sure linoff is valid
187     if (linoff > (stride * mapper.getHeight())) {
188         ELOGTRACE("invalid source crop");
189         return false;
190     }
191 
192     // update context
193     if (mType == PLANE_SPRITE)
194         mContext.type = DC_SPRITE_PLANE;
195     else
196         mContext.type = DC_PRIMARY_PLANE;
197 
198     // setup plane alpha
199     if (0 < mPlaneAlpha && mPlaneAlpha < 0xff) {
200        planeAlpha = mPlaneAlpha | 0x80000000;
201     } else {
202        // disable plane alpha to offload HW
203        planeAlpha = 0xff;
204     }
205 
206     mContext.ctx.sp_ctx.index = mIndex;
207     mContext.ctx.sp_ctx.pipe = mDevice;
208     mContext.ctx.sp_ctx.cntr = spriteFormat | 0x80000000;
209     mContext.ctx.sp_ctx.linoff = linoff;
210     mContext.ctx.sp_ctx.stride = stride;
211 
212     // turn off premultipled alpha blending for HWC_BLENDING_COVERAGE
213     if (mBlending == HWC_BLENDING_COVERAGE) {
214         mContext.ctx.sp_ctx.cntr |= (0x1 << 23);
215     }
216 
217     if (mPanelOrientation == PANEL_ORIENTATION_180)
218         mContext.ctx.sp_ctx.cntr |= (0x1 << 15);
219 
220     if (mapper.isCompression()) {
221         mContext.ctx.sp_ctx.stride = align_to(srcW, 32) * 4;
222         mContext.ctx.sp_ctx.linoff = (align_to(srcW, 32) * srcH / 64) - 1;
223         mContext.ctx.sp_ctx.tileoff = (srcY & 0xfff) << 16 | (srcX & 0xfff);
224         mContext.ctx.sp_ctx.cntr |= (0x1 << 11);
225     }
226 
227     mContext.ctx.sp_ctx.surf = mapper.getGttOffsetInPage(0) << 12;
228 
229     if (mPanelOrientation == PANEL_ORIENTATION_180) {
230         if (mode->vdisplay && mode->hdisplay)
231             mContext.ctx.sp_ctx.pos = ((mode->vdisplay - dstY - dstH) & 0xfff) << 16 | ((mode->hdisplay - dstX - dstW) & 0xfff);
232         else
233             mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff);
234     } else {
235         mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff);
236     }
237 
238     mContext.ctx.sp_ctx.size =
239         ((dstH - 1) & 0xfff) << 16 | ((dstW - 1) & 0xfff);
240     mContext.ctx.sp_ctx.contalpa = planeAlpha;
241     mContext.ctx.sp_ctx.update_mask = SPRITE_UPDATE_ALL;
242 
243     VLOGTRACE("type = %d, index = %d, cntr = %#x, linoff = %#x, stride = %#x,"
244           "surf = %#x, pos = %#x, size = %#x, contalpa = %#x", mType, mIndex,
245           mContext.ctx.sp_ctx.cntr,
246           mContext.ctx.sp_ctx.linoff,
247           mContext.ctx.sp_ctx.stride,
248           mContext.ctx.sp_ctx.surf,
249           mContext.ctx.sp_ctx.pos,
250           mContext.ctx.sp_ctx.size,
251           mContext.ctx.sp_ctx.contalpa);
252     return true;
253 }
254 
enablePlane(bool enabled)255 bool AnnRGBPlane::enablePlane(bool enabled)
256 {
257     RETURN_FALSE_IF_NOT_INIT();
258 
259     struct drm_psb_register_rw_arg arg;
260     memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
261     if (enabled) {
262         arg.plane_enable_mask = 1;
263     } else {
264         arg.plane_disable_mask = 1;
265     }
266 
267     if (mType == PLANE_SPRITE)
268         arg.plane.type = DC_SPRITE_PLANE;
269     else
270         arg.plane.type = DC_PRIMARY_PLANE;
271 
272     arg.plane.index = mIndex;
273     arg.plane.ctx = 0;
274 
275     // issue ioctl
276     Drm *drm = Hwcomposer::getInstance().getDrm();
277     bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
278     if (ret == false) {
279         WLOGTRACE("plane enabling (%d) failed with error code %d", enabled, ret);
280         return false;
281     }
282 
283     return true;
284 }
285 
isDisabled()286 bool AnnRGBPlane::isDisabled()
287 {
288     RETURN_FALSE_IF_NOT_INIT();
289 
290     struct drm_psb_register_rw_arg arg;
291     memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
292 
293     if (mType == PLANE_SPRITE)
294         arg.plane.type = DC_SPRITE_PLANE;
295     else
296         arg.plane.type = DC_PRIMARY_PLANE;
297 
298     arg.get_plane_state_mask = 1;
299     arg.plane.index = mIndex;
300     arg.plane.ctx = 0;
301 
302     // issue ioctl
303     Drm *drm = Hwcomposer::getInstance().getDrm();
304     bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
305     if (ret == false) {
306         WLOGTRACE("plane state query failed with error code %d", ret);
307         return false;
308     }
309 
310     return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
311 }
312 
postFlip()313 void AnnRGBPlane::postFlip()
314 {
315     // prevent mUpdateMasks from being reset
316     // skipping flip may cause flicking
317 }
318 
setFramebufferTarget(uint32_t handle)319 void AnnRGBPlane::setFramebufferTarget(uint32_t handle)
320 {
321     uint32_t stride;
322     uint32_t planeAlpha;
323 
324     CTRACE();
325 
326     // do not need to update the buffer handle
327     if (mCurrentDataBuffer != handle)
328         mUpdateMasks |= PLANE_BUFFER_CHANGED;
329     else
330         mUpdateMasks &= ~PLANE_BUFFER_CHANGED;
331 
332     // if no update then do Not need set data buffer
333     if (!mUpdateMasks)
334         return;
335 
336     // don't need to map data buffer for primary plane
337     if (mType == PLANE_SPRITE)
338         mContext.type = DC_SPRITE_PLANE;
339     else
340         mContext.type = DC_PRIMARY_PLANE;
341 
342     stride = align_to((4 * align_to(mPosition.w, 32)), 64);
343 
344     if (0 < mPlaneAlpha && mPlaneAlpha < 0xff) {
345        planeAlpha = mPlaneAlpha | 0x80000000;
346     } else {
347        // disable plane alpha to offload HW
348        planeAlpha = 0xff;
349     }
350 
351     // FIXME: use sprite context for sprite plane
352     mContext.ctx.prim_ctx.update_mask = SPRITE_UPDATE_ALL;
353     mContext.ctx.prim_ctx.index = mIndex;
354     mContext.ctx.prim_ctx.pipe = mDevice;
355 
356     if (mPanelOrientation == PANEL_ORIENTATION_180)
357         mContext.ctx.prim_ctx.linoff = (mPosition.h  - 1) * stride + (mPosition.w - 1) * 4;
358     else
359         mContext.ctx.prim_ctx.linoff = 0;
360 
361     mContext.ctx.prim_ctx.stride = stride;
362     mContext.ctx.prim_ctx.tileoff = 0;
363     mContext.ctx.prim_ctx.pos = 0;
364     mContext.ctx.prim_ctx.size =
365         ((mPosition.h - 1) & 0xfff) << 16 | ((mPosition.w - 1) & 0xfff);
366     mContext.ctx.prim_ctx.surf = 0;
367     mContext.ctx.prim_ctx.contalpa = planeAlpha;
368     mContext.ctx.prim_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888;
369     mContext.ctx.prim_ctx.cntr |= 0x80000000;
370 
371     // turn off premultipled alpha blending for HWC_BLENDING_COVERAGE
372     if (mBlending == HWC_BLENDING_COVERAGE) {
373         mContext.ctx.prim_ctx.cntr |= (0x1 << 23);
374     }
375 
376     if (mPanelOrientation == PANEL_ORIENTATION_180)
377         mContext.ctx.prim_ctx.cntr |= (0x1 << 15);
378 
379     VLOGTRACE("type = %d, index = %d, cntr = %#x, linoff = %#x, stride = %#x,"
380           "surf = %#x, pos = %#x, size = %#x, contalpa = %#x", mType, mIndex,
381           mContext.ctx.prim_ctx.cntr,
382           mContext.ctx.prim_ctx.linoff,
383           mContext.ctx.prim_ctx.stride,
384           mContext.ctx.prim_ctx.surf,
385           mContext.ctx.prim_ctx.pos,
386           mContext.ctx.prim_ctx.size,
387           mContext.ctx.sp_ctx.contalpa);
388 
389     mCurrentDataBuffer = handle;
390 }
391 
392 } // namespace intel
393 } // namespace android
394