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
17#include <HwcTrace.h>
18#include <Hwcomposer.h>
19#include <BufferManager.h>
20#include <anniedale/AnnCursorPlane.h>
21#include <tangier/TngGrallocBuffer.h>
22#include <hal_public.h>
23
24namespace android {
25namespace intel {
26
27AnnCursorPlane::AnnCursorPlane(int index, int disp)
28    : DisplayPlane(index, PLANE_CURSOR, disp)
29{
30    CTRACE();
31    memset(&mContext, 0, sizeof(mContext));
32    memset(&mCrop, 0, sizeof(mCrop));
33}
34
35AnnCursorPlane::~AnnCursorPlane()
36{
37    CTRACE();
38}
39
40bool AnnCursorPlane::enable()
41{
42    return enablePlane(true);
43
44}
45
46bool AnnCursorPlane::disable()
47{
48    return enablePlane(false);
49}
50
51bool AnnCursorPlane::reset()
52{
53    // clear mCrop once reset
54    memset(&mCrop, 0, sizeof(mCrop));
55    return true;
56}
57
58void* AnnCursorPlane::getContext() const
59{
60    CTRACE();
61    return (void *)&mContext;
62}
63
64void AnnCursorPlane::setZOrderConfig(ZOrderConfig& config, void *nativeConfig)
65{
66    (void) config;
67    (void) nativeConfig;
68
69    CTRACE();
70}
71
72bool AnnCursorPlane::setDataBuffer(buffer_handle_t handle)
73{
74    bool ret;
75
76    if (!handle) {
77        ETRACE("handle is NULL");
78        return false;
79    }
80
81    ret = DisplayPlane::setDataBuffer(handle);
82    if (ret == false) {
83        ETRACE("failed to set data buffer");
84        return ret;
85    }
86
87    return true;
88}
89
90bool AnnCursorPlane::setDataBuffer(BufferMapper& mapper)
91{
92    int w = mapper.getWidth();
93    int h = mapper.getHeight();
94    int cursorSize = 0;
95
96    CTRACE();
97
98    // setup plane position
99    int dstX = mPosition.x;
100    int dstY = mPosition.y;
101
102    if (h < w) {
103        cursorSize = h;
104    } else {
105        cursorSize = w;
106    }
107
108    uint32_t cntr = 0;
109    if (64 <= cursorSize && cursorSize < 128) {
110        cursorSize = 64;
111        cntr = 0x7;
112    } else if (128 <= cursorSize && cursorSize < 256) {
113        cursorSize = 128;
114        cntr = 0x2;
115    } else {
116        cursorSize = 256;
117        cntr = 0x3;
118    }
119
120    if (mapper.getFormat() == HAL_PIXEL_FORMAT_RGBA_8888) {
121        cntr |= 1 << 5;
122    } else if (mapper.getFormat() == HAL_PIXEL_FORMAT_BGRA_8888) {
123        // swap color from BGRA to RGBA - alpha is MSB
124        uint8_t *p = (uint8_t *)(mapper.getCpuAddress(0));
125        uint8_t *srcPixel;
126        uint32_t stride = mapper.getStride().rgb.stride;
127        uint8_t temp;
128        if (!p) {
129            return false;
130        }
131
132        for (int i = 0; i < cursorSize; i++) {
133            for (int j = 0; j < cursorSize; j++) {
134                srcPixel = p + i*stride + j*4;
135                temp = srcPixel[0];
136                srcPixel[0] = srcPixel[2];
137                srcPixel[2] = temp;
138            }
139        }
140        cntr |= 1 << 5;
141    } else {
142        ETRACE("invalid color format");
143        return false;
144    }
145
146    // update context
147    mContext.type = DC_CURSOR_PLANE;
148    mContext.ctx.cs_ctx.index = mIndex;
149    mContext.ctx.cs_ctx.pipe = mDevice;
150    mContext.ctx.cs_ctx.cntr = cntr;
151    mContext.ctx.cs_ctx.surf = mapper.getGttOffsetInPage(0) << 12;
152
153    mContext.ctx.cs_ctx.pos = 0;
154    if (dstX < 0) {
155        mContext.ctx.cs_ctx.pos |= 1 << 15;
156        dstX = -dstX;
157    }
158    if (dstY < 0) {
159        mContext.ctx.cs_ctx.pos |= 1 << 31;
160        dstY = -dstY;
161    }
162    mContext.ctx.cs_ctx.pos |= (dstY & 0xfff) << 16 | (dstX & 0xfff);
163    return true;
164}
165
166bool AnnCursorPlane::enablePlane(bool enabled)
167{
168    RETURN_FALSE_IF_NOT_INIT();
169
170    struct drm_psb_register_rw_arg arg;
171    memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
172    if (enabled) {
173        arg.plane_enable_mask = 1;
174    } else {
175        arg.plane_disable_mask = 1;
176    }
177
178    arg.plane.type = DC_CURSOR_PLANE;
179    arg.plane.index = mIndex;
180    arg.plane.ctx = 0;
181
182    // issue ioctl
183    Drm *drm = Hwcomposer::getInstance().getDrm();
184    bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
185    if (ret == false) {
186        WTRACE("plane enabling (%d) failed with error code %d", enabled, ret);
187        return false;
188    }
189
190    return true;
191}
192
193bool AnnCursorPlane::isDisabled()
194{
195    RETURN_FALSE_IF_NOT_INIT();
196
197    struct drm_psb_register_rw_arg arg;
198    memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
199
200    arg.plane.type = DC_CURSOR_PLANE;
201    arg.get_plane_state_mask = 1;
202    arg.plane.index = mIndex;
203    arg.plane.ctx = 0;
204
205    // issue ioctl
206    Drm *drm = Hwcomposer::getInstance().getDrm();
207    bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
208    if (ret == false) {
209        WTRACE("plane state query failed with error code %d", ret);
210        return false;
211    }
212
213    return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
214}
215
216void AnnCursorPlane::postFlip()
217{
218    // prevent mUpdateMasks from being reset
219    // skipping flip may cause flicking
220}
221
222} // namespace intel
223} // namespace android
224