Fix webgl crash issue.
[framework/web/webkit-efl.git] / Source / WebCore / platform / graphics / surfaces / efl / GraphicsSurfaceEfl.cpp
1 /*
2     Copyright (C) 2012 Samsung Electronics
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "GraphicsSurface.h"
22
23 #if USE(GRAPHICS_SURFACE) || ENABLE(TIZEN_CANVAS_GRAPHICS_SURFACE)
24 #if !ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
25 #include "TextureMapperGL.h"
26
27 #include "NotImplemented.h"
28 #include <EGL/egl.h>
29 #include <GLES2/gl2.h>
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32 #include <X11/extensions/XShm.h>
33
34 #include <sys/ipc.h>
35 #include <sys/shm.h>
36
37 namespace WebCore {
38
39 static Display *g_display = 0;
40 struct GraphicsSurfacePrivate {
41     GraphicsSurfacePrivate()
42         : m_textureIsYInverted(false)
43         , m_hasAlpha(false)
44         , m_xImage(0)
45         , m_platformSurfaceID(0)
46     {
47         if (!g_display)
48             g_display = XOpenDisplay(0);
49     }
50
51     ~GraphicsSurfacePrivate()
52     {
53         if (m_xImage) {
54             XShmDetach(g_display, &(m_shmInfo));
55             XDestroyImage(m_xImage);
56             shmdt(m_shmInfo.shmaddr);
57             shmctl(m_shmInfo.shmid, IPC_RMID, 0);
58             m_xImage = NULL;
59         }
60     }
61
62     uint32_t createSurface(const IntSize& size)
63     {
64         return 0;
65     }
66
67     void createPlatformSurface(uint32_t winId)
68     {
69     }
70
71     void createImage(const IntSize& size, uint32_t platformSurfaceID)
72     {
73         m_platformSurfaceID = platformSurfaceID;
74         int x=0, y=0;
75         unsigned int w=0, h=0, bw=0, d=0;
76         Window root_win = 0;
77
78         if (!g_display) {
79             fprintf(stderr, "Can not open display\n");
80             return;
81         }
82
83         XGetGeometry(g_display, platformSurfaceID, &root_win, &x, &y, &w, &h, &bw, &d);
84         m_size = IntSize(w, h);
85
86         Screen* screen = DefaultScreenOfDisplay(g_display);
87         m_xImage = XShmCreateImage(g_display, DefaultVisualOfScreen(screen), 24, ZPixmap, NULL, &(m_shmInfo), m_size.width(), m_size.height());
88         if (!m_xImage) {
89             fprintf(stderr, "Error creating the shared image\n");
90             return;
91         }
92         m_shmInfo.shmid = shmget(IPC_PRIVATE, m_xImage->bytes_per_line * m_xImage->height, IPC_CREAT | 0666);
93         if (m_shmInfo.shmid == -1) {
94             XDestroyImage(m_xImage);
95             m_xImage = NULL;
96             fprintf(stderr, "Error getting the shared image info\n");
97             return;
98         }
99         m_shmInfo.readOnly = false;
100         m_shmInfo.shmaddr = (char*)shmat(m_shmInfo.shmid, 0, 0);
101         m_xImage->data = (char*)m_shmInfo.shmaddr;
102
103         if ((m_xImage->data == (char *)-1) || (!m_xImage->data)) {
104             shmdt(m_shmInfo.shmaddr);
105             shmctl(m_shmInfo.shmid, IPC_RMID, 0);
106             XDestroyImage(m_xImage);
107             m_xImage = NULL;
108             return;
109         }
110
111         XShmAttach(g_display, &m_shmInfo);
112     }
113
114     void copyImage()
115     {
116         if (!g_display) {
117             fprintf(stderr, "Can not open display\n");
118             return;
119         }
120
121         if (!m_xImage)
122             return;
123
124         XGrabServer(g_display);
125         if (!XShmGetImage(g_display, (Drawable)m_platformSurfaceID, m_xImage, 0, 0, 0xffffffff))
126             fprintf(stderr, "Error Getting ShmGetImage\n");
127         XUngrabServer(g_display);
128         XSync(g_display, false);
129
130         // Convert to RGBA
131         int totalBytes = m_size.width() * m_size.height() * 4;
132         for (int i = 0; i < totalBytes; i += 4)
133             std::swap(m_xImage->data[i], m_xImage->data[i + 2]);
134     }
135
136     void* xImageData() { return m_xImage ? m_xImage->data : 0; }
137     void swapBuffers() { }
138     IntSize size() const { return m_size; }
139
140 private:
141     IntSize m_size;
142     bool m_textureIsYInverted;
143     bool m_hasAlpha;
144     XImage         *m_xImage;
145     XShmSegmentInfo m_shmInfo;
146     int m_platformSurfaceID;
147 };
148
149 uint64_t GraphicsSurface::platformExport()
150 {
151     return m_platformSurface;
152 }
153
154 uint32_t GraphicsSurface::platformGetTextureID()
155 {
156     if (!m_texture) {
157         glGenTextures(1, &m_texture);
158         glBindTexture(GL_TEXTURE_2D, m_texture);
159         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
160         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
161         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
162         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
163     }
164     if (m_texture) {
165         m_private->copyImage();
166         glBindTexture(GL_TEXTURE_2D, m_texture);
167         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_size.width(), m_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, m_private->xImageData());
168     }
169     return m_texture;
170 }
171
172 void GraphicsSurface::platformPaintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity)
173 {
174     static_cast<TextureMapperGL*>(textureMapper)->drawTexture(platformGetTextureID(), 0, m_size, targetRect, transform, opacity);
175 }
176
177 PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, Flags flags)
178 {
179     return 0;
180 }
181
182 #if ENABLE(TIZEN_CANVAS_GRAPHICS_SURFACE)
183 PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(uint64_t platformSurfaceID)
184 {
185     RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(IntSize(), 0));
186     surface->m_private = new GraphicsSurfacePrivate();
187     surface->m_platformSurface = (uint64_t)platformSurfaceID;
188     return surface;
189 }
190
191 PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, uint64_t token, Flags canvasFlags)
192 {
193     // X11 does not support CopyToTexture, so we do not create a GraphicsSurface if this is requested.
194     // GraphicsSurfaceGLX uses an XWindow as native surface. This one always has a front and a back buffer.
195     // Therefore single buffered GraphicsSurfaces are not supported.
196     RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags));
197     surface->m_private = new GraphicsSurfacePrivate();
198     surface->m_platformSurface = token;
199     surface->m_canvasFlags = canvasFlags;
200
201     surface->m_private->createImage(IntSize(), token);
202     surface->m_size = surface->m_private->size();
203
204     return surface;
205
206
207 }
208 #endif
209
210 PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, uint64_t token)
211 {
212     // X11 does not support CopyToTexture, so we do not create a GraphicsSurface if this is requested.
213     // GraphicsSurfaceGLX uses an XWindow as native surface. This one always has a front and a back buffer.
214     // Therefore single buffered GraphicsSurfaces are not supported.
215     RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags));
216     surface->m_private = new GraphicsSurfacePrivate();
217     surface->m_platformSurface = token;
218
219     surface->m_private->createImage(IntSize(), token);
220     surface->m_size = surface->m_private->size();
221
222     return surface;
223 }
224
225 void GraphicsSurface::platformDestroy()
226 {
227     if (m_texture) {
228         glDeleteTextures(1, &m_texture);
229         m_texture = 0;
230     }
231
232     if (m_private) {
233         delete m_private;
234         m_private = 0;
235     }
236 }
237
238 void GraphicsSurface::platformCopyToGLTexture(uint32_t target, uint32_t id, const IntRect& targetRect, const IntPoint& offset)
239 {
240     // This is not supported by GLX/Xcomposite.
241 }
242
243 void GraphicsSurface::platformCopyFromFramebuffer(uint32_t originFbo, const IntRect& sourceRect)
244 {
245 }
246
247 uint32_t GraphicsSurface::platformFrontBuffer() const
248 {
249     return 0;
250 }
251
252 uint32_t GraphicsSurface::platformSwapBuffers()
253 {
254     m_private->swapBuffers();
255     return 0;
256 }
257
258 #if ENABLE(TIZEN_CANVAS_GRAPHICS_SURFACE)
259 uint32_t GraphicsSurface::platformSwapBuffers(uint32_t)
260 {
261     return 0;
262 }
263 #endif
264
265 char* GraphicsSurface::platformLock(const IntRect& rect, int* outputStride, LockOptions lockOptions)
266 {
267     // GraphicsSurface is currently only being used for WebGL, which does not require this locking mechanism.
268     return 0;
269 }
270
271 void GraphicsSurface::platformUnlock()
272 {
273     // GraphicsSurface is currently only being used for WebGL, which does not require this locking mechanism.
274 }
275
276 PassOwnPtr<GraphicsContext> GraphicsSurface::platformBeginPaint(const IntSize& size, char* bits, int stride)
277 {
278     notImplemented();
279     return nullptr;
280 }
281
282 PassRefPtr<Image> GraphicsSurface::createReadOnlyImage(const IntRect& rect)
283 {
284     notImplemented();
285     return 0;
286 }
287 }
288 #endif
289 #endif