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