#define ENABLE_TIZEN_2D_CANVAS_JS_SUSPEND 0 /* Hyunki Baik(hyunki.baik@samsung.com): Suspend JavasScript during UIProcess access the shared platformSurface for 2D Canvas */
#endif
+#if !USE(MESA)
+#define ENABLE_TIZEN_DDK_WORKAROUND 1 /* kalyan.kondapally@intel.com WorkAround in AcceleratedPlatformLayer for ddk issues*/
+#endif
+
#if ENABLE(TIZEN_WEBKIT2)
#define ENABLE_TIZEN_MOBILE_WEB_PRINT 1 /* Hyunsoo Shim(hyunsoo.shim@samsung.com) : Mobile Web Print for AC layer */
#endif
#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
+#if PLATFORM(WAYLAND)
+#define ENABLE_TIZEN_ACCELERATED_PLATFORM_LAYER 1 /* Kalyan Kondapally(kalyan.kondapally@intel.com) : GraphicsPlatformLayer used with Wayland. */
+#endif
#define ENABLE_TIZEN_ACCELERATED_COMPOSITING_PLUGIN_LAYER_EFL 1 /* Hyunsoo Shim(hyunsoo.shim@samsung.com) : Accelerated Compositing plugin layer */
#if ENABLE(REQUEST_ANIMATION_FRAME)
#define ENABLE_TIZEN_SYNC_REQUEST_ANIMATION_FRAME 1 /* YongGeol Jung(yg48.jung@samsung.com) : Synchronize callback function of ScriptedAnimationController between UI Process and Web Process to 1 : 1 */
platform/graphics/efl/tizen/Extensions3DTizen.cpp
platform/graphics/efl/tizen/GraphicsContext3D.cpp
platform/graphics/efl/tizen/GraphicsContext3DInternal.cpp
- platform/graphics/efl/tizen/GraphicsContext3DOffscreen.cpp
platform/graphics/efl/tizen/SharedPlatformSurfaceTizen.cpp
platform/graphics/efl/tizen/TizenGraphicsContext3DEfl.cpp
platform/graphics/gpu/DrawingBuffer.cpp
platform/graphics/gstreamer/tizen/VideoLayerTizen.cpp
platform/graphics/gstreamer/tizen/WebKitCameraSourceGStreamerTizen.cpp
platform/graphics/surfaces/GraphicsSurface.cpp
- platform/graphics/surfaces/tizen/GraphicsSurfaceTizen.cpp
- platform/graphics/texmap/tizen/PlatformSurfaceTextureGL.cpp
platform/mediastream/tizen/LocalMediaServer.cpp
platform/mediastream/tizen/MediaRecorder.cpp
IF (WTF_PLATFORM_X11)
LIST(APPEND WebCore_SOURCES
+ platform/graphics/efl/tizen/GraphicsContext3DOffscreen.cpp
platform/graphics/surfaces/x/X11Helper.cpp
platform/graphics/surfaces/egl/EGLXSurface.cpp
platform/graphics/surfaces/tizen/SharedVideoPlatformSurfaceTizenX.cpp
+ platform/graphics/surfaces/tizen/GraphicsSurfaceTizen.cpp
+ platform/graphics/texmap/tizen/PlatformSurfaceTextureGL.cpp
)
ELSEIF (WTF_PLATFORM_WAYLAND)
LIST(APPEND WebCore_SOURCES
+ platform/graphics/efl/tizen/AcceleratedPlatformLayer.cpp
platform/graphics/surfaces/egl/EGLWaylandSurface.cpp
- platform/graphics/surfaces/wayland/WaylandHelper.cpp
+ platform/graphics/surfaces/wayland/PlatformTextureWayland.cpp
+ platform/graphics/surfaces/wayland/WaylandCompositor.cpp
+ platform/graphics/surfaces/wayland/WaylandDisplay.cpp
+ platform/graphics/surfaces/wayland/WaylandSurface.cpp
+ platform/graphics/surfaces/wayland/GraphicsSurfaceWayland.cpp
)
ENDIF()
ENDIF()
--- /dev/null
+/*
+ Copyright (C) 2011 Samsung Electronics
+ Copyright (C) 2013 Intel Corporation. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "AcceleratedPlatformLayer.h"
+
+#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && ENABLE(TIZEN_ACCELERATED_PLATFORM_LAYER)
+
+#if ENABLE(TIZEN_DDK_WORKAROUND)
+#include "Extensions3D.h"
+#endif
+
+#include "ImageBuffer.h"
+#include "ImageData.h"
+#include "NotImplemented.h"
+
+#define GL_GLEXT_PROTOTYPES 1
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#ifndef GLchar
+#define GLchar char
+#endif
+
+#include <wtf/OwnArrayPtr.h>
+
+namespace WebCore {
+
+PassOwnPtr<AcceleratedPlatformLayer> AcceleratedPlatformLayer::create(GraphicsContext3D::Attributes attrs, GraphicsContext3D::RenderStyle renderStyle)
+{
+ if (renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow)
+ return nullptr;
+
+ OwnPtr<AcceleratedPlatformLayer> internal = adoptPtr(new AcceleratedPlatformLayer(attrs, renderStyle));
+ if (!internal->initialize(0))
+ return nullptr;
+
+ return internal.release();
+}
+
+State::State()
+ : activeTexture(GraphicsContext3D::TEXTURE0)
+ , boundFBO(0)
+ , boundTexture0(0)
+ , sourceFactor(GraphicsContext3D::ONE)
+ , destinationFactor(GraphicsContext3D::ZERO)
+ , depthMask(true)
+ , scissorX(0)
+ , scissorY(0)
+ , scissorWidth(0)
+ , scissorHeight(0)
+ , stencilFunc(GraphicsContext3D::ALWAYS)
+ , stencilRef(0)
+ , stencilMask(UINT_MAX)
+ , stencilFail(GraphicsContext3D::KEEP)
+ , stencilZFail(GraphicsContext3D::KEEP)
+ , stencilZPass(GraphicsContext3D::KEEP)
+ , viewportX(0)
+ , viewportY(0)
+ , viewportWidth(0)
+ , viewportHeight(0)
+{
+ m_state = BlendFuncCacheDirty | DepthMaskCacheDirty | StencilFuncCacheDirty | StencilOpCacheDirty | ViewportCacheDirty;
+}
+
+State::~State()
+{
+ if (!pixelStoreIntMap.isEmpty())
+ pixelStoreIntMap.clear();
+
+ if (!capabilityStateMap.isEmpty())
+ capabilityStateMap.clear();
+}
+
+AcceleratedPlatformLayer::AcceleratedPlatformLayer(GraphicsContext3D::Attributes attrs, GraphicsContext3D::RenderStyle renderStyle)
+ : GraphicsContext3DInternal(attrs, GraphicsContext3D::RenderOffscreen)
+ , m_compositorTexture(0)
+ , m_layerComposited(false)
+ , m_swapBuffers(true)
+ , m_width(1)
+ , m_height(1)
+ , m_surfaceFlags(0)
+ , m_surfaceHandle(0)
+ , m_renderStyle(renderStyle)
+ , m_state(adoptPtr(new State()))
+{
+}
+
+AcceleratedPlatformLayer::~AcceleratedPlatformLayer()
+{
+ if (m_renderStyle == GraphicsContext3D::RenderToCurrentGLContext)
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, 0));
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, 0));
+
+ if (m_compositorTexture)
+ GL_CMD(glDeleteTextures(1, &m_compositorTexture));
+
+ releaseResources();
+}
+
+void AcceleratedPlatformLayer::releaseResources()
+{
+ // Release the current context and drawable only after destroying any associated gl resources.
+ m_surfaceHandle = 0;
+ if (m_offScreenSurface)
+ m_offScreenSurface->destroy();
+
+ if (m_offScreenContext) {
+ m_offScreenContext->destroy();
+ m_offScreenContext->releaseCurrent();
+ }
+}
+
+PlatformLayer* AcceleratedPlatformLayer::platformLayer() const
+{
+ return const_cast<TextureMapperPlatformLayer*>(static_cast<const TextureMapperPlatformLayer*>(this));
+}
+
+bool AcceleratedPlatformLayer::initialize(HostWindow*)
+{
+ if (!initializeSurface())
+ return false;
+
+ validateAttributes();
+
+ // ANGLE integration starts
+ ShBuiltInResources ANGLEResources;
+ ShInitBuiltInResources(&ANGLEResources);
+
+ GL_CMD(getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs));
+ GL_CMD(getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors));
+ GL_CMD(getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors));
+ GL_CMD(getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits));
+ GL_CMD(getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits));
+ GL_CMD(getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits));
+ GL_CMD(getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors));
+
+ // Always set to 1 for OpenGL ES.
+ ANGLEResources.MaxDrawBuffers = 1;
+ m_compiler.setResources(ANGLEResources);
+ // ANGLE Integration block ENDs
+
+ if (m_renderStyle != GraphicsContext3D::RenderToCurrentGLContext)
+ GL_CMD(glClearColor(0.0, 0.0, 0.0, 0.0));
+
+ return true;
+}
+
+bool AcceleratedPlatformLayer::initializeSurface()
+{
+ m_offScreenContext = GLPlatformContext::createContext(m_renderStyle);
+ if (!m_offScreenContext)
+ return false;
+
+ if (m_renderStyle == GraphicsContext3D::RenderOffscreen) {
+ GLPlatformSurface::SurfaceAttributes sharedSurfaceAttributes = GLPlatformSurface::Default;
+ if (m_attributes.alpha)
+ sharedSurfaceAttributes |= GLPlatformSurface::SupportAlpha;
+
+ if (m_attributes.depth)
+ sharedSurfaceAttributes |= GLPlatformSurface::SupportDepth;
+
+ if (m_attributes.stencil)
+ sharedSurfaceAttributes |= GLPlatformSurface::SupportStencil;
+
+ m_offScreenSurface = GLPlatformSurface::createOffScreenSurface(sharedSurfaceAttributes, IntSize(m_width, m_height));
+
+ if (!m_offScreenSurface)
+ return false;
+
+ if (!m_offScreenContext->initialize(m_offScreenSurface.get()))
+ return false;
+
+ if (!makeContextCurrent())
+ return false;
+
+ if (m_offScreenSurface->attributes() & GLPlatformSurface::SupportAlpha)
+ m_surfaceFlags |= GraphicsSurface::Alpha;
+
+ if (m_attributes.premultipliedAlpha)
+ m_surfaceFlags |= GraphicsSurface::PremultipliedAlpha;
+
+ // synchronize the attributes,
+ m_attributes.stencil = m_offScreenSurface->attributes() & GLPlatformSurface::SupportStencil;
+ m_attributes.depth = m_offScreenSurface->attributes() & GLPlatformSurface::SupportDepth;
+ m_attributes.alpha = m_offScreenSurface->attributes() & GLPlatformSurface::SupportAlpha;
+
+ m_surfaceHandle = m_offScreenSurface->handle();
+ }
+
+ return true;
+}
+
+bool AcceleratedPlatformLayer::makeContextCurrent()
+{
+ bool success = m_offScreenContext->makeCurrent(m_offScreenSurface.get());
+
+ if (!m_offScreenContext->isValid()) {
+ // FIXME: Restore context
+ if (m_contextLostCallback)
+ m_contextLostCallback->onContextLost();
+
+ return false;
+ }
+
+ return success;
+}
+
+void AcceleratedPlatformLayer::setContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callBack)
+{
+ m_contextLostCallback = callBack;
+}
+
+bool AcceleratedPlatformLayer::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context)
+{
+ if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
+ return false;
+
+ cairo_t* cr = context->cr();
+ context->save();
+
+ RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data(
+ const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4));
+
+ cairo_rectangle(cr, 0, 0, canvasWidth, canvasHeight);
+
+ // OpenGL keeps the pixels stored bottom up, so we need to flip the image here.
+ cairo_matrix_t matrix;
+ cairo_matrix_init(&matrix, 1.0, 0.0, 0.0, -1.0, 0.0, imageHeight);
+ cairo_set_matrix(cr, &matrix);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_surface(cr, imageSurface.get(), 0, 0);
+ cairo_fill(cr);
+ context->restore();
+
+ return true;
+}
+
+void AcceleratedPlatformLayer::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, int width, int height)
+{
+ int totalBytes = 4 * width * height;
+
+ OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]);
+ if (!pixels)
+ return;
+
+ readRenderingResults(pixels.get(), totalBytes , width , height);
+
+#if ENABLE(TIZEN_CANVAS_CAIRO_GLES_RENDERING)
+ cairo_surface_t* surface = imageBuffer->getSurface();
+ if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_GL) {
+ // TODO: premultipliedAlpha currently not getting applied. Need to apply the value properly.
+ if (!m_attributes.premultipliedAlpha) {
+ for (int i = 0; i < totalBytes; i = 4) {
+ // Premultiply alpha.
+ pixels[i+0] = std::min(255, pixels[i+0] * pixels[i+3] / 255);
+ pixels[i+1] = std::min(255, pixels[i+1] * pixels[i+3] / 255);
+ pixels[i+2] = std::min(255, pixels[i+2] * pixels[i+3] / 255);
+ }
+ }
+ }
+#endif
+ paintToCanvas(pixels.get(), width, height,
+ imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context()->platformContext());
+}
+
+PassRefPtr<ImageData> AcceleratedPlatformLayer::paintRenderingResultsToImageData(int width, int height)
+{
+ // Reading premultiplied alpha would involve unpremultiplying, which is
+ // lossy
+ if (m_attributes.premultipliedAlpha)
+ return 0;
+
+ RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
+ unsigned char* pixels = imageData->data()->data();
+ int totalBytes = 4 * width * height;
+
+ readRenderingResults(pixels, totalBytes, width, height);
+
+ // Convert to RGBA
+ for (int i = 0; i < totalBytes; i = 4)
+ std::swap(pixels[i], pixels[i+2]);
+
+ return imageData.release();
+}
+
+void AcceleratedPlatformLayer::markContextChanged()
+{
+ m_layerComposited = false;
+ m_swapBuffers = true;
+}
+
+bool AcceleratedPlatformLayer::swapPlatformSurfaces()
+{
+ if (!m_swapBuffers)
+ return true;
+
+ makeContextCurrent();
+ m_swapBuffers = false;
+ m_offScreenSurface->swapBuffers();
+ m_layerComposited = true;
+ return true;
+}
+
+void AcceleratedPlatformLayer::prepareTexture(int width, int height)
+{
+ if (m_layerComposited)
+ return;
+
+ GLuint internalColorFormat = 0;
+ if (m_attributes.alpha)
+ internalColorFormat = GL_RGBA;
+ else
+ internalColorFormat = GL_RGB;
+
+ makeContextCurrent();
+ GL_CMD(glActiveTexture(GL_TEXTURE0));
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, m_compositorTexture));
+ GL_CMD(glCopyTexImage2D(GL_TEXTURE_2D, 0, internalColorFormat, 0, 0, width, height, 0));
+ GL_CMD(glBindTexture(GL_TEXTURE_2D, m_state->boundTexture0));
+ GL_CMD(glActiveTexture(m_state->activeTexture));
+ GL_CMD(glFinish());
+
+ m_layerComposited = true;
+}
+
+void AcceleratedPlatformLayer::readRenderingResults(unsigned char *pixels, int pixelsSize, int width, int height)
+{
+ int totalBytes = width * height * 4;
+ if (pixelsSize < totalBytes)
+ return;
+
+ makeContextCurrent();
+ if (m_attributes.antialias)
+ notImplemented();
+
+ GLint packAlignment = 4;
+ bool mustRestorePackAlignment = false;
+ GL_CMD(glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment));
+ if (packAlignment > 4) {
+ pixelStorei(GL_PACK_ALIGNMENT, 4);
+ mustRestorePackAlignment = true;
+ }
+
+ GL_CMD(glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
+ // Convert to BGRA
+ for (int i = 0; i < totalBytes; i = 4)
+ std::swap(pixels[i], pixels[i+2]);
+
+ if (mustRestorePackAlignment)
+ pixelStorei(GL_PACK_ALIGNMENT, packAlignment);
+}
+
+void AcceleratedPlatformLayer::reshape(int width, int height)
+{
+ if ((m_width == width) && (m_height == height))
+ return;
+
+ m_width = width;
+ m_height = height;
+ makeContextCurrent();
+
+ if (m_offScreenSurface && (m_offScreenSurface->attributes() & GLPlatformSurface::DoubleBuffered)) {
+ m_offScreenSurface->swapBuffers();
+ m_offScreenSurface->setGeometry(IntRect(0, 0, m_width, m_height));
+ }
+ // FIXME: Handle resize case for single buffered surface.
+
+ m_surfaceHandle = m_offScreenSurface->handle();
+
+ if (m_attributes.antialias)
+ notImplemented();
+
+ // Initialize renderbuffers to 0.
+ GLfloat clearColorValue[] = {0, 0, 0, 0}, clearDepthValue = 0;
+ GLint clearStencilValue = 0;
+ GLboolean colorMaskValue[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMaskValue = GL_TRUE;
+ GLuint stencilMask = 0xffffffff;
+ GLboolean isScissorEnabled = GL_FALSE;
+ GLboolean isDitherEnabled = GL_FALSE;
+
+ GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
+
+ GL_CMD(glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColorValue));
+ GL_CMD(glClearColor(0, 0, 0, 0));
+ GL_CMD(glGetBooleanv(GL_COLOR_WRITEMASK, colorMaskValue));
+ GL_CMD(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
+
+ if (m_attributes.depth) {
+ GL_CMD(glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepthValue));
+ GL_CMD(glClearDepthf(1.0));
+ GL_CMD(glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMaskValue));
+ GL_CMD(glDepthMask(GL_TRUE));
+ clearMask |= GL_DEPTH_BUFFER_BIT;
+ }
+
+ if (m_attributes.stencil) {
+ GL_CMD(glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencilValue));
+ GL_CMD(glClearStencil(0));
+ GL_CMD(glGetIntegerv(GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&stencilMask)));
+ GL_CMD(glStencilMaskSeparate(GL_FRONT, 0xffffffff));
+ clearMask |= GL_STENCIL_BUFFER_BIT;
+ }
+
+ isScissorEnabled = GL_CMD(glIsEnabled(GL_SCISSOR_TEST));
+ GL_CMD(glDisable(GL_SCISSOR_TEST));
+ isDitherEnabled = GL_CMD(glIsEnabled(GL_DITHER));
+ GL_CMD(glDisable(GL_DITHER));
+
+ GL_CMD(glClear(clearMask));
+
+ GL_CMD(glClearColor(clearColorValue[0], clearColorValue[1], clearColorValue[2], clearColorValue[3]));
+ GL_CMD(glColorMask(colorMaskValue[0], colorMaskValue[1], colorMaskValue[2], colorMaskValue[3]));
+
+ if (m_attributes.depth) {
+ GL_CMD(glClearDepthf(clearDepthValue));
+ GL_CMD(glDepthMask(depthMaskValue));
+ }
+ if (m_attributes.stencil) {
+ GL_CMD(glClearStencil(clearStencilValue));
+ GL_CMD(glStencilMaskSeparate(GL_FRONT, stencilMask));
+ }
+
+ if (isScissorEnabled)
+ GL_CMD(glEnable(GL_SCISSOR_TEST));
+ else
+ GL_CMD(glDisable(GL_SCISSOR_TEST));
+
+ if (isDitherEnabled)
+ GL_CMD(glEnable(GL_DITHER));
+ else
+ GL_CMD(glDisable(GL_DITHER));
+}
+
+void AcceleratedPlatformLayer::activeTexture(GC3Denum texture)
+{
+ if (m_state->activeTexture != texture) {
+ m_state->activeTexture = texture;
+ GraphicsContext3DInternal::activeTexture(texture);
+ }
+}
+
+void AcceleratedPlatformLayer::bindFramebuffer(GC3Denum target, Platform3DObject framebuffer)
+{
+ GLuint fbo = framebuffer;
+ if (framebuffer != m_state->boundFBO) {
+ m_state->boundFBO = fbo;
+ // FIXME : Below lines are workaround codes.(driver issue)
+ // PlatformSurface surface is not updated properly after binding FBO.
+ // It seems previous frame is remained.
+#if ENABLE(TIZEN_DDK_WORKAROUND)
+ if (flush && framebuffer && !m_layerComposited)
+ GL_CMD(glFlush());
+#endif
+ GraphicsContext3DInternal::bindFramebuffer(target, fbo);
+ }
+}
+
+#if ENABLE(TIZEN_DDK_WORKAROUND)
+void AcceleratedPlatformLayer::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
+{
+ // We should probably remove the tid that was set to framebuffer from m_renderTargetTextures
+ // if texture is no longer rendered to, but since this is temporary code that will be removed
+ // when the DDK is fixed, and that scenario is quite unlikely to happen, I'll just leave it as is.
+ if (target != Extensions3D::READ_FRAMEBUFFER && texture)
+ m_renderTargetTextures.add(texture);
+
+ GraphicsContext3DInternal::framebufferTexture2D(target, attachment, textarget, texture, level);
+}
+
+void AcceleratedPlatformLayer::generateMipmap(GC3Denum target)
+{
+ // FIXME: Render to texture related driver issue.
+ // Remove GC3DOffscreen::generateMipmap and related code when driver issue is fixed.
+ // The rendered texture contents are not properly flushed before generating mipmaps.
+ int boundTexture;
+ GL_CMD(glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture));
+ if (m_renderTargetTextures.contains(boundTexture))
+ GL_CMD(glFlush());
+
+ GraphicsContext3DInternal::generateMipmap(target);
+}
+#endif
+
+void AcceleratedPlatformLayer::bindTexture(GC3Denum target, Platform3DObject texture)
+{
+ if (m_state->activeTexture == GL_TEXTURE0 && target == GL_TEXTURE_2D) {
+ if (m_state->boundTexture0 == texture)
+ return;
+
+ m_state->boundTexture0 = texture;
+ }
+
+ GraphicsContext3DInternal::bindTexture(target, texture);
+}
+
+void AcceleratedPlatformLayer::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
+{
+ GraphicsContext3DInternal::bufferData(target, size, data, usage);
+
+ // FIXME : Driver issue!
+ // Following lines are temporary to avoid webgl conformance test failures.
+ // See draw-arrays-out-of-bounds.html.
+ // If a parameter size inputted to glBufferData is zero,
+ // GL_OUT_OF_MEMORY error is occurred while running in Mali driver.
+ if (!size) {
+ GC3Denum error = getError();
+ if (error == GL_OUT_OF_MEMORY)
+ return; // No error.
+ synthesizeGLError(error); // Push the error back again.
+ }
+}
+
+bool AcceleratedPlatformLayer::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
+{
+ if (!program) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+
+ makeContextCurrent();
+ GLint maxAttributeSize = 0;
+ GL_CMD(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize));
+
+ GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination
+ GLsizei nameLength = 0;
+ GLint size = 0;
+ GLenum type = 0;
+ GL_CMD(glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name));
+ if (!nameLength)
+ return false;
+
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+ return true;
+}
+
+bool AcceleratedPlatformLayer::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
+{
+ if (!program) {
+ synthesizeGLError(GL_INVALID_VALUE);
+ return false;
+ }
+
+ makeContextCurrent();
+ GC3Dint maxUniformSize = 0;
+ GL_CMD(glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize));
+
+ GLchar name[maxUniformSize]; // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination
+ GC3Dsizei nameLength = 0;
+ GC3Dint size = 0;
+ GC3Denum type = 0;
+ GL_CMD(glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name));
+ if (!nameLength)
+ return false;
+
+ info.name = String(name, nameLength);
+ info.type = type;
+ info.size = size;
+
+ // FIXME : "[0]" is added at end of name in WebGLRenderingContext::getActiveUniform()
+ // when isGLES2Compliant is only false. I can't understand the reason.
+ // I add "[0]" here to avoid faling webgl conformance test(get-active-test.html),
+ // but if it makes something wrong later, remove following lines
+ if (isGLES2Compliant() && info.size > 1 && !info.name.endsWith("[0]"))
+ info.name.append("[0]");
+
+ return true;
+}
+
+void AcceleratedPlatformLayer::getFloatv(GC3Denum pname, GC3Dfloat* value)
+{
+ GraphicsContext3DInternal::getFloatv(pname, value);
+
+ // FIXME : Fllowing lines are for fixing SGX & Mali driver issue.
+ switch (pname) {
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ if (value[0] == value[1]) {
+ if (!value[0])
+ value[1] = 1.0;
+ else {
+ if (value[0] < 1.0)
+ value[1] = 1.0;
+ else
+ value[0] = 1.0;
+ }
+ } else {
+ if (value[0] < value[1]) {
+ if (value[1] < 1.0) {
+ value[0] = value[1];
+ value[1] = 1.0;
+ } else
+ value[0] = 1.0;
+ } else {
+ if (value[0] < 1.0)
+ value[1] = 1.0;
+ else {
+ value[1] = value[0];
+ value[0] = 1.0;
+ }
+ }
+ }
+ break;
+ }
+}
+
+void AcceleratedPlatformLayer::getIntegerv(GC3Denum pname, GC3Dint* value)
+{
+ makeContextCurrent();
+ GL_CMD(glGetIntegerv(pname, value));
+}
+
+void AcceleratedPlatformLayer::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ if (!updateViewportCache(x, y, width, height))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glViewport(x, y, width, height));
+}
+
+void AcceleratedPlatformLayer::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
+{
+ if (!updateStencilOpCache(fail, zfail, zpass))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glStencilOp(fail, zfail, zpass));
+}
+
+void AcceleratedPlatformLayer::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
+{
+ if (!updateStencilFuncCache(func, ref, mask))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glStencilFunc(func, ref, mask));
+}
+
+void AcceleratedPlatformLayer::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ if (!updateScissorCache(x, y, width, height))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glScissor(x, y, width, height));
+}
+
+void AcceleratedPlatformLayer::pixelStorei(GC3Denum pname, GC3Dint param)
+{
+ if (!updatePixelStoreiCache(pname, param))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glPixelStorei(pname, param));
+}
+
+GC3Dboolean AcceleratedPlatformLayer::isEnabled(GC3Denum cap)
+{
+ State::CapabilityState state = getCapabilityState(cap);
+ if (state != State::CapabilityUnknown)
+ return state == State::CapabilityEnabled ? true : false;
+
+ makeContextCurrent();
+ return GL_CMD(glIsEnabled(cap));
+}
+
+void AcceleratedPlatformLayer::enable(GC3Denum cap)
+{
+ if (!updateCapabilityCache(cap, State::CapabilityEnabled))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glEnable(cap));
+}
+
+void AcceleratedPlatformLayer::disable(GC3Denum cap)
+{
+ if (!updateCapabilityCache(cap, State::CapabilityDisabled))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glDisable(cap));
+}
+
+void AcceleratedPlatformLayer::depthMask(GC3Dboolean flag)
+{
+ if (!updateDepthMaskCache(flag))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glDepthMask(flag));
+}
+
+void AcceleratedPlatformLayer::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
+{
+ if (!updateBlendFuncCache(sfactor, dfactor))
+ return;
+
+ makeContextCurrent();
+ GL_CMD(glBlendFunc(sfactor, dfactor));
+}
+
+// below functions are for ANGLE integration
+void AcceleratedPlatformLayer::compileShader(Platform3DObject shader)
+{
+ ASSERT(shader);
+ makeContextCurrent();
+
+ int GLshaderType;
+ ANGLEShaderType shaderType;
+
+ GL_CMD(glGetShaderiv(shader, GraphicsContext3D::SHADER_TYPE, &GLshaderType));
+
+ if (GLshaderType == GraphicsContext3D::VERTEX_SHADER)
+ shaderType = SHADER_TYPE_VERTEX;
+ else if (GLshaderType == GraphicsContext3D::FRAGMENT_SHADER)
+ shaderType = SHADER_TYPE_FRAGMENT;
+ else
+ return; // Invalid shader type.
+
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+
+ if (result == m_shaderSourceMap.end())
+ return;
+
+ ShaderSourceEntry& entry = result->second;
+
+ String translatedShaderSource;
+ String shaderInfoLog;
+
+ bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog);
+
+ entry.log = shaderInfoLog;
+ entry.isValid = isValid;
+
+ if (!isValid)
+ return; // Shader didn't validate, don't move forward with compiling translated source.
+
+ int len = entry.source.length();
+ CString cstr = entry.source.utf8();
+ const char* s = cstr.data();
+
+ GL_CMD(glShaderSource(shader, 1, &s, &len));
+ GL_CMD(glCompileShader(shader));
+
+}
+
+void AcceleratedPlatformLayer::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
+{
+ ASSERT(shader);
+
+ makeContextCurrent();
+
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+
+ switch (pname) {
+ case GraphicsContext3D::DELETE_STATUS:
+ case GraphicsContext3D::SHADER_TYPE:
+ GL_CMD(glGetShaderiv(shader, pname, value));
+ break;
+ case GraphicsContext3D::COMPILE_STATUS:
+ if (result == m_shaderSourceMap.end()) {
+ *value = static_cast<int>(false);
+ return;
+ }
+ *value = static_cast<int>(result->second.isValid);
+ break;
+ case GraphicsContext3D::INFO_LOG_LENGTH:
+ if (result == m_shaderSourceMap.end()) {
+ *value = 0;
+ return;
+ }
+ *value = getShaderInfoLog(shader).length();
+ break;
+ case GraphicsContext3D::SHADER_SOURCE_LENGTH:
+ *value = getShaderSource(shader).length();
+ break;
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ }
+}
+
+String AcceleratedPlatformLayer::getShaderInfoLog(Platform3DObject shader)
+{
+ ASSERT(shader);
+
+ makeContextCurrent();
+
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+ if (result == m_shaderSourceMap.end())
+ return String();
+
+ ShaderSourceEntry entry = result->second;
+ if (!entry.isValid)
+ return entry.log;
+
+ GLint length = 0;
+ GL_CMD(glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length));
+ if (!length)
+ return String();
+
+ GLsizei size = 0;
+ OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]);
+ GL_CMD(glGetShaderInfoLog(shader, length, &size, info.get()));
+
+ return String(info.get());
+}
+
+String AcceleratedPlatformLayer::getShaderSource(Platform3DObject shader)
+{
+ ASSERT(shader);
+
+ makeContextCurrent();
+
+ HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
+ if (result == m_shaderSourceMap.end())
+ return String();
+
+ return result->second.source;
+}
+
+void AcceleratedPlatformLayer::shaderSource(Platform3DObject shader, const String& string)
+{
+ ASSERT(shader);
+
+ makeContextCurrent();
+
+ ShaderSourceEntry entry;
+
+ entry.source = string;
+ entry.isValid = false;
+
+ m_shaderSourceMap.set(shader, entry);
+}
+
+bool AcceleratedPlatformLayer::updateBlendFuncCache(GC3Denum sourceFactor, GC3Denum destinationFactor)
+{
+ if (m_state->m_state & State::BlendFuncCacheDirty)
+ m_state->m_state &= ~State::BlendFuncCacheDirty;
+ else if (m_state->sourceFactor == sourceFactor && m_state->destinationFactor == destinationFactor)
+ return false;
+
+ m_state->sourceFactor = sourceFactor;
+ m_state->destinationFactor = destinationFactor;
+ return true;
+}
+
+bool AcceleratedPlatformLayer::updateDepthMaskCache(GC3Dboolean depthMask)
+{
+ if (m_state->m_state & State::DepthMaskCacheDirty)
+ m_state->m_state &= ~State::DepthMaskCacheDirty;
+ else if (m_state->depthMask == depthMask)
+ return false;
+
+ m_state->depthMask = depthMask;
+ return true;
+}
+
+bool AcceleratedPlatformLayer::updateScissorCache(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ if (m_state->m_state & State::ScissorCacheDirty)
+ m_state->m_state &= ~State::ScissorCacheDirty;
+ else if (m_state->scissorX == x && m_state->scissorY == y && m_state->scissorWidth == width && m_state->scissorHeight == height)
+ return false;
+
+ m_state->scissorX = x;
+ m_state->scissorY = y;
+ m_state->scissorWidth = width;
+ m_state->scissorHeight = height;
+ return true;
+}
+
+bool AcceleratedPlatformLayer::updateStencilFuncCache(GC3Denum func, GC3Dint ref, GC3Duint mask)
+{
+ if (m_state->m_state & State::StencilFuncCacheDirty)
+ m_state->m_state &= ~State::StencilFuncCacheDirty;
+ else if (m_state->stencilFunc == func && m_state->stencilRef == ref && m_state->stencilMask == mask)
+ return false;
+
+ m_state->stencilFunc = func;
+ m_state->stencilRef = ref;
+ m_state->stencilMask = mask;
+ return true;
+}
+
+bool AcceleratedPlatformLayer::updateStencilOpCache(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
+{
+ return true;
+
+ if (m_state->m_state & State::StencilOpCacheDirty)
+ m_state->m_state &= ~State::StencilOpCacheDirty;
+ else if (m_state->stencilFail == fail && m_state->stencilZFail == zfail && m_state->stencilZPass == zpass)
+ return false;
+
+ m_state->stencilFail = fail;
+ m_state->stencilZFail = zfail;
+ m_state->stencilZPass = zpass;
+ return true;
+}
+
+bool AcceleratedPlatformLayer::updateViewportCache(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
+{
+ if (m_state->m_state & State::ViewportCacheDirty)
+ m_state->m_state &= ~State::ViewportCacheDirty;
+ else if (m_state->viewportX == x && m_state->viewportY == y && m_state->viewportWidth == width && m_state->viewportHeight == height)
+ return false;
+
+ m_state->viewportX = x;
+ m_state->viewportY = y;
+ m_state->viewportWidth = width;
+ m_state->viewportHeight = height;
+ return true;
+}
+
+bool AcceleratedPlatformLayer::updatePixelStoreiCache(GC3Denum pname, GC3Dint param)
+{
+ State::PixelStoreIntMap::const_iterator it = m_state->pixelStoreIntMap.find(pname);
+ if (it != m_state->pixelStoreIntMap.end() && it->second == param)
+ return false;
+
+ m_state->pixelStoreIntMap.set(pname, param);
+ return true;
+}
+
+State::CapabilityState AcceleratedPlatformLayer::getCapabilityState(GC3Denum cap)
+{
+ State::CapabilityStateMap::const_iterator it = m_state->capabilityStateMap.find(cap);
+ if (it == m_state->capabilityStateMap.end())
+ return State::CapabilityUnknown;
+
+ return it->second;
+}
+
+bool AcceleratedPlatformLayer::updateCapabilityCache(GC3Denum cap, State::CapabilityState isEnabled)
+{
+ State::CapabilityStateMap::const_iterator it = m_state->capabilityStateMap.find(cap);
+ if (it != m_state->capabilityStateMap.end() && it->second == isEnabled)
+ return false;
+
+ m_state->capabilityStateMap.set(cap, isEnabled);
+ return true;
+}
+
+} // namespace WebCore
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2011 Samsung Electronics
+ Copyright (C) 2013 Intel Corporation. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef AcceleratedPlatformLayer_h
+#define AcceleratedPlatformLayer_h
+
+#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && ENABLE(TIZEN_ACCELERATED_PLATFORM_LAYER)
+
+#include "GLPlatformContext.h"
+#include "GraphicsContext3D.h"
+#include "GraphicsContext3DInternal.h"
+#include "GraphicsSurface.h"
+#include "TextureMapperPlatformLayer.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class HostWindow;
+struct State {
+// This is based on initial work done here: https://bugs.webkit.org/show_bug.cgi?id=110883
+public:
+ State();
+ ~State();
+
+ enum state {
+ BlendFuncCacheDirty = 0x01,
+ DepthMaskCacheDirty = 0x02,
+ StencilFuncCacheDirty = 0x04,
+ StencilOpCacheDirty = 0x08,
+ ViewportCacheDirty = 0x10,
+ ScissorCacheDirty = 0x20
+ };
+
+ enum CapabilityState {
+ CapabilityUnknown = 0x01,
+ CapabilityEnabled = 0x02,
+ CapabilityDisabled = 0x04
+ };
+
+ typedef unsigned StateAttributes;
+
+
+ GC3Denum activeTexture;
+ GC3Duint boundFBO;
+ GC3Duint boundTexture0;
+
+ // Used by glBlendFunc.
+ GC3Denum sourceFactor;
+ GC3Denum destinationFactor;
+
+ // Used by glDepthMask.
+ GC3Dboolean depthMask;
+
+ // Used by glScissor.
+ GC3Dint scissorX;
+ GC3Dint scissorY;
+ GC3Dsizei scissorWidth;
+ GC3Dsizei scissorHeight;
+
+ // Used by glStencilFunc.
+ GC3Denum stencilFunc;
+ GC3Dint stencilRef;
+ GC3Duint stencilMask;
+
+ // Used by glStencilOp.
+ GC3Denum stencilFail;
+ GC3Denum stencilZFail;
+ GC3Denum stencilZPass;
+
+ // Used by glViewport.
+ GC3Dint viewportX;
+ GC3Dint viewportY;
+ GC3Dsizei viewportWidth;
+ GC3Dsizei viewportHeight;
+
+ // Used by glPixelStorei.
+ typedef HashMap<GC3Denum, GC3Dint> PixelStoreIntMap;
+ PixelStoreIntMap pixelStoreIntMap;
+
+ // Used by glEnable and glDisable.
+ typedef HashMap<GC3Denum, CapabilityState> CapabilityStateMap;
+ CapabilityStateMap capabilityStateMap;
+
+ StateAttributes m_state;
+};
+
+class AcceleratedPlatformLayer : public GraphicsContext3DInternal
+ , public TextureMapperPlatformLayer {
+public:
+ static PassOwnPtr<AcceleratedPlatformLayer> create(GraphicsContext3D::Attributes, GraphicsContext3D::RenderStyle);
+ virtual ~AcceleratedPlatformLayer();
+
+ virtual Platform3DObject platformTexture() const OVERRIDE { return m_compositorTexture; }
+ virtual PlatformLayer* platformLayer() const OVERRIDE;
+ virtual PlatformGraphicsContext3D platformGraphicsContext3D() const OVERRIDE { return m_offScreenContext->handle(); }
+
+ virtual void paintRenderingResultsToCanvas(ImageBuffer*, int, int) OVERRIDE;
+ virtual PassRefPtr<ImageData> paintRenderingResultsToImageData(int width, int height) OVERRIDE;
+ virtual bool paintsIntoCanvasBuffer() const OVERRIDE { return false; }
+ virtual void paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float) OVERRIDE { }
+ virtual bool paintToCanvas(const unsigned char*, int, int, int, int, PlatformContextCairo*) OVERRIDE;
+
+ virtual bool swapPlatformSurfaces() OVERRIDE;
+ virtual PlatformBufferHandle copyToGraphicsSurface() OVERRIDE { return m_surfaceHandle; }
+ virtual PlatformBufferHandle graphicsSurfaceToken() OVERRIDE const { return m_surfaceHandle; }
+ virtual int graphicsSurfaceFlags() const OVERRIDE { return m_surfaceFlags; }
+
+ virtual bool makeContextCurrent() OVERRIDE;
+ virtual void prepareTexture(int, int) OVERRIDE;
+ virtual void reshape(int, int) OVERRIDE;
+ virtual void readRenderingResults(unsigned char* pixels, int pixelsSize, int width, int height) OVERRIDE;
+ virtual void markContextChanged() OVERRIDE;
+ virtual void markLayerComposited() OVERRIDE { m_layerComposited = true; }
+ virtual bool layerComposited() const OVERRIDE { return m_layerComposited; }
+
+ virtual void activeTexture(GC3Denum) OVERRIDE;
+ virtual void bindFramebuffer(GC3Denum, Platform3DObject) OVERRIDE;
+ virtual void bindTexture(GC3Denum, Platform3DObject) OVERRIDE;
+ virtual void bufferData(GC3Denum, GC3Dsizeiptr, const void*, GC3Denum) OVERRIDE;
+ virtual bool getActiveAttrib(Platform3DObject, GC3Duint, ActiveInfo&) OVERRIDE;
+ virtual bool getActiveUniform(Platform3DObject, GC3Duint, ActiveInfo&) OVERRIDE;
+ virtual void getFloatv(GC3Denum, GC3Dfloat*) OVERRIDE;
+ virtual void getIntegerv(GC3Denum, GC3Dint*) OVERRIDE;
+ virtual void viewport(GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei) OVERRIDE;
+ virtual void stencilOp(GC3Denum, GC3Denum, GC3Denum) OVERRIDE;
+ virtual void stencilFunc(GC3Denum, GC3Dint, GC3Duint) OVERRIDE;
+ virtual void scissor(GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei) OVERRIDE;
+ virtual void pixelStorei(GC3Denum, GC3Dint) OVERRIDE;
+ virtual GC3Dboolean isEnabled(GC3Denum) OVERRIDE;
+ virtual void enable(GC3Denum) OVERRIDE;
+ virtual void disable(GC3Denum) OVERRIDE;
+ virtual void depthMask(GC3Dboolean) OVERRIDE;
+ virtual void blendFunc(GC3Denum sfactor, GC3Denum dfactor) OVERRIDE;
+#if ENABLE(TIZEN_DDK_WORKAROUND)
+ virtual void framebufferTexture2D(GC3Denum, GC3Denum, GC3Denum, Platform3DObject, GC3Dint);
+ virtual void generateMipmap(GC3Denum);
+#endif
+
+ virtual void setContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback>) OVERRIDE;
+
+private:
+ typedef struct {
+ String source;
+ String log;
+ bool isValid;
+ } ShaderSourceEntry;
+
+ AcceleratedPlatformLayer(GraphicsContext3D::Attributes, GraphicsContext3D::RenderStyle);
+ virtual bool initialize(HostWindow*) OVERRIDE;
+ bool initializeSurface();
+ void releaseResources();
+ // Angle intgration block
+ virtual void compileShader(Platform3DObject);
+ virtual void getShaderiv(Platform3DObject, GC3Denum, GC3Dint*);
+ virtual String getShaderInfoLog(Platform3DObject);
+ virtual String getShaderSource(Platform3DObject);
+ virtual void shaderSource(Platform3DObject, const String&);
+
+ // State Cache.
+ bool updateBlendFuncCache(GC3Denum, GC3Denum);
+ bool updateDepthMaskCache(GC3Dboolean);
+ bool updateScissorCache(GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei);
+ bool updateStencilFuncCache(GC3Denum, GC3Dint, GC3Duint);
+ bool updateStencilOpCache(GC3Denum, GC3Denum, GC3Denum);
+ bool updateViewportCache(GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei);
+ bool updatePixelStoreiCache(GC3Denum, GC3Dint);
+ bool updateCapabilityCache(GC3Denum, State::CapabilityState);
+ State::CapabilityState getCapabilityState(GC3Denum);
+
+ GLuint m_compositorTexture;
+ bool m_layerComposited :1;
+ bool m_swapBuffers :1;
+ int m_width;
+ int m_height;
+ GraphicsSurface::Flags m_surfaceFlags;
+ PlatformBufferHandle m_surfaceHandle;
+ GraphicsContext3D::RenderStyle m_renderStyle;
+ OwnPtr<State> m_state;
+ OwnPtr<GLPlatformContext> m_offScreenContext;
+ OwnPtr<GLPlatformSurface> m_offScreenSurface;
+ OwnPtr<GraphicsContext3D::ContextLostCallback> m_contextLostCallback;
+#if ENABLE(TIZEN_DDK_WORKAROUND)
+ HashSet<Platform3DObject> m_renderTargetTextures;
+#endif
+ HashMap<Platform3DObject, ShaderSourceEntry> m_shaderSourceMap;
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // AcceleratedPlatformLayer_h
#include "GraphicsContext3DInternal.h"
#include "Extensions3DTizen.h"
-#if ENABLE(WEBGL)
+#if ENABLE(TIZEN_ACCELERATED_PLATFORM_LAYER)
+#include "AcceleratedPlatformLayer.h"
+#elif ENABLE(WEBGL)
#include "GraphicsContext3DOffscreen.h"
#endif
-
#if ENABLE(TIZEN_WEBKIT2)
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
return nullptr;
#endif
-#if ENABLE(WEBGL)
+#if ENABLE(WEBGL) && !ENABLE(TIZEN_ACCELERATED_PLATFORM_LAYER)
return GraphicsContext3DOffscreen::create(attrs, hostWindow);
#else
return nullptr;
#endif
}
+PassOwnPtr<GraphicsContext3DInternal> GraphicsContext3DInternal::create(GraphicsContext3D::Attributes attrs, GraphicsContext3D::RenderStyle renderStyle)
+{
+#if ENABLE(TIZEN_ACCELERATED_PLATFORM_LAYER)
+ return AcceleratedPlatformLayer::create(attrs, renderStyle);
+#else
+ return nullptr;
+#endif
+}
+
GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, GraphicsContext3D::RenderStyle renderStyle)
: m_attributes(attrs)
, m_renderStyle(renderStyle)
{
public:
static PassOwnPtr<GraphicsContext3DInternal> create(GraphicsContext3D::Attributes, HostWindow*, bool);
+ static PassOwnPtr<GraphicsContext3DInternal> create(GraphicsContext3D::Attributes, GraphicsContext3D::RenderStyle);
virtual ~GraphicsContext3DInternal();
PlatformGraphicsContext3D platformGraphicsContext3D() const { return m_context; }
PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, RenderStyle renderStyle)
{
bool renderDirectlyToEvasGLObject = (renderStyle == RenderDirectlyToHostWindow);
-
+#if PLATFORM(WAYLAND)
+ OwnPtr<GraphicsContext3DInternal> internal = GraphicsContext3DInternal::create(attrs, renderStyle);
+ if (!internal)
+ return 0;
+#else
OwnPtr<GraphicsContext3DInternal> internal = GraphicsContext3DInternal::create(attrs, hostWindow, renderDirectlyToEvasGLObject);
if (!internal)
return 0;
+#endif
RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attrs, hostWindow, renderDirectlyToEvasGLObject));
context->m_internal = internal.release();
-#if USE(ACCELERATED_COMPOSITING)
+#if USE(ACCELERATED_COMPOSITING) && !PLATFORM(WAYLAND)
#if !USE(TIZEN_TEXTURE_MAPPER)
if (!renderDirectlyToEvasGLObject)
static_cast<EflLayer*>(context->platformLayer())->setContentsToCanvas(context.get());
#endif
#endif
+
return context.release();
}
#if USE(EGL) || ENABLE(TIZEN_CANVAS_GRAPHICS_SURFACE)
#include "EGLHelper.h"
+#include <wtf/HashMap.h>
#include <stdlib.h>
#include <string.h>
-#include <wtf/HashMap.h>
-
namespace WebCore {
#if !defined(EGL_FORMAT_RGBA_8888_EXACT_KHR)
static bool isVendorMesa = EGLHelper::isVendor("mesa");
static bool isVendorArm = EGLHelper::isVendor("arm");
- if (isVendorMesa)
+ if (isVendorMesa || isVendorImagination)
expectedDepthSize = attributes & GLPlatformSurface::SupportDepth ? 24 : 0;
if (!expectedAlpha && isVendorImagination)
: m_attributes(attributes)
{
static bool isVendorMesa = EGLHelper::isVendor("mesa");
- if (isVendorMesa) {
+ static bool isVendorImagination = EGLHelper::isVendor("imagination");
+ if (isVendorMesa || isVendorImagination) {
if ((m_attributes & GLPlatformSurface::SupportStencil) || (m_attributes & GLPlatformSurface::SupportDepth)) {
m_attributes |= GLPlatformSurface::SupportStencil;
m_attributes |= GLPlatformSurface::SupportDepth;
return false;
static bool isRobustnessExtensionSupported = GLPlatformContext::supportsEGLExtension(display, "EGL_EXT_create_context_robustness");
- if (isRobustnessExtensionSupported)
+ if (!(surface->attributes() & GLPlatformSurface::Lockable) && isRobustnessExtensionSupported)
m_contextHandle = eglCreateContext(display, config, sharedContext, contextRobustnessAttributes);
if (m_contextHandle != EGL_NO_CONTEXT) {
#if PLATFORM(X11)
#include "X11Helper.h"
-#elif PLATFORM(WAYLAND)
-#include "WaylandHelper.h"
#endif
namespace WebCore {
typedef X11Helper NativeWrapper;
typedef Display NativeSharedDisplay;
#elif PLATFORM(WAYLAND)
-typedef WaylandHelper NativeWrapper;
+typedef WaylandDisplay NativeWrapper;
typedef struct wl_display NativeSharedDisplay;
#endif
EGLDisplayConnection(NativeSharedDisplay* display = 0)
{
+ m_terminateNativeDisplay = false;
+#if PLATFORM(WAYLAND)
+ if (!display) {
+ NativeWrapper::connect();
+ m_terminateNativeDisplay = true;
+ display = NativeWrapper::instance()->nativeDisplay();
+ }
+#endif
if (display)
m_eglDisplay = eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(display));
else
eglTerminate(m_eglDisplay);
eglReleaseThread();
m_eglDisplay = EGL_NO_DISPLAY;
+#if PLATFORM(WAYLAND)
+ if (m_terminateNativeDisplay)
+ NativeWrapper::disconnect();
+#endif
}
EGLDisplay m_eglDisplay;
+ bool m_terminateNativeDisplay :1;
};
PlatformDisplay EGLHelper::eglDisplay()
{
// Display connection will only be broken at program shutdown.
+#if PLATFORM(WAYLAND)
+ static EGLDisplayConnection displayConnection(0);
+#else
static EGLDisplayConnection displayConnection(NativeWrapper::nativeDisplay());
+#endif
return displayConnection.display();
}
return display;
}
+#if PLATFORM(WAYLAND)
+PlatformDisplay EGLHelper::compositorEGLDisplay(NativeSharedDisplay* display)
+{
+ // Display connection will only be broken at program shutdown.
+ static EGLDisplayConnection displayConnection(display);
+ return displayConnection.display();
+}
+#endif
+
void EGLHelper::resolveEGLBindings(EGLDisplay eglDisplay)
{
static bool initialized = false;
#endif
eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR");
eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR");
- eglImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
} else
#if PLATFORM(WAYLAND)
LOG_ERROR("Platform doesn't support EGL_KHR_image_base or EGL_WL_bind_wayland_display. Support for these extensions is required for Hardware Acceleration.");
if (eglCreateImageKHR && eglDestroyImageKHR)
tempHandle = eglCreateImageKHR(display, EGL_NO_CONTEXT, target, clientBuffer, attributes);
+ if (tempHandle == EGL_NO_IMAGE_KHR)
+ HandleEGLError("eglcreateimagekhr");
+
*image = tempHandle;
}
#ifndef EGLHelper_h
#define EGLHelper_h
-#if USE(EGL) || ENABLE(TIZEN_CANVAS_GRAPHICS_SURFACE)
+#if USE(EGL)
#include "EGLSurface.h"
#if PLATFORM(WAYLAND)
-#include "WaylandHelper.h"
+#include "WaylandDisplay.h"
#endif
#include <wtf/text/WTFString.h>
public:
static PlatformDisplay eglDisplay();
static PlatformDisplay currentDisplay();
+#if PLATFORM(WAYLAND)
+ static PlatformDisplay compositorEGLDisplay(wl_display*);
+#endif
static void resolveEGLBindings(EGLDisplay = EGL_NO_DISPLAY);
static void createEGLImage(EGLImageKHR*, GLenum, const EGLClientBuffer, const EGLint* = 0, EGLDisplay = EGL_NO_DISPLAY);
static void destroyEGLImage(const EGLImageKHR, EGLDisplay = EGL_NO_DISPLAY);
#include "EGLConfigSelector.h"
#include "EGLHelper.h"
-#include "WaylandHelper.h"
+#include "WaylandDisplay.h"
#include <wtf/UnusedParam.h>
namespace WebCore {
-static int sharedBufferHandle = 0;
+
EGLWindowSurface::EGLWindowSurface(const IntSize& size, GLPlatformSurface::SurfaceAttributes attributes)
: EGLOffScreenSurface(attributes)
, m_nativeWindow(0)
- , m_surface(0)
{
if (!m_configSelector)
return;
if (!m_configSelector->surfaceContextConfig()) {
+ LOG_ERROR("No supported Configuration found.");
destroy();
return;
}
- m_surface = wl_compositor_create_surface(WaylandHelper::compositor());
+ m_surface = WaylandDisplay::instance()->createSurface();
if (!m_surface) {
LOG_ERROR("Failed to create surface.");
return;
}
- m_nativeWindow = wl_egl_window_create(m_surface, size.width(), size.height());
+ m_nativeWindow = wl_egl_window_create(m_surface->wlSurface(), size.width(), size.height());
if (!m_nativeWindow) {
LOG_ERROR("Failed to create Native Window.");
return;
}
- sharedBufferHandle++;
- m_bufferHandle = sharedBufferHandle;
+ m_bufferHandle = m_surface->handle();
+ WaylandDisplay::instance()->syncDisplay();
+ m_rect = IntRect(0, 0, size.width(), size.height());
}
EGLWindowSurface::~EGLWindowSurface()
{
- if (m_nativeWindow || m_surface || (m_drawable != EGL_NO_SURFACE))
+ if (m_nativeWindow || (m_drawable != EGL_NO_SURFACE))
LOG_ERROR("Resources not destroyed for surface with id: %d", m_bufferHandle);
m_bufferHandle = 0;
void EGLWindowSurface::swapBuffers()
{
- if (!eglSwapBuffers(m_sharedDisplay, m_drawable))
- LOG_ERROR("Failed to SwapBuffers(%d).", eglGetError());
+ if (m_surface->ensureFrameCallBackDone() == -1)
+ return;
- wl_display_dispatch(WaylandHelper::nativeDisplay());
+ m_surface->addFrameCallBack();
+
+ if (!eglSwapBuffers(m_sharedDisplay, m_drawable)) {
+ LOG_ERROR("Failed to SwapBuffers(%d).", eglGetError());
+ m_surface->deleteFrameCallBack();
+ }
}
void EGLWindowSurface::destroy()
{
- EGLOffScreenSurface::destroy();
+ if (m_surface)
+ m_surface->deleteFrameCallBack();
- if (!m_nativeWindow && !m_surface)
- return;
+ EGLOffScreenSurface::destroy();
if (m_nativeWindow) {
wl_egl_window_destroy(m_nativeWindow);
m_nativeWindow = 0;
}
- if (m_surface) {
- wl_surface_destroy(m_surface);
- m_surface = 0;
- }
+ m_surface = nullptr;
}
PlatformSurfaceConfig EGLWindowSurface::configuration()
return m_configSelector->surfaceContextConfig();
}
+void EGLWindowSurface::setGeometry(const IntRect& rect)
+{
+ if (rect != m_rect) {
+ m_rect = rect;
+ m_surface->ensureFrameCallBackDone();
+ wl_egl_window_resize(m_nativeWindow, m_rect.width(), m_rect.height(), m_rect.x(), m_rect.y());
+ WaylandDisplay::instance()->syncDisplay();
+ }
+}
+
+bool EGLWindowSurface::lockSurface()
+{
+ static EGLint lockAttrib[] = { EGL_LOCK_USAGE_HINT_KHR, EGL_WRITE_SURFACE_BIT_KHR, EGL_NONE };
+ return EGLHelper::lockSurface(m_drawable, lockAttrib);
+}
+
+bool EGLWindowSurface::unlockSurface()
+{
+ return EGLHelper::unlockSurface(m_drawable);
+}
+
}
#endif
#if PLATFORM(WAYLAND) && (USE(EGL) || ENABLE(TIZEN_CANVAS_GRAPHICS_SURFACE))
#include "EGLSurface.h"
+#include "WaylandDisplay.h"
namespace WebCore {
virtual void swapBuffers() OVERRIDE;
virtual void destroy() OVERRIDE;
virtual PlatformSurfaceConfig configuration() OVERRIDE;
+ virtual void setGeometry(const IntRect&) OVERRIDE;
+ virtual bool lockSurface() OVERRIDE;
+ virtual bool unlockSurface() OVERRIDE;
private:
struct wl_egl_window* m_nativeWindow;
- struct wl_surface* m_surface;
+ OwnPtr<WaylandSurface> m_surface;
};
}
--- /dev/null
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GraphicsSurface.h"
+
+#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && PLATFORM(WAYLAND)
+#include "NotImplemented.h"
+#include "PlatformTextureWayland.h"
+#include "TextureMapperGL.h"
+
+namespace WebCore {
+
+class GraphicsSurfacePrivate {
+public:
+ GraphicsSurfacePrivate()
+ : m_useLinearFilter(false)
+ {
+ }
+
+ GraphicsSurfacePrivate(PlatformBufferHandle token, const IntSize& size, bool useLinearFilter)
+ : m_useLinearFilter(useLinearFilter)
+ {
+ m_platformTexture = adoptPtr(new PlatformTextureWayland(token, size));
+ }
+
+ virtual ~GraphicsSurfacePrivate()
+ {
+ }
+
+ int getPlatformSurfaceTextureID()
+ {
+ int textureId = m_platformTexture->id();
+ if (!textureId) {
+ m_platformTexture->initialize(m_useLinearFilter);
+ textureId = m_platformTexture->id();
+ }
+
+ return textureId;
+ }
+
+private:
+ bool m_useLinearFilter : 1;
+ OwnPtr<PlatformTextureWayland> m_platformTexture;
+};
+
+PlatformBufferHandle GraphicsSurface::platformExport()
+{
+ return m_platformSurface;
+}
+
+uint32_t GraphicsSurface::platformGetTextureID()
+{
+ return m_private->getPlatformSurfaceTextureID();
+}
+
+void GraphicsSurface::platformPaintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity)
+{
+ bool alpha = m_canvasFlags & GraphicsSurface::Alpha;
+ int textureId = m_private->getPlatformSurfaceTextureID();
+ if (!textureId)
+ return;
+
+ static_cast<TextureMapperGL*>(textureMapper)->drawTexture(textureId, alpha ? TextureMapperGL::SupportsBlending : 0, m_size, targetRect, transform, opacity, expandedIntSize(targetRect.size()), m_canvasFlags & GraphicsSurface::PremultipliedAlpha);
+}
+
+PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, Flags flags)
+{
+ return 0;
+}
+
+PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(PlatformBufferHandle platformSurfaceID)
+{
+ RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(IntSize(), 0));
+ surface->m_private = new GraphicsSurfacePrivate();
+ surface->m_platformSurface = platformSurfaceID;
+ return surface;
+}
+
+PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, PlatformBufferHandle token, Flags canvasFlags)
+{
+ RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags));
+ surface->m_private = new GraphicsSurfacePrivate(token, size, canvasFlags & GraphicsSurface::UseLinearFilter);
+ surface->m_platformSurface = token;
+ surface->m_canvasFlags = canvasFlags;
+ surface->m_size = size;
+ return surface;
+}
+
+PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, PlatformBufferHandle token)
+{
+ RefPtr<GraphicsSurface> surface = adoptRef(new GraphicsSurface(size, flags));
+ surface->m_private = new GraphicsSurfacePrivate(token, size, flags & GraphicsSurface::UseLinearFilter);
+ surface->m_platformSurface = token;
+ surface->m_size = size;
+
+ return surface;
+}
+
+void GraphicsSurface::platformDestroy()
+{
+ delete m_private;
+ m_private = 0;
+}
+
+void GraphicsSurface::platformCopyToGLTexture(uint32_t, uint32_t, const IntRect&, const IntPoint&)
+{
+ notImplemented();
+}
+
+void GraphicsSurface::platformCopyFromFramebuffer(uint32_t, const IntRect&)
+{
+ notImplemented();
+}
+
+PlatformBufferHandle GraphicsSurface::platformFrontBuffer() const
+{
+ return m_platformSurface;
+}
+
+PlatformBufferHandle GraphicsSurface::platformSwapBuffers()
+{
+ notImplemented();
+ return 0;
+}
+
+PlatformBufferHandle GraphicsSurface::platformSwapBuffers(PlatformBufferHandle)
+{
+ notImplemented();
+ return 0;
+}
+
+char* GraphicsSurface::platformLock(const IntRect& rect, int* outputStride, LockOptions lockOptions)
+{
+ notImplemented();
+ return 0;
+}
+
+void GraphicsSurface::platformUnlock()
+{
+ notImplemented();
+}
+
+PassOwnPtr<GraphicsContext> GraphicsSurface::platformBeginPaint(const IntSize& size, char* bits, int stride)
+{
+ notImplemented();
+ return nullptr;
+}
+
+PassRefPtr<Image> GraphicsSurface::createReadOnlyImage(const IntRect& rect)
+{
+ notImplemented();
+ return 0;
+}
+
+}
+#endif
--- /dev/null
+/*
+ Copyright (C) 2013 Intel Corporation. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && ENABLE(TIZEN_ACCELERATED_PLATFORM_LAYER)
+
+#include "PlatformTextureWayland.h"
+
+namespace WebCore {
+PlatformTextureWayland::PlatformTextureWayland(int platformSurfaceID, const IntSize& size)
+ : m_buffer(0)
+ , m_platformSurfaceID(platformSurfaceID)
+ , m_textureSize(size)
+ , m_used(false)
+{
+}
+
+PlatformTextureWayland::~PlatformTextureWayland()
+{
+ if (m_buffer) {
+ m_buffer = 0;
+ WaylandDisplay* display = WaylandDisplay::instance();
+ if (display)
+ display->unMapBuffer(m_platformSurfaceID, this);
+ }
+}
+
+bool PlatformTextureWayland::initialize(bool useLinearFilter)
+{
+ if (m_buffer)
+ return true;
+
+ if (!m_platformSurfaceID) {
+ LOG_ERROR("ID is invalid!");
+ return 0;
+ }
+
+ if (!m_buffer) {
+ WaylandDisplay* display = WaylandDisplay::instance();
+ if (!display) {
+ LOG_ERROR("WaylandDisplay not initialized");
+ return false;
+ }
+
+ m_buffer = display->mapBuffer(m_platformSurfaceID, this, useLinearFilter);
+ if (!m_buffer) {
+ LOG_ERROR("Failed to map buffer for the surface");
+ return 0;
+ }
+ }
+
+ return true;
+}
+
+uint32_t PlatformTextureWayland::id() const
+{
+ return m_buffer ? m_buffer->textureId() :0;
+}
+
+void PlatformTextureWayland::bufferDestroyed()
+{
+ m_buffer = 0;
+ m_platformSurfaceID = 0;
+}
+
+};
+#endif
--- /dev/null
+/*
+ Copyright (C) 2013 Intel Corporation. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PlatformTextureWayland_h
+#define PlatformTextureWayland_h
+
+#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && ENABLE(TIZEN_ACCELERATED_PLATFORM_LAYER)
+#include "IntSize.h"
+#include "TextureMapperGL.h"
+#include "WaylandDisplay.h"
+#include "WaylandSurface.h"
+
+namespace WebCore {
+
+class PlatformTextureWayland : public PlatformSurfaceTexture
+ , public WaylandBufferListener {
+public:
+ PlatformTextureWayland(int platformSurfaceID, const IntSize&);
+ ~PlatformTextureWayland();
+ bool initialize(bool useLinearFilter);
+ virtual uint32_t id() const OVERRIDE;
+ virtual int platformSurfaceId() const OVERRIDE { return m_platformSurfaceID; }
+ virtual void updateTexture() OVERRIDE { }
+ virtual void setUsed(bool used) OVERRIDE { m_used = used; }
+ virtual bool used() OVERRIDE { return m_used; }
+ virtual IntSize size() const OVERRIDE { return m_textureSize; }
+ virtual void bufferDestroyed() OVERRIDE;
+
+private:
+ WaylandBuffer* m_buffer;
+ PlatformBufferHandle m_platformSurfaceID;
+ IntSize m_textureSize;
+ bool m_used :1;
+};
+
+}
+#endif
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WaylandCompositor.h"
+
+#include "EGLHelper.h"
+#include "GLPlatformContext.h"
+#include "WaylandSurface.h"
+#include <sys/time.h>
+
+namespace WebCore {
+
+WaylandCompositor* WaylandCompositor::m_instance = 0;
+#if !defined(PFNEGLBINDWAYLANDDISPLAYWL)
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay, struct wl_display*);
+#endif
+
+#if !defined(PFNEGLUNBINDWAYLANDDISPLAYWL)
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay, struct wl_display*);
+#endif
+
+static PFNEGLBINDWAYLANDDISPLAYWL bindWaylanddisplayWL = 0;
+static PFNEGLUNBINDWAYLANDDISPLAYWL unbindWaylanddisplayWL = 0;
+
+static const struct wl_compositor_interface compositorInterface = {
+ WaylandCompositor::compositorCreateSurface,
+ WaylandCompositor::compositorCreateRegion
+};
+
+WaylandCompositor* WaylandCompositor::initialize(wl_display* display, wl_display* nestedDisplay)
+{
+ if (!m_instance && display) {
+ m_instance = new WaylandCompositor(display, nestedDisplay);
+ if (!m_instance->m_eglDisplay) {
+ delete m_instance;
+ m_instance = 0;
+ }
+ }
+
+ return m_instance;
+}
+
+WaylandCompositor* WaylandCompositor::getInstance()
+{
+ return m_instance;
+}
+
+void WaylandCompositor::release()
+{
+ if (m_instance)
+ delete m_instance;
+
+ m_instance = 0;
+}
+
+WaylandCompositor::WaylandCompositor(wl_display* display, wl_display* nestedDisplay)
+ : m_global(0)
+ , m_nestedDisplay(nestedDisplay)
+{
+ if (!m_nestedDisplay) {
+ LOG_ERROR("WaylandCompositor Initialization failed: Invalid Nested Display.");
+ return;
+ }
+
+ m_eglDisplay = EGLHelper::compositorEGLDisplay(display);
+ if (m_eglDisplay == EGL_NO_DISPLAY) {
+ LOG_ERROR("WaylandCompositor Initialization failed: Unable to initialize EGL.");
+ return;
+ }
+
+ m_global = wl_global_create(m_nestedDisplay, &wl_compositor_interface, 1, this, WaylandCompositor::compositorBind);
+ if (!m_global)
+ return;
+
+ if (GLPlatformContext::supportsEGLExtension(m_eglDisplay, "EGL_WL_bind_wayland_display")) {
+ bindWaylanddisplayWL = (PFNEGLBINDWAYLANDDISPLAYWL)eglGetProcAddress("eglBindWaylandDisplayWL");
+ unbindWaylanddisplayWL = (PFNEGLUNBINDWAYLANDDISPLAYWL)eglGetProcAddress("eglUnbindWaylandDisplayWL");
+ } else {
+ LOG_ERROR("WaylandCompositor Initialization failed: EGL_WL_bind_wayland_display is not supported.");
+ m_eglDisplay = EGL_NO_DISPLAY;
+ return;
+ }
+
+ bool validConnection = false;
+ if (bindWaylanddisplayWL && unbindWaylanddisplayWL)
+ validConnection = bindWaylanddisplayWL(m_eglDisplay, m_nestedDisplay);
+
+ if (!validConnection) {
+ LOG_ERROR("WaylandCompositor Initialization failed: Unable to bind Wayland display.");
+ m_eglDisplay = EGL_NO_DISPLAY;
+ return;
+ }
+
+ EGLHelper::resolveEGLBindings(m_eglDisplay);
+ m_threadMutex = adoptPtr(new Mutex);
+}
+
+WaylandCompositor::~WaylandCompositor()
+{
+ if (!m_eglDisplay || !m_nestedDisplay)
+ return;
+
+ if (m_global) {
+ wl_global_destroy(m_global);
+ m_global = 0;
+ }
+
+ m_listenerMap.clear();
+ if (!m_bufferMarkedForDeletion.isEmpty()) {
+ deleteAllValues(m_bufferMarkedForDeletion);
+ m_bufferMarkedForDeletion.clear();
+ }
+
+ if (!m_bufferMap.isEmpty()) {
+ deleteAllValues(m_bufferMap);
+ m_bufferMap.clear();
+ }
+
+ if (bindWaylanddisplayWL && unbindWaylanddisplayWL)
+ unbindWaylanddisplayWL(m_eglDisplay, m_nestedDisplay);
+}
+
+void WaylandCompositor::cleanUpBufferMap()
+{
+ if (m_bufferMarkedForDeletion.isEmpty())
+ return;
+
+ if (!m_listenerMap.isEmpty()) {
+ PlatformBufferMap::iterator end = m_bufferMarkedForDeletion.end();
+ PlatformBufferMap::iterator it;
+ for (it = m_bufferMarkedForDeletion.begin(); it != end; ++it) {
+ PlatformListenerMap::iterator i = m_listenerMap.find(it->first);
+ if (i != m_listenerMap.end()) {
+ i->second->bufferDestroyed();
+ m_listenerMap.remove(i);
+ }
+
+ PlatformBufferMap::iterator d = m_dirtyBufferMap.find(it->first);
+ if (d != m_dirtyBufferMap.end())
+ m_dirtyBufferMap.remove(d);
+
+ delete it->second;
+ }
+ }
+
+ m_bufferMarkedForDeletion.clear();
+}
+
+void WaylandCompositor::bufferDestroyed(uint32_t id)
+{
+ if (!m_bufferMap.isEmpty()) {
+ WaylandBuffer* buffer = 0;
+ PlatformBufferMap::iterator it = m_bufferMap.find(id);
+ if (it != m_bufferMap.end()) {
+ m_bufferMarkedForDeletion.add(id, buffer);
+ m_bufferMap.remove(it);
+ }
+ }
+}
+
+WaylandBuffer* WaylandCompositor::mapBuffer(WaylandSurfaceId id, WaylandBufferListener* listener, bool useLinearFilter)
+{
+ cleanUpBufferMap();
+
+ if (m_bufferMap.isEmpty()) {
+ LOG_ERROR("No Wayland Surface available.");
+ return 0;
+ }
+
+ WaylandBuffer* buffer = 0;
+ PlatformBufferMap::iterator it = m_bufferMap.find(id);
+ if (it != m_bufferMap.end())
+ buffer = it->second;
+
+ if (!buffer) {
+ LOG_ERROR("Trying to map an invalid surface.");
+ return 0;
+ }
+
+
+ if (!m_listenerMap.isEmpty()) {
+ PlatformListenerMap::iterator i = m_listenerMap.find(id);
+ if (i != m_listenerMap.end()) {
+ if (listener != i->second)
+ LOG_ERROR("Trying to map surface to a buffer already in use.");
+
+ return buffer;
+ }
+ }
+
+ buffer->mapSurface(useLinearFilter);
+ m_listenerMap.add(id, listener);
+ return buffer;
+}
+
+void WaylandCompositor::unMapBuffer(WaylandSurfaceId id, WaylandBufferListener* listener)
+{
+ if (m_listenerMap.isEmpty())
+ return;
+
+ PlatformListenerMap::iterator i = m_listenerMap.find(id);
+
+ if (i == m_listenerMap.end() || listener != i->second)
+ return;
+
+ m_listenerMap.remove(id);
+
+ if (!m_bufferMap.isEmpty()) {
+ WaylandBuffer* buffer = 0;
+ PlatformBufferMap::iterator it = m_bufferMap.find(id);
+ if (it != m_bufferMap.end()) {
+ buffer = it->second;
+ if (buffer)
+ buffer->unmapSurface();
+ }
+ }
+
+ cleanUpBufferMap();
+}
+
+void WaylandCompositor::addBufferToPendingQueue(WaylandBuffer* buffer)
+{
+ PlatformBufferMap::iterator it = m_dirtyBufferMap.find(buffer->handle());
+ if (it == m_dirtyBufferMap.end())
+ m_dirtyBufferMap.add(buffer->handle(), buffer);
+}
+
+void WaylandCompositor::flush()
+{
+ if (m_dirtyBufferMap.isEmpty())
+ return;
+
+ PlatformBufferMap::iterator end = m_dirtyBufferMap.end();
+ PlatformBufferMap::iterator it;
+ for (it = m_dirtyBufferMap.begin(); it != end; ++it)
+ it->second->handleSurfaceCommit();
+
+ m_dirtyBufferMap.clear();
+}
+
+void WaylandCompositor::prepareForEventHandling()
+{
+ m_time = 0;
+ struct timeval currenTime;
+ int ret = gettimeofday(¤Time, 0);
+ if (!ret)
+ m_time = currenTime.tv_sec*1000 + currenTime.tv_usec / 1000;
+}
+
+void WaylandCompositor::compositorBind(wl_client* client, void* data, uint32_t version, uint32_t id)
+{
+ WaylandCompositor* compositor = static_cast<WaylandCompositor*>(data);
+ struct wl_resource* resource = wl_resource_create(client, &wl_compositor_interface, std::min(static_cast<int>(version), 3), id);
+ wl_resource_set_implementation(resource, &compositorInterface, compositor, 0);
+}
+
+void WaylandCompositor::compositorCreateSurface(wl_client* client, wl_resource* resource, uint32_t id)
+{
+ WaylandCompositor* compositor = static_cast<WaylandCompositor*>(resource->data);
+ WaylandBuffer* buffer = new WaylandBuffer(client, id);
+ if (!buffer) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ compositor->m_bufferMap.add(buffer->handle(), buffer);
+}
+
+void WaylandCompositor::compositorCreateRegion(wl_client*, struct wl_resource*, uint32_t)
+{
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WaylandCompositor_h
+#define WaylandCompositor_h
+
+#include "GLDefs.h"
+#include "WaylandDisplay.h"
+#include <wayland-client.h>
+#include <wayland-server.h>
+
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class WaylandBuffer;
+
+class WaylandCompositor {
+public:
+ void bufferDestroyed(uint32_t);
+ WaylandBuffer* mapBuffer(WaylandSurfaceId, WaylandBufferListener*, bool);
+ void unMapBuffer(WaylandSurfaceId, WaylandBufferListener*);
+ bool hasPendingEvents() const { return !m_dirtyBufferMap.isEmpty(); }
+ void prepareForEventHandling();
+ void flush();
+
+ static WaylandCompositor* initialize(wl_display*, wl_display*);
+ // Ownership is not transferred to the caller.
+ static WaylandCompositor* getInstance();
+ static void release();
+
+ // Call back functions.
+ static void compositorBind(wl_client*, void*, uint32_t, uint32_t);
+ static void compositorCreateRegion(wl_client*, struct wl_resource*, uint32_t);
+ static void compositorCreateSurface(wl_client*, wl_resource*, uint32_t);
+protected:
+ WaylandCompositor(wl_display*, wl_display*);
+ virtual ~WaylandCompositor();
+private:
+ static WaylandCompositor* m_instance;
+ void cleanUpBufferMap();
+ void addBufferToPendingQueue(WaylandBuffer*);
+ // Map Id and WaylandBuffer
+ typedef HashMap<WaylandSurfaceId, WaylandBuffer*> PlatformBufferMap;
+ PlatformBufferMap m_bufferMap;
+ PlatformBufferMap m_bufferMarkedForDeletion;
+ PlatformBufferMap m_dirtyBufferMap;
+
+ // Map Id and WaylandBufferListener
+ typedef HashMap<WaylandSurfaceId, WaylandBufferListener*> PlatformListenerMap;
+ PlatformListenerMap m_listenerMap;
+ uint32_t m_time;
+ wl_global* m_global;
+ wl_display* m_nestedDisplay;
+ PlatformDisplay m_eglDisplay;
+ OwnPtr<Mutex> m_threadMutex;
+ friend class WaylandBuffer;
+};
+
+}
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WaylandDisplay.h"
+
+#include "WaylandCompositor.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/epoll.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
+
+// os-compatibility
+extern "C" {
+int osEpollCreateCloExec(void);
+
+static int setCloExecOrClose(int fd)
+{
+ long flags;
+
+ if (fd == -1)
+ return -1;
+
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1)
+ goto err;
+
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+ goto err;
+
+ return fd;
+
+err:
+ close(fd);
+ return -1;
+}
+
+int osEpollCreateCloExec(void)
+{
+ int fd;
+
+#ifdef EPOLL_CLOEXEC
+ fd = epoll_create1(EPOLL_CLOEXEC);
+ if (fd >= 0)
+ return fd;
+ if (errno != EINVAL)
+ return -1;
+#endif
+
+ fd = epoll_create(1);
+ return setCloExecOrClose(fd);
+}
+
+} // os-compatibility
+
+namespace WebCore {
+
+WaylandDisplay* WaylandDisplay::m_instance = 0;
+static int MAXEVENTS = 64;
+
+static const struct wl_registry_listener registrylistener = {
+ WaylandDisplay::handleGlobal,
+ WaylandDisplay::handleGlobalRemove
+};
+
+static const struct wl_callback_listener syncListener = {
+ WaylandDisplay::syncCallback
+};
+
+bool WaylandDisplay::connect(wl_display* display)
+{
+ if (!m_instance)
+ m_instance = openStaticConnection();
+
+ if (display) {
+ if (m_instance && m_instance->m_eventDispatcher)
+ return m_instance->m_eventDispatcher->isRunning();
+
+ m_instance->initialize(display);
+
+ if (m_instance && !m_instance->m_eventDispatcher->isRunning()) {
+ LOG_ERROR("Failed to initialize WaylandDisplay.");
+ return 0;
+ }
+
+ } else {
+ if (m_instance && m_instance->m_queue)
+ return 1;
+
+ m_instance->initialize(display);
+
+ if (m_instance && !m_instance->m_queue) {
+ LOG_ERROR("Failed to initialize WaylandDisplay.");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+WaylandDisplay* WaylandDisplay::instance()
+{
+ return m_instance;
+}
+
+void WaylandDisplay::disconnect()
+{
+ if (m_instance)
+ m_instance->terminate();
+}
+
+WaylandDisplay* WaylandDisplay::openStaticConnection()
+{
+ static WaylandDisplay display;
+ return &display;
+}
+
+PassOwnPtr<WaylandPollThread> WaylandPollThread::create()
+{
+ OwnPtr<WaylandPollThread> thread = adoptPtr(new WaylandPollThread());
+ if (thread.get() && thread->m_epollFd)
+ return thread.release();
+
+ return nullptr;
+}
+
+WaylandPollThread::WaylandPollThread()
+ : m_display(0)
+ , m_clientDisplay(0)
+ , m_threadId(0)
+ , m_isRunning(false)
+ , m_isLocked(false)
+{
+ m_epollFd = osEpollCreateCloExec();
+}
+
+WaylandPollThread::~WaylandPollThread()
+{
+ ASSERT(isMainThread());
+ terminate();
+ ASSERT(!m_threadId);
+}
+
+void WaylandPollThread::terminate()
+{
+ ASSERT(isMainThread());
+ if (!m_display)
+ return;
+
+ lock();
+ m_isRunning = false;
+ unlock();
+
+ if (m_threadId) {
+ detachThread(m_threadId);
+ m_threadId = 0;
+ }
+
+ if (m_clientDisplay)
+ cancelCallOnMainThread(handleMainEventQueue, this);
+
+ if (m_epollFd) {
+ close(m_epollFd);
+ m_epollFd = 0;
+ }
+
+ m_display = 0;
+ m_clientDisplay = 0;
+}
+
+bool WaylandPollThread::createAndWatchFd()
+{
+ int fd = 0;
+
+ wl_event_loop* loop = wl_display_get_event_loop(m_display);
+ if (!loop) {
+ LOG_ERROR("WaylandPollThread initialization failed: Failed to initialize event loop.");
+ return 0;
+ }
+
+ fd = wl_event_loop_get_fd(loop);
+
+ if (fd < 0) {
+ LOG_ERROR("WaylandPollThread initialization failed: Cannot listen to current fd.");
+ return 0;
+ }
+
+ struct epoll_event ep;
+ ep.events = EPOLLIN;
+ ep.data.ptr = 0;
+ epoll_ctl(m_epollFd, EPOLL_CTL_ADD, fd, &ep);
+ return 1;
+}
+
+void WaylandPollThread::start(wl_display* display, wl_display* clientDisplay)
+{
+ m_isRunning = false;
+ if (m_threadId)
+ terminate();
+
+ m_display = display;
+ m_clientDisplay = clientDisplay;
+
+ if (!createAndWatchFd()) {
+ terminate();
+ return;
+ }
+
+ // Start worker thread.
+ if (!m_threadId) {
+ m_isRunning = true;
+
+ m_threadCreationMutex = adoptPtr(new Mutex);
+ // Start worker thread.
+ MutexLocker lock(*m_threadCreationMutex.get());
+ m_threadId = createThread(WaylandPollThread::threadEntry, this, "WaylandPoll.Thread");
+ m_threadMutex = adoptPtr(new Mutex);
+ }
+}
+
+void WaylandPollThread::handleMainEventQueue(void* context)
+{
+ WaylandPollThread* thread = static_cast<WaylandPollThread*>(context);
+ thread->flushClientDisplay();
+ WaylandCompositor* compositor = WaylandCompositor::getInstance();
+ if (compositor && compositor->hasPendingEvents()) {
+ ScopedDisplayLocker lock(thread);
+ compositor->flush();
+ }
+}
+
+void WaylandPollThread::flushClientDisplay()
+{
+ int i = 1;
+ while (i > 0)
+ i = wl_display_dispatch_pending(m_clientDisplay);
+
+ wl_display_flush(m_clientDisplay);
+}
+
+void WaylandPollThread::stop()
+{
+ terminate();
+}
+
+bool WaylandPollThread::lock()
+{
+ if (m_isLocked)
+ return false;
+
+ if (!m_threadMutex->tryLock())
+ return false;
+
+ m_isLocked = true;
+ return true;
+}
+
+void WaylandPollThread::unlock()
+{
+ if (m_isLocked) {
+ m_threadMutex->unlock();
+ m_isLocked = false;
+ }
+}
+
+void WaylandPollThread::threadEntry(void* threadData)
+{
+ ASSERT(threadData);
+ WaylandPollThread* handler = reinterpret_cast<WaylandPollThread*>(threadData);
+ handler->pollEventLoop();
+}
+
+int WaylandPollThread::pollEventLoop()
+{
+ // Wait for until we have m_threadId established before starting the run loop.
+ MutexLocker lock(*m_threadCreationMutex.get());
+ ASSERT(!isMainThread());
+
+ epoll_event ep[MAXEVENTS];
+ int i, ret, count = 0;
+ bool flushClient = false;
+ wl_event_loop* loop = wl_display_get_event_loop(m_display);
+ // Keep running tasks until we're killed.
+ while (m_isRunning) {
+ count = epoll_wait(m_epollFd, ep, MAXEVENTS, -1);
+
+ if (count >0 && m_isRunning) {
+
+ for (i = 0; i < count; i++) {
+ if (ep[i].events & EPOLLIN) {
+ flushClient = true;
+ break;
+ }
+ }
+
+ if (flushClient) {
+ flushClient = false;
+ m_threadMutex->lock();
+ WaylandCompositor* compositor = WaylandCompositor::getInstance();
+ if (compositor)
+ compositor->prepareForEventHandling();
+
+ ret = wl_event_loop_dispatch(loop, 0);
+ if (ret == -1)
+ LOG_ERROR("WaylandDisplay Error: wl_event_loop_dispatch error %d \n", ret);
+
+ wl_display_flush_clients(m_display);
+ m_threadMutex->unlock();
+ callOnMainThread(WaylandPollThread::handleMainEventQueue, this);
+ }
+ }
+ }
+
+ return 0;
+}
+
+WaylandDisplay::WaylandDisplay()
+ : m_display(0)
+ , m_compositor(0)
+ , m_registry(0)
+ , m_wlCompositor(0)
+ , m_queue(0)
+{
+}
+
+void WaylandDisplay::initialize(wl_display* display)
+{
+
+ if (display) {
+ m_eventDispatcher = WaylandPollThread::create();
+ m_display = wl_display_create();
+ if (!m_display) {
+ LOG_ERROR("WaylandDisplay initialization failed:: Failed to make connection with Wayland for client display.");
+ terminate();
+ return;
+ }
+
+ String socketString("Wayland-");
+ socketString.append(String::format("%d", m_eventDispatcher->id()));
+ setenv("WAYLAND_NESTED_CLIENT", socketString.utf8().data(), 1);
+
+ if (wl_display_add_socket(m_display, socketString.utf8().data())) {
+ LOG_ERROR("WaylandDisplay initialization failed:: Failed to Add socket.");
+ terminate();
+ return;
+ }
+
+ m_compositor = WaylandCompositor::initialize(display, m_display);
+ if (!m_compositor) {
+ LOG_ERROR("WaylandDisplay initialization failed: Compositor initialization failed.");
+ terminate();
+ return;
+ }
+
+ m_eventDispatcher->start(m_display, display);
+
+ } else {
+ const char* nestedSocket = getenv("WAYLAND_NESTED_CLIENT");
+ m_display = wl_display_connect(nestedSocket);
+
+ if (!m_display) {
+ LOG_ERROR("WaylandDisplay initialization failed: Failed to make connection with Wayland.");
+ terminate();
+ return;
+ }
+
+ m_registry = wl_display_get_registry(m_display);
+ wl_registry_add_listener(m_registry, ®istrylistener, this);
+
+ if (wl_display_roundtrip(m_display) < 0) {
+ LOG_ERROR("WaylandDisplay initialization failed: Failed to process Wayland connection.");
+ terminate();
+ return;
+ }
+
+ m_queue = wl_display_create_queue(m_display);
+ wl_proxy_set_queue((struct wl_proxy *)m_registry, m_queue);
+ }
+}
+
+WaylandDisplay::~WaylandDisplay()
+{
+ terminate();
+}
+
+void WaylandDisplay::terminate()
+{
+ if (m_eventDispatcher) {
+ m_eventDispatcher->stop();
+ m_eventDispatcher = nullptr;
+ }
+
+ if (m_compositor) {
+ m_compositor->release();
+ m_compositor = 0;
+ }
+
+ if (m_registry) {
+ wl_registry_destroy(m_registry);
+ m_registry = 0;
+
+ if (m_display) {
+ wl_display_flush(m_display);
+ wl_display_disconnect(m_display);
+ m_display = 0;
+ }
+ }
+
+ m_instance = 0;
+ m_display = 0;
+}
+
+struct wl_display* WaylandDisplay::nativeDisplay()
+{
+ wl_display* wlDisplay = 0;
+ if (m_instance)
+ wlDisplay = m_instance->m_display;
+
+ return wlDisplay;
+}
+
+struct wl_compositor* WaylandDisplay::compositor()
+{
+ struct wl_compositor* wlCompositor = 0;
+ if (m_instance)
+ wlCompositor = m_instance->m_wlCompositor;
+
+ return wlCompositor;
+}
+
+struct wl_registry* WaylandDisplay::registry()
+{
+ struct wl_registry* wlRegistry = 0;
+ if (m_instance)
+ wlRegistry = m_instance->m_registry;
+
+ return wlRegistry;
+}
+
+WaylandBuffer* WaylandDisplay::mapBuffer(WaylandSurfaceId sharedBufferId, WaylandBufferListener* listener, bool useLinearFilter)
+{
+ if (m_compositor && m_eventDispatcher) {
+ ScopedDisplayLocker lock(m_eventDispatcher.get());
+ return m_compositor->mapBuffer(sharedBufferId, listener, useLinearFilter);
+ }
+
+ return 0;
+}
+
+void WaylandDisplay::unMapBuffer(WaylandSurfaceId id, WaylandBufferListener* listener)
+{
+ if (m_compositor && m_eventDispatcher) {
+ ScopedDisplayLocker lock(m_eventDispatcher.get());
+ m_compositor->unMapBuffer(id, listener);
+ }
+}
+
+PassOwnPtr<WaylandSurface> WaylandDisplay::createSurface()
+{
+ if (!m_wlCompositor)
+ return nullptr;
+
+ OwnPtr<WaylandSurface> surface = adoptPtr(new WaylandSurface(m_wlCompositor));
+ if (surface && surface->wlSurface())
+ return surface.release();
+
+ return nullptr;
+}
+
+void WaylandDisplay::handleGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t)
+{
+ WaylandDisplay* display = static_cast<WaylandDisplay*>(data);
+ if (display && !strcmp(interface, "wl_compositor"))
+ display->m_wlCompositor = static_cast<struct wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 1));
+}
+
+void WaylandDisplay::handleGlobalRemove(void*, struct wl_registry*, uint32_t)
+{
+}
+
+void WaylandDisplay::syncCallback(void *data, struct wl_callback *callback, uint32_t serial)
+{
+ int* done = static_cast<int*>(data);
+ *done = 1;
+ wl_callback_destroy(callback);
+}
+
+int WaylandDisplay::syncDisplay()
+{
+ if (!m_queue)
+ return -1;
+
+ int done = 0, ret = 0;
+ struct wl_callback* callback = wl_display_sync(m_display);
+ wl_callback_add_listener(callback, &syncListener, &done);
+ wl_proxy_set_queue((struct wl_proxy *) callback, m_queue);
+ while (ret != -1 && !done)
+ ret = wl_display_dispatch_queue(m_display, m_queue);
+
+ wl_display_dispatch_pending(m_display);
+
+ return ret;
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WaylandDisplay_h
+#define WaylandDisplay_h
+
+#include "WaylandHelper.h"
+#include "WaylandSurface.h"
+
+namespace WebCore {
+class WaylandBuffer;
+
+class WaylandBufferListener {
+public:
+ virtual void bufferDestroyed() = 0;
+};
+
+class WaylandDisplay {
+public:
+ static bool connect(wl_display* = 0);
+ // Ownership is not transferred.
+ static WaylandDisplay* instance();
+ static void disconnect();
+ // client apis.
+ struct wl_display* nativeDisplay();
+ struct wl_compositor* compositor();
+ struct wl_registry* registry();
+ int syncDisplay();
+ // Ownership is transferred.
+ PassOwnPtr<WaylandSurface> createSurface();
+
+ // Ownership is not transferred.
+ WaylandBuffer* mapBuffer(WaylandSurfaceId, WaylandBufferListener*, bool);
+ void unMapBuffer(WaylandSurfaceId, WaylandBufferListener*);
+
+ // Used for registration purpose only.
+ static void handleGlobal(void*, struct wl_registry*, uint32_t, const char*, uint32_t);
+ static void handleGlobalRemove(void*, struct wl_registry*, uint32_t);
+
+ // callback handlers.
+ static void syncCallback(void*, struct wl_callback*, uint32_t);
+
+protected:
+ WaylandDisplay();
+ virtual ~WaylandDisplay();
+
+private:
+ void terminate();
+ void initialize(wl_display* = 0);
+ static WaylandDisplay* openStaticConnection();
+
+ // Display
+ wl_display* m_display;
+
+ // Thread
+ OwnPtr<WaylandPollThread> m_eventDispatcher;
+
+ // Intance
+ static WaylandDisplay* m_instance;
+
+ // Compositor
+ WaylandCompositor* m_compositor;
+
+ // wl registry
+ struct wl_registry* m_registry;
+ struct wl_compositor* m_wlCompositor;
+ struct wl_event_queue* m_queue;
+};
+
+}
+#endif
+++ /dev/null
-/*
- * Copyright (C) 2013 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "WaylandHelper.h"
-
-#include <string.h>
-
-namespace WebCore {
-struct wl_compositor* WaylandHelper::m_compositor = 0;
-
-static const struct wl_registry_listener registrylistener = {
- WaylandHelper::handleGlobal,
- WaylandHelper::handleGlobalRemove
-};
-
-struct DisplayConnection {
- DisplayConnection()
- : m_display(0)
- , m_registry(0)
- {
- m_display = wl_display_connect(0);
- if (!m_display) {
- LOG_ERROR("Failed to make connection with Wayland.");
- return;
- }
-
- m_registry = wl_display_get_registry(m_display);
- wl_registry_add_listener(m_registry, ®istrylistener, 0);
-
- if (wl_display_roundtrip(m_display) < 0) {
- LOG_ERROR("Failed to process Wayland connection.");
- close();
- }
- }
-
- ~DisplayConnection()
- {
- close();
- }
-
- struct wl_display* display() const { return m_display; }
-
-private:
- void close()
- {
- if (m_registry) {
- wl_registry_destroy(m_registry);
- m_registry = 0;
- }
-
- if (m_display) {
- wl_display_flush(m_display);
- wl_display_disconnect(m_display);
- m_display = 0;
- }
- }
-
- struct wl_display* m_display;
- struct wl_registry* m_registry;
-};
-
-struct wl_display* WaylandHelper::nativeDisplay()
-{
- // Display connection will only be broken at program shutdown.
- static DisplayConnection displayConnection;
- return displayConnection.display();
-}
-
-void WaylandHelper::handleGlobal(void*, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t)
-{
- if (!strcmp(interface, "wl_compositor"))
- m_compositor = static_cast<struct wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 1));
-}
-
-void WaylandHelper::handleGlobalRemove(void*, struct wl_registry*, uint32_t)
-{
-}
-
-}
#include <wayland-client.h>
#include <wayland-egl.h>
+#include <wayland-server.h>
+
+#include <wtf/MainThread.h>
+#include <wtf/MessageQueue.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Threading.h>
+#include <wtf/threads/BinarySemaphore.h>
namespace WebCore {
+class WaylandDisplay;
+class ScopedDisplayLocker;
-class WaylandHelper {
+// To be only used internally by WaylandDisplay.
+class WaylandPollThread {
public:
- static struct wl_display* nativeDisplay();
- static struct wl_compositor* compositor() { return m_compositor; }
+ // Call Baack
+ static void handleMainEventQueue(void*);
+ virtual ~WaylandPollThread();
- // Used for registration purpose only.
- static void handleGlobal(void*, struct wl_registry*, uint32_t, const char*, uint32_t);
- static void handleGlobalRemove(void*, struct wl_registry*, uint32_t);
private:
- static struct wl_compositor* m_compositor;
+ static PassOwnPtr<WaylandPollThread> create();
+ void start(wl_display*, wl_display*);
+ void stop();
+ bool isRunning() { return m_isRunning; }
+ void flushClientDisplay();
+ bool lock();
+ void unlock();
+ int id() const { return m_epollFd; }
+
+ WaylandPollThread();
+ void terminate();
+ bool createAndWatchFd();
+ static void threadEntry(void*);
+ int pollEventLoop();
+ wl_display* m_display;
+ wl_display* m_clientDisplay;
+
+ // Thread
+ ThreadIdentifier m_threadId;
+ OwnPtr<Mutex> m_threadCreationMutex;
+ OwnPtr<Mutex> m_threadMutex;
+ int m_epollFd;
+ bool m_isRunning :1;
+ bool m_isLocked :1;
+ friend class WaylandDisplay;
+ friend class ScopedDisplayLocker;
+};
+
+class ScopedDisplayLocker {
+public:
+ ScopedDisplayLocker(WaylandPollThread* thread) : m_thread(thread)
+ {
+ bool lockedDisplay = false;
+ // Aquire lock.
+ while (!lockedDisplay)
+ lockedDisplay = m_thread->lock();
+ }
+
+ ~ScopedDisplayLocker()
+ {
+ m_thread->unlock();
+ }
+
+private:
+ ScopedDisplayLocker(const ScopedDisplayLocker&);
+ ScopedDisplayLocker& operator=(const ScopedDisplayLocker&);
+ static void* operator new (size_t);
+ static void operator delete (void*);
+ WaylandPollThread* m_thread;
};
}
#endif
+
+
--- /dev/null
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WaylandSurface.h"
+
+#include "EGLHelper.h"
+#include "GLPlatformContext.h"
+#include "WaylandCompositor.h"
+#include "WaylandDisplay.h"
+
+namespace WebCore {
+static const struct wl_callback_listener frameListener = {
+ WaylandSurface::surfaceFrameCallback
+};
+
+static const struct wl_surface_interface surfaceInterface = {
+ WaylandBuffer::surfaceDestroy,
+ WaylandBuffer::surfaceAttach,
+ WaylandBuffer::surfaceDamage,
+ WaylandBuffer::surfaceFrame,
+ WaylandBuffer::surfaceSetOpaqueRegion,
+ WaylandBuffer::surfaceSetInputRegion,
+ WaylandBuffer::surfaceCommit,
+ WaylandBuffer::surfaceSetBufferTransform,
+ WaylandBuffer::surfaceSetBufferScale
+};
+
+WaylandSurface::WaylandSurface(struct wl_compositor* compositor)
+ : m_surface(0)
+ , m_frameCallBack(0)
+ , m_queue(0)
+ , m_id(0)
+{
+ static WaylandSurfaceId bufferHandleId = 0;
+ m_surface = wl_compositor_create_surface(compositor);
+
+ if (!m_surface) {
+ LOG_ERROR("WaylandSurface: Failed to create surface.");
+ return;
+ }
+
+ bufferHandleId++;
+ m_id = bufferHandleId;
+ m_queue = wl_display_create_queue(WaylandDisplay::instance()->nativeDisplay());
+ wl_proxy_set_queue((struct wl_proxy *)WaylandDisplay::instance()->registry(), m_queue);
+}
+
+void WaylandSurface::addFrameCallBack()
+{
+ if (m_frameCallBack)
+ return;
+
+ if (!m_queue) {
+ m_queue = wl_display_create_queue(WaylandDisplay::instance()->nativeDisplay());
+ wl_proxy_set_queue((struct wl_proxy *)WaylandDisplay::instance()->registry(), m_queue);
+ }
+
+ m_frameCallBack = wl_surface_frame(m_surface);
+ wl_callback_add_listener(m_frameCallBack, &frameListener, this);
+ wl_proxy_set_queue((struct wl_proxy *)m_frameCallBack, m_queue);
+}
+
+void WaylandSurface::deleteFrameCallBack()
+{
+ if (m_frameCallBack) {
+ wl_callback_destroy(m_frameCallBack);
+ m_frameCallBack = 0;
+ }
+
+ if (m_queue) {
+ wl_event_queue_destroy(m_queue);
+ m_queue = 0;
+ }
+}
+
+int WaylandSurface::ensureFrameCallBackDone()
+{
+ int ret = 0;
+ if (m_frameCallBack) {
+ while (m_frameCallBack && ret != -1)
+ ret = wl_display_dispatch_queue(WaylandDisplay::instance()->nativeDisplay(), m_queue);
+
+ wl_display_dispatch_pending(WaylandDisplay::instance()->nativeDisplay());
+ }
+
+ return ret;
+}
+
+void WaylandSurface::surfaceFrameCallback(void* data, struct wl_callback* callback, uint32_t)
+{
+ WaylandSurface* surface = static_cast<WaylandSurface *>(data);
+ wl_callback_destroy(callback);
+ surface->destroyFrameCallBack();
+}
+
+void WaylandSurface::destroyFrameCallBack()
+{
+ m_frameCallBack = 0;
+}
+
+WaylandSurface::~WaylandSurface()
+{
+ m_id = 0;
+ deleteFrameCallBack();
+
+ if (m_surface) {
+ wl_surface_destroy(m_surface);
+ m_surface = 0;
+ }
+}
+
+WaylandBuffer::WaylandBuffer(wl_client* client, uint32_t id)
+ : m_bufferResource(0)
+ , m_commitedResource(0)
+ , m_useLinearFilter(false)
+ , m_state(Default)
+ , m_id(0)
+ , m_textureId(0)
+{
+ static WaylandSurfaceId bufferHandleId = 0;
+ bufferHandleId++;
+ m_id = bufferHandleId;
+ wl_resource* resource = wl_resource_create(client, &wl_surface_interface, 1, id);
+ wl_resource_set_implementation(resource, &surfaceInterface, this, WaylandBuffer::destroySurface);
+ wl_list_init(&m_callbackList);
+}
+
+WaylandBuffer::~WaylandBuffer()
+{
+ unmapSurface();
+ m_id = 0;
+}
+
+uint WaylandBuffer::textureId()
+{
+ if (m_state & PendingUpdate)
+ bindTextureToImage();
+
+ return m_textureId;
+}
+
+void WaylandBuffer::mapSurface(bool useLinearFilter)
+{
+ if ((m_state & Destroyed) || (m_state & Mapped))
+ return;
+
+ m_state |= Mapped;
+ m_useLinearFilter = useLinearFilter;
+ if (!m_textureId)
+ m_state |= PendingUpdate;
+}
+
+void WaylandBuffer::unmapSurface()
+{
+ m_state &= ~Mapped;
+ release();
+}
+
+void WaylandBuffer::release()
+{
+ if (m_textureId) {
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &m_textureId);
+ m_textureId = 0;
+ }
+}
+
+void WaylandBuffer::attach(wl_resource* bufferResource)
+{
+ if (m_bufferResource == bufferResource)
+ return;
+
+ if (m_bufferResource)
+ wl_buffer_send_release(m_bufferResource);
+
+ m_bufferResource = bufferResource;
+}
+
+void WaylandBuffer::handleSurfaceCommit()
+{
+ m_commitedResource = m_bufferResource;
+
+ if (m_commitedResource)
+ m_state |= PendingUpdate;
+}
+
+void WaylandBuffer::bindTextureToImage()
+{
+ if (!m_commitedResource || (m_state & Destroyed))
+ return;
+
+ m_state &= ~PendingUpdate;
+ EGLDisplay display = WaylandCompositor::getInstance()->m_eglDisplay;
+ EGLImageKHR image;
+ EGLHelper::createEGLImage(&image, EGL_WAYLAND_BUFFER_WL, wl_resource_get_user_data(m_commitedResource), 0, display);
+ if (image == EGL_NO_IMAGE_KHR) {
+ LOG_ERROR("Failed to create EGLImage.");
+ return;
+ }
+
+ if (!m_textureId)
+ glGenTextures(1, &m_textureId);
+
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ EGLHelper::imageTargetTexture2DOES(image);
+ updateFilter();
+ EGLHelper::destroyEGLImage(image, display);
+ m_commitedResource = 0;
+}
+
+void WaylandBuffer::updateFilter()
+{
+ GLfloat filter = GL_NEAREST;
+ if (m_useLinearFilter)
+ filter = GL_LINEAR;
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+void WaylandBuffer::surfaceCommitCallBack()
+{
+ struct frameCallback* frameCallback;
+ struct frameCallback* next;
+ bool callbackSent = false;
+
+ uint32_t time = 0;
+ WaylandCompositor* compositor = WaylandCompositor::getInstance();
+ if (compositor)
+ time = compositor->m_time;
+
+ wl_list_for_each_safe(frameCallback, next, &m_callbackList, link)
+ {
+ wl_callback_send_done(frameCallback->resource, time);
+ wl_resource_destroy(frameCallback->resource);
+ callbackSent = true;
+ }
+
+ if (callbackSent)
+ wl_list_init(&m_callbackList);
+}
+
+void WaylandBuffer::destroySurface(wl_resource* resource)
+{
+ WaylandBuffer* buffer = getBuffer(resource);
+ if (!buffer) {
+ LOG_ERROR("Not a valid buffer");
+ return;
+ }
+
+ if (!(buffer->m_state & WaylandBuffer::Destroyed)) {
+ buffer->m_state |= WaylandBuffer::Destroyed;
+ buffer->m_state &= ~WaylandBuffer::Mapped;
+ WaylandCompositor* compositor = WaylandCompositor::getInstance();
+ if (compositor)
+ compositor->bufferDestroyed(buffer->handle());
+ }
+}
+
+void WaylandBuffer::surfaceDestroy(wl_client*, wl_resource* resource)
+{
+ wl_resource_destroy(resource);
+}
+
+WaylandBuffer* WaylandBuffer::getBuffer(wl_resource* resource)
+{
+ return static_cast<WaylandBuffer*>(wl_resource_get_user_data(resource));
+}
+
+void WaylandBuffer::surfaceAttach(wl_client*, wl_resource* resource, wl_resource* buffer_resource, int32_t, int32_t)
+{
+ WaylandBuffer* buffer = getBuffer(resource);
+ buffer->attach(buffer_resource);
+}
+
+void WaylandBuffer::surfaceDamage(wl_client*, wl_resource*, int32_t, int32_t, int32_t, int32_t)
+{
+}
+
+void WaylandBuffer::surfaceFrame(wl_client* client, wl_resource* resource, uint32_t id)
+{
+ WaylandBuffer* buffer = getBuffer(resource);
+ if (!buffer)
+ return;
+
+ struct frameCallback* callback = new frameCallback;
+ if (!callback) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ callback->resource = wl_resource_create(client, &wl_callback_interface, 1, id);
+ wl_resource_set_implementation(callback->resource, 0, callback, WaylandBuffer::destroyFrameCallback);
+ wl_list_insert(buffer->m_callbackList.prev, &callback->link);
+}
+
+void WaylandBuffer::surfaceSetOpaqueRegion(wl_client*, wl_resource*, wl_resource*)
+{
+}
+
+void WaylandBuffer::surfaceSetInputRegion(wl_client*, wl_resource*, wl_resource*)
+{
+}
+
+void WaylandBuffer::surfaceCommit(wl_client*, wl_resource* resource)
+{
+ WaylandBuffer* buffer = getBuffer(resource);
+ if (!buffer)
+ return;
+
+ buffer->surfaceCommitCallBack();
+
+ if (!(buffer->m_state & WaylandBuffer::Mapped))
+ return;
+
+ WaylandCompositor* compositor = WaylandCompositor::getInstance();
+ if (compositor)
+ compositor->addBufferToPendingQueue(buffer);
+}
+
+void WaylandBuffer::surfaceSetBufferTransform(struct wl_client *, struct wl_resource *, int)
+{
+}
+
+void WaylandBuffer::surfaceSetBufferScale(struct wl_client*, struct wl_resource*, int32_t)
+{
+}
+
+void WaylandBuffer::destroyFrameCallback(struct wl_resource* resource)
+{
+ struct frameCallback* callback = static_cast<struct frameCallback*>(wl_resource_get_user_data(resource));
+ if (callback) {
+ wl_list_remove(&callback->link);
+ delete callback;
+ }
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WaylandSurface_h
+#define WaylandSurface_h
+
+#include <wayland-client.h>
+#include <wayland-server.h>
+
+namespace WebCore {
+class WaylandCompositor;
+class WaylandDisplay;
+
+typedef uint WaylandSurfaceId;
+
+class WaylandSurface {
+public:
+ virtual ~WaylandSurface();
+ struct wl_surface* wlSurface() const { return m_surface; }
+ WaylandSurfaceId handle() const { return m_id; }
+
+ // FrameCallBack.
+ // Example usage to swap buffers
+ // if (m_surface->ensureFrameCallBackDone() == -1)
+ // return;
+ // m_surface->addFrameCallBack();
+ // Swap buffers.
+ void addFrameCallBack();
+ // Ensure that deleteFrameCallBack is called before
+ // destroying any EGL resources associated with the
+ // surface.
+ // Example usage:
+ // deleteFrameCallBack();
+ // destroy egl window etc
+ // m_surface = nullptr; i.e destroy WaylandSurface.
+ void deleteFrameCallBack();
+ // see addFrameCallBack.
+ int ensureFrameCallBackDone();
+
+ // callback
+ static void surfaceFrameCallback(void*, struct wl_callback*, uint32_t);
+
+private:
+ WaylandSurface(struct wl_compositor*);
+ void destroyFrameCallBack();
+ struct wl_surface* m_surface;
+ struct wl_callback* m_frameCallBack;
+ struct wl_event_queue* m_queue;
+ WaylandSurfaceId m_id;
+ friend class WaylandDisplay;
+};
+
+class WaylandBuffer {
+public:
+ struct frameCallback {
+ struct wl_resource* resource;
+ struct wl_list link;
+ };
+
+ enum State {
+ Default = 0x00,
+ Mapped = 0x01,
+ PendingUpdate = 0x02,
+ Destroyed = 0x04
+ };
+
+ virtual ~WaylandBuffer();
+ typedef unsigned WaylandBufferState;
+ uint handle() const { return m_id; }
+
+ // texture.
+ uint textureId();
+ WaylandBufferState state() const { return m_state; }
+
+ static WaylandBuffer* getBuffer(wl_resource*);
+ static void surfaceDestroy(wl_client*, wl_resource*);
+ static void surfaceAttach(wl_client*, wl_resource*, wl_resource*, int32_t, int32_t);
+ static void surfaceDamage(wl_client*, wl_resource*, int32_t, int32_t, int32_t, int32_t);
+ static void surfaceFrame(wl_client*, wl_resource*, uint32_t);
+ static void surfaceSetOpaqueRegion(wl_client*, wl_resource*, wl_resource*);
+ static void surfaceSetInputRegion(wl_client*, wl_resource*, wl_resource*);
+ static void surfaceCommit(wl_client*, wl_resource*);
+ static void surfaceSetBufferTransform(struct wl_client*, struct wl_resource *, int);
+ static void destroySurface(wl_resource*);
+ static void surfaceSetBufferScale(struct wl_client*, struct wl_resource*, int32_t);
+ static void destroyFrameCallback(struct wl_resource*);
+private:
+ WaylandBuffer(wl_client*, uint32_t);
+ void mapSurface(bool);
+ void unmapSurface();
+ void attach(wl_resource*);
+ void surfaceCommitCallBack();
+ void handleSurfaceCommit();
+ void release();
+ void updateFilter();
+ void bindTextureToImage();
+ struct wl_resource* m_bufferResource;
+ struct wl_resource* m_commitedResource;
+ struct wl_list m_callbackList;
+ bool m_useLinearFilter :1;
+ WaylandBufferState m_state :6;
+ uint m_id;
+ uint32_t m_textureId;
+ friend class WaylandCompositor;
+};
+
+}
+
+#endif
m_graphicsSurfaceSize = surfaceSize;
}
+#if !PLATFORM(WAYLAND)
RefPtr<WebCore::GraphicsSurface> surface = graphicsSurface();
if (surface && surface->frontBuffer() != frontBuffer)
#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
#else
surface->swapBuffers();
#endif
+#endif
}
PassRefPtr<BitmapTexture> TextureMapperSurfaceBackingStore::texture() const
#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
PassRefPtr<PlatformSurfaceTexture> TextureMapperGL::createPlatformSurfaceTexture(int platformSurfaceID, IntSize size, bool useLinearFilter)
{
+#if PLATFORM(WAYLAND)
+ PlatformTextureWayland* texture = new PlatformTextureWayland(platformSurfaceID, size);
+#else
PlatformSurfaceTextureGL* texture = new PlatformSurfaceTextureGL(platformSurfaceID, size);
+#endif
texture->initialize(useLinearFilter);
return adoptRef(texture);
}
#include "TransformationMatrix.h"
#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
+#if PLATFORM(WAYLAND)
+#include "PlatformTextureWayland.h"
+#else
#include "PlatformSurfaceTextureGL.h"
#endif
+#endif
#if USE(TIZEN_TEXTURE_MAPPER)
// FIXME
${UIGadget_INCLUDE_DIRS}
)
+IF (WTF_PLATFORM_WAYLAND)
+ LIST(APPEND WebKit2StaticForDebug_INCLUDE_DIRECTORIES
+ "${WEBCORE_DIR}/platform/graphics/surfaces/wayland"
+ )
+ENDIF()
+
IF (ENABLE_PLUGIN_PROCESS)
LIST(APPEND PluginProcess_LIBRARIES
${GLES20_LIBRARIES}
#include "ScreenReaderProxy.h"
#endif
+#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && PLATFORM(WAYLAND)
+#include "Evas_Engine_Wayland_Egl.h"
+#include "WaylandDisplay.h"
+#endif
+
using namespace WebCore;
using namespace std;
, m_isAcceleratedCompositingModeInitialized(false)
{
initializeAcceleratedCompositingMode();
+#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && PLATFORM(WAYLAND)
+ Evas_Engine_Info_Wayland_Egl* einfo = (Evas_Engine_Info_Wayland_Egl*)evas_engine_info_get(evas_object_evas_get(m_viewImpl->view()));
+ WaylandDisplay::connect(einfo->info.display);
+#endif
}
PageClientEvasGL::~PageClientEvasGL()
{
+#if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && PLATFORM(WAYLAND)
+ WaylandDisplay::disconnect();
+#endif
if (m_viewImpl && m_viewImpl->page())
m_viewImpl->page()->close();
}