1#include "dsa.h"
2#include "sdlepocapi.h"
3#include <cdsb.h>
4
5
6LOCAL_C TInt BytesPerPixel(TDisplayMode aMode)
7	{
8	return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1;
9	}
10
11
12NONSHARABLE_CLASS(TDsa)
13	{
14	public:
15		inline TDsa(const CDsa& aDsa);
16		inline TBool IsFlip() const;
17		inline TBool IsTurn() const;
18		inline const TSize& SwSize() const;
19		inline void Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const;
20	private:
21		const CDsa& iDsa;
22	};
23
24
25inline TDsa::TDsa(const CDsa& aDsa) : iDsa(aDsa)
26	{
27	}
28
29inline TBool TDsa::IsTurn() const
30	{
31	return iDsa.iStateFlags & CDsa::EOrientation90;
32	}
33
34inline TBool TDsa::IsFlip() const
35	{
36	return iDsa.iStateFlags & CDsa::EOrientation180;
37	}
38
39inline const TSize& TDsa::SwSize() const
40	{
41	return iDsa.SwSize();
42	}
43
44inline void TDsa::Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const
45	{
46	iDsa.iCopyFunction(iDsa, aTarget, aSrc, aBytes, aHeight);
47	}
48
49template<class T, class S>
50void ClipCopy(const TDsa& iDsa, TUint8* aTarget,
51 					const TUint8* aSource,
52 					const TRect& aUpdateRect,
53 					const TRect& aSourceRect)
54	{
55	const S* source = reinterpret_cast<const S*>(aSource);
56	const TInt lineWidth = aSourceRect.Width();
57
58	source += (aUpdateRect.iTl.iY * lineWidth);
59	const TInt sourceStartOffset = aUpdateRect.iTl.iX;
60	source += sourceStartOffset;
61
62	T* targetPtr = reinterpret_cast<T*>(aTarget);
63
64	const TInt scanLineWidth = iDsa.SwSize().iWidth;
65
66	targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * scanLineWidth;
67	const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX);
68
69	targetPtr += targetStartOffset;
70
71
72	const TInt height = aUpdateRect.Height();
73
74	const TInt lineMove = iDsa.IsTurn() ? 1 : lineWidth;
75	const TInt copyLen = aUpdateRect.Width();
76
77
78	if(iDsa.IsFlip())
79		{
80
81		targetPtr += scanLineWidth *  (height - 1);
82
83		for(TInt i = 0; i < height; i++) //source is always smaller
84			{
85			iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height);
86			source += lineMove;
87			targetPtr -= scanLineWidth;
88			}
89		}
90	else
91		{
92
93
94		for(TInt i = 0; i < height; i++) //source is always smaller
95			{
96			iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height);
97			source += lineMove;
98			targetPtr += scanLineWidth; // >> 2;
99			}
100		}
101
102	}
103
104
105
106NONSHARABLE_CLASS(CDsaA) : public CDsa
107	{
108	public:
109		CDsaA(RWsSession& aSession);
110	private:
111		~CDsaA();
112		TUint8* LockSurface();
113		void UnlockHWSurfaceRequestComplete();
114		void UnlockHwSurface();
115		void CreateSurfaceL();
116		void Wipe(TInt aLength);
117		void Free();
118		void Update(CFbsBitmap& aBmp);
119		void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice);
120		TInt ExternalUpdate();
121	//	void ExternalUpdate();
122	protected:
123		CFbsBitmap* iBmp;
124		CFbsBitmap* iCopyBmp;
125	};
126
127
128CDsaA::CDsaA(RWsSession& aSession) : CDsa(aSession)
129	{
130	}
131
132
133void CDsaA::Free()
134	{
135	delete iBmp;
136	iBmp = NULL;
137	}
138
139CDsaA::~CDsaA()
140	{
141	__ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady));
142	delete iCopyBmp;
143	}
144
145TUint8* CDsaA::LockSurface()
146	{
147	iBmp->LockHeap();
148	return reinterpret_cast<TUint8*>(iBmp->DataAddress());
149	}
150
151void CDsaA::UnlockHWSurfaceRequestComplete()
152	{
153	PANIC(KErrNotSupported);
154	}
155
156void CDsaA::UnlockHwSurface()
157	{
158	iBmp->UnlockHeap();
159	SetUpdating(EFalse);
160	Update(*iBmp);
161	}
162
163void CDsaA::Update(CFbsBitmap& aBmp)
164	{
165	if(!Blitter(aBmp))
166		{
167		if(SwSize() == HwRect().Size())
168			Dsa().Gc()->BitBlt(HwRect().iTl, &aBmp);
169		else
170			Dsa().Gc()->DrawBitmap(HwRect(), &aBmp);
171		}
172	DrawOverlays();
173	Dsa().ScreenDevice()->Update();
174	}
175void CDsaA::CreateSurfaceL()
176	{
177	delete iBmp;
178	iBmp = NULL;
179	iBmp  = new (ELeave) CFbsBitmap();
180	User::LeaveIfError(iBmp->Create(SwSize(), DisplayMode()));
181	}
182
183void CDsaA::Wipe(TInt aLength) //dont call in drawing
184	{
185	iBmp->LockHeap();
186	Mem::FillZ(iBmp->DataAddress(), aLength);
187	iBmp->UnlockHeap();
188	}
189
190
191
192TInt CDsaA::ExternalUpdate()
193	{
194	if(iCopyBmp->Handle() == 0)
195		{
196		const TInt err = iCopyBmp->Duplicate(iBmp->Handle());
197		if(err != KErrNone)
198			return err;
199		}
200	Update(*iCopyBmp);
201	return KErrNone;
202	}
203
204void CDsaA::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice)
205	{
206	iCopyBmp = new (ELeave) CFbsBitmap();
207	CDsa::ConstructL(aWindow, aDevice);
208	}
209
210
211//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
212
213NONSHARABLE_CLASS(MDsbObs)
214	{
215	public:
216		virtual void SurfaceReady() = 0;
217		virtual CDirectScreenBitmap& Dsb() = 0;
218	};
219
220NONSHARABLE_CLASS(CDsbSurface) : public CActive
221	{
222	public:
223		CDsbSurface(MDsbObs& aDsb);
224		TUint8* Address();
225		void Complete();
226		~CDsbSurface();
227	private:
228		void RunL();
229		void DoCancel();
230	private:
231		MDsbObs& iDsb;
232		TUint8* iAddress;
233	};
234
235CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb)
236	{
237	CActiveScheduler::Add(this);
238	}
239
240CDsbSurface::~CDsbSurface()
241	{
242	Cancel();
243	}
244
245void CDsbSurface::Complete()
246	{
247	if(iAddress != NULL && !IsActive())
248		{
249		iAddress = NULL;
250		SetActive();
251		iDsb.Dsb().EndUpdate(iStatus);
252		}
253	}
254
255TUint8* CDsbSurface::Address()
256	{
257	if(iAddress == NULL && !IsActive())
258		{
259		TAcceleratedBitmapInfo info;
260		if(KErrNone == iDsb.Dsb().BeginUpdate(info))
261			iAddress = info.iAddress;
262		}
263	return iAddress;
264	}
265
266void CDsbSurface::RunL()
267	{
268	iDsb.SurfaceReady();
269	}
270
271void CDsbSurface::DoCancel()
272	{
273	//empty
274	}
275
276NONSHARABLE_CLASS(CDsaB) : public CDsa, public MDsbObs
277	{
278	public:
279		CDsaB(RWsSession& aSession, TInt aFlags);
280	private:
281		~CDsaB();
282		TUint8* LockSurface();
283		void UnlockHWSurfaceRequestComplete();
284		void UnlockHwSurface();
285		void CreateSurfaceL();
286		void Wipe(TInt aLength);
287		void RecreateL();
288		void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice);
289		CDirectScreenBitmap& Dsb();
290		void SurfaceReady();
291		TInt ExternalUpdate();
292	private:
293		CDsbSurface* iSurface1;
294		CDsbSurface* iSurface2;
295		CDirectScreenBitmap* iDsb;
296		TInt iType;
297	};
298
299CDsaB::CDsaB(RWsSession& aSession, TInt aFlags) : CDsa(aSession), iType(aFlags)
300	{
301	}
302
303
304
305void CDsaB::UnlockHWSurfaceRequestComplete()
306	{
307	iSurface1->Complete();
308	if(iSurface2 != NULL)
309		iSurface2->Complete();
310	}
311
312void CDsaB::CreateSurfaceL()
313	{
314	__ASSERT_ALWAYS(SwSize() == HwRect().Size(), PANIC(KErrNotSupported));
315	}
316
317void CDsaB::Wipe(TInt aLength) //dont call in drawing
318	{
319	TUint8* addr = LockSurface();
320	if(addr != NULL)
321		{
322		Mem::FillZ(addr, aLength);
323		UnlockHwSurface();
324		}
325	}
326
327
328void CDsaB::UnlockHwSurface()
329	{
330	EpocSdlEnv::Request(CDsa::ERequestUpdate);
331	}
332
333TUint8* CDsaB::LockSurface()
334	{
335	TUint8* addr =  iSurface1->Address();
336	if(addr == NULL && iSurface2 != NULL)
337		addr =  iSurface2->Address();
338	SetUpdating(addr == NULL);
339	return addr;
340	}
341
342void CDsaB::SurfaceReady()
343	{
344	SetUpdating(EFalse);
345	}
346
347CDirectScreenBitmap& CDsaB::Dsb()
348	{
349	return *iDsb;
350	}
351
352void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice)
353	{
354	if(iDsb == NULL)
355		iDsb = CDirectScreenBitmap::NewL();
356	CDsa::ConstructL(aWindow, aDevice);
357	if(iSurface1 == NULL)
358		iSurface1 = new (ELeave) CDsbSurface(*this);
359	if(iSurface2 == NULL && iType & CDirectScreenBitmap::EDoubleBuffer)
360		iSurface2 = new (ELeave) CDsbSurface(*this);
361	}
362
363CDsaB::~CDsaB()
364	{
365	delete iSurface1;
366	delete iSurface2;
367	delete iDsb;
368	}
369
370void CDsaB::RecreateL()
371	{
372    iDsb->Close();
373    iDsb->Create(HwRect(), CDirectScreenBitmap::TSettingsFlags(iType));
374	}
375
376TInt CDsaB::ExternalUpdate()
377	{
378	if(LockSurface())
379		{
380		UnlockHWSurfaceRequestComplete();
381		return KErrNone;
382		}
383	return KErrNotReady;
384	}
385
386
387/////////////////////////////////////////////////////////////////////////////////////////////////////
388
389
390CDsa* CDsa::CreateL(RWsSession& aSession)
391	{
392	if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB))
393		{
394		TInt flags = CDirectScreenBitmap::ENone;
395		if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer))
396			flags |= CDirectScreenBitmap::EDoubleBuffer;
397		if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrentalUpdate))
398			flags |= CDirectScreenBitmap::EIncrementalUpdate;
399		return new (ELeave) CDsaB(aSession, flags);
400		}
401    else
402        return new (ELeave) CDsaA(aSession);
403	}
404
405
406void CDsa::RecreateL()
407	{
408	}
409
410void CDsa::Free()
411	{
412	}
413
414TSize CDsa::WindowSize() const
415	{
416	TSize size = iSwSize;
417	if(iStateFlags & EOrientation90)
418		{
419		const TInt tmp = size.iWidth;
420		size.iWidth = size.iHeight;
421		size.iHeight = tmp;
422		}
423	return size;
424	}
425
426void CDsa::SetSuspend()
427	{
428	iStateFlags |= ESdlThreadSuspend;
429	}
430
431void CDsa::ReleaseStop()
432	{
433	iStateFlags &= ~ESdlThreadExplicitStop;
434	}
435
436
437TBool CDsa::Stopped() const
438	{
439	return (iStateFlags & ESdlThreadExplicitStop);
440	}
441
442void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation)
443	{
444	TInt flags = 0;
445	switch(aOrientation)
446		{
447		case CSDL::EOrientation90:
448			flags = EOrientation90;
449			break;
450		case CSDL::EOrientation180:
451			flags = EOrientation180;
452			break;
453		case CSDL::EOrientation270:
454			flags = EOrientation90 | EOrientation180;
455			break;
456		case CSDL::EOrientation0:
457			flags = 0;
458			break;
459		}
460	if(flags != (iStateFlags & EOrientationFlags))
461		{
462		iStateFlags |= EOrientationChanged;
463		iNewFlags = flags; //cannot be set during drawing...
464		}
465	}
466
467CDsa::~CDsa()
468    {
469    if(iDsa != NULL)
470        {
471        iDsa->Cancel();
472        }
473    iOverlays.Close();
474    delete iDsa;
475    User::Free(iLut256);
476    }
477
478void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice)
479    {
480    if(iDsa != NULL)
481    	{
482    	iDsa->Cancel();
483    	delete iDsa;
484    	iDsa = NULL;
485    	}
486
487    iDsa = CDirectScreenAccess::NewL(
488    				iSession,
489					aDevice,
490					aWindow,
491					*this);
492
493	if(iLut256 == NULL)
494		iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32));
495	iTargetMode = aWindow.DisplayMode();
496	iTargetBpp = BytesPerPixel(DisplayMode());
497	iScreenRect = TRect(aWindow.Position(), aWindow.Size());
498	SetTargetRect();
499    RestartL();
500    }
501
502void CDsa::DrawOverlays()
503	{
504	const TInt last = iOverlays.Count() - 1;
505	for(TInt i = last; i >= 0 ; i--)
506		iOverlays[i].iOverlay->Draw(*iDsa->Gc(), HwRect(), SwSize());
507	}
508
509TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority)
510	{
511	TInt i;
512	for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++)
513		{}
514	const TOverlay overlay = {&aOverlay, aPriority};
515	return iOverlays.Insert(overlay, i);
516	}
517
518TInt CDsa::RemoveOverlay(MOverlay& aOverlay)
519	{
520	for(TInt i = 0; i < iOverlays.Count(); i++)
521		{
522		if(iOverlays[i].iOverlay == &aOverlay)
523			{
524			iOverlays.Remove(i);
525			return KErrNone;
526			}
527		}
528	return KErrNotFound;
529	}
530
531void CDsa::LockPalette(TBool aLock)
532	{
533	if(aLock)
534		iStateFlags |= EPaletteLocked;
535	else
536		iStateFlags &= ~EPaletteLocked;
537	}
538TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette)
539	{
540	if(iLut256 == NULL)
541		return KErrNotFound;
542	const TInt count = aCount - aFirst;
543	if(count > 256)
544		return KErrArgument;
545	if(iStateFlags & EPaletteLocked)
546		return KErrNone;
547	for(TInt i = aFirst; i < count; i++) //not so busy here:-)
548		{
549		iLut256[i] = aPalette[i];
550		}
551	return KErrNone;
552	}
553
554
555
556void CDsa::RestartL()
557    {
558    //const TBool active = iDsa->IsActive();
559
560    //if(!active)
561
562    iDsa->StartL();
563
564    const RRegion* r = iDsa->DrawingRegion();
565    const TRect rect = r->BoundingRect();
566    iDsa->Gc()->SetClippingRegion(r);
567
568    if(rect != iScreenRect)
569    	{
570    //	iDsa->Cancel();
571    	return ;
572   	 	}
573
574
575
576    //iScreenRect = rect; //to ensure properly set, albeit may not(?) match to value SDL has - therefore may has to clip
577	//targetrect shall no change
578	SetTargetRect();
579	RecreateL();
580
581    iStateFlags |= ERunning;
582
583    ReleaseStop();
584    if(iStateFlags & ESdlThreadSuspend)
585    	{
586    	EpocSdlEnv::Resume();
587    	iStateFlags &= ~ ESdlThreadSuspend;
588    	}
589    EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved);
590    }
591
592CDsa::CDsa(RWsSession& aSession) :
593 	iSession(aSession),
594  	iStateFlags(0)
595	{
596//	CActiveScheduler::Add(this);
597	iCFTable[0] = CopyMem;
598	iCFTable[1] = CopyMemFlipReversed;
599	iCFTable[2] = CopyMemReversed;
600	iCFTable[3] = CopyMemFlip;
601
602	iCFTable[4] = Copy256;
603	iCFTable[5] = Copy256FlipReversed;
604	iCFTable[6] = Copy256Reversed;
605	iCFTable[7] = Copy256Flip;
606
607
608	iCFTable[8] = CopySlow;
609	iCFTable[9] = CopySlowFlipReversed;
610	iCFTable[10] = CopySlowReversed;
611	iCFTable[11] = CopySlowFlip;
612	}
613
614RWsSession& CDsa::Session()
615	{
616	return iSession;
617	}
618
619TInt CDsa::RedrawRequest()
620	{
621	if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning)))
622		{
623		return ExternalUpdate();
624		}
625	return KErrNotReady;
626	}
627
628TUint8* CDsa::LockHwSurface()
629	{
630	if((iStateFlags & EUpdating) == 0) //else frame is skipped
631		{
632		return LockSurface();
633		}
634	return NULL;
635	}
636
637/*
638void CDsa::RunL()
639	{
640	iStateFlags &= ~EUpdating;
641	}
642
643
644void CDsa::DoCancel()
645	{
646	iStateFlags &= ~EUpdating;
647	//nothing can do, just wait?
648	}
649*/
650
651
652TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode)
653	{
654	if(aHwSurface && aMode != DisplayMode())
655		return KErrArgument;
656
657	iSourceMode = aMode;
658
659	iSourceBpp = BytesPerPixel(aMode);
660
661	const TSize size = WindowSize();
662	if(aSize.iWidth > size.iWidth)
663		return KErrTooBig;
664	if(aSize.iHeight > size.iHeight)
665		return KErrTooBig;
666
667	TRAPD(err, CreateSurfaceL());
668	if(err != KErrNone)
669		return err;
670
671	SetCopyFunction();
672
673	return KErrNone;
674	}
675
676
677void CDsa::CreateZoomerL(const TSize& aSize)
678	{
679	iSwSize = aSize;
680	iStateFlags |= EResizeRequest;
681	CreateSurfaceL();
682	SetTargetRect();
683	}
684
685
686/*
687void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode)
688	{
689	CFbsBitmap* s = new CFbsBitmap();
690	s->Create(aSz, aMode);
691	s->LockHeap();
692	TUint32* addr = s->DataAddress();
693	Mem::Copy(addr, aData, aLength);
694	s->UnlockHeap();
695	s->Save(aName);
696	s->Reset();
697	delete s;
698	}
699
700void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz)
701	{
702	CFbsBitmap* s = new CFbsBitmap();
703	s->Create(aSz, EColor64K);
704	TBitmapUtil bmp(s);
705	bmp.Begin(TPoint(0, 0));
706	for(TInt j = 0; j < aSz.iHeight; j++)
707		{
708		bmp.SetPos(TPoint(0, j));
709		for(TInt i = 0; i < aSz.iWidth; i++)
710			{
711			bmp.SetPixel(*aData);
712			aData++;
713			bmp.IncXPos();
714			}
715		}
716	bmp.End();
717	s->Save(aName);
718	s->Reset();
719	delete s;
720	}
721
722TBuf<16> FooName(TInt aFoo)
723	{
724	TBuf<16> b;
725	b.Format(_L("C:\\pic%d.mbm"), aFoo);
726	return b;
727	}
728
729void ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TPoint& aTargetPos)
730	{
731	const TInt iSourceBpp = 1;
732	const TInt iTargetBpp = 4;
733	const TInt iScanLineWidth = 800;
734
735	TUint8* target = aTarget;
736	const TUint8* source = aSource;
737	const TInt lineWidth = aRect.Width();
738	source += iSourceBpp * (aRect.iTl.iY * lineWidth);
739	const TInt sourceStartOffset = iSourceBpp *  aRect.iTl.iX;
740	source += sourceStartOffset;
741	target += iTargetBpp * ((aTargetPos.iY + aRect.iTl.iY ) * lineWidth);
742	const TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iX);
743	target += targetStartOffset;
744	TUint32* targetPtr = reinterpret_cast<TUint32*>(target);
745	const TInt targetWidth = iScanLineWidth >> 2;
746	const TInt height = aRect.Height();
747	}
748*/
749/*
750void CDsa::ClipCopy(TUint8* aTarget,
751 					const TUint8* aSource,
752 					const TRect& aUpdateRect,
753 					const TRect& aSourceRect) const
754	{
755	//TUint8* target = aTarget;
756	const TUint32* source = (const TUint32*) aSource;
757	const TInt lineWidth = aSourceRect.Width();
758
759	source +=  (aUpdateRect.iTl.iY * lineWidth);
760	const TInt sourceStartOffset =   aUpdateRect.iTl.iX;
761	source += sourceStartOffset;
762
763	TUint32* targetPtr = reinterpret_cast<TUint32*>(aTarget);
764
765	targetPtr +=  (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * SwSize().iWidth;
766	const TInt targetStartOffset =  (aUpdateRect.iTl.iX + aSourceRect.iTl.iX);
767
768	targetPtr += targetStartOffset;
769
770//	TUint32* targetPtr = reinterpret_cast<TUint32*>(target);
771
772	const TInt targetWidth32 = SwSize().iWidth;
773
774	const TInt height = aUpdateRect.Height();
775
776	const TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth;
777	const TInt copyLen = aUpdateRect.Width();
778
779
780	if(iStateFlags & EOrientation180)
781		{
782
783		targetPtr += targetWidth32 *  (height - 1);
784
785		for(TInt i = 0; i < height; i++) //source is always smaller
786			{
787			iCopyFunction(*this, targetPtr, (TUint8*)source, copyLen, height);
788			source += lineMove;
789			targetPtr -= targetWidth32;
790			}
791		}
792	else
793		{
794
795
796		for(TInt i = 0; i < height; i++) //source is always smaller
797			{
798			iCopyFunction(*this, targetPtr, (TUint8*)source, copyLen, height);
799			source += lineMove;
800			targetPtr += targetWidth32; // >> 2;
801			}
802		}
803
804	}
805
806*/
807
808void CDsa::ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TPoint& aTargetPos) const
809	{
810	TUint8* target = aTarget;
811	const TUint8* source = aSource;
812	const TInt lineWidth = aRect.Width();
813	source += iSourceBpp * (aRect.iTl.iY * lineWidth);
814	TInt sourceStartOffset = iSourceBpp *  aRect.iTl.iX;
815	source += sourceStartOffset;
816	target += iTargetBpp * ((aTargetPos.iY + aRect.iTl.iY ) * lineWidth);
817	TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iX);
818	target += targetStartOffset;
819	TUint32* targetPtr = reinterpret_cast<TUint32*>(target);
820	const TInt targetWidth = iScanLineWidth >> 2;
821	const TInt height = aRect.Height();
822
823	TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth;
824
825	if(iStateFlags & EOrientation180)
826		{
827
828		targetPtr += targetWidth *  (height - 1);
829
830		for(TInt i = 0; i < height; i++) //source is always smaller
831			{
832			iCopyFunction(*this, targetPtr, source, lineWidth, height);
833			source += lineMove;
834			targetPtr -= targetWidth;
835			}
836		}
837	else
838		{
839
840
841		for(TInt i = 0; i < height; i++) //source is always smaller
842			{
843			iCopyFunction(*this, targetPtr, source, lineWidth, height);
844			source += lineMove;
845			targetPtr += targetWidth;
846			}
847		}
848
849	}
850
851
852
853	/*
854void CDsa::ClipCopy(TUint8* aTarget,
855 					const TUint8* aSource,
856 					const TRect& aUpdateRect,
857 					const TRect& aSourceRect) const
858 		{
859 		const TDsa dsa(*this);
860 		switch(iSourceBpp)
861 			{
862 			case 1:
863 				::ClipCopy<TUint32, TUint8>(dsa, aTarget, aSource, aUpdateRect, aSourceRect);
864 				break;
865 			case 2:
866 				::ClipCopy<TUint32, TUint16>(dsa, aTarget, aSource, aUpdateRect, aSourceRect);
867 				break;
868 			case 4:
869 				::ClipCopy<TUint32, TUint32>(dsa, aTarget, aSource, aUpdateRect, aSourceRect);
870 				break;
871 			}
872 		}
873
874
875*/
876
877
878
879void CDsa::Wipe() //dont call in drawing
880	{
881	if(IsDsaAvailable())
882		Wipe(iTargetBpp * SwSize().iWidth * SwSize().iHeight);
883	}
884
885void CDsa::SetCopyFunction()
886	{
887	//calculate offset to correct function in iCFTable according to given parameters
888	TInt function = 0;
889	const TInt KCopyFunctions = 4;
890	const TInt KOffsetToNative = 0;
891	const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions;
892	const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions;
893	const TInt KOffsetTo90Functions = 1;
894	const TInt KOffsetTo180Functions = 2;
895
896	if(iSourceMode == DisplayMode())
897		function = KOffsetToNative; 		//0
898	else if(iSourceMode == EColor256)
899		function = KOffsetTo256;			//4
900	else
901		function = KOffsetToOtherModes; 	//8
902
903	if(iStateFlags & EOrientation90)
904		function += KOffsetTo90Functions; 	// + 1
905	if(iStateFlags & EOrientation180)
906		function += KOffsetTo180Functions; 	//+ 2
907
908	iCopyFunction = iCFTable[function];
909
910	Wipe();
911	}
912
913inline void Rotate(TRect& aRect)
914	{
915	const TInt dx = aRect.iBr.iX - aRect.iTl.iX;
916	const TInt dy = aRect.iBr.iY - aRect.iTl.iY;
917
918	aRect.iBr.iX = aRect.iTl.iX + dy;
919	aRect.iBr.iY = aRect.iTl.iY + dx;
920
921	const TInt tmp = aRect.iTl.iX;
922	aRect.iTl.iX = aRect.iTl.iY;
923	aRect.iTl.iY = tmp;
924	}
925
926/*
927int bar = 0;
928*/
929/*
930TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect)
931	{
932
933	if(iStateFlags & EOrientationChanged)
934		{
935		iStateFlags &= ~EOrientationFlags;
936		iStateFlags |= iNewFlags;
937		SetCopyFunction();
938		iStateFlags &= ~EOrientationChanged;
939	    EpocSdlEnv::WaitDeviceChange();
940	    return EFalse; //skip this frame as data is may be changed
941		}
942
943	if(iTargetAddr == NULL)
944		{
945		iTargetAddr = LockHwSurface();
946		}
947
948	TUint8* target = iTargetAddr;
949	if(target == NULL)
950		return EFalse;
951
952
953	TRect targetRect = TRect(TPoint(0, 0), SwSize());
954
955	TRect sourceRect = aRect;
956	TRect updateRect = aUpdateRect;
957
958//	TPoint move(0, 0);
959
960
961	if(iStateFlags & EOrientation90)
962		{
963		Rotate(sourceRect);
964		Rotate(updateRect);
965		}
966
967	if(iSourceMode != DisplayMode() ||  targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0))
968		{
969		sourceRect.Intersection(targetRect); //so source always smaller or equal than target
970		//updateRect.Intersection(targetRect);
971		ClipCopy(target, aBits, updateRect, sourceRect);
972		}
973	else
974		{
975		const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored
976		Mem::Copy(target, aBits, byteCount);
977		}
978
979	return ETrue;
980	}
981	*/
982
983TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect)
984	{
985
986	if(iStateFlags & EOrientationChanged)
987		{
988		iStateFlags &= ~EOrientationFlags;
989		iStateFlags |= iNewFlags;
990		SetCopyFunction();
991		iStateFlags &= ~EOrientationChanged;
992	    EpocSdlEnv::WaitDeviceChange();
993	    return EFalse; //skip this frame as data is may be changed
994		}
995
996	if(iTargetAddr == NULL)
997		{
998		iTargetAddr = LockHwSurface();
999		}
1000	TUint8* target = iTargetAddr;
1001	if(target == NULL)
1002		return EFalse;
1003
1004
1005	TRect targetRect = Rect();
1006	TRect sourceRect = aRect;
1007	TRect updateRect = aUpdateRect;
1008
1009	if(iStateFlags & EOrientation90)
1010		{
1011		Rotate(sourceRect);
1012		Rotate(updateRect);
1013		}
1014
1015	if(iSourceMode != DisplayMode() ||  targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0))
1016		{
1017		sourceRect.Intersection(targetRect); //so source always smaller or equal than target
1018		updateRect.Intersection(targetRect);
1019		ClipCopy(target, aBits, updateRect, sourceRect.iTl);
1020		}
1021	else
1022		{
1023		const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored
1024		Mem::Copy(target, aBits, byteCount);
1025		}
1026
1027	return ETrue;
1028	}
1029void CDsa::UpdateSwSurface()
1030	{
1031	iTargetAddr = NULL;
1032	UnlockHwSurface();	//could be faster if does not use AO, but only check status before redraw, then no context switch needed
1033	}
1034
1035
1036void CDsa::Resume()
1037	{
1038	if(Stopped())
1039		Restart(RDirectScreenAccess::ETerminateRegion);
1040	}
1041
1042void CDsa::DoStop()
1043	{
1044	if(IsDsaAvailable())
1045		iStateFlags |= ESdlThreadExplicitStop;
1046	Stop();
1047	}
1048
1049void CDsa::Stop()
1050	{
1051	iStateFlags &= ~ERunning;
1052//	Cancel(); //can be called only from main!
1053	iDsa->Cancel();
1054	}
1055
1056void CDsa::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/)
1057	{
1058//	iStateFlags |= EChangeNotify;
1059	Stop();
1060	}
1061
1062void CDsa::Restart(RDirectScreenAccess::TTerminationReasons aReason)
1063	{
1064	if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart
1065		{
1066		TRAPD(err, RestartL());
1067		PANIC_IF_ERROR(err);
1068		}
1069	}
1070
1071void CDsa::SetBlitter(MBlitter* aBlitter)
1072	{
1073	iBlitter = aBlitter;
1074	}
1075
1076
1077TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const
1078	{
1079	TPoint pos = aPoint - iScreenRect.iTl;
1080	const TSize asz = iScreenRect.Size();
1081	if(iStateFlags & EOrientation180)
1082		{
1083		pos.iX = asz.iWidth - pos.iX;
1084		pos.iY = asz.iHeight - pos.iY;
1085		}
1086	if(iStateFlags & EOrientation90)
1087		{
1088		pos.iX = aPoint.iY;
1089		pos.iY = aPoint.iX;
1090		}
1091	pos.iX <<= 16;
1092	pos.iY <<= 16;
1093	pos.iX /= asz.iWidth;
1094	pos.iY /= asz.iHeight;
1095	pos.iX *= iSwSize.iWidth;
1096	pos.iY *= iSwSize.iHeight;
1097	pos.iX >>= 16;
1098	pos.iY >>= 16;
1099	return pos;
1100	}
1101
1102void CDsa::SetTargetRect()
1103	{
1104	iTargetRect = iScreenRect;
1105	if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio))
1106		{
1107		const TSize asz = iScreenRect.Size();
1108		const TSize sz = iSwSize;
1109
1110		TRect rect;
1111
1112		const TInt dh = (sz.iHeight << 16) / sz.iWidth;
1113
1114		if((asz.iWidth * dh ) >> 16 <= asz.iHeight)
1115			{
1116			rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16));
1117			}
1118		else
1119			{
1120			const TInt dw = (sz.iWidth << 16) / sz.iHeight;
1121	    	rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight));
1122			}
1123		rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1);
1124
1125		iTargetRect = rect;
1126		iTargetRect.Move(iScreenRect.iTl);
1127
1128		}
1129	if(!(iStateFlags & EResizeRequest))
1130		iSwSize = iScreenRect.Size();
1131//	iScanLineWidth = /*iTargetBpp **/ SwSize().iWidth;
1132	}
1133
1134/*)
1135TBool CDsa::ChangeTrigger()
1136	{
1137	const TBool change = iStateFlags & EChangeNotify;
1138	iStateFlags &= ~EChangeNotify;
1139	return change;
1140	}
1141*/
1142/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1143
1144void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt)
1145	{
1146	TUint32* target = aTarget;
1147	const TUint32* endt = target + aBytes;
1148	const TUint8* source = aSource;
1149	while(target < endt)
1150		{
1151		*target++ = aDsa.iLut256[*source++];
1152		}
1153	}
1154
1155void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt)
1156	{
1157	const TUint32* target = aTarget;
1158	TUint32* endt = aTarget + aBytes;
1159	const TUint8* source = aSource;
1160	while(target < endt)
1161		{
1162		*(--endt) = aDsa.iLut256[*source++];
1163		}
1164	}
1165
1166void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen)
1167	{
1168	TUint32* target = aTarget;
1169	const TUint32* endt = target + aBytes;
1170	const TUint8* column = aSource;
1171
1172	while(target < endt)
1173		{
1174		*target++ = aDsa.iLut256[*column];
1175		column += aLineLen;
1176		}
1177	}
1178
1179void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen)
1180	{
1181	const TUint32* target = aTarget;
1182	TUint32* endt = aTarget + aBytes;
1183	const TUint8* column = aSource;
1184
1185	while(target < endt)
1186		{
1187		*(--endt) = aDsa.iLut256[*column];
1188		column += aLineLen;
1189		}
1190	}
1191
1192void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt)
1193	{
1194	const TUint32* src = reinterpret_cast<const TUint32*>(aSource);
1195	Mem::Copy(aTarget, src, aBytes << 2);
1196	}
1197
1198void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen)
1199	{
1200	TUint32* target = aTarget;
1201	const TUint32* endt = target + aBytes;
1202	const TUint32* column = reinterpret_cast<const TUint32*>(aSource);
1203
1204	while(target < endt)
1205		{
1206		*target++ = *column;
1207		column += aLineLen;
1208		}
1209	}
1210
1211void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt)
1212	{
1213	const TUint32* target = aTarget;
1214	TUint32* endt = aTarget + aBytes;
1215	const TUint32* source = reinterpret_cast<const TUint32*>(aSource);
1216	while(target < endt)
1217		{
1218		*(--endt) = *source++;
1219		}
1220	}
1221
1222
1223void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen)
1224	{
1225	const TUint32* target = aTarget;
1226	TUint32* endt = aTarget + aBytes;
1227	const TUint32* column = reinterpret_cast<const TUint32*>(aSource);
1228
1229	while(target < endt)
1230		{
1231		*(--endt) = *column;
1232		column += aLineLen;
1233		}
1234	}
1235
1236/*
1237
1238LOCAL_C TRgb rgb16MA(TInt aValue)
1239	{
1240	return TRgb::Color16MA(aValue);
1241	}
1242*/
1243NONSHARABLE_CLASS(MRgbCopy)
1244	{
1245	public:
1246	virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0;
1247	virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0;
1248	};
1249
1250template <class T>
1251NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy
1252	{
1253	public:
1254	TRgbCopy(TDisplayMode aMode);
1255	void* operator new(TUint aBytes, TAny* aMem);
1256	void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed);
1257	void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed);
1258	static TUint32 Gray256(const TUint8& aPixel);
1259	static TUint32 Color256(const TUint8& aPixel);
1260	static TUint32 Color4K(const TUint16& aPixel);
1261	static TUint32 Color64K(const TUint16& aPixel);
1262	static TUint32 Color16M(const TUint32& aPixel);
1263	static TUint32 Color16MU(const TUint32& aPixel);
1264	static TUint32 Color16MA(const TUint32& aPixel);
1265	private:
1266		typedef TUint32 (*TRgbFunc) (const T& aValue);
1267		TRgbFunc iFunc;
1268	};
1269
1270
1271template <class T>
1272void* TRgbCopy<T>::operator new(TUint /*aBytes*/, TAny* aMem)
1273	{
1274	return aMem;
1275	}
1276
1277template <class T>
1278TRgbCopy<T>::TRgbCopy(TDisplayMode aMode)
1279	{
1280	switch(aMode)
1281		{
1282		case EGray256 : iFunc = (TRgbFunc) Gray256; break;
1283		case EColor256 : iFunc =  (TRgbFunc) Color256; break;
1284		case EColor4K : iFunc =  (TRgbFunc) Color4K; break;
1285		case EColor64K : iFunc =  (TRgbFunc) Color64K; break;
1286		case EColor16M : iFunc =  (TRgbFunc) Color16M; break;
1287		case EColor16MU : iFunc =  (TRgbFunc) Color16MU; break;
1288		case EColor16MA : iFunc =  (TRgbFunc) Color16MA; break;
1289		default:
1290			PANIC(KErrNotSupported);
1291		}
1292	}
1293
1294template <class T>
1295void TRgbCopy<T>::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed)
1296	{
1297	const T* source = reinterpret_cast<const T*>(aSource);
1298	TUint32* target = aTarget;
1299	TUint32* endt = target + aBytes;
1300
1301	if(aReversed)
1302		{
1303		while(target < endt)
1304			{
1305			const T value = *source++;
1306			*(--endt) = iFunc(value);//iFunc(value).Value();
1307			}
1308		}
1309	else
1310		{
1311		while(target < endt)
1312			{
1313			const T value = *source++;
1314			*target++ = iFunc(value);//iFunc(value).Value();
1315			}
1316		}
1317	}
1318
1319template <class T>
1320void TRgbCopy<T>::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed)
1321	{
1322	const T* column = reinterpret_cast<const T*>(aSource);
1323	TUint32* target = aTarget;
1324	TUint32* endt = target + aBytes;
1325
1326	if(aReversed)
1327		{
1328		while(target < endt)
1329			{
1330			*(--endt) = iFunc(*column);
1331			column += aLineLen;
1332			}
1333		}
1334	else
1335		{
1336		while(target < endt)
1337			{
1338			*target++ = iFunc(*column);
1339			column += aLineLen;
1340			}
1341		}
1342	}
1343
1344template <class T> TUint32 TRgbCopy<T>::Gray256(const TUint8& aPixel)
1345	{
1346	const TUint32 px = aPixel << 16 | aPixel << 8 | aPixel;
1347	return px;
1348	}
1349
1350template <class T> TUint32 TRgbCopy<T>::Color256(const TUint8& aPixel)
1351	{
1352	return TRgb::Color256(aPixel).Value();
1353	}
1354
1355template <class T> TUint32 TRgbCopy<T>::Color4K(const TUint16& aPixel)
1356	{
1357	TUint32 col = (aPixel & 0xF00) << 12;
1358	col |= (aPixel & 0xF00) << 8;
1359
1360	col |= (aPixel & 0x0F0) << 8;
1361	col |= (aPixel & 0x0F0);
1362
1363	col |= (aPixel & 0x00F) << 4;
1364	col |= (aPixel & 0x00F);
1365
1366	return col;
1367	}
1368
1369template <class T> TUint32 TRgbCopy<T>::Color64K(const TUint16& aPixel)
1370	{
1371	TUint32 col = (aPixel & 0xF800)<< 8;
1372	col |= (aPixel & 0xE000) << 3;
1373
1374	col |= (aPixel & 0x07E0) << 5;
1375	col |= (aPixel & 0xC0) >> 1;
1376
1377	col |= (aPixel & 0x07E0) << 3;
1378	col |= (aPixel & 0x1C) >> 2;
1379
1380	return col;
1381	}
1382
1383template <class T> TUint32 TRgbCopy<T>::Color16M(const TUint32& aPixel)
1384	{
1385	return TRgb::Color16M(aPixel).Value();
1386	}
1387
1388template <class T> TUint32 TRgbCopy<T>::Color16MU(const TUint32& aPixel)
1389	{
1390	return TRgb::Color16MU(aPixel).Value();
1391	}
1392
1393template <class T> TUint32 TRgbCopy<T>::Color16MA(const TUint32& aPixel)
1394	{
1395	return TRgb::Color16MA(aPixel).Value();
1396	}
1397
1398typedef TUint64 TStackMem;
1399
1400LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode)
1401	{
1402	if(aMode == EColor256 || aMode == EGray256)
1403		{
1404		return new (mem) TRgbCopy<TUint8>(aMode);
1405		}
1406	if(aMode == EColor4K || aMode == EColor64K)
1407		{
1408		return new (mem) TRgbCopy<TUint16>(aMode);
1409		}
1410	if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA)
1411		{
1412		return new (mem) TRgbCopy<TUint32>(aMode);
1413		}
1414	PANIC(KErrNotSupported);
1415	return NULL;
1416	}
1417
1418
1419void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen)
1420	{
1421	TStackMem mem = 0;
1422	GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue);
1423	}
1424
1425void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen)
1426	{
1427	TStackMem mem = 0;
1428	GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse);
1429	}
1430
1431void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt)
1432	{
1433	TStackMem mem = 0;
1434	GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse);
1435	}
1436
1437void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt)
1438	{
1439	TStackMem mem = 0;
1440	GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue);
1441	}
1442
1443////////////////////////////////////////////////////////////////////////////////////////////////////////////////7
1444