openthos / multidisp-analysis

1 stars 1 forks source link

Multidisplay-T45 can't display in secondary HDMI screen. #19

Open faxiang1230 opened 8 years ago

faxiang1230 commented 8 years ago

T45(THTF) connect secondary screen,but it can't display on secondary screen.

faxiang1230 commented 8 years ago

下面的'显示'代表在第二个显示屏上的显示功能 问题相关参考信息: 1.T45不能双屏显示,其他型号机器可以双屏显示 2.通过modetest工具可以手动设置显示颜色 初步的结论: 1.出现的问题应该是和GPU型号相关 2.GPU的KMS driver部分是好的

第二个显示屏插入之后的活动过程: 1.有个线程一直在轮询一个/sys/device下的节点,当状态改变时开始进行HDMI初始化 2.获取connector(这个和物理接口是固定关联的),encoder,crtc信息,进行配对;然后从connector的显示模式中选取一种最合适的; 3.向driver申请内存,并将内存和一个fb设备绑定,最终获得一个fb_id(代表内存) 4.SurfaceFlinger将会周期性把绘好的图像发送过来,参数为gralloc_drm_bo_t *bo,就是显示器将要显示的图像信息; 5.gralloc kms部分将会处理该信息;当发现HDMI是第一次连接时,将会设置drm_kms_set_crtc,就是绑定crtc和fb_id; 6.下面将会进行pageflip动作,SurfaceFlinger下发的bo将会直接被主屏所使用,HDMI接口会在显示之前先进行一个blit动作,基本是复制bo的信息到HDMI->bo中; 7.下面就是告诉driver有新的数据到来,请刷出显示()

faxiang1230 commented 8 years ago

我尝试过的方法: 1.在第一次对HDMI进行drm_kms_set_crtc之前,我不再使用hdmi->bo而是直接使用主屏的bo

@@ -593,8 +644,10 @@ int gralloc_drm_bo_post(struct gralloc_drm_bo_t *bo)
        ret = drm_kms_set_crtc(drm, &drm->primary, bo->fb_id);

        pthread_mutex_lock(&drm->hdmi_mutex);
-       if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo)
+       if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo){
+           drm->hdmi.bo = bo;
            drm_kms_set_crtc(drm, &drm->hdmi, drm->hdmi.bo->fb_id);
+       }
        pthread_mutex_unlock(&drm->hdmi_mutex);

        drm->current_front = bo; 
@@ -605,6 +658,7 @@ int gralloc_drm_bo_post(struct gralloc_drm_bo_t *bo)

结果如下: 双屏都可以显示,但是会出现严重的裂屏现象,猜测是两个屏公用一个bo导致双方拿到的数据都不完全; 分析: 第二个屏拿到了正确的数据就可以显示,那么KMS部分是没有任何问题的;可能第二个屏没有拿到数据; 2.我就手动建一块有颜色的数据并放在hdmi->bo的虚拟地址部分;

@@ -40,13 +40,29 @@
 #include <poll.h>
 #include <math.h>
 #include "gralloc_drm.h"
+#include "gralloc_drm_handle.h"
 #include "gralloc_drm_priv.h"
 #include <hardware_legacy/uevent.h>
-
+#include <cutils/native_handle.h>
 #include <drm_fourcc.h>
-
+#include "buffers.h"
 #define HDMI_TMP_PATH  "/data/hdmi_display"
-
+struct private_handle_t {
+       struct native_handle nativeHandle;
+               enum {
+                       PRIV_FLAGS_FRAMEBUFFER = 0x00000001
+               };
+               // file-descriptors
+       int     fd;
+   // ints
+    int     magic;
+    int     flags;
+    int     size;
+    int     offset;
+        // FIXME: the attributes below should be out-of-line
+       uint64_t base __attribute__((aligned(8)));
+       int     pid;
+};

        pthread_mutex_unlock(&drm->hdmi_mutex);

@@ -552,8 +604,17 @@ int gralloc_drm_bo_post(struct gralloc_drm_bo_t *bo)
                }

                pthread_mutex_lock(&drm->hdmi_mutex);
-               if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo)
+               if (drm->hdmi.active && drm->hdmi_mode == HDMI_CLONED && drm->hdmi.bo){
+                       struct private_handle_t *test = (struct private_handle_t *)drm->hdmi.bo->handle;  
+                       struct rgb_info *rgb = NULL;
+                       rgb = calloc(1, sizeof(struct rgb_info));
+                       fill_smpte_rgb32(rgb, (void *)test->base, 1920, 1080, 7680);
+                       drm_kms_set_crtc(drm, &drm->hdmi, drm->hdmi.bo->fb_id);
+                       drmModeDirtyFB(drm->fd, drm->hdmi.bo->fb_id, NULL, 0);       
                        drm_kms_set_crtc(drm, &drm->hdmi, drm->hdmi.bo->fb_id);
+               }
                pthread_mutex_unlock(&drm->hdmi_mutex);

                return ret;

结果:第一个屏可以正常显示,但是第二个屏在显示时只能显示字符部分,当主屏切换到图形模式下,第二个屏仍然显示字符模式且不刷新;还会导致android重启; 结论:这种方式阻塞了正常的刷新,应该是中间的操作比较耗时造成的; 3.下面和GPU型号相关的操作只有blit操作了,用于复制bo数据到HDMI->bo位置,我尝试了读取hdmi->bo和bo代表的地址块的起始的32个字节数据,对比时候进行了数据复制的操作;

@@ -397,7 +413,10 @@ static int drm_kms_page_flip(struct gralloc_drm_t *drm,
                struct gralloc_drm_bo_t *bo)
 {
        int ret;
-
+       struct gralloc_drm_handle_t *tmp;
+       char testbuffer[32],srcbuffer[32];
+       memset(testbuffer, 0, 32);
+       memset(srcbuffer, 0 ,32);
        /* there is another flip pending */
        while (drm->next_front) {
                drm->waiting_flip = 1;
...skipping...
+               struct private_handle_t *test = (struct private_handle_t *)tmp;  
+               memcpy(srcbuffer, (void *)(((struct private_handle_t *)bo->handle)->base), 31);
+               srcbuffer[32]='\0';
+               memcpy(testbuffer, (void *)test->base, 31);
+               testbuffer[32] = '\0';
+               ALOGE("before blit:HDMI fd:%d, size:%d, offset:%d,base:%p", test->fd, test->size, test->offset, test->base);
+//             ALOGE("memory testbuffer:%s, srcbuffer:%s", testbuffer,srcbuffer);
+               ALOGE("memory testbuffer:%s", testbuffer);
+               memset(testbuffer, 0, 32);
                drm->drv->blit(drm->drv, drm->hdmi.bo, bo,
                        dst_x1, dst_y1,
                        dst_x1 + bo->handle->width,
       ``                 dst_y1 + bo->handle->height,
                        0, 0, bo->handle->width, bo->handle->height);
-
+               ALOGE("After blit:HDMI fd:%d, size:%d, offset:%d,base:%p", test->fd, test->size, test->offset, test->base);
+               memcpy(testbuffer, (void *)test->base, 31);
+               testbuffer[32] = '\0';
+               memcpy(srcbuffer, (void *)(((struct private_handle_t *)bo->handle)->base), 31);
+               srcbuffer[32]='\0';
+               //ALOGE("memory testbuffer:%s, srcbuffer:%s", testbuffer,srcbuffer);
+               ALOGE("memory testbuffer:%s", testbuffer);
+               ALOGE("After HDMI blit:");
+               ALOGE("HDMI bo info:fd:%d, imported:%d, fb_handle:%d,lock_count:%d,locked_for:%d,refcount:%d",drm->hdmi.bo->fb_id, 
+                               drm->hdmi.bo->imported, drm->hdmi.bo->fb_handle, drm->hdmi.bo->lock_count, drm->hdmi.bo->locked_for, drm->hdmi.bo->refcount);
+               ALOGE("HDMI bo  handle info:numFds:%d,numInts:%d,magic:%d,width:%d,height:%d,format:%d,usage:%d,plane_mask:%u,name:%d,stride:%d",
+                               tmp->base.numFds, tmp->base.numInts, tmp->magic,tmp->width, tmp->height, tmp->format, tmp->usage, tmp->plane_mask, tmp->name, tmp->stride);
                ret = drmModePageFlip(drm->fd, drm->hdmi.crtc_id, drm->hdmi.bo->fb_id, 0, NULL);
                if (ret && errno != EBUSY)
                        ALOGE("failed to perform page flip for hdmi (%s) (crtc %d fb %d))",
                                strerror(errno), drm->hdmi.crtc_id, drm->hdmi.bo->fb_id);

结果:没有任何的log输出

中间的部分有些可能是我加的代码有问题,所以我尝试过的方向不一定不管用;

faxiang1230 commented 8 years ago

Now I'm confirming with the fb_id,crtc,connector match. I confirm the match status, modetest show status match the log status. So I think the match don't have any issue.