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);
	}
示例#6
0
文件: io.c 项目: berkus/nemesis
/* ---------------------------------- 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,
				      &copyreq,
				      &ext,
				      &notify))
	    {
		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,
			       &copyreq,
			       &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");
}