Add copySurfaceTye argument to copySurface function.
[framework/web/webkit-efl.git] / Source / WebCore / platform / graphics / gstreamer / tizen / SharedVideoPlatformSurfaceTizen.cpp
1 /*
2  * Copyright (C) 2012 Samsung Electronics. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
29
30 #include "SharedVideoPlatformSurfaceTizen.h"
31 #include "GraphicsContextPlatformPrivateCairo.h"
32 #include "IntRect.h"
33 #include <cairo.h>
34 #include <cairo-xlib.h>
35 #include <EGL/egl.h>
36 #include <EGL/eglext.h>
37 #include <X11/Xlib.h>
38 #include <X11/Xutil.h>
39
40 #if ENABLE(TIZEN_CANVAS_GRAPHICS_SURFACE)
41 #include "GraphicsSurface.h"
42 #endif
43
44 namespace WebCore {
45
46 class VideoPlatformSurface {
47 public:
48     static PassOwnPtr<VideoPlatformSurface> create(IntSize size);
49     ~VideoPlatformSurface();
50
51     int id() const { return m_platformSurface; }
52     void paintCurrentFrameInContext(GraphicsContext*, const IntRect&);
53     void copySurface(VideoPlatformSurface* other, SharedVideoPlatformSurfaceTizen::CopySurfaceType type);
54     bool hasAlpha() { return m_hasAlpha; }
55
56 private:
57     VideoPlatformSurface();
58
59     bool initialize(IntSize size);
60     bool createPlatformSurface(IntSize size);
61     bool destroyPlatformSurface();
62     bool createPlatformSurfaceSurface();
63     bool destroyPlatformSurfaceSurface();
64     void clearPlatformSurfaceSurface();
65
66     int m_platformSurface;
67     int m_nativeWindow;
68     Display* m_nativeDisplay;
69
70     EGLDisplay m_eglDisplay;
71     EGLContext m_eglContext;
72     EGLSurface m_eglSurface;
73
74     IntSize m_size;
75     bool m_hasAlpha;
76 };
77
78 PassOwnPtr<VideoPlatformSurface> VideoPlatformSurface::create(IntSize size)
79 {
80     OwnPtr<VideoPlatformSurface> videoPlatformSurface = adoptPtr(new VideoPlatformSurface());
81     if (!videoPlatformSurface->initialize(size))
82         return nullptr;
83     return videoPlatformSurface.release();
84 }
85
86 VideoPlatformSurface::VideoPlatformSurface()
87     : m_platformSurface(0)
88     , m_nativeWindow(0)
89     , m_nativeDisplay(0)
90     , m_eglDisplay(EGL_NO_DISPLAY)
91     , m_eglContext(EGL_NO_CONTEXT)
92     , m_eglSurface(EGL_NO_SURFACE)
93     , m_size(IntSize())
94     , m_hasAlpha(true)
95 {
96 }
97
98 VideoPlatformSurface::~VideoPlatformSurface()
99 {
100     destroyPlatformSurfaceSurface();
101     destroyPlatformSurface();
102 }
103
104 void VideoPlatformSurface::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect)
105 {
106     if (context->paintingDisabled())
107         return;
108
109     if (m_size.isEmpty())
110         return;
111
112     cairo_surface_t* surface = cairo_xlib_surface_create(m_nativeDisplay, m_platformSurface, DefaultVisual(m_nativeDisplay, DefaultScreen(m_nativeDisplay)), m_size.width(), m_size.height());
113     if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
114         return;
115
116     cairo_t* cr = context->platformContext()->cr();
117     cairo_save(cr);
118
119     cairo_set_source_surface(cr, surface, 0, 0);
120     cairo_paint(cr);
121
122     cairo_restore(cr);
123     cairo_surface_destroy(surface);
124 }
125
126 void VideoPlatformSurface::copySurface(VideoPlatformSurface* other, SharedVideoPlatformSurfaceTizen::CopySurfaceType type)
127 {
128     RefPtr<cairo_surface_t> surface = adoptRef(cairo_xlib_surface_create(m_nativeDisplay, m_platformSurface, DefaultVisual(m_nativeDisplay, DefaultScreen(m_nativeDisplay)), m_size.width(), m_size.height()));
129     RefPtr<cairo_t> context = adoptRef(cairo_create(surface.get()));
130     OwnPtr<WebCore::GraphicsContext> graphicsContext = adoptPtr(new GraphicsContext(context.get()));
131
132     float xScale = static_cast<float>(m_size.width()) / other->m_size.width();
133     float yScale = static_cast<float>(m_size.height()) / other->m_size.height();
134     float xPosition = 0;
135     float yPosition = 0;
136
137     if (xScale != yScale) {
138         switch (type) {
139         case SharedVideoPlatformSurfaceTizen::FitToWidth:
140             yPosition = (m_size.height() - other->m_size.height() * xScale) / 2;
141             yScale = xScale;
142             break;
143         case SharedVideoPlatformSurfaceTizen::FitToHeight:
144             xPosition = (m_size.width() - other->m_size.width() * yScale) / 2;
145             xScale = yScale;
146             break;
147         }
148     }
149     graphicsContext->translate(xPosition, yPosition);
150     graphicsContext->scale(FloatSize(xScale, yScale));
151     other->paintCurrentFrameInContext(graphicsContext.get(), IntRect());
152 }
153
154 bool VideoPlatformSurface::initialize(IntSize size)
155 {
156     if (!createPlatformSurface(size))
157         return false;
158
159     if (!createPlatformSurfaceSurface())
160         return false;
161
162     m_size = size;
163
164     clearPlatformSurfaceSurface();
165
166     return true;
167 }
168
169 bool VideoPlatformSurface::createPlatformSurface(IntSize size)
170 {
171     if (size.isEmpty())
172         return false;
173
174     if (!m_nativeDisplay) {
175         ecore_x_init(0);
176         m_nativeDisplay = (Display*)ecore_x_display_get();
177     }
178
179     if (!m_nativeWindow)
180         m_nativeWindow = XCreateSimpleWindow(m_nativeDisplay, DefaultRootWindow(m_nativeDisplay), 0, 0, 1, 1, 0, BlackPixel(m_nativeDisplay, 0), WhitePixel(m_nativeDisplay, 0));
181
182     XSync(m_nativeDisplay, false);
183
184     int visualDepth = XDefaultDepth(m_nativeDisplay, DefaultScreen(m_nativeDisplay));
185     m_platformSurface = XCreatePixmap(m_nativeDisplay, m_nativeWindow, size.width(), size.height(), visualDepth);
186
187     XFlush(m_nativeDisplay);
188
189 #if USE(ACCELERATED_VIDEO_VAAPI)
190     m_hasAlpha = visualDepth == 32 ?  true : false;
191 #endif
192
193     return true;
194 }
195
196 bool VideoPlatformSurface::destroyPlatformSurface()
197 {
198     if (m_platformSurface) {
199         XFreePixmap(m_nativeDisplay, m_platformSurface);
200         m_platformSurface = 0;
201     }
202
203     if (m_nativeWindow) {
204         XDestroyWindow(m_nativeDisplay, m_nativeWindow);
205         m_nativeWindow = 0;
206     }
207
208     m_nativeDisplay = 0;
209
210     return true;
211 }
212
213 bool VideoPlatformSurface::createPlatformSurfaceSurface()
214 {
215     m_eglDisplay = eglGetDisplay(m_nativeDisplay);
216     if (m_eglDisplay == EGL_NO_DISPLAY)
217         return false;
218
219     EGLint major, minor;
220     if (eglInitialize(m_eglDisplay, &major, &minor) != EGL_TRUE)
221         return false;
222
223     int i = 0;
224     EGLint configAttribs[32];
225     configAttribs[i++] = EGL_LEVEL;
226     configAttribs[i++] = 0;
227     // FIXME : Create PlatformSurface surface with RGB_565 when alpha is off. Graphics driver needs to be fixed first.
228     configAttribs[i++] = EGL_RED_SIZE;
229     configAttribs[i++] = 8;
230     configAttribs[i++] = EGL_GREEN_SIZE;
231     configAttribs[i++] = 8;
232     configAttribs[i++] = EGL_BLUE_SIZE;
233     configAttribs[i++] = 8;
234     configAttribs[i++] = EGL_ALPHA_SIZE;
235     configAttribs[i++] = m_hasAlpha ? 8 : 0;
236     configAttribs[i++] = EGL_MATCH_FORMAT_KHR;
237     configAttribs[i++] = EGL_FORMAT_RGBA_8888_EXACT_KHR;
238     configAttribs[i++] = EGL_SURFACE_TYPE;
239     configAttribs[i++] = EGL_PIXMAP_BIT | EGL_LOCK_SURFACE_BIT_KHR;
240     configAttribs[i++] = EGL_DEPTH_SIZE;
241     configAttribs[i++] = 0;
242     configAttribs[i++] = EGL_STENCIL_SIZE;
243     configAttribs[i++] = 0;
244     configAttribs[i++] = EGL_RENDERABLE_TYPE;
245     configAttribs[i++] = EGL_OPENGL_ES2_BIT;
246     configAttribs[i++] = EGL_NONE;
247
248     EGLConfig config;
249     EGLint configCount = 0;
250     if (eglChooseConfig(m_eglDisplay, configAttribs, &config, 1, &configCount) != EGL_TRUE)
251         return false;
252
253     EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
254     m_eglContext = eglCreateContext(m_eglDisplay, config, EGL_NO_CONTEXT, contextAttribs);
255     if( m_eglContext == EGL_NO_CONTEXT)
256         return false;
257
258     m_eglSurface = eglCreatePixmapSurface(m_eglDisplay, config, m_platformSurface, NULL);
259     if (m_eglSurface == EGL_NO_SURFACE)
260         return false;
261
262     return true;
263 }
264
265 bool VideoPlatformSurface::destroyPlatformSurfaceSurface()
266 {
267     if (m_eglSurface) {
268         eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
269         eglDestroySurface(m_eglDisplay, m_eglSurface);
270         m_eglSurface = EGL_NO_SURFACE;
271     }
272
273     if (m_eglContext) {
274         eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
275         eglDestroyContext(m_eglDisplay, m_eglContext);
276         m_eglContext = EGL_NO_CONTEXT;
277     }
278
279     m_eglDisplay = EGL_NO_DISPLAY;
280
281     return true;
282 }
283
284 void VideoPlatformSurface::clearPlatformSurfaceSurface()
285 {
286     RefPtr<cairo_surface_t> surface = adoptRef(cairo_xlib_surface_create(m_nativeDisplay, m_platformSurface, DefaultVisual(m_nativeDisplay, DefaultScreen(m_nativeDisplay)), m_size.width(), m_size.height()));
287     if (cairo_surface_status(surface.get()) != CAIRO_STATUS_SUCCESS)
288         return;
289
290     RefPtr<cairo_t> cr = adoptRef(cairo_create(surface.get()));
291     cairo_set_source_surface(cr.get(), surface.get(), 0, 0);
292     int alphaValue = m_hasAlpha ? 1 : 0;
293     cairo_set_source_rgba(cr.get(), 0, 0, 0, alphaValue);
294     cairo_rectangle(cr.get(), 0, 0, m_size.width(), m_size.height());
295     cairo_fill(cr.get());
296 }
297
298 PassOwnPtr<SharedVideoPlatformSurfaceTizen> SharedVideoPlatformSurfaceTizen::create(IntSize size)
299 {
300     return adoptPtr(new SharedVideoPlatformSurfaceTizen(size));
301 }
302
303 SharedVideoPlatformSurfaceTizen::SharedVideoPlatformSurfaceTizen(IntSize size)
304     : m_damage(0)
305     , m_damageHandler(0)
306     , m_listener(0)
307     , m_platformSurface(VideoPlatformSurface::create(size))
308 {
309     if (!m_platformSurface)
310         return;
311
312     registerDamageHandler();
313     m_flags = GraphicsSurface::Is2D | GraphicsSurface::UseLinearFilter;
314     if (m_platformSurface->hasAlpha())
315         m_flags |= GraphicsSurface::Alpha;
316
317 }
318
319 SharedVideoPlatformSurfaceTizen::~SharedVideoPlatformSurfaceTizen()
320 {
321     m_listener = 0;
322
323     unregisterDamageHandler();
324 }
325
326 static Eina_Bool notifyDamageUpdated(void* data, int type, void* event)
327 {
328     SharedVideoPlatformSurfaceTizen* sharedVideoPlatformSurface = reinterpret_cast<SharedVideoPlatformSurfaceTizen*>(data);
329     sharedVideoPlatformSurface->platformSurfaceUpdated();
330
331     return ECORE_CALLBACK_PASS_ON;
332 }
333
334 int SharedVideoPlatformSurfaceTizen::id() const
335 {
336     return m_platformSurface ? m_platformSurface->id() : 0;
337 }
338
339 void SharedVideoPlatformSurfaceTizen::platformSurfaceUpdated()
340 {
341     if (m_listener)
342         m_listener->platformSurfaceUpdated();
343 }
344
345 void SharedVideoPlatformSurfaceTizen::setVideoPlatformSurfaceUpdateListener(VideoPlatformSurfaceUpdateListener* listener)
346 {
347     m_listener = listener;
348 }
349
350 void SharedVideoPlatformSurfaceTizen::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect)
351 {
352     if (m_platformSurface)
353         m_platformSurface->paintCurrentFrameInContext(context, rect);
354 }
355
356 void SharedVideoPlatformSurfaceTizen::copySurface(SharedVideoPlatformSurfaceTizen* other, CopySurfaceType type)
357 {
358     if (m_platformSurface)
359         m_platformSurface->copySurface(other->m_platformSurface.get(), type);
360 }
361
362 void SharedVideoPlatformSurfaceTizen::registerDamageHandler()
363 {
364     if (!m_platformSurface)
365         return;
366
367     m_damage = ecore_x_damage_new(m_platformSurface->id(), ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES);
368     m_damageHandler = ecore_event_handler_add(ECORE_X_EVENT_DAMAGE_NOTIFY, notifyDamageUpdated, this);
369 }
370
371 void SharedVideoPlatformSurfaceTizen::unregisterDamageHandler()
372 {
373     if (m_damage) {
374         ecore_x_damage_free(m_damage);
375         m_damage = 0;
376     }
377
378     if (m_damageHandler) {
379         ecore_event_handler_del(m_damageHandler);
380         m_damageHandler = 0;
381     }
382 }
383
384 int SharedVideoPlatformSurfaceTizen::graphicsSurfaceFlags() const
385 {
386     return m_flags;
387 }
388
389 } // WebCore
390
391 #endif // ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)