AnnRGBPlane.cpp revision 3f021f9136639ae37de057ac74e5bc74b37e0fd6
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
23namespace android {
24namespace intel {
25
26AnnRGBPlane::AnnRGBPlane(int index, int type, int disp)
27    : DisplayPlane(index, type, disp)
28{
29    CTRACE();
30    memset(&mContext, 0, sizeof(mContext));
31}
32
33AnnRGBPlane::~AnnRGBPlane()
34{
35    CTRACE();
36}
37
38bool AnnRGBPlane::enable()
39{
40    return enablePlane(true);
41}
42
43bool AnnRGBPlane::disable()
44{
45    return enablePlane(false);
46}
47
48bool 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
59bool 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
72void* AnnRGBPlane::getContext() const
73{
74    CTRACE();
75    return (void *)&mContext;
76}
77
78void AnnRGBPlane::setZOrderConfig(ZOrderConfig& /* config */, void * /* nativeConfig */)
79{
80    CTRACE();
81}
82
83bool 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
147bool 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
255bool 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
286bool 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
313void AnnRGBPlane::postFlip()
314{
315    // prevent mUpdateMasks from being reset
316    // skipping flip may cause flicking
317}
318
319void 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