|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "directgdipaniccodes.h" // Included first to resolve dependency |
|
17 |
|
18 #include <graphics/sgimage.h> |
|
19 #include <graphics/directgdiimagetarget.h> |
|
20 #include <graphics/directgdidrawablesource.h> |
|
21 #include <graphics/directgdipanics.h> |
|
22 #include <graphics/directgdidriverinternal.h> |
|
23 #include <e32svr.h> |
|
24 #include <u32hal.h> |
|
25 |
|
26 #include "directgdidriver.h" |
|
27 #include "directgditypes.h" |
|
28 #include "directgdidriverinternallibrary.inl" |
|
29 |
|
30 typedef TInt (*TDriverCreateFunction)(CDirectGdiDriverInternal*&, RLibrary); |
|
31 |
|
32 /** |
|
33 Returns the singleton instance of CDirectGdiDriver for the calling thread. |
|
34 |
|
35 @return Pointer to an opened CDirectGdiDriver object else NULL if a CDirectGdiDriver had not been opened yet. |
|
36 */ |
|
37 EXPORT_C CDirectGdiDriver* CDirectGdiDriver::Static() |
|
38 { |
|
39 return static_cast<CDirectGdiDriver*>(Dll::Tls()); |
|
40 } |
|
41 |
|
42 /** |
|
43 Creates a new CDirectGdiDriver object if one has not already been created in this thread. |
|
44 Performs any adaptation initialisation that is needed to allow the calling thread to use |
|
45 functionality provided by the new DirectGDI interfaces. Calling this method multiple times |
|
46 from the same client thread has no effect after the first call, other than to increase the |
|
47 open count. |
|
48 |
|
49 @see CDirectGdiDriver::Close() |
|
50 |
|
51 @pre None. |
|
52 @post The object reference counter is incremented. Adaptation resources for the |
|
53 calling thread are created and initialised. The new DirectGDI interfaces are ready |
|
54 to be used from the calling thread. |
|
55 |
|
56 @return KErrNone if successful, otherwise one of the system-wide error codes. |
|
57 */ |
|
58 EXPORT_C TInt CDirectGdiDriver::Open() |
|
59 { |
|
60 TInt err = KErrNone; |
|
61 CDirectGdiDriver* self = Static(); |
|
62 |
|
63 // Check we're not already opened |
|
64 if (!self) |
|
65 { |
|
66 self = new CDirectGdiDriver(); |
|
67 if (!self) |
|
68 { |
|
69 err = KErrNoMemory; |
|
70 return err; |
|
71 } |
|
72 |
|
73 #ifdef __WINS__ |
|
74 // Dynamically load DirectGDI adapter library. |
|
75 // Under WINS two dlls will be available - directgdiadapter_sw.dll and directgdiadapter_vg.dll |
|
76 // Need to select which dll to load. The value of the keyword SYMBIAN_GRAPHICS_DIRECTGDI_USE |
|
77 // in the epoc.ini file will determine the dll to load. |
|
78 // If this keyword does not appear in the epoc.ini file, the software version of |
|
79 // directgdiadapter will be loaded by default. |
|
80 _LIT(KVgAdapterDllName, "directgdiadapter_vg.dll"); |
|
81 _LIT(KSwAdapterDllName, "directgdiadapter_sw.dll"); |
|
82 TBool useOpenVg = EFalse; |
|
83 UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalBoolProperty, (TAny*)"symbian_graphics_directgdi_use_openvg", &useOpenVg); |
|
84 TPtrC libraryName; |
|
85 if(useOpenVg) |
|
86 { |
|
87 libraryName.Set(KVgAdapterDllName); |
|
88 } |
|
89 else |
|
90 { |
|
91 libraryName.Set(KSwAdapterDllName); |
|
92 } |
|
93 RLibrary lib; |
|
94 err = lib.Load(libraryName); |
|
95 if (err != KErrNone) |
|
96 { |
|
97 delete self; |
|
98 return (err==KErrNotFound ? KErrNotSupported : err); |
|
99 } |
|
100 |
|
101 // Create internal driver |
|
102 err = self->CreateInternalDriver(lib); |
|
103 if (err != KErrNone) |
|
104 { |
|
105 delete self; |
|
106 lib.Close(); |
|
107 return err; |
|
108 } |
|
109 #else |
|
110 // Under armv5, the appropriate dll (software or vg) is determined at rom build time. |
|
111 err = self->CreateInternalDriver(); |
|
112 if (err != KErrNone) |
|
113 { |
|
114 delete self; |
|
115 return err; |
|
116 } |
|
117 #endif |
|
118 |
|
119 // Store a pointer to the new driver instance in thread local storage: |
|
120 err = Dll::SetTls(self); |
|
121 if (err != KErrNone) |
|
122 { |
|
123 delete self; |
|
124 } |
|
125 } |
|
126 |
|
127 if (err == KErrNone) |
|
128 { |
|
129 ++(self->iOpenCount); |
|
130 } |
|
131 |
|
132 return err; |
|
133 } |
|
134 |
|
135 /** |
|
136 Create the adaptation/internal object for this driver. |
|
137 |
|
138 @pre The adaptation/internal driver object has not been created yet. |
|
139 @post The adaptation/internal object has been created. |
|
140 |
|
141 @return KErrNone if successful, otherwise one of the system-wide error codes. |
|
142 */ |
|
143 #ifdef __WINS__ |
|
144 TInt CDirectGdiDriver::CreateInternalDriver(const RLibrary& aLibrary) |
|
145 { |
|
146 // Function at ordinal 1 creates new CDirectGdiDriverInternal |
|
147 TDriverCreateFunction create = reinterpret_cast<TDriverCreateFunction>(aLibrary.Lookup(1)); |
|
148 return create(iDriverInternal, aLibrary); |
|
149 } |
|
150 #else |
|
151 TInt CDirectGdiDriver::CreateInternalDriver() |
|
152 { |
|
153 return CDirectGdiDriverInternal::New(iDriverInternal, RLibrary()); |
|
154 } |
|
155 #endif |
|
156 |
|
157 /** |
|
158 Performs adaptation termination which is needed to release any internal resources |
|
159 allocated by the calling thread. It will also perform an implicit Finish() by submitting |
|
160 all outstanding requests from the calling thread. A DirectGDI client's thread that |
|
161 uses the new DirectGDI interfaces must call this method at the end of its lifetime. |
|
162 |
|
163 @see CDirectGdiDriver::Open() |
|
164 |
|
165 @pre The driver is open from a call to Open(). |
|
166 @post The object open count is decremented. If the open count reaches zero, any |
|
167 adaptation resources allocated to the calling thread must be released, and the CDirectGdiDriver |
|
168 object for the calling thread is destroyed. |
|
169 |
|
170 @panic DGDI 14, if Close() is called on a CDirectGdiDriver object that is not open. |
|
171 */ |
|
172 EXPORT_C void CDirectGdiDriver::Close() |
|
173 { |
|
174 GRAPHICS_ASSERT_ALWAYS(iOpenCount > 0, EDirectGdiPanicDriverOpenCountError); |
|
175 |
|
176 if (--iOpenCount == 0) |
|
177 { |
|
178 // We call Finish() instead of Flush() because it will decrease the reference count |
|
179 // of images used in DrawResource() (if any) and is guaranteed that it will complete. |
|
180 // Flush() cannot guarantee completion so we can't decrement image reference counts. |
|
181 Finish(); |
|
182 |
|
183 // Get the handle to the DLL used by iDriverInternal so that we can close |
|
184 // it once iDriverInternal has been deleted. |
|
185 RLibrary lib = iDriverInternal->Library(); |
|
186 delete this; |
|
187 lib.Close(); |
|
188 |
|
189 // Free the space we saved for the driver singleton pointer in thead local storage |
|
190 Dll::FreeTls(); |
|
191 } |
|
192 } |
|
193 |
|
194 /** |
|
195 Ensures all outstanding requests on the calling thread are submitted for processing. |
|
196 The method immediately returns and does not wait until all outstanding requests are |
|
197 completely processed. Clients can continue issuing rendering requests after calling |
|
198 this method. |
|
199 |
|
200 @see CDirectGdiDriver::Finish() |
|
201 |
|
202 @pre CDirectGdiDriver object has been initialised for the calling thread. |
|
203 @post All outstanding requests have been submitted for processing. |
|
204 */ |
|
205 EXPORT_C void CDirectGdiDriver::Flush() |
|
206 { |
|
207 iDriverInternal->Flush(); |
|
208 } |
|
209 |
|
210 /** |
|
211 Ensures all outstanding rendering requests from the calling thread are submitted |
|
212 and processed. This method will wait until all the outstanding rendering requests |
|
213 have been completely processed. |
|
214 |
|
215 @see CDirectGdiDriver::Flush() |
|
216 |
|
217 @pre CDirectGdiDriver object has been initialised for the calling thread. |
|
218 @post All outstanding requests have been completely processed. |
|
219 */ |
|
220 EXPORT_C void CDirectGdiDriver::Finish() |
|
221 { |
|
222 iDriverInternal->Finish(); |
|
223 } |
|
224 |
|
225 /** |
|
226 Returns the first error code (as the result of calling any DirectGDI API), if any, |
|
227 since the last call to this function or, if it has not previously been called, since |
|
228 the CDirectGdiDriver was initialised. Calling this function clears the error code. |
|
229 |
|
230 @see CDirectGdiDriver::SetError(TInt) |
|
231 |
|
232 @pre CDirectGdiDriver object has been initialised for the calling thread. |
|
233 @post The error code has been reset after being read. |
|
234 |
|
235 @return The first error code, if any, since the last call to this function or, |
|
236 if it has not previously been called, since the CDirectGdiDriver was initialised. |
|
237 KErrNone will indicate that no such error has occurred. |
|
238 */ |
|
239 EXPORT_C TInt CDirectGdiDriver::GetError() |
|
240 { |
|
241 return iDriverInternal->GetError(); |
|
242 } |
|
243 |
|
244 |
|
245 /** |
|
246 Sets the error code on the driver. If the error code is already set to a value other |
|
247 than KErrNone, the error code will not be modified. |
|
248 |
|
249 @see CDirectGdiDriver::GetError() |
|
250 |
|
251 @param aErr The error code to set. |
|
252 |
|
253 @pre CDirectGdiDriver object has been initialised for the calling thread. |
|
254 @post The error code has been set. |
|
255 */ |
|
256 EXPORT_C void CDirectGdiDriver::SetError(TInt aErr) |
|
257 { |
|
258 iDriverInternal->SetError(aErr); |
|
259 } |
|
260 |
|
261 /** |
|
262 Retrieves a pointer to an instance of the requested extension interface implementation, if provided. |
|
263 |
|
264 @param aInterfaceId The globally unique identifier of the requested interface. |
|
265 @param aInterface On return, holds the specified interface, or NULL if the interface cannot be found. |
|
266 |
|
267 @pre CDirectGdiDriver object has been initialised for the calling thread. |
|
268 |
|
269 @return KErrNone If the interface is supported, KErrExtensionNotSupported otherwise. |
|
270 */ |
|
271 EXPORT_C TInt CDirectGdiDriver::GetInterface(TUid aInterfaceId, TAny*& aInterface) |
|
272 { |
|
273 return iDriverInternal->GetInterface(aInterfaceId, aInterface); |
|
274 } |
|
275 |
|
276 /** |
|
277 CDirectGdiDriver private constructor as this class is singleton. |
|
278 |
|
279 @pre None. |
|
280 @post Initialises the member reference counter to zero. |
|
281 */ |
|
282 CDirectGdiDriver::CDirectGdiDriver() |
|
283 { |
|
284 } |
|
285 |
|
286 /** |
|
287 CDirectGdiDriver default destructor. |
|
288 |
|
289 @pre None. |
|
290 @post None. |
|
291 |
|
292 @panic DGDI 15, if the resource count is not zero. |
|
293 */ |
|
294 CDirectGdiDriver::~CDirectGdiDriver() |
|
295 { |
|
296 GRAPHICS_ASSERT_ALWAYS(iOpenCount == 0, EDirectGdiPanicDriverDestructorOpenCountError); |
|
297 delete iDriverInternal; |
|
298 } |
|
299 |
|
300 /** |
|
301 Delegates the call to the CDirectGdiDriverInternal object, which creates a DirectGDI |
|
302 adaptation-specific resource from the given drawable resource so it can be drawn |
|
303 using the DirectGDI rendering API. |
|
304 |
|
305 @see CloseDrawableSource() |
|
306 |
|
307 @param aRDirectGdiDrawableSource The RDirectGdiDrawableSource object to be created |
|
308 @param aRSgDrawable The RSgDrawable object to use when creating aRDirectGdiDrawableSource |
|
309 |
|
310 @pre CDirectGdiDriver object has been initialised from the calling thread. |
|
311 @post The DirectGDI adaptation-specific resource that is bound to the given |
|
312 drawable resource is created and this handle is now associated with it. The reference |
|
313 counter on the drawable resource is incremented. The CDirectGdiDriver for this thread |
|
314 is now aware of and owns the adaptation specific resource. |
|
315 |
|
316 @return KErrNone if successful, KErrNotSupported if the drawable resource is not |
|
317 created with the correct usage (ESgUsageDirectGdiSource must be set), otherwise one of the system-wide error codes. |
|
318 |
|
319 @panic DGDI 19, if this handle is already associated with a DirectGDI adaptation-specific drawable resource. |
|
320 @panic DGDI 20, if the drawable resource is not valid. |
|
321 */ |
|
322 TInt CDirectGdiDriver::CreateDrawableSource(RDirectGdiDrawableSource& aRDirectGdiDrawableSource, const RSgDrawable& aRSgDrawable) |
|
323 { |
|
324 GRAPHICS_ASSERT_ALWAYS(aRDirectGdiDrawableSource.Handle() == KNullHandle, EDirectGdiPanicDrawableSourceAlreadyExists); |
|
325 |
|
326 if(aRSgDrawable.DrawableType() == KSgImageTypeUid) |
|
327 {// make sure that drawable was created with the flag ESgUsageDirectGdiSource |
|
328 RSgImage *image = (RSgImage*) &aRSgDrawable; |
|
329 TSgImageInfo info; |
|
330 TInt err = image ->GetInfo (info); |
|
331 GRAPHICS_ASSERT_ALWAYS(err == KErrNone, EDirectGdiPanicImageSourceInfoError); |
|
332 |
|
333 if (!(info.iUsage & ESgUsageDirectGdiSource)) |
|
334 { |
|
335 return KErrNotSupported; |
|
336 } |
|
337 } |
|
338 return iDriverInternal->CreateDrawableSource(aRDirectGdiDrawableSource.iHandle, aRSgDrawable); |
|
339 } |
|
340 |
|
341 /** |
|
342 Delegates call to the CDirectGdiDriverInternal object, which destroys the DirectGDI |
|
343 adaptation-specific resource associated with this handle. Calling this method on a |
|
344 handle that is not associated with any DirectGDI adaptation specific resource will |
|
345 do nothing. Once Close() is called, this handle can be reused. |
|
346 |
|
347 @see CreateDrawableSource() |
|
348 |
|
349 @param aSource The RDirectGdiDrawableSource object. |
|
350 |
|
351 @pre CDirectGdiDriver object has been initialised from the calling thread. |
|
352 @post The DirectGDI specific resource associated with this handle will be |
|
353 destroyed (at any time preferred by the adaptation). This handle is no longer |
|
354 associated with a DirectGDI specific resource. The reference counter of the |
|
355 underlying non-image resource is decremented. |
|
356 */ |
|
357 void CDirectGdiDriver::CloseDrawableSource(RDirectGdiDrawableSource& aSource) |
|
358 { |
|
359 iDriverInternal->CloseDrawableSource(aSource.iHandle); |
|
360 } |
|
361 |
|
362 /** |
|
363 Delegates call to the CDirectGdiDriverInternal object, which creates a DirectGDI |
|
364 adaptation-specific resource from the given image resource so it can be used as a |
|
365 target of DirectGDI rendering. |
|
366 |
|
367 @see CloseImageTarget() |
|
368 |
|
369 @param aTarget The RDirectGdiImageTarget object. |
|
370 @param aImage The RSgImage object. |
|
371 |
|
372 @pre CDirectGdiDriver object has been initialised from the calling thread. |
|
373 The image resource has been fully constructed and created with the correct usage |
|
374 that allows it to be used as a DirectGDI target. |
|
375 |
|
376 @post The DirectGDI adaptation-specific resource that is bound to the given image |
|
377 resource is created and this handle is now associated with it. The reference counter |
|
378 on the image resource is incremented. |
|
379 |
|
380 @return KErrNone if successful, KErrNotSupported if the image resource is not |
|
381 created with the correct usage, otherwise one of the system-wide error codes. |
|
382 |
|
383 @panic DGDI 17, if this handle is already associated with a DirectGDI adaptation-specific resource. |
|
384 @panic DGDI 21, if the image resource is not valid. |
|
385 */ |
|
386 TInt CDirectGdiDriver::CreateImageTarget(RDirectGdiImageTarget& aTarget, const RSgImage& aImage) |
|
387 { |
|
388 GRAPHICS_ASSERT_ALWAYS(aTarget.Handle() == KNullHandle, EDirectGdiPanicImageTargetAlreadyExists); |
|
389 TSgImageInfo info; |
|
390 TInt err = aImage.GetInfo(info); |
|
391 GRAPHICS_ASSERT_ALWAYS(err == KErrNone, EDirectGdiPanicImageTargetInfoError); |
|
392 |
|
393 if (!(info.iUsage & ESgUsageDirectGdiTarget)) |
|
394 { |
|
395 return KErrNotSupported; |
|
396 } |
|
397 return iDriverInternal->CreateImageTarget(aTarget.iHandle, aImage); |
|
398 } |
|
399 |
|
400 /** |
|
401 Delegates call to the CDirectGdiDriverInternal object, which destroys the DirectGDI |
|
402 adaptation specific resource associated with this handle. Calling this method on a |
|
403 handle that is not associated with any DirectGDI adaptation specific resource will |
|
404 do nothing. Once Close() is called, this handle can be reused. |
|
405 |
|
406 @see CreateImageTarget() |
|
407 |
|
408 @param aTarget The RDirectGdiImageTarget object. |
|
409 |
|
410 @pre CDirectGdiDriver object has been initialised from the calling thread. |
|
411 |
|
412 @post The DirectGDI specific resource associated with this handle will be destroyed |
|
413 (at any time preferred by the adaptation). This handle is no longer associated with |
|
414 a DirectGDI specific resource. The reference counter of the underlying image |
|
415 resource is decremented. |
|
416 */ |
|
417 void CDirectGdiDriver::CloseImageTarget(RDirectGdiImageTarget& aTarget) |
|
418 { |
|
419 iDriverInternal->CloseImageTarget(aTarget.iHandle); |
|
420 } |
|
421 |
|
422 /** |
|
423 Delegates call to the CDirectGdiDriverInternal object, which creates a |
|
424 MDirectGdiEngine object. |
|
425 |
|
426 @param aEngine The MDirectGdiEngine object. |
|
427 |
|
428 @pre CDirectGdiDriver object has been initialised from the calling thread. |
|
429 @post None. |
|
430 |
|
431 @return KErrNone if successful, otherwise one of the system-wide error codes. |
|
432 */ |
|
433 TInt CDirectGdiDriver::CreateEngine(MDirectGdiEngine*& aEngine) |
|
434 { |
|
435 return iDriverInternal->CreateEngine(aEngine); |
|
436 } |
|
437 |
|
438 /** |
|
439 Delegates call to the CDirectGdiDriverInternal object, which destroys a |
|
440 MDirectGdiEngine object. |
|
441 |
|
442 @param aEngine The MDirectGdiEngine object. |
|
443 |
|
444 @pre CDirectGdiDriver object has been initialised from the calling thread. |
|
445 @post None. |
|
446 */ |
|
447 void CDirectGdiDriver::DestroyEngine(MDirectGdiEngine* aEngine) |
|
448 { |
|
449 iDriverInternal->DestroyEngine(aEngine); |
|
450 } |
|
451 |