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
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
48void* AnnRGBPlane::getContext() const
49{
50    CTRACE();
51    return (void *)&mContext;
52}
53
54void AnnRGBPlane::setZOrderConfig(ZOrderConfig& config, void *nativeConfig)
55{
56    CTRACE();
57}
58
59bool 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
88bool 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
197bool 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
228bool 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
255void AnnRGBPlane::postFlip()
256{
257    // prevent mUpdateMasks from being reset
258    // skipping flip may cause flicking
259}
260
261void 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