#include #include #include #include #include #include #include #include #include "bo.h" #include "dev.h" #include "drmDsp.h" #include "modeset.h" struct drmDsp { struct fb_var_screeninfo vinfo; unsigned long screensize; char* fbp; struct sp_dev* dev; struct sp_plane** plane; struct sp_crtc* test_crtc; struct sp_plane* test_plane; int num_test_planes; struct sp_bo* bo[2]; struct sp_bo* nextbo; } gDrmDsp; int initDrmDsp() { int ret = 0, i = 0; struct drmDsp* pDrmDsp = &gDrmDsp; memset(pDrmDsp, 0, sizeof(struct drmDsp)); pDrmDsp->dev = create_sp_dev(); if (!pDrmDsp->dev) { fprintf(stderr, "Failed to create sp_dev\n"); return -1; } ret = initialize_screens(pDrmDsp->dev); if (ret) { fprintf(stderr, "Failed to initialize screens\n"); return ret; } pDrmDsp->plane = (struct sp_plane**)calloc(pDrmDsp->dev->num_planes, sizeof(struct sp_plane*)); if (!pDrmDsp->plane) { fprintf(stderr, "Failed to allocate plane array\n"); return -1; } pDrmDsp->test_crtc = &pDrmDsp->dev->crtcs[0]; pDrmDsp->num_test_planes = pDrmDsp->test_crtc->num_planes; for (i = 0; i < pDrmDsp->test_crtc->num_planes; i++) { pDrmDsp->plane[i] = get_sp_plane(pDrmDsp->dev, pDrmDsp->test_crtc); if (is_supported_format(pDrmDsp->plane[i], DRM_FORMAT_NV12)) pDrmDsp->test_plane = pDrmDsp->plane[i]; } if (!pDrmDsp->test_plane) { fprintf(stderr, "pDrmDsp->test_plane is null\n"); return -1; } else { fprintf(stderr, "pDrmDsp->test_plane is no null\n"); return 0; } } void deInitDrmDsp() { struct drmDsp* pDrmDsp = &gDrmDsp; if (pDrmDsp->plane) free(pDrmDsp->plane); if (pDrmDsp->bo[0]) { drmModeRmFB(pDrmDsp->dev->fd, pDrmDsp->bo[0]->fb_id); free_sp_bo(pDrmDsp->bo[0]); } if (pDrmDsp->bo[1]) { drmModeRmFB(pDrmDsp->dev->fd, pDrmDsp->bo[1]->fb_id); free_sp_bo(pDrmDsp->bo[1]); } destroy_sp_dev(pDrmDsp->dev); memset(pDrmDsp, 0, sizeof(struct drmDsp)); } static int arm_camera_yuv420_scale_arm(char* srcbuf, char* dstbuf, int src_w, int src_h, int dst_w, int dst_h) { unsigned char *psY, *pdY, *psUV, *pdUV; unsigned char *src, *dst; int srcW, srcH, cropW, cropH, dstW, dstH; long zoomindstxIntInv, zoomindstyIntInv; long x, y; long yCoeff00, yCoeff01, xCoeff00, xCoeff01; long sX, sY; long r0, r1, a, b, c, d; int ret = 0; int nv21DstFmt = 0, mirror = 0; int ratio = 0; int top_offset = 0, left_offset = 0; // need crop ? if ((src_w * 100 / src_h) != (dst_w * 100 / dst_h)) { ratio = ((src_w * 100 / dst_w) >= (src_h * 100 / dst_h)) ? (src_h * 100 / dst_h) : (src_w * 100 / dst_w); cropW = ratio * dst_w / 100; cropH = ratio * dst_h / 100; left_offset = ((src_w - cropW) >> 1) & (~0x01); top_offset = ((src_h - cropH) >> 1) & (~0x01); } else { cropW = src_w; cropH = src_h; top_offset = 0; left_offset = 0; } src = psY = (unsigned char*)(srcbuf) + top_offset * src_w + left_offset; // psUV = psY +src_w*src_h+top_offset*src_w/2+left_offset; psUV = (unsigned char*)(srcbuf) + src_w * src_h + top_offset * src_w / 2 + left_offset; srcW = src_w; srcH = src_h; // cropW = src_w; // cropH = src_h; dst = pdY = (unsigned char*)dstbuf; pdUV = pdY + dst_w * dst_h; dstW = dst_w; dstH = dst_h; zoomindstxIntInv = ((unsigned long)(cropW) << 16) / dstW + 1; zoomindstyIntInv = ((unsigned long)(cropH) << 16) / dstH + 1; // y // for(y = 0; y> 16); sY = (sY >= srcH - 1) ? (srcH - 2) : sY; for (x = 0; x < dstW; x++) { xCoeff00 = (x * zoomindstxIntInv) & 0xffff; xCoeff01 = 0xffff - xCoeff00; sX = (x * zoomindstxIntInv >> 16); sX = (sX >= srcW - 1) ? (srcW - 2) : sX; a = psY[sY * srcW + sX]; b = psY[sY * srcW + sX + 1]; c = psY[(sY + 1) * srcW + sX]; d = psY[(sY + 1) * srcW + sX + 1]; r0 = (a * xCoeff01 + b * xCoeff00) >> 16; r1 = (c * xCoeff01 + d * xCoeff00) >> 16; r0 = (r0 * yCoeff01 + r1 * yCoeff00) >> 16; if (mirror) pdY[dstW - 1 - x] = r0; else pdY[x] = r0; } pdY += dstW; } dstW /= 2; dstH /= 2; srcW /= 2; srcH /= 2; // UV // for(y = 0; y> 16); sY = (sY >= srcH - 1) ? (srcH - 2) : sY; for (x = 0; x < dstW; x++) { xCoeff00 = (x * zoomindstxIntInv) & 0xffff; xCoeff01 = 0xffff - xCoeff00; sX = (x * zoomindstxIntInv >> 16); sX = (sX >= srcW - 1) ? (srcW - 2) : sX; // U a = psUV[(sY * srcW + sX) * 2]; b = psUV[(sY * srcW + sX + 1) * 2]; c = psUV[((sY + 1) * srcW + sX) * 2]; d = psUV[((sY + 1) * srcW + sX + 1) * 2]; r0 = (a * xCoeff01 + b * xCoeff00) >> 16; r1 = (c * xCoeff01 + d * xCoeff00) >> 16; r0 = (r0 * yCoeff01 + r1 * yCoeff00) >> 16; if (mirror && nv21DstFmt) pdUV[dstW * 2 - 1 - (x * 2)] = r0; else if (mirror) pdUV[dstW * 2 - 1 - (x * 2 + 1)] = r0; else if (nv21DstFmt) pdUV[x * 2 + 1] = r0; else pdUV[x * 2] = r0; // V a = psUV[(sY * srcW + sX) * 2 + 1]; b = psUV[(sY * srcW + sX + 1) * 2 + 1]; c = psUV[((sY + 1) * srcW + sX) * 2 + 1]; d = psUV[((sY + 1) * srcW + sX + 1) * 2 + 1]; r0 = (a * xCoeff01 + b * xCoeff00) >> 16; r1 = (c * xCoeff01 + d * xCoeff00) >> 16; r0 = (r0 * yCoeff01 + r1 * yCoeff00) >> 16; if (mirror && nv21DstFmt) pdUV[dstW * 2 - 1 - (x * 2 + 1)] = r0; else if (mirror) pdUV[dstW * 2 - 1 - (x * 2)] = r0; else if (nv21DstFmt) pdUV[x * 2] = r0; else pdUV[x * 2 + 1] = r0; } pdUV += dstW * 2; } return 0; } int drmDspFrame(int width, int height, void* dmaFd, int fmt) { int ret; struct drm_mode_create_dumb cd; struct sp_bo* bo; struct drmDsp* pDrmDsp = &gDrmDsp; int ori_width = width; int ori_height = height; if (width > 1920) { width = 1920; height = 1080; } int wAlign16 = ((width + 15) & (~15)); int hAlign16 = ((height + 15) & (~15)); int frameSize = wAlign16 * hAlign16 * 3 / 2; uint32_t handles[4], pitches[4], offsets[4]; if (DRM_FORMAT_NV12 != fmt) { fprintf(stderr, "%s just support NV12 to display\n", __func__); return -1; } // create bo #if 1 if (!pDrmDsp->bo[0]) { fprintf(stderr, "%s:bo widthxheight:%dx%d\n", __func__, wAlign16, hAlign16); pDrmDsp->bo[0] = create_sp_bo(pDrmDsp->dev, wAlign16, hAlign16, 16, 32, DRM_FORMAT_NV12, 0); pDrmDsp->bo[1] = create_sp_bo(pDrmDsp->dev, wAlign16, hAlign16, 16, 32, DRM_FORMAT_NV12, 0); if (!pDrmDsp->bo[0] || !pDrmDsp->bo[1]) { fprintf(stderr, "%s:create bo failed ! \n", __func__); return -1; } pDrmDsp->nextbo = pDrmDsp->bo[0]; } if (!pDrmDsp->nextbo) { fprintf(stderr, "%s:no available bo ! \n", __func__); return -1; } bo = pDrmDsp->nextbo; #else bo = create_sp_bo(pDrmDsp->dev, wAlign16, hAlign16, 16, 32, DRM_FORMAT_NV12, 0); if (!bo) fprintf(stderr, "%s:create bo failed ! \n", __func__); #endif handles[0] = bo->handle; pitches[0] = wAlign16; offsets[0] = 0; handles[1] = bo->handle; pitches[1] = wAlign16; offsets[1] = width * height; // wAlign16 * hAlign16; // copy src data to bo if (ori_width == width) memcpy(bo->map_addr, dmaFd, wAlign16 * hAlign16 * 3 / 2); else arm_camera_yuv420_scale_arm(dmaFd, bo->map_addr, ori_width, ori_height, width, height); if (bo->fb_id <= 0) { ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height, bo->format, handles, pitches, offsets, &bo->fb_id, bo->flags); if (ret) { fprintf(stderr, "%s:failed to create fb ret=%d\n", __func__, ret); fprintf(stderr, "fd:%d " ",wxh:%ux%u,format:%u,handles:%u,%u,pictches:%u,%u,offsets:%u,%u,fb_id:" "%u,flags:%u \n", bo->dev->fd, bo->width, bo->height, bo->format, handles[0], handles[1], pitches[0], pitches[1], offsets[0], offsets[1], bo->fb_id, bo->flags); return ret; } else { fprintf(stderr, "%s:create fb success fb_id:%u\n", __func__, bo->fb_id); } } ret = drmModeSetPlane(pDrmDsp->dev->fd, pDrmDsp->test_plane->plane->plane_id, pDrmDsp->test_crtc->crtc->crtc_id, bo->fb_id, 0, 0, 0, // pDrmDsp->test_crtc->crtc->mode.hdisplay, wAlign16, hAlign16, // pDrmDsp->test_crtc->crtc->mode.vdisplay, 0, 0, width << 16, height << 16); if (ret) { fprintf(stderr, "failed to set plane to crtc ret=%d\n", ret); return ret; } // free_sp_bo(bo); #if 0 if (pDrmDsp->test_plane->bo) { if (pDrmDsp->test_plane->bo->fb_id) { ret = drmModeRmFB(pDrmDsp->dev->fd, pDrmDsp->test_plane->bo->fb_id); if (ret) fprintf(stderr, "Failed to rmfb ret=%d!\n", ret); } if (pDrmDsp->test_plane->bo->handle) { struct drm_gem_close req = { .handle = pDrmDsp->test_plane->bo->handle, }; drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); fprintf(stderr, "%s:close bo success!\n", __func__); } if (!pDrmDsp->nextbo) free_sp_bo(pDrmDsp->test_plane->bo); } pDrmDsp->test_plane->bo = bo; //last po #endif #if 1 // switch bo if (pDrmDsp->nextbo == pDrmDsp->bo[0]) pDrmDsp->nextbo = pDrmDsp->bo[1]; else pDrmDsp->nextbo = pDrmDsp->bo[0]; #endif }