This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM5728: GC320 compositing issue

Part Number: AM5728

Tool/software: Linux

I am successfully using the GC320 in the AM5728 to composite ( "multiblit" ) 2 images, but I cannot seem to set the destination rectangle ( for placement in the destination surface ) for either input image. When I set the target rectangle, I immediately get the error: gcvSTATUS_NOT_SUPPORTED.

Currently, I blit the source image ( 640x480) of the first index into the target surface with the same dimensions as the target surface ( 640x480 ). I then change the rectangle for a different source image ( 640x480 ) of the second index with the API call "gco2D_SetSource(m_Engine2d, &sourceIRRect)".

The rectangle is defined as follows:

    // Source Rectangle
    uint modifierSrcIR = 100;
    sourceIRRect.left = modifierSrcIR;
    sourceIRRect.top = modifierSrcIR;
    sourceIRRect.right = sourceIRRect.left + modifierSrcIR*3; 
    sourceIRRect.bottom = sourceIRRect.top + modifierSrcIR*3; 

This results in an image as shown below. The second image is "cropped" with the rectangle define above and placed in the destination image at the location of this same rectangle.

I've studied the examples in the ti-gc320-test repository for the MultiBlit functionality, and they call "gco2D_SetTargetRect" and "gco2D_SetClipping". When I call "gco2D_SetTargetRect", I get the error: gcvSTATUS_NOT_SUPPORTED.

http://git.ti.com/graphics/ti-gc320-test/blobs/ti-5.0.11.p7/tests/src/test/hal/common/UnitTest/units/gal2D/blit/MultiSourceBlit/014/014.c

How can I set the target rectangle for one of the multiblit input frames? Thanks.

My code that fails:

/**
 * gc320 renderCompositedFrames()
 * Purpose: Perform a render cycle for compositing 2 input rames together
 *
 * @param inputBuffer1 - DMABUF type input buffer
 * @param inputBuffer2 - DMABUF type input buffer
 *
 * @return Return bool success or failure
 */
gctBOOL Gc320::renderCompositedFrames(dmabuf_buffer *inputBuffer1, dmabuf_buffer *inputBuffer2) {

    // Track Status
    gceSTATUS status;

    // Destination Rectangle
    gcsRECT targetRect;
    gcsRECT sourceVLRect;
    gcsRECT sourceIRRect;
    gcsRECT destinationVLRect;
    gcsRECT destinationIRRect;

    // Set the destination size / stride - NOTE: Height here because we are rotating
    quint32 hijackedDestinationStride = inputBuffer1->width * 4; // RGBA

    // This modifier moves the rectangle of the final image from the Temp Destination image
    uint modifierTargetRect = 0;
    targetRect.left = 0 + modifierTargetRect;
    targetRect.top = 0 + modifierTargetRect;
    targetRect.right = FRAME_WIDTH;// - modifierTargetRect; // These affect the output image ( destination rect )
    targetRect.bottom = FRAME_HEIGHT;// - modifierTargetRect; // These affect the output image ( destination rect )

    // VL Source Rectangle
    uint modifierSrcVL = 0;
    sourceVLRect.left = 0 + modifierSrcVL;
    sourceVLRect.top = 0 + modifierSrcVL;
    sourceVLRect.right = sourceVLRect.left + FRAME_WIDTH; // These affect the input image ( source rect )
    sourceVLRect.bottom = sourceVLRect.top + FRAME_HEIGHT; // These affect the input image ( source rect )

    // IR Source Rectangle
    uint modifierSrcIR = 100;
    sourceIRRect.left = 0 + modifierSrcIR;
    sourceIRRect.top = 0 + modifierSrcIR;
    sourceIRRect.right = sourceIRRect.left + modifierSrcIR*3; // These affect the input image ( source rect )
    sourceIRRect.bottom = sourceIRRect.top + modifierSrcIR*3; // These affect the input image ( source rect )

    // VL Destination Rectangle
    uint modifierDstVL = 0;
    destinationVLRect.left = 0 + modifierDstVL;
    destinationVLRect.top = 0 + modifierDstVL;
    destinationVLRect.right = destinationVLRect.left + FRAME_WIDTH; // These affect the input image ( source rect )
    destinationVLRect.bottom = destinationVLRect.top + FRAME_HEIGHT; // These affect the input image ( source rect )

    // IR Destination Rectangle
    uint modifierDstIR = 100;
    destinationIRRect.left = 0 + modifierDstIR;
    destinationIRRect.top = 0 + modifierDstIR;
    destinationIRRect.right = destinationIRRect.left + modifierDstIR; // These affect the input image ( source rect )
    destinationIRRect.bottom = destinationIRRect.top + modifierDstIR; // These affect the input image ( source rect )

    // Set the underlying buffer for VL
    void *VLDataPtr = omap_bo_map(inputBuffer1->bo[0]); // mmap the DMABUF
    qDebug() << VLDataPtr;
    configureYuYvSourceSurfaceForVL(VLDataPtr);

    // Set the underlying buffer for IR
    void *IRDataPtr = omap_bo_map(inputBuffer2->bo[0]); // mmap the DMABUF
    qDebug() << IRDataPtr;
    configureYuYvSourceSurfaceForIR(IRDataPtr);

//#ifdef DEBUG_GC320
#if 0

        {
            // display -size 640x480 -depth 8 -sampling-factor 4:2:2 -colorspace YCbCr inputVL.yuv
            QString filename = QString("/home/root/inputVL.yuv");
            QFile d(filename);d.open(QFile::WriteOnly);QDataStream ds(&d);
            ds.writeRawData((const char*)VLDataPtr,inputBuffer1->width*inputBuffer1->height*2);
            d.flush();d.close();sync();
        }

        {
            // display -size 640x480 -depth 8 -sampling-factor 4:2:2 -colorspace YCbCr inputIR.yuv
            QString filename = QString("/home/root/inputIR.yuv");
            QFile d(filename);d.open(QFile::WriteOnly);QDataStream ds(&d);
            ds.writeRawData((const char*)IRDataPtr,inputBuffer2->width*inputBuffer2->height*2);
            d.flush();d.close();sync();
            qDebug() << "sudo cp ~/am57xx/build/exported-nfs/home/root/inputVL.yuv . ; display -size 640x480 -depth 8 -sampling-factor 4:2:2 -colorspace YCbCr inputVL.yuv &";
            qDebug() << "sudo cp ~/am57xx/build/exported-nfs/home/root/inputIR.yuv . ; display -size 640x480 -depth 8 -sampling-factor 4:2:2 -colorspace YCbCr inputIR.yuv";
        }

        sleep(86400);

    }

#endif

    // clear dest temp with color
    gcmONERROR(Gal2DCleanSurface(m_Hal, m_TempDstSurf, COLOR_ARGB8(0xFF, 0x00, 0xFF, 0x00)));
    gcmONERROR(Gal2DCleanSurface(m_Hal, m_DstSurf, COLOR_ARGB8(0xFF, 0x00, 0x00, 0xFF)));

    // Index 1 for VL and index 2 for IR

    ////////////////////// VL //////////////////////////////////////////

    gcmONERROR(gco2D_SetCurrentSourceIndex(m_Engine2d, 0));

    gcmONERROR(gco2D_SetGdiStretchMode(m_Engine2d, gcvTRUE));

    // TODO: Fix this
    m_VLSrcStride = 1280;

    gcmONERROR(gco2D_SetGenericSource(
                   m_Engine2d,
                   (gctUINT32_PTR)&m_VLSrcPhysAddr, 1,
                   (gctUINT32_PTR)&m_VLSrcStride, 1,
                   gcvLINEAR,
                   m_VLSrcFormat,
                   gcvSURF_0_DEGREE,
                   (gctUINT32)inputBuffer1->width,
                   (gctUINT32)inputBuffer1->height));

    gcmONERROR(gco2D_SetSource(m_Engine2d, &sourceVLRect));

    // These lines fail and cause "renderCompositedFrames(1670) failed:gcvSTATUS_NOT_SUPPORTED"
    gcmONERROR(gco2D_SetTargetRect(m_Engine2d, &destinationVLRect));

    gcmONERROR(gco2D_SetClipping(m_Engine2d, &destinationVLRect));

    gcmONERROR(gco2D_SetROP(m_Engine2d, 0xCC, 0xCC));

    ////////////////////// IR //////////////////////////////////////////

    gcmONERROR(gco2D_SetCurrentSourceIndex(m_Engine2d, 1));

    gcmONERROR(gco2D_SetGdiStretchMode(m_Engine2d, gcvTRUE));

    // TODO: Fix this
    m_IRSrcStride = 1280;

    gcmONERROR(gco2D_SetGenericSource(
                   m_Engine2d,
                   (gctUINT32_PTR)&m_IRSrcPhysAddr, 1,
                   (gctUINT32_PTR)&m_IRSrcStride, 1,
                   gcvLINEAR,
                   m_IRSrcFormat,
                   gcvSURF_0_DEGREE,
                   (gctUINT32)inputBuffer2->width,
                   (gctUINT32)inputBuffer2->height));

    gcmONERROR(gco2D_SetSource(m_Engine2d, &sourceIRRect));

    // These lines fail and cause "renderCompositedFrames(1670) failed:gcvSTATUS_NOT_SUPPORTED"
    gcmONERROR(gco2D_SetTargetRect(m_Engine2d, &destinationIRRect));

    gcmONERROR(gco2D_SetClipping(m_Engine2d, &destinationIRRect));

    gcmONERROR(gco2D_SetROP(m_Engine2d, 0xCC, 0xCC));

    ////////////////////////////////////////////////////////////////////

    gcmONERROR(gco2D_SetGenericTarget(
                   m_Engine2d,
                   (gctUINT32_PTR)&m_DstPhysAddr, 1,
                   (gctUINT32_PTR)&hijackedDestinationStride, 1,
                   gcvLINEAR,
                   m_DstFormat,
                   gcvSURF_0_DEGREE,
                   (gctUINT32)inputBuffer2->width,
                   (gctUINT32)inputBuffer2->height));

    gcmONERROR(gco2D_MultiSourceBlit(m_Engine2d, 0x3, &targetRect, 1));

    gcmONERROR(gco2D_Flush(m_Engine2d));

    gcmONERROR(gcoHAL_Commit(m_Hal, gcvTRUE));

#ifdef DEBUG_GC320

    ////////////////////////////////////////////////////////////////////////////////

    // Save RGB24
    {

        // sudo cp ~/am57xx/build/exported-nfs/home/root/gc320-yuv-to-rgb-MULTIBLIT.rgb . ; sudo convert -depth 8 -size 612x432+0 RGBA:gc320-yuv-to-rgb-MULTIBLIT.rgb gc320-yuv-to-rgb-MULTIBLIT.png ; eog gc320-yuv-to-rgb-MULTIBLIT.png
        qDebug() << QString("Writing the frame out to /home/root/gc320-yuv-to-rgb-MULTIBLIT");
        QString filename = QString("/home/root/gc320-yuv-to-rgb-MULTIBLIT.rgb");
        QFile d(filename);
        d.open(QFile::WriteOnly);
        QDataStream ds(&d);
        ds.writeRawData((const char*)m_DstVirtAddr,inputBuffer2->width*inputBuffer2->height*4);
        d.flush();
        d.close();
        sync();
        QString cmd = QString("sudo cp ~/am57xx/build/exported-nfs/home/root/gc320-yuv-to-rgb-MULTIBLIT.rgb . ; sudo convert -depth 8 -size %1x%2+0 RGBA:gc320-yuv-to-rgb-MULTIBLIT.rgb gc320-yuv-to-rgb-MULTIBLIT.png ; eog gc320-yuv-to-rgb-MULTIBLIT.png &").arg(inputBuffer2->width).arg(inputBuffer2->height);
        qDebug() << cmd;

        QTextStream stream( &m_DebugScript );
        stream << cmd << endl;

    }

#endif

    return gcvTRUE;

OnError:
    fprintf(stderr,"%s(%d) failed:%s\n",__FUNCTION__, __LINE__, gcoOS_DebugStatus2Name(status));
    return gcvFALSE;

}

  • It looks as though the feature is not available in TiSDK.

    Page 53 of the Vivate_2D_API shows that gco2d_SetTargetRect requires the Multi-Source EX2 Feature of the API.

    I've checked for gco2D_SetTargetRect with the following code:

        if(gcoHAL_IsFeatureAvailable(m_Hal, gcvFEATURE_2D_MULTI_SOURCE_BLT_EX2) == gcvTRUE){
    
            qDebug() << "Set Target Rect is Available";
    
        }

    The feature is not available based on that check.

    Is this true? We cannot set the target rect in a multisource blit?

    Thanks

  • I've drawn a diagram of what I need to accomplish with multisource blitting. Please let me know how I can accomplish the multisource blit operation. Thanks.

  • Hi Phil,

    I will look into this and respond. Please expect some delay in my response.

    Regards,
    Manisha
  • Hi Manisha,

    Thanks, I look forward to hearing your response.

    Phil
  • Hi Phil,

    I confirm that gcvFEATURE_2D_MULTI_SOURCE_BLT_EX2 is not supported by GC320 IP on AM57x device.

    Regards,
    Manisha
  • Manisha,

    Is there any other HW method in the AM5728 for scaling and blending two DMABUFs that is not the GPU (Perhaps updated/fixed DSS support)? If so, would you please share a software example of it?

    In our system the GPU will be dedicated to a very intensive task and we do not want to sacrifice performance there to share GPU resources to simply composite these 2 DMABUFs.

    Thanks,

    Phil
  • Phil,

    The last scenario in your diagram can be supported through GC320 as well however not through the Multi-source EX2 feature as you have noted. The EX2 feature enables multi-source blits with scaling/rotation. If you want to do scaling/rotation along with multisource blits on AM5x you would need to serialize the operations. Take a look at the StretchBlit006 unit-test, which performs alpha blending of two sources with scaling on one.

    git.ti.com/.../006.c

    Thanks,
    Gowtham

  • Hi Gowtham,

    Thanks for clarifying that. I have looked at that example but I will study it again.

    Is the EX2 feature not available due to hardware limitations or software licensing issues?

    Thanks,

    Phil
  • Phil,

    It's hardware limitation, not supported on the IP version we have on AM5x platform.

    Thanks,
    Gowtham