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