blob: cf23b6558b6856327f120be2b616cb2c1bdd9b71 [file] [log] [blame]
Ramkumar Radhakrishnand224a1a2013-04-05 17:46:55 -07001/*
2 * Copyright (c) 2012-2013, Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifndef LOG_TAG
31#define LOG_TAG "qsfdump"
32#endif
33#define LOG_NDEBUG 0
34#include <hwc_utils.h>
35#include <hwc_dump_layers.h>
36#include <cutils/log.h>
37#include <sys/stat.h>
38#include <comptype.h>
39#include <SkBitmap.h>
40#include <SkImageEncoder.h>
41
42namespace qhwc {
43
44// MAX_ALLOWED_FRAMEDUMPS must be capped to (LONG_MAX - 1)
45// 60fps => 216000 frames per hour
46// Below setting of 216000 * 24 * 7 => 1 week or 168 hours of capture.
47 enum {
48 MAX_ALLOWED_FRAMEDUMPS = (216000 * 24 * 7)
49 };
50
51bool HwcDebug::sDumpEnable = false;
52
53HwcDebug::HwcDebug(uint32_t dpy):
54 mDumpCntLimRaw(0),
55 mDumpCntrRaw(1),
56 mDumpCntLimPng(0),
57 mDumpCntrPng(1),
58 mDpy(dpy) {
59 char dumpPropStr[PROPERTY_VALUE_MAX];
60 if(mDpy) {
61 strncpy(mDisplayName, "external", strlen("external"));
62 } else {
63 strncpy(mDisplayName, "primary", strlen("primary"));
64 }
65 sprintf(mDumpPropKeyDisplayType, "debug.sf.dump.%s", (char *)mDisplayName);
66
67 if ((property_get("debug.sf.dump.enable", dumpPropStr, NULL) > 0)) {
68 if(!strncmp(dumpPropStr, "true", strlen("true"))) {
69 sDumpEnable = true;
70 }
71 }
72}
73
74void HwcDebug::dumpLayers(hwc_display_contents_1_t* list)
75{
76 // Check need for dumping layers for debugging.
77 if (UNLIKELY(sDumpEnable) && UNLIKELY(needToDumpLayers()) && LIKELY(list)) {
78 logHwcProps(list->flags);
79 for (size_t i = 0; i < list->numHwLayers; i++) {
80 logLayer(i, list->hwLayers);
81 dumpLayer(i, list->hwLayers);
82 }
83 }
84}
85
86bool HwcDebug::needToDumpLayers()
87{
88 bool bDumpLayer = false;
89 char dumpPropStr[PROPERTY_VALUE_MAX];
90 // Enable primary dump and disable external dump by default.
91 bool bDumpEnable = !mDpy;
92 time_t timeNow;
93 tm dumpTime;
94
95 // Override the bDumpEnable based on the property value, if the property
96 // is present in the build.prop file.
97 if ((property_get(mDumpPropKeyDisplayType, dumpPropStr, NULL) > 0)) {
98 if(!strncmp(dumpPropStr, "true", strlen("true")))
99 bDumpEnable = true;
100 else
101 bDumpEnable = false;
102 }
103
104 if (false == bDumpEnable)
105 return false;
106
107 time(&timeNow);
108 localtime_r(&timeNow, &dumpTime);
109
110 if ((property_get("debug.sf.dump.png", dumpPropStr, NULL) > 0) &&
111 (strncmp(dumpPropStr, mDumpPropStrPng, PROPERTY_VALUE_MAX - 1))) {
112 // Strings exist & not equal implies it has changed, so trigger a dump
113 strncpy(mDumpPropStrPng, dumpPropStr, PROPERTY_VALUE_MAX - 1);
114 mDumpCntLimPng = atoi(dumpPropStr);
115 if (mDumpCntLimPng > MAX_ALLOWED_FRAMEDUMPS) {
116 ALOGW("Warning: Using debug.sf.dump.png %d (= max)",
117 MAX_ALLOWED_FRAMEDUMPS);
118 mDumpCntLimPng = MAX_ALLOWED_FRAMEDUMPS;
119 }
120 mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
121 if (mDumpCntLimPng) {
122 sprintf(mDumpDirPng,
123 "/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
124 dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
125 dumpTime.tm_mday, dumpTime.tm_hour,
126 dumpTime.tm_min, dumpTime.tm_sec);
127 if (0 == mkdir(mDumpDirPng, 0777))
128 mDumpCntrPng = 0;
129 else {
130 ALOGE("Error: %s. Failed to create sfdump directory: %s",
131 strerror(errno), mDumpDirPng);
132 mDumpCntrPng = mDumpCntLimPng + 1;
133 }
134 }
135 }
136
137 if (mDumpCntrPng <= mDumpCntLimPng)
138 mDumpCntrPng++;
139
140 if ((property_get("debug.sf.dump", dumpPropStr, NULL) > 0) &&
141 (strncmp(dumpPropStr, mDumpPropStrRaw, PROPERTY_VALUE_MAX - 1))) {
142 // Strings exist & not equal implies it has changed, so trigger a dump
143 strncpy(mDumpPropStrRaw, dumpPropStr, PROPERTY_VALUE_MAX - 1);
144 mDumpCntLimRaw = atoi(dumpPropStr);
145 if (mDumpCntLimRaw > MAX_ALLOWED_FRAMEDUMPS) {
146 ALOGW("Warning: Using debug.sf.dump %d (= max)",
147 MAX_ALLOWED_FRAMEDUMPS);
148 mDumpCntLimRaw = MAX_ALLOWED_FRAMEDUMPS;
149 }
150 mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
151 if (mDumpCntLimRaw) {
152 sprintf(mDumpDirRaw,
153 "/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
154 dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
155 dumpTime.tm_mday, dumpTime.tm_hour,
156 dumpTime.tm_min, dumpTime.tm_sec);
157 if (0 == mkdir(mDumpDirRaw, 0777))
158 mDumpCntrRaw = 0;
159 else {
160 ALOGE("Error: %s. Failed to create sfdump directory: %s",
161 strerror(errno), mDumpDirRaw);
162 mDumpCntrRaw = mDumpCntLimRaw + 1;
163 }
164 }
165 }
166
167 if (mDumpCntrRaw <= mDumpCntLimRaw)
168 mDumpCntrRaw++;
169
170 bDumpLayer = (mDumpCntLimPng || mDumpCntLimRaw)? true : false;
171 return bDumpLayer;
172}
173
174void HwcDebug::logHwcProps(uint32_t listFlags)
175{
176 static int hwcModuleCompType = -1;
177 static int sMdpCompMaxLayers = 0;
178 static String8 hwcModuleCompTypeLog("");
179 if (-1 == hwcModuleCompType) {
180 // One time stuff
181 char mdpCompPropStr[PROPERTY_VALUE_MAX];
182 if (property_get("debug.mdpcomp.maxlayer", mdpCompPropStr, NULL) > 0) {
183 sMdpCompMaxLayers = atoi(mdpCompPropStr);
184 }
185 hwcModuleCompType =
186 qdutils::QCCompositionType::getInstance().getCompositionType();
187 hwcModuleCompTypeLog.appendFormat("%s%s%s%s%s%s",
188 // Is hwc module composition type now a bit-field?!
189 (hwcModuleCompType == qdutils::COMPOSITION_TYPE_GPU)?
190 "[GPU]": "",
191 (hwcModuleCompType & qdutils::COMPOSITION_TYPE_MDP)?
192 "[MDP]": "",
193 (hwcModuleCompType & qdutils::COMPOSITION_TYPE_C2D)?
194 "[C2D]": "",
195 (hwcModuleCompType & qdutils::COMPOSITION_TYPE_CPU)?
196 "[CPU]": "",
197 (hwcModuleCompType & qdutils::COMPOSITION_TYPE_DYN)?
198 "[DYN]": "",
199 (hwcModuleCompType >= (qdutils::COMPOSITION_TYPE_DYN << 1))?
200 "[???]": "");
201 }
202 ALOGI("Display[%s] Layer[*] %s-HwcModuleCompType, %d-layer MdpComp %s",
203 mDisplayName, hwcModuleCompTypeLog.string(), sMdpCompMaxLayers,
204 (listFlags & HWC_GEOMETRY_CHANGED)? "[HwcList Geometry Changed]": "");
205}
206
207void HwcDebug::logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
208{
209 if (NULL == hwLayers) {
210 ALOGE("Display[%s] Layer[%d] Error. No hwc layers to log.",
211 mDisplayName, layerIndex);
212 return;
213 }
214
215 hwc_layer_1_t *layer = &hwLayers[layerIndex];
216 hwc_rect_t sourceCrop = layer->sourceCrop;
217 hwc_rect_t displayFrame = layer->displayFrame;
218 size_t numHwcRects = layer->visibleRegionScreen.numRects;
219 hwc_rect_t const *hwcRects = layer->visibleRegionScreen.rects;
220 private_handle_t *hnd = (private_handle_t *)layer->handle;
221
222 char pixFormatStr[32] = "None";
223 String8 hwcVisRegsScrLog("[None]");
224
225 for (size_t i = 0 ; (hwcRects && (i < numHwcRects)); i++) {
226 if (0 == i)
227 hwcVisRegsScrLog.clear();
228 hwcVisRegsScrLog.appendFormat("[%dl, %dt, %dr, %db]",
229 hwcRects[i].left, hwcRects[i].top,
230 hwcRects[i].right, hwcRects[i].bottom);
231 }
232
233 if (hnd)
234 getHalPixelFormatStr(hnd->format, pixFormatStr);
235
236 // Log Line 1
237 ALOGI("Display[%s] Layer[%d] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
238 "DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
239 (hnd)? hnd->width : -1, (hnd)? hnd->height : -1,
240 sourceCrop.left, sourceCrop.top,
241 sourceCrop.right, sourceCrop.bottom,
242 displayFrame.left, displayFrame.top,
243 displayFrame.right, displayFrame.bottom,
244 hwcVisRegsScrLog.string());
245 // Log Line 2
246 ALOGI("Display[%s] Layer[%d] LayerCompType = %s, Format = %s, "
247 "Orientation = %s, Flags = %s%s%s, Hints = %s%s%s, "
248 "Blending = %s%s%s", mDisplayName, layerIndex,
249 (layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer(GPU)":
250 (layer->compositionType == HWC_OVERLAY)? "Overlay":
251 (layer->compositionType == HWC_BACKGROUND)? "Background":"???",
252 pixFormatStr,
253 (layer->transform == 0)? "ROT_0":
254 (layer->transform == HWC_TRANSFORM_FLIP_H)? "FLIP_H":
255 (layer->transform == HWC_TRANSFORM_FLIP_V)? "FLIP_V":
256 (layer->transform == HWC_TRANSFORM_ROT_90)? "ROT_90":
257 "ROT_INVALID",
258 (layer->flags)? "": "[None]",
259 (layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
260 (layer->flags & qhwc::HWC_MDPCOMP)? "[MDP Comp]":"",
261 (layer->hints)? "":"[None]",
262 (layer->hints & HWC_HINT_TRIPLE_BUFFER)? "[Triple Buffer]":"",
263 (layer->hints & HWC_HINT_CLEAR_FB)? "[Clear FB]":"",
264 (layer->blending == HWC_BLENDING_NONE)? "[None]":"",
265 (layer->blending == HWC_BLENDING_PREMULT)? "[PreMult]":"",
266 (layer->blending == HWC_BLENDING_COVERAGE)? "[Coverage]":"");
267}
268
269void HwcDebug::dumpLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
270{
271 char dumpLogStrPng[128] = "";
272 char dumpLogStrRaw[128] = "";
273 bool needDumpPng = (mDumpCntrPng <= mDumpCntLimPng)? true:false;
274 bool needDumpRaw = (mDumpCntrRaw <= mDumpCntLimRaw)? true:false;
275
276 if (needDumpPng) {
277 sprintf(dumpLogStrPng, "[png-dump-frame: %03d of %03d]", mDumpCntrPng,
278 mDumpCntLimPng);
279 }
280 if (needDumpRaw) {
281 sprintf(dumpLogStrRaw, "[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
282 mDumpCntLimRaw);
283 }
284
285 if (!(needDumpPng || needDumpRaw))
286 return;
287
288 if (NULL == hwLayers) {
289 ALOGE("Display[%s] Layer[%d] %s%s Error: No hwc layers to dump.",
290 mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
291 return;
292 }
293
294 hwc_layer_1_t *layer = &hwLayers[layerIndex];
295 private_handle_t *hnd = (private_handle_t *)layer->handle;
296 char pixFormatStr[32] = "None";
297
298 if (NULL == hnd) {
299 ALOGI("Display[%s] Layer[%d] %s%s Skipping dump: Bufferless layer.",
300 mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
301 return;
302 }
303
304 getHalPixelFormatStr(hnd->format, pixFormatStr);
305
306 if (needDumpPng && hnd->base) {
307 bool bResult = false;
308 char dumpFilename[PATH_MAX];
309 SkBitmap *tempSkBmp = new SkBitmap();
310 SkBitmap::Config tempSkBmpConfig = SkBitmap::kNo_Config;
311 sprintf(dumpFilename, "%s/sfdump%03d.layer%d.%s.png", mDumpDirPng,
312 mDumpCntrPng, layerIndex, mDisplayName);
313
314 switch (hnd->format) {
315 case HAL_PIXEL_FORMAT_RGBA_8888:
316 case HAL_PIXEL_FORMAT_RGBX_8888:
317 case HAL_PIXEL_FORMAT_BGRA_8888:
318 tempSkBmpConfig = SkBitmap::kARGB_8888_Config;
319 break;
320 case HAL_PIXEL_FORMAT_RGB_565:
321 case HAL_PIXEL_FORMAT_RGBA_5551:
322 case HAL_PIXEL_FORMAT_RGBA_4444:
323 tempSkBmpConfig = SkBitmap::kRGB_565_Config;
324 break;
325 case HAL_PIXEL_FORMAT_RGB_888:
326 default:
327 tempSkBmpConfig = SkBitmap::kNo_Config;
328 break;
329 }
330 if (SkBitmap::kNo_Config != tempSkBmpConfig) {
331 tempSkBmp->setConfig(tempSkBmpConfig, hnd->width, hnd->height);
332 tempSkBmp->setPixels((void*)hnd->base);
333 bResult = SkImageEncoder::EncodeFile(dumpFilename,
334 *tempSkBmp, SkImageEncoder::kPNG_Type, 100);
335 ALOGI("Display[%s] Layer[%d] %s Dump to %s: %s",
336 mDisplayName, layerIndex, dumpLogStrPng,
337 dumpFilename, bResult ? "Success" : "Fail");
338 } else {
339 ALOGI("Display[%s] Layer[%d] %s Skipping dump: Unsupported layer"
340 " format %s for png encoder",
341 mDisplayName, layerIndex, dumpLogStrPng, pixFormatStr);
342 }
343 delete tempSkBmp; // Calls SkBitmap::freePixels() internally.
344 }
345
346 if (needDumpRaw && hnd->base) {
347 char dumpFilename[PATH_MAX];
348 bool bResult = false;
349 sprintf(dumpFilename, "%s/sfdump%03d.layer%d.%dx%d.%s.%s.raw",
350 mDumpDirRaw, mDumpCntrRaw,
351 layerIndex, hnd->width, hnd->height,
352 pixFormatStr, mDisplayName);
353 FILE* fp = fopen(dumpFilename, "w+");
354 if (NULL != fp) {
355 bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
356 fclose(fp);
357 }
358 ALOGI("Display[%s] Layer[%d] %s Dump to %s: %s",
359 mDisplayName, layerIndex, dumpLogStrRaw,
360 dumpFilename, bResult ? "Success" : "Fail");
361 }
362}
363
364void HwcDebug::getHalPixelFormatStr(int format, char pixFormatStr[])
365{
366 if (!pixFormatStr)
367 return;
368
369 switch(format) {
370 case HAL_PIXEL_FORMAT_RGBA_8888:
371 strcpy(pixFormatStr, "RGBA_8888");
372 break;
373 case HAL_PIXEL_FORMAT_RGBX_8888:
374 strcpy(pixFormatStr, "RGBX_8888");
375 break;
376 case HAL_PIXEL_FORMAT_RGB_888:
377 strcpy(pixFormatStr, "RGB_888");
378 break;
379 case HAL_PIXEL_FORMAT_RGB_565:
380 strcpy(pixFormatStr, "RGB_565");
381 break;
382 case HAL_PIXEL_FORMAT_BGRA_8888:
383 strcpy(pixFormatStr, "BGRA_8888");
384 break;
385 case HAL_PIXEL_FORMAT_RGBA_5551:
386 strcpy(pixFormatStr, "RGBA_5551");
387 break;
388 case HAL_PIXEL_FORMAT_RGBA_4444:
389 strcpy(pixFormatStr, "RGBA_4444");
390 break;
391 case HAL_PIXEL_FORMAT_YV12:
392 strcpy(pixFormatStr, "YV12");
393 break;
394 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
395 strcpy(pixFormatStr, "YCbCr_422_SP_NV16");
396 break;
397 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
398 strcpy(pixFormatStr, "YCrCb_420_SP_NV21");
399 break;
400 case HAL_PIXEL_FORMAT_YCbCr_422_I:
401 strcpy(pixFormatStr, "YCbCr_422_I_YUY2");
402 break;
403 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
404 strcpy(pixFormatStr, "NV12_ENCODEABLE");
405 break;
406 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
407 strcpy(pixFormatStr, "YCbCr_420_SP_TILED_TILE_4x2");
408 break;
409 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
410 strcpy(pixFormatStr, "YCbCr_420_SP");
411 break;
412 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
413 strcpy(pixFormatStr, "YCrCb_420_SP_ADRENO");
414 break;
415 case HAL_PIXEL_FORMAT_YCrCb_422_SP:
416 strcpy(pixFormatStr, "YCrCb_422_SP");
417 break;
418 case HAL_PIXEL_FORMAT_R_8:
419 strcpy(pixFormatStr, "R_8");
420 break;
421 case HAL_PIXEL_FORMAT_RG_88:
422 strcpy(pixFormatStr, "RG_88");
423 break;
424 case HAL_PIXEL_FORMAT_INTERLACE:
425 strcpy(pixFormatStr, "INTERLACE");
426 break;
427 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
428 strcpy(pixFormatStr, "YCbCr_420_SP_VENUS");
429 break;
430 default:
431 sprintf(pixFormatStr, "Unknown0x%X", format);
432 break;
433 }
434}
435
436} // namespace qhwc
437