|
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 "directgdiadapter.h" |
|
17 #include "directgdiimagetargetimpl.h" |
|
18 #include "directgdidriverimpl.h" |
|
19 #include "confighelper.h" |
|
20 |
|
21 /** |
|
22 Constructs a CDirectGdiImageTargetImpl. |
|
23 @param aDriver The driver implementation which created this target. |
|
24 */ |
|
25 CDirectGdiImageTargetImpl::CDirectGdiImageTargetImpl(CDirectGdiDriverImpl& aDriver) : |
|
26 iDriver(aDriver), |
|
27 iSurface(EGL_NO_SURFACE), |
|
28 iContext(EGL_NO_CONTEXT) |
|
29 { |
|
30 } |
|
31 |
|
32 /** |
|
33 Destructor for CDirectGdiImageTargetImpl - Destroys the EGL surface. |
|
34 It will remove itself from the driver's image target array, before deleting itself. |
|
35 */ |
|
36 CDirectGdiImageTargetImpl::~CDirectGdiImageTargetImpl() |
|
37 { |
|
38 #ifdef _DEBUG_DIRECTGDI |
|
39 GRAPHICS_LOG_DEBUG("Destroying CDirectGdiImageTargetImpl"); |
|
40 #endif |
|
41 if (iDriver.IsCurrentTarget(this)) |
|
42 { |
|
43 iDriver.SetCurrentTarget(NULL); |
|
44 } |
|
45 |
|
46 if (iSurface != EGL_NO_SURFACE) |
|
47 { |
|
48 // If the surface being deleted is current to EGL, it will defer the destruction of the surface |
|
49 // until something else is made current. Destruction would rather be immediate so that the |
|
50 // associated native pixmap can be used again. In that case, the surface is dereferenced by making |
|
51 // something else current. |
|
52 if (eglGetCurrentSurface(EGL_DRAW) == iSurface) |
|
53 { |
|
54 eglMakeCurrent(iDriver.EglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
|
55 } |
|
56 |
|
57 eglDestroySurface(iDriver.EglDisplay(), iSurface); |
|
58 } |
|
59 iDriver.UnregisterTargetImage(*this); |
|
60 } |
|
61 |
|
62 /** |
|
63 Two-phase construction of a CDirectGdiImageTargetImpl object. |
|
64 @param aImage On success, holds a pointer to the newly-created image. |
|
65 @param aDriver The driver to register this image with. |
|
66 @param aSgImage The RSgImage which this image will be based upon. |
|
67 @param aContexts A hash map of already-created EGLContext/Config pairs. |
|
68 @param aConfigs A hash map of EGLConfig/Attribute pairs. |
|
69 @param aSharedContext A reference to the current shared context. |
|
70 @return KErrNone if successful, KErrNoMemory if not enough memory could be allocated, otherwise a return |
|
71 value from Construct(). |
|
72 */ |
|
73 TInt CDirectGdiImageTargetImpl::New(CDirectGdiImageTargetImpl*& aImage, |
|
74 CDirectGdiDriverImpl& aDriver, |
|
75 const RSgImage& aSgImage, |
|
76 RHashMap<TInt, EGLContext>& aContexts, |
|
77 RHashMap<TInt, EGLConfig>& aConfigs, |
|
78 EGLContext& aSharedContext) |
|
79 { |
|
80 CDirectGdiImageTargetImpl* image = new CDirectGdiImageTargetImpl(aDriver); |
|
81 if (!image) |
|
82 return KErrNoMemory; |
|
83 TInt err = image->Construct(aSgImage, aContexts, aConfigs, aSharedContext); |
|
84 if (err == KErrNone) |
|
85 aImage = image; |
|
86 else |
|
87 delete image; |
|
88 return err; |
|
89 } |
|
90 |
|
91 /** |
|
92 Gets the supplied image structure and sets the internal data. It creates a new image target by creating |
|
93 an EGL context corresponding to a pixel type and an EGL config (if the EGLContext is not already created). |
|
94 If it was already there, it fetches the EGL context from the hash map. Creates an EGL surface that is then |
|
95 set for use by the new target object. Targets that are successfully created are added to an array of targets |
|
96 so that they can be closed and deleted correctly at a later stage. |
|
97 |
|
98 @param aSgImage The RSgImage to create the source image from. |
|
99 @param aContexts A hash map of already-created EGLContext/Config pairs. |
|
100 @param aConfigs A hash map of EGLConfig/Attribute pairs. |
|
101 @param aSharedContext A reference to the current shared context. |
|
102 @return KErrNone if successful, otherwise an error from CDirectGdiImageRef::Construct(). |
|
103 |
|
104 @panic DGDIAdapter 41, if a matching EGL config is not found for this RSgImage. |
|
105 @panic DGDIAdapter 42, if an EGLSurface cannot be created. |
|
106 @panic DGDIAdapter 43, if an EGLContext cannot be created. |
|
107 */ |
|
108 TInt CDirectGdiImageTargetImpl::Construct(const RSgImage& aSgImage, RHashMap<TInt, EGLContext>& aContexts, RHashMap<TInt, EGLConfig>& aConfigs, EGLContext& aSharedContext) |
|
109 { |
|
110 TSgImageInfo info; |
|
111 EGLSurface surface = EGL_NO_SURFACE; |
|
112 EGLContext* context = NULL; |
|
113 EGLContext newContext = EGL_NO_CONTEXT; |
|
114 TBool createdNewContext = EFalse; |
|
115 TInt pixmapAttribs = 0; |
|
116 const EGLDisplay display = iDriver.EglDisplay(); |
|
117 |
|
118 TInt err = CDirectGdiImageRef::Construct(aSgImage); |
|
119 |
|
120 if (err == KErrNone) |
|
121 { |
|
122 err = iSgImage.GetInfo(info); |
|
123 } |
|
124 |
|
125 if (err == KErrNone) |
|
126 { |
|
127 // Create an EGL target surface. |
|
128 // Get the right Config index for this RSgImage format. |
|
129 pixmapAttribs = TConfigHelper::MatchPixelType(info.iPixelFormat); |
|
130 EGLConfig* currentConfig = aConfigs.Find(pixmapAttribs); |
|
131 GRAPHICS_ASSERT_ALWAYS(currentConfig, EDirectGdiPanicNoConfigFound); |
|
132 |
|
133 // Set up the surface attribs. |
|
134 const EGLint eglAlphaFormat = (info.iPixelFormat == EUidPixelFormatARGB_8888_PRE) ? EGL_VG_ALPHA_FORMAT_PRE : EGL_VG_ALPHA_FORMAT_NONPRE; |
|
135 EGLint attributeList[] = {EGL_VG_ALPHA_FORMAT, eglAlphaFormat, |
|
136 EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB, |
|
137 EGL_NONE}; |
|
138 |
|
139 // Create an EGL target surface. |
|
140 surface = eglCreatePixmapSurface(display, *currentConfig, (RSgImage*)&iSgImage, attributeList); |
|
141 GRAPHICS_ASSERT_ALWAYS(surface != EGL_NO_SURFACE, EDirectGdiPanicNoDrawingSurface); |
|
142 |
|
143 // See if we have already created a context for this pixel format, create |
|
144 // one if we haven't and save it for reuse later. |
|
145 context = aContexts.Find(pixmapAttribs); |
|
146 if (context == NULL) |
|
147 { |
|
148 newContext = eglCreateContext(display, *currentConfig, aSharedContext, NULL); |
|
149 GRAPHICS_ASSERT_ALWAYS(newContext != EGL_NO_CONTEXT, EDirectGdiPanicNoContext); |
|
150 err = aContexts.Insert(pixmapAttribs, newContext); |
|
151 if (err == KErrNone) |
|
152 context = &newContext; |
|
153 createdNewContext = ETrue; |
|
154 } |
|
155 } |
|
156 |
|
157 if (err == KErrNone) |
|
158 { |
|
159 err = iDriver.RegisterTargetImage(*this); |
|
160 } |
|
161 |
|
162 if (err == KErrNone) |
|
163 { |
|
164 // Everything went well. |
|
165 iContext = *context; |
|
166 iSurface = surface; |
|
167 if (createdNewContext) |
|
168 aSharedContext = iContext; |
|
169 Open(); |
|
170 } |
|
171 else |
|
172 { |
|
173 // Cleanup. |
|
174 if (surface != EGL_NO_SURFACE) |
|
175 { |
|
176 eglDestroySurface(display, surface); |
|
177 } |
|
178 if (createdNewContext) |
|
179 { |
|
180 if (context) |
|
181 { |
|
182 eglDestroyContext(display, *context); |
|
183 } |
|
184 if (aContexts.Find(pixmapAttribs)) |
|
185 { |
|
186 aContexts.Remove(pixmapAttribs); |
|
187 } |
|
188 } |
|
189 } |
|
190 |
|
191 return err; |
|
192 } |
|
193 |
|
194 /** |
|
195 Sets the passed EGLSurface as the current rendering target for EGL, sets the passed |
|
196 EGLContext as the current context. The surface will be used for both read and write |
|
197 operations. The previously current context will be flushed at this point. |
|
198 |
|
199 @pre The target has been successfully constructed. |
|
200 |
|
201 @return ETrue if activation was successful, otherwise EFalse. |
|
202 */ |
|
203 TBool CDirectGdiImageTargetImpl::Activate() |
|
204 { |
|
205 return (EGL_TRUE == eglMakeCurrent(iDriver.EglDisplay(), iSurface, iSurface, iContext)); |
|
206 } |