void CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doThreadFunctionL(TInt aIdx) { INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doThreadFunctionL, Thread %d"),aIdx); CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx); eglSess->InitializeL(); eglSess->OpenSgDriverL(); EGLImageKHR eglImageLocal = EGL_NO_IMAGE_KHR; if(aIdx == 0) { INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx); eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue); ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR); } Rendezvous(aIdx); if(aIdx == 1) { INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx); eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue); ASSERT_EGL_TRUE(eglImageLocal == EGL_NO_IMAGE_KHR); ASSERT_EGL_ERROR(EGL_BAD_ACCESS); } Rendezvous(aIdx); // cleanup if(aIdx == 0) { ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, eglImageLocal)); } eglSess->CloseSgDriver(); CleanupStack::PopAndDestroy(eglSess); }
void CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doThreadFunctionL(TInt aIdx) { INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doThreadFunctionL, Thread %d"),aIdx); GetDisplayL(); CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx); eglSess->InitializeL(); eglSess->OpenSgDriverL(); TRequestStatus statusThread1; VGImage vgImageLocal = VG_INVALID_HANDLE; EGLint surfaceWidth; EGLint surfaceHeigth; //Thread0 asks to be notified when Thread1 exits //Creates a RSgImage having the reference bitmap as content //Creates a EGLImage from the RSgImage //Creates a surface //Creates a VGImage from the EGLImage if(aIdx == 0) { // Thread0 asks to be notified when Thread1 exits iThreadStatus[1].iThread.Logon(statusThread1); RSgImage rSgImageLocal; CleanupClosePushL(rSgImageLocal); // create a reference bitmap (we give index 9, as there's only 1 image in this test case) TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat); CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 9); CleanupStack::PushL(bitmap); // Create an RSgImage INFO_PRINTF2(_L("Thread %d, Creating a RSgImage having the reference bitmap's content"),aIdx); TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize); ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone); CleanupStack::PopAndDestroy(bitmap); INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx); EGLImageKHR eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue); ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR); CleanupStack::PopAndDestroy(&rSgImageLocal); //transferring ownership of the buffer to the EGLImage INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx); TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat); TSgImageInfoOpenVgTarget imageInfo2 = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize); // Create a pixmap surface matching the native image pixel format eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo2,CTestEglSession::EResourceCloseSgImageEarly); //We now store the size of the surface because after eglTerminate is called on the display //it will not be possible to use explicitly all the resources linked to it //i.e. every call to an EGL API who takes a display as an argument will raise a EGL_BAD_DISPLAY error eglQuerySurface(iDisplay, eglSess->Surface(), EGL_WIDTH, &surfaceWidth); eglQuerySurface(iDisplay, eglSess->Surface(), EGL_HEIGHT, &surfaceHeigth); INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the EGLImage"),aIdx); vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal); ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE); ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, eglImageLocal)); } Rendezvous(aIdx); //Thread1 calls eglTerminate and exit if(aIdx == 1) { INFO_PRINTF2(_L(", Thread %d, Calling eglTerminate and exiting"),aIdx); TerminateDisplayL(); } Rendezvous(aIdx); //Thread0 resumes when Thread1 exits //and it uses the resources that are linked to the just destroyed display if(aIdx == 0) { User::WaitForRequest(statusThread1); // It's still possible to use the current context, surface and VGImage even though the display has been terminated //Copy the source VGImage to the surface vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight); ASSERT_TRUE(vgGetError()==VG_NO_ERROR); eglWaitClient(); // we can now compare the VgImage to the one we would expect for this particular thread TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat); CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 9); CleanupStack::PushL(refBitmap); eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap); CleanupStack::PopAndDestroy(refBitmap); INFO_PRINTF2(_L("Drawing successful, Thread %d"),aIdx); vgDestroyImage(vgImageLocal); ASSERT_TRUE(vgGetError() == VG_NO_ERROR); eglReleaseThread(); } // cleanup eglSess->CloseSgDriver(); CleanupStack::PopAndDestroy(eglSess); }
void CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doThreadFunctionL(TInt aIdx) { INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doThreadFunctionL, Thread %d"),aIdx); CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx); eglSess->InitializeL(); eglSess->OpenSgDriverL(); // check there is no eglImage at the start of either thread ASSERT_EGL_TRUE(iEGLImageShared == EGL_NO_IMAGE_KHR); TRequestStatus statusThread0; if(aIdx == 1) { INFO_PRINTF2(_L("Thread %d, Asking to be notified when thread 0 exits"),aIdx); iThreadStatus[0].iThread.Logon(statusThread0); } Rendezvous(aIdx); //Thread 0 creates the EGLImage and exit if(aIdx == 0) { // Create an EGLImage from the RSgImage (member variable as it is 'shared' in the thread function...) INFO_PRINTF2(_L("Thread %d, Creating the shared EGLImage"),aIdx); iEGLImageShared = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue); ASSERT_EGL_TRUE(iEGLImageShared != EGL_NO_IMAGE_KHR); iSgImageShared.Close(); INFO_PRINTF2(_L("Thread %d ----- Exiting ---- EGLImage should be kept alive"),aIdx); } //Thread1 waits for Thread0 to exit and then uses the EGLImage and performs some drawing if(aIdx == 1) { INFO_PRINTF2(_L("Thread %d, Waiting for thread 0 to exit"),aIdx); User::WaitForRequest(statusThread0); INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx); TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat); TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize); // Create a pixmap surface matching the native image pixel format eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly); // Create a VGImage from the EGLImage INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx); VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared); ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE); INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx); // Copy the source VGImage to the surface vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight); ASSERT_TRUE(vgGetError()==VG_NO_ERROR); eglWaitClient(); // we can now compare the VgImage to the one we expect after changing it in the other thread TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat); CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 2); CleanupStack::PushL(refBitmap); eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap); CleanupStack::PopAndDestroy(refBitmap); INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx); vgDestroyImage(vgImageLocal); ASSERT_TRUE(vgGetError() == VG_NO_ERROR); ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, iEGLImageShared)); iEGLImageShared = EGL_NO_IMAGE_KHR; } // cleanup eglSess->CloseSgDriver(); CleanupStack::PopAndDestroy(eglSess); }
void CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doThreadFunctionL(TInt aIdx) { INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doThreadFunctionL, Thread %d"),aIdx); CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx); eglSess->InitializeL(); eglSess->OpenSgDriverL(); // check there is no eglImage at the start of either thread ASSERT_EGL_TRUE(iEGLImageShared == EGL_NO_IMAGE_KHR); // Wait for both thread to reach this point // This is important for multicore platforms (i.e., naviengine) as the execution order is not known and it could // happen that the first thread has already created the image before the second checks there is no eglImage Rendezvous(aIdx); if(aIdx == 0) { // Create an EGLImage from the RSgImage (member variable as it is 'shared' in the thread function...) INFO_PRINTF2(_L("Thread %d, Creating the shared EGLImage"),aIdx); iEGLImageShared = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue); ASSERT_EGL_TRUE(iEGLImageShared != EGL_NO_IMAGE_KHR); iSgImageShared.Close(); } Rendezvous(aIdx); if(aIdx == 1) { INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx); TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat); TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize); // Create a pixmap surface matching the native image pixel format eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly); // Create a VGImage from the EGLImage INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx); VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared); ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE); INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx); // Copy the source VGImage to the surface vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight); ASSERT_TRUE(vgGetError()==VG_NO_ERROR); eglWaitClient(); // we can now compare the VgImage to the one we expect from the main thread TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat); CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 5); CleanupStack::PushL(refBitmap); eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap); CleanupStack::PopAndDestroy(refBitmap); INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx); vgDestroyImage(vgImageLocal); ASSERT_TRUE(vgGetError() == VG_NO_ERROR); } Rendezvous(aIdx); if(aIdx == 0) { ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, iEGLImageShared)); iEGLImageShared = EGL_NO_IMAGE_KHR; } // cleanup eglSess->CloseSgDriver(); CleanupStack::PopAndDestroy(eglSess); }
void CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doThreadFunctionL(TInt aIdx) { INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doThreadFunctionL, Thread %d"),aIdx); CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx); eglSess->InitializeL(); eglSess->OpenSgDriverL(); INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx); TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat); TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize); // Create a pixmap surface matching the native image pixel format eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly); // Create a VGImage from the EGLImage INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx); VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared); ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE); Rendezvous(aIdx); if(aIdx == 0) { INFO_PRINTF2(_L("Thread %d, Updating contents of the VGImage from the shared EGLImage"),aIdx); TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat); CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 8); // Add pixel data to the VGImage reference from the bitmap reference. // Mind the fact that CFbsBitmap and VGImages use different coordinates origin! TSize bitmapSize = bitmap->SizeInPixels(); TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress()); TInt stride = bitmap->DataStride(); address += (bitmapSize.iHeight - 1) * stride; vgImageSubData(vgImageLocal, address, -stride, KDefaultSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight); delete bitmap; bitmap = NULL; ASSERT_TRUE(vgGetError()==VG_NO_ERROR); eglWaitClient(); } Rendezvous(aIdx); if(aIdx == 1) { INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx); // Copy the source VGImage to the surface vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight); ASSERT_TRUE(vgGetError()==VG_NO_ERROR); eglWaitClient(); // we can now compare the VgImage to the one we expect after changing it in the other thread TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat); CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 8); CleanupStack::PushL(refBitmap); eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap); CleanupStack::PopAndDestroy(refBitmap); INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx); } // cleanup vgDestroyImage(vgImageLocal); ASSERT_TRUE(vgGetError() == VG_NO_ERROR); eglSess->CloseSgDriver(); CleanupStack::PopAndDestroy(eglSess); }
/* ---------------------------------- Server side IO implementation ---- */ PUBLIC void IOThread(disk_t *disk) { stream_t *stream; QoSEntry_clp qosentry = disk->qosentry; Time_T pre,post; IO_clp io; IO_Rec recs[2]; uint32_t nrecs; word_t value; uint32_t offset; Time_ns cost; uint32_t notify; USD_Extent ext; FileIO_Request copyreq; FileIO_Request *req; while (True) { TRC(printf(__FUNCTION__": about to Rendezvous...\n")); io = IOEntry$Rendezvous((IOEntry_clp)qosentry, FOREVER); /* ** Account the time we're about to spend processing this packet ** to the QosEntry: for now, we just are sych. and so can ** actually count the amount of time. XXX no overhead accounted. */ pre = NOW(); TRC(printf(__FUNCTION__": back from Rdzvs, io at %p\n", io)); /* Find out whose IO it is */ stream = (stream_t *)IO_HANDLE(io); offset = stream->usd->partition->p_offset; TRC(printf("(It's stream %d)\n",stream->sid)); /* XXX SMH: nasty hardwired request/buffer IO_Rec pair */ if (IO$GetPkt(io, 2, recs, 0, &nrecs, &value)) { FTRC("got packet.\n"); req = (FileIO_Request *)recs[0].base; copyreq = *req; IOTRC(printf("req=%p\n",req)); IOTRC(printf("%qx:(%qd,%d)\n", stream->sid, copyreq.blockno, copyreq.nblocks)); /* Translate the addresses in the request */ if(!USDCallback$Translate(stream->usd->callbacks, stream->sid, stream->cid, ©req, &ext, ¬ify)) { TRC(printf("denied %qx:(%qd,%x)\n", stream->sid, copyreq.blockno, copyreq.nblocks)); req->rc = FileIO_RC_DENIED; goto denied; } /* Actually do the transaction */ switch(copyreq.op) { case FileIO_Op_Read: FTRC("trying to read.\n"); MU_LOCK(&disk->mu); if (BlockDev$Read((BlockDev_clp)disk->device, ext.base + offset, ext.len, recs[1].base)) { req->rc = FileIO_RC_OK; FTRC("done.\n"); } else { req->rc = FileIO_RC_FAILURE; FTRC("failure trying to read.\n"); } MU_RELEASE(&disk->mu); break; case FileIO_Op_Write: FTRC("trying to write.\n"); MU_LOCK(&disk->mu); if (BlockDev$Write((BlockDev_clp)disk->device, ext.base + offset, ext.len, recs[1].base)) { req->rc = FileIO_RC_OK; FTRC("done.\n"); } else { req->rc = FileIO_RC_FAILURE; FTRC("failure trying to write.\n"); } MU_RELEASE(&disk->mu); break; case FileIO_Op_Sync: FTRC("trying to sync.\n"); printf(__FUNCTION__": FileIO_Op_Sync unimplemented.\n"); FTRC("done.\n"); break; default: printf(__FUNCTION__": bad FileIO_Op %x\n", copyreq.op); ntsc_dbgstop(); } USDCallback$Notify(stream->usd->callbacks, stream->sid, stream->cid, ©req, &ext, notify, recs[1].base); denied: post = NOW(); cost = post - pre; QoSEntry$Charge(qosentry, io, cost); /* Return the IO_Rec vector */ TRC(printf("USD$IOThread: returning IOs.\n")); IO$PutPkt(io, nrecs, &recs[0], cost, 0); } } /* while true */ printf("USD$IOThread: BAD NEWS. Exiting (?)\n"); }