From 46b7436ce5cb8d89c7496b27635816a90de8a57a Mon Sep 17 00:00:00 2001 From: hujiajie Date: Sun, 24 May 2015 20:39:27 +0800 Subject: [PATCH] [Blink] WebCL support for Crosswalk. WebCL 1.0 defines a JavaScript binding to the Khronos OpenCL standard for heterogeneous parallel computing. Its spec is available at: http://www.khronos.org/registry/webcl/specs/latest/1.0/ This patch includes WebCL basic APIs support, dynamic loading mechanism etc. WebCL support is controlled by "ENABLE_WEBCL" flag, and it's enabled by default on Android. If you want to disable with WebCL, please add "-Denable_webcl=0" when running the "xwalk/gyp_xwalk" before building. Currently, Intel CPU/GPU, Qualcomm CPU/GPU and Power VR GPU are supported. But OpenCL library isn't always shipped with device by default, even it supports OpenCL. For example: Google Nexus series. It requires to install OpenCL library manually. TEST=WebCL conformances test on Asus MemoPad and Xiaomi3. Known issue: 1. miss oilpan support. 2. miss cl_khr_gl_sharing extension support. 3. load library in render process. R=dongseong.hwang@intel.com, halton.huo@intel.com, kenneth.r.christiansen@intel.com BUG=XWALK-4254 --- .../bindings/core/v8/ExceptionState.cpp | 12 + .../Source/bindings/core/v8/ExceptionState.h | 1 + .../bindings/core/v8/V8ThrowException.cpp | 43 + .../bindings/core/v8/V8ThrowException.h | 2 + .../v8/custom/V8WebCLCommandQueueCustom.cpp | 1552 +++++++++++++++++ .../v8/custom/V8WebCLProgramCustom.cpp | 54 + .../bindings/modules/v8/custom/custom.gypi | 2 + third_party/WebKit/Source/core/core.gypi | 3 + .../Source/core/webcl/WebCLException.cpp | 229 +++ .../WebKit/Source/core/webcl/WebCLException.h | 153 ++ .../Source/core/webcl/WebCLException.idl | 8 + .../WebKit/Source/modules/modules.gypi | 64 + .../Source/modules/webcl/DOMWindowWebCL.cpp | 77 + .../Source/modules/webcl/DOMWindowWebCL.h | 42 + .../WebKit/Source/modules/webcl/WebCL.cpp | 413 +++++ .../WebKit/Source/modules/webcl/WebCL.h | 84 + .../WebKit/Source/modules/webcl/WebCL.idl | 347 ++++ .../Source/modules/webcl/WebCLBuffer.cpp | 128 ++ .../WebKit/Source/modules/webcl/WebCLBuffer.h | 37 + .../Source/modules/webcl/WebCLBuffer.idl | 11 + .../Source/modules/webcl/WebCLCallback.h | 24 + .../Source/modules/webcl/WebCLCallback.idl | 9 + .../modules/webcl/WebCLCommandQueue.cpp | 1313 ++++++++++++++ .../Source/modules/webcl/WebCLCommandQueue.h | 117 ++ .../modules/webcl/WebCLCommandQueue.idl | 239 +++ .../WebKit/Source/modules/webcl/WebCLConfig.h | 30 + .../Source/modules/webcl/WebCLContext.cpp | 728 ++++++++ .../Source/modules/webcl/WebCLContext.h | 102 ++ .../Source/modules/webcl/WebCLContext.idl | 29 + .../Source/modules/webcl/WebCLDevice.cpp | 472 +++++ .../WebKit/Source/modules/webcl/WebCLDevice.h | 57 + .../Source/modules/webcl/WebCLDevice.idl | 14 + .../Source/modules/webcl/WebCLEvent.cpp | 239 +++ .../WebKit/Source/modules/webcl/WebCLEvent.h | 56 + .../Source/modules/webcl/WebCLEvent.idl | 16 + .../Source/modules/webcl/WebCLExtension.cpp | 78 + .../Source/modules/webcl/WebCLExtension.h | 35 + .../Source/modules/webcl/WebCLHTMLUtil.cpp | 187 ++ .../Source/modules/webcl/WebCLHTMLUtil.h | 45 + .../Source/modules/webcl/WebCLImage.cpp | 57 + .../WebKit/Source/modules/webcl/WebCLImage.h | 41 + .../Source/modules/webcl/WebCLImage.idl | 9 + .../modules/webcl/WebCLImageDescriptor.idl | 14 + .../modules/webcl/WebCLInputChecker.cpp | 364 ++++ .../Source/modules/webcl/WebCLInputChecker.h | 45 + .../Source/modules/webcl/WebCLKernel.cpp | 449 +++++ .../WebKit/Source/modules/webcl/WebCLKernel.h | 64 + .../Source/modules/webcl/WebCLKernel.idl | 16 + .../Source/modules/webcl/WebCLKernelArgInfo.h | 125 ++ .../modules/webcl/WebCLKernelArgInfo.idl | 14 + .../webcl/WebCLKernelArgInfoProvider.cpp | 246 +++ .../webcl/WebCLKernelArgInfoProvider.h | 44 + .../modules/webcl/WebCLMemoryObject.cpp | 104 ++ .../Source/modules/webcl/WebCLMemoryObject.h | 54 + .../modules/webcl/WebCLMemoryObject.idl | 11 + .../Source/modules/webcl/WebCLMemoryUtil.cpp | 182 ++ .../Source/modules/webcl/WebCLMemoryUtil.h | 54 + .../Source/modules/webcl/WebCLObject.cpp | 47 + .../WebKit/Source/modules/webcl/WebCLObject.h | 45 + .../Source/modules/webcl/WebCLOpenCL.cpp | 389 +++++ .../WebKit/Source/modules/webcl/WebCLOpenCL.h | 226 +++ .../Source/modules/webcl/WebCLPlatform.cpp | 186 ++ .../Source/modules/webcl/WebCLPlatform.h | 51 + .../Source/modules/webcl/WebCLPlatform.idl | 14 + .../Source/modules/webcl/WebCLProgram.cpp | 510 ++++++ .../Source/modules/webcl/WebCLProgram.h | 63 + .../Source/modules/webcl/WebCLProgram.idl | 19 + .../Source/modules/webcl/WebCLSampler.cpp | 82 + .../Source/modules/webcl/WebCLSampler.h | 45 + .../Source/modules/webcl/WebCLSampler.idl | 11 + .../Source/modules/webcl/WebCLUserEvent.cpp | 90 + .../Source/modules/webcl/WebCLUserEvent.h | 39 + .../Source/modules/webcl/WebCLUserEvent.idl | 12 + .../Source/modules/webcl/WindowWebCL.idl | 10 + 74 files changed, 10784 insertions(+) create mode 100644 third_party/WebKit/Source/bindings/modules/v8/custom/V8WebCLCommandQueueCustom.cpp create mode 100644 third_party/WebKit/Source/bindings/modules/v8/custom/V8WebCLProgramCustom.cpp create mode 100644 third_party/WebKit/Source/core/webcl/WebCLException.cpp create mode 100644 third_party/WebKit/Source/core/webcl/WebCLException.h create mode 100644 third_party/WebKit/Source/core/webcl/WebCLException.idl create mode 100644 third_party/WebKit/Source/modules/webcl/DOMWindowWebCL.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/DOMWindowWebCL.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCL.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCL.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCL.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLBuffer.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLBuffer.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLBuffer.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLCallback.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLCallback.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLConfig.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLContext.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLContext.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLContext.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLDevice.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLDevice.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLDevice.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLEvent.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLEvent.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLEvent.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLExtension.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLExtension.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLHTMLUtil.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLHTMLUtil.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLImage.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLImage.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLImage.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLImageDescriptor.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLInputChecker.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLInputChecker.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLKernel.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLKernel.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLKernel.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfo.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfo.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfoProvider.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfoProvider.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLMemoryUtil.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLMemoryUtil.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLObject.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLObject.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLOpenCL.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLOpenCL.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLPlatform.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLPlatform.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLPlatform.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLProgram.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLProgram.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLProgram.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLSampler.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLSampler.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLSampler.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLUserEvent.cpp create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLUserEvent.h create mode 100644 third_party/WebKit/Source/modules/webcl/WebCLUserEvent.idl create mode 100644 third_party/WebKit/Source/modules/webcl/WindowWebCL.idl diff --git a/third_party/WebKit/Source/bindings/core/v8/ExceptionState.cpp b/third_party/WebKit/Source/bindings/core/v8/ExceptionState.cpp index 134a447cadf2a..751d7beecfc5a 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ExceptionState.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ExceptionState.cpp @@ -72,6 +72,18 @@ void ExceptionState::throwDOMException(const ExceptionCode& ec, const String& me setException(V8ThrowException::createDOMException(m_isolate, ec, processedMessage, m_creationContext)); } +void ExceptionState::throwWebCLException(const ExceptionCode& ec, const String& message) +{ + ASSERT(ec); + ASSERT(m_isolate); + ASSERT(!m_creationContext.IsEmpty()); + + m_code = ec; + String processedMessage = addExceptionContext(message); + m_message = processedMessage; + setException(V8ThrowException::createWebCLException(m_isolate, ec, message, processedMessage, m_creationContext)); +} + void ExceptionState::throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage) { ASSERT(m_isolate); diff --git a/third_party/WebKit/Source/bindings/core/v8/ExceptionState.h b/third_party/WebKit/Source/bindings/core/v8/ExceptionState.h index f4d2351e980b4..326716dd850af 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ExceptionState.h +++ b/third_party/WebKit/Source/bindings/core/v8/ExceptionState.h @@ -80,6 +80,7 @@ class CORE_EXPORT ExceptionState { , m_isolate(isolate) { ASSERT(m_context == ConstructionContext || m_context == EnumerationContext || m_context == IndexedSetterContext || m_context == IndexedGetterContext || m_context == IndexedDeletionContext); } virtual void throwDOMException(const ExceptionCode&, const String& message); + virtual void throwWebCLException(const ExceptionCode&, const String& message); virtual void throwTypeError(const String& message); virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()); virtual void throwRangeError(const String& message); diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ThrowException.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ThrowException.cpp index 58e221eacb716..e35f123a19428 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ThrowException.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8ThrowException.cpp @@ -28,8 +28,11 @@ #include "bindings/core/v8/BindingSecurity.h" #include "bindings/core/v8/V8Binding.h" #include "bindings/core/v8/V8DOMException.h" +#include "bindings/core/v8/V8WebCLException.h" #include "core/dom/DOMException.h" #include "core/dom/ExceptionCode.h" +#include "core/webcl/WebCLException.h" +#include "wtf/RefPtr.h" namespace blink { @@ -47,6 +50,19 @@ static void domExceptionStackSetter(v8::Local name, v8::Local name, const v8::PropertyCallbackInfo& info) +{ + v8::Isolate* isolate = info.GetIsolate(); + v8::Local value; + if (info.Data().As()->Get(isolate->GetCurrentContext(), v8AtomicString(isolate, "stack")).ToLocal(&value)) + v8SetReturnValue(info, value); +} + +static void webclExceptionStackSetter(v8::Local name, v8::Local value, const v8::PropertyCallbackInfo& info) +{ + info.Data().As()->Set(v8AtomicString(info.GetIsolate(), "stack"), value); +} + v8::Local V8ThrowException::createDOMException(v8::Isolate* isolate, int ec, const String& sanitizedMessage, const String& unsanitizedMessage, const v8::Local& creationContext) { if (ec <= 0 || v8::V8::IsExecutionTerminating()) @@ -104,6 +120,33 @@ v8::Local V8ThrowException::throwDOMException(int ec, const String& s return V8ThrowException::throwException(exception, isolate); } +v8::Local V8ThrowException::createWebCLException(v8::Isolate* isolate, int ec, const String& name, const String& message, const v8::Local& creationContext) +{ + if (ec <= 0 || v8::V8::IsExecutionTerminating()) + return v8Undefined(); + + v8::TryCatch tryCatch; + + RefPtr webclException = WebCLException::create(ec, name, message); + v8::Local exception = toV8(webclException, creationContext, isolate); + + if (tryCatch.HasCaught()) { + ASSERT(exception.IsEmpty()); + return tryCatch.Exception(); + } + ASSERT(!exception.IsEmpty()); + + // Attach an Error object to the WebCLException. This is then lazily used to get the stack value. + v8::Local error = v8::Exception::Error(v8String(isolate, webclException->message())); + ASSERT(!error.IsEmpty()); + v8::Local exceptionObject = exception.As(); + v8::Maybe result = exceptionObject->SetAccessor(isolate->GetCurrentContext(), v8AtomicString(isolate, "stack"), webclExceptionStackGetter, webclExceptionStackSetter, v8::MaybeLocal(error)); + ASSERT_UNUSED(result, result.FromJust()); + V8HiddenValue::setHiddenValue(isolate, exceptionObject, V8HiddenValue::error(isolate), error); + + return exception; +} + v8::Local V8ThrowException::createGeneralError(v8::Isolate* isolate, const String& message) { return v8::Exception::Error(v8String(isolate, message.isNull() ? "Error" : message)); diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ThrowException.h b/third_party/WebKit/Source/bindings/core/v8/V8ThrowException.h index 2f04e692ce67c..f552cf636ed67 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8ThrowException.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8ThrowException.h @@ -46,6 +46,8 @@ class CORE_EXPORT V8ThrowException { } static v8::Local throwDOMException(int, const String& sanitizedMessage, const String& unsanitizedMessage, const v8::Local& creationContext, v8::Isolate*); + static v8::Local createWebCLException(v8::Isolate*, int, const String& name, const String& message, const v8::Local& creationContext); + static v8::Local throwException(v8::Local, v8::Isolate*); static v8::Local createGeneralError(v8::Isolate*, const String&); diff --git a/third_party/WebKit/Source/bindings/modules/v8/custom/V8WebCLCommandQueueCustom.cpp b/third_party/WebKit/Source/bindings/modules/v8/custom/V8WebCLCommandQueueCustom.cpp new file mode 100644 index 0000000000000..8fc6c78ce5696 --- /dev/null +++ b/third_party/WebKit/Source/bindings/modules/v8/custom/V8WebCLCommandQueueCustom.cpp @@ -0,0 +1,1552 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/core/v8/V8ArrayBufferView.h" +#include "bindings/core/v8/V8HTMLCanvasElement.h" +#include "bindings/core/v8/V8HTMLImageElement.h" +#include "bindings/core/v8/V8HTMLVideoElement.h" +#include "bindings/core/v8/V8ImageData.h" +#include "bindings/modules/v8/V8WebCLBuffer.h" +#include "bindings/modules/v8/V8WebCLCallback.h" +#include "bindings/modules/v8/V8WebCLCommandQueue.h" +#include "bindings/modules/v8/V8WebCLEvent.h" +#include "bindings/modules/v8/V8WebCLImage.h" +#include "bindings/modules/v8/V8WebCLKernel.h" +#include "bindings/modules/v8/V8WebCLMemoryObject.h" + +namespace blink { + +void V8WebCLCommandQueue::enqueueCopyBufferMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueCopyBuffer", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* srcBuffer; + WebCLBuffer* dstBuffer; + unsigned srcOffset; + unsigned dstOffset; + unsigned numBytes; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + srcBuffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + if (info.Length() > 1 && !V8WebCLBuffer::hasInstance(info[1], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 2 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + dstBuffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[1]); + + srcOffset = toUInt32(info.GetIsolate(), info[2], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + dstOffset = toUInt32(info.GetIsolate(), info[3], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + numBytes = toUInt32(info.GetIsolate(), info[4], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + impl->enqueueCopyBuffer(srcBuffer, dstBuffer, srcOffset, dstOffset, numBytes, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueCopyBufferRectMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueCopyBufferRect", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 9)) { + setMinimumArityTypeError(exceptionState, 9, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* srcBuffer; + WebCLBuffer* dstBuffer; + Vector srcOrigin; + Vector dstOrigin; + Vector region; + unsigned srcRowPitch; + unsigned srcSlicePitch; + unsigned dstRowPitch; + unsigned dstSlicePitch; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + srcBuffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + if (info.Length() > 1 && !V8WebCLBuffer::hasInstance(info[1], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 2 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + dstBuffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[1]); + + srcOrigin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + dstOrigin = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + srcRowPitch = toUInt32(info.GetIsolate(), info[5], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + srcSlicePitch = toUInt32(info.GetIsolate(), info[6], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + dstRowPitch = toUInt32(info.GetIsolate(), info[7], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + dstSlicePitch = toUInt32(info.GetIsolate(), info[8], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 9 && !isUndefinedOrNull(info[9])) { + eventWaitList = toRefPtrNativeArray(info[9], 10, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 10) { + if (!isUndefinedOrNull(info[10]) && !V8WebCLEvent::hasInstance(info[10], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 11 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[10]); + } + } + impl->enqueueCopyBufferRect(srcBuffer, dstBuffer, srcOrigin, dstOrigin, region, srcRowPitch, srcSlicePitch, dstRowPitch, dstSlicePitch, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueCopyImageMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueCopyImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLImage* srcImage; + WebCLImage* dstImage; + Vector srcOrigin; + Vector dstOrigin; + Vector region; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLImage::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + srcImage = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[0]); + if (info.Length() > 1 && !V8WebCLImage::hasInstance(info[1], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 2 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + dstImage = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[1]); + srcOrigin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + dstOrigin = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + impl->enqueueCopyImage(srcImage, dstImage, srcOrigin, dstOrigin, region, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueCopyImageToBufferMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueCopyImageToBuffer", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLImage* srcImage; + WebCLBuffer* dstBuffer; + Vector srcOrigin; + Vector srcRegion; + unsigned dstOffset; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLImage::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + srcImage = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[0]); + if (info.Length() > 1 && !V8WebCLBuffer::hasInstance(info[1], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 2 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + dstBuffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[1]); + + srcOrigin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + srcRegion = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + dstOffset = toUInt32(info.GetIsolate(), info[4], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + impl->enqueueCopyImageToBuffer(srcImage, dstBuffer, srcOrigin, srcRegion, dstOffset, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueCopyBufferToImageMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueCopyBufferToImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* srcBuffer; + WebCLImage* dstImage; + unsigned srcOffset; + Vector dstOrigin; + Vector dstRegion; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + srcBuffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + if (info.Length() > 1 && !V8WebCLImage::hasInstance(info[1], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 2 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + dstImage = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[1]); + + srcOffset = toUInt32(info.GetIsolate(), info[2], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + dstOrigin = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + dstRegion = toImplArray>(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + impl->enqueueCopyBufferToImage(srcBuffer, dstImage, srcOffset, dstOrigin, dstRegion, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +static void enqueueReadBuffer1Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadBuffer", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* buffer; + bool blockingRead; + unsigned bufferOffset; + unsigned numBytes; + HTMLCanvasElement* canvas; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + buffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingRead = info[1]->BooleanValue(); + + bufferOffset = toUInt32(info.GetIsolate(), info[2], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + numBytes = toUInt32(info.GetIsolate(), info[3], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 4 && !V8HTMLCanvasElement::hasInstance(info[4], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 5 is not of type 'HTMLCanvasElement'."); + exceptionState.throwIfNeeded(); + return; + } + + canvas = V8HTMLCanvasElement::toImplWithTypeCheck(info.GetIsolate(), info[4]); + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + impl->enqueueReadBuffer(buffer, blockingRead, bufferOffset, numBytes, canvas, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +static void enqueueReadBuffer2Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadBuffer", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* buffer; + bool blockingRead; + unsigned bufferOffset; + unsigned numBytes; + DOMArrayBufferView* hostPtr; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + buffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingRead = info[1]->BooleanValue(); + bufferOffset = toUInt32(info.GetIsolate(), info[2], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + numBytes = toUInt32(info.GetIsolate(), info[3], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 4 && !V8ArrayBufferView::hasInstance(info[4], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 5 is not of type 'ArrayBufferView'."); + exceptionState.throwIfNeeded(); + return; + } + + hostPtr = info[4]->IsArrayBufferView() ? V8ArrayBufferView::toImpl(v8::Handle::Cast(info[4])) : 0; + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + impl->enqueueReadBuffer(buffer, blockingRead, bufferOffset, numBytes, hostPtr, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueReadBufferMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadBuffer", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + switch (std::min(5, info.Length())) { + case 5: + if (V8HTMLCanvasElement::hasInstance(info[4], info.GetIsolate())) { + enqueueReadBuffer1Method(info); + return; + } + + enqueueReadBuffer2Method(info); + return; + default: + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(5, info.Length())); + exceptionState.throwIfNeeded(); + return; + } + + exceptionState.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + exceptionState.throwIfNeeded(); +} + +static void enqueueReadBufferRect1Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadBufferRect", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 8)) { + setMinimumArityTypeError(exceptionState, 8, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* buffer; + bool blockingRead; + Vector bufferOrigin; + Vector hostOrigin; + Vector region; + unsigned hostRowPitch; + unsigned hostSlicePitch; + HTMLCanvasElement* canvas; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + buffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingRead = info[1]->BooleanValue(); + bufferOrigin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostOrigin = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostRowPitch = toUInt32(info.GetIsolate(), info[5], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostSlicePitch = toUInt32(info.GetIsolate(), info[6], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 7 && !V8HTMLCanvasElement::hasInstance(info[7], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 8 is not of type 'HTMLCanvasElement'."); + exceptionState.throwIfNeeded(); + return; + } + + canvas = V8HTMLCanvasElement::toImplWithTypeCheck(info.GetIsolate(), info[7]); + if (info.Length() > 8 && !isUndefinedOrNull(info[8])) { + eventWaitList = toRefPtrNativeArray(info[8], 9, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 9) { + if (!isUndefinedOrNull(info[9]) && !V8WebCLEvent::hasInstance(info[9], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 10 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[9]); + } + } + + impl->enqueueReadBufferRect(buffer, blockingRead, bufferOrigin, hostOrigin, region, hostRowPitch, hostSlicePitch, canvas, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +static void enqueueReadBufferRect2Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadBufferRect", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 10)) { + setMinimumArityTypeError(exceptionState, 10, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* buffer; + bool blockingRead; + Vector bufferOrigin; + Vector hostOrigin; + Vector region; + unsigned bufferRowPitch; + unsigned bufferSlicePitch; + unsigned hostRowPitch; + unsigned hostSlicePitch; + DOMArrayBufferView* hostPtr; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + buffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingRead = info[1]->BooleanValue(); + bufferOrigin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostOrigin = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + bufferRowPitch = toUInt32(info.GetIsolate(), info[5], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + bufferSlicePitch = toUInt32(info.GetIsolate(), info[6], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostRowPitch = toUInt32(info.GetIsolate(), info[7], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostSlicePitch = toUInt32(info.GetIsolate(), info[8], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 9 && !V8ArrayBufferView::hasInstance(info[9], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 10 is not of type 'ArrayBufferView'."); + exceptionState.throwIfNeeded(); + return; + } + + hostPtr = info[9]->IsArrayBufferView() ? V8ArrayBufferView::toImpl(v8::Handle::Cast(info[9])) : 0; + if (info.Length() > 10 && !isUndefinedOrNull(info[10])) { + eventWaitList = toRefPtrNativeArray(info[10], 11, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 11) { + if (!isUndefinedOrNull(info[11]) && !V8WebCLEvent::hasInstance(info[11], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 12 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[11]); + } + } + + impl->enqueueReadBufferRect(buffer, blockingRead, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, hostPtr, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueReadBufferRectMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadBufferRect", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + switch (std::min(8, info.Length())) { + case 8: + if (V8HTMLCanvasElement::hasInstance(info[7], info.GetIsolate())) { + enqueueReadBufferRect1Method(info); + return; + } + + enqueueReadBufferRect2Method(info); + return; + default: + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(8, info.Length())); + exceptionState.throwIfNeeded(); + return; + } + + exceptionState.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + exceptionState.throwIfNeeded(); +} + +static void enqueueReadImage1Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLImage* image; + bool blockingRead; + Vector origin; + Vector region; + HTMLCanvasElement* canvas; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLImage::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + image = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingRead = info[1]->BooleanValue(); + origin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 4 && !V8HTMLCanvasElement::hasInstance(info[4], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 5 is not of type 'HTMLCanvasElement'."); + exceptionState.throwIfNeeded(); + return; + } + + canvas = V8HTMLCanvasElement::toImplWithTypeCheck(info.GetIsolate(), info[4]); + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + impl->enqueueReadImage(image, blockingRead, origin, region, canvas, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +static void enqueueReadImage2Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 6)) { + setMinimumArityTypeError(exceptionState, 6, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLImage* image; + bool blockingRead; + Vector origin; + Vector region; + unsigned hostRowPitch; + DOMArrayBufferView* hostPtr; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLImage::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + image = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingRead = info[1]->BooleanValue(); + origin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostRowPitch = toUInt32(info.GetIsolate(), info[4], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 5 && !V8ArrayBufferView::hasInstance(info[5], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 6 is not of type 'ArrayBufferView'."); + exceptionState.throwIfNeeded(); + return; + } + + hostPtr = info[5]->IsArrayBufferView() ? V8ArrayBufferView::toImpl(v8::Handle::Cast(info[5])) : 0; + if (info.Length() > 6 && !isUndefinedOrNull(info[6])) { + eventWaitList = toRefPtrNativeArray(info[6], 7, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 7) { + if (!isUndefinedOrNull(info[7]) && !V8WebCLEvent::hasInstance(info[7], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 8 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[7]); + } + } + impl->enqueueReadImage(image, blockingRead, origin, region, hostRowPitch, hostPtr, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueReadImageMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueReadImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + switch (std::min(5, info.Length())) { + case 5: + if (V8HTMLCanvasElement::hasInstance(info[4], info.GetIsolate())) { + enqueueReadImage1Method(info); + return; + } + enqueueReadImage2Method(info); + return; + default: + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(5, info.Length())); + exceptionState.throwIfNeeded(); + return; + } + + exceptionState.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + exceptionState.throwIfNeeded(); +} + +static void enqueueWriteBuffer1Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteBuffer", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 4)) { + setMinimumArityTypeError(exceptionState, 4, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* buffer; + bool blockingWrite; + unsigned bufferOffset; + ImageData* imageData = nullptr; + HTMLCanvasElement* canvas = nullptr; + HTMLImageElement* image = nullptr; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + buffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingWrite = info[1]->BooleanValue(); + bufferOffset = toUInt32(info.GetIsolate(), info[2], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (V8ImageData::hasInstance(info[3], info.GetIsolate())) { + if (info.Length() > 3 && !V8ImageData::hasInstance(info[3], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 4 is not of type 'ImageData'."); + exceptionState.throwIfNeeded(); + return; + } + + imageData = V8ImageData::toImplWithTypeCheck(info.GetIsolate(), info[3]); + } else if (V8HTMLCanvasElement::hasInstance(info[3], info.GetIsolate())) { + if (info.Length() > 3 && !V8HTMLCanvasElement::hasInstance(info[3], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 4 is not of type 'HTMLCanvasElement'."); + exceptionState.throwIfNeeded(); + return; + } + + canvas = V8HTMLCanvasElement::toImplWithTypeCheck(info.GetIsolate(), info[3]); + } else if (V8HTMLImageElement::hasInstance(info[3], info.GetIsolate())) { + if (info.Length() > 3 && !V8HTMLImageElement::hasInstance(info[3], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 4 is not of type 'HTMLImageElement'."); + exceptionState.throwIfNeeded(); + return; + } + + image = V8HTMLImageElement::toImplWithTypeCheck(info.GetIsolate(), info[3]); + } + + if (info.Length() > 4 && !isUndefinedOrNull(info[4])) { + eventWaitList = toRefPtrNativeArray(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 5) { + if (!isUndefinedOrNull(info[5]) && !V8WebCLEvent::hasInstance(info[5], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 6 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[5]); + } + } + + if (V8ImageData::hasInstance(info[3], info.GetIsolate())) + impl->enqueueWriteBuffer(buffer, blockingWrite, bufferOffset, imageData, eventWaitList, event, exceptionState); + else if (V8HTMLCanvasElement::hasInstance(info[3], info.GetIsolate())) + impl->enqueueWriteBuffer(buffer, blockingWrite, bufferOffset, canvas, eventWaitList, event, exceptionState); + else if (V8HTMLImageElement::hasInstance(info[3], info.GetIsolate())) + impl->enqueueWriteBuffer(buffer, blockingWrite, bufferOffset, image, eventWaitList, event, exceptionState); + + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +static void enqueueWriteBuffer2Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteBuffer", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* bufferId; + bool blockingWrite; + unsigned bufferOffset; + unsigned numBytes; + DOMArrayBufferView* hostPtr; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + bufferId = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingWrite = info[1]->BooleanValue(); + bufferOffset = toUInt32(info.GetIsolate(), info[2], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + numBytes = toUInt32(info.GetIsolate(), info[3], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 4 && !V8ArrayBufferView::hasInstance(info[4], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 5 is not of type 'ArrayBufferView'."); + exceptionState.throwIfNeeded(); + return; + } + + hostPtr = info[4]->IsArrayBufferView() ? V8ArrayBufferView::toImpl(v8::Handle::Cast(info[4])) : 0; + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + impl->enqueueWriteBuffer(bufferId, blockingWrite, bufferOffset, numBytes, hostPtr, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueWriteBufferMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteBuffer", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + switch (std::min(4, info.Length())) { + case 4: + if (V8ImageData::hasInstance(info[3], info.GetIsolate()) || V8HTMLCanvasElement::hasInstance(info[3], info.GetIsolate()) || V8HTMLImageElement::hasInstance(info[3], info.GetIsolate())) { + enqueueWriteBuffer1Method(info); + return; + } + + enqueueWriteBuffer2Method(info); + return; + default: + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(4, info.Length())); + exceptionState.throwIfNeeded(); + return; + } + + exceptionState.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + exceptionState.throwIfNeeded(); +} + +static void enqueueWriteBufferRect1Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteBufferRect", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 8)) { + setMinimumArityTypeError(exceptionState, 8, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* buffer; + bool blockingWrite; + Vector bufferOrigin; + Vector hostOrigin; + Vector region; + unsigned hostRowPitch; + unsigned hostSlicePitch; + ImageData* imageData = nullptr; + HTMLCanvasElement* canvas = nullptr; + HTMLImageElement* image = nullptr; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + buffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingWrite = info[1]->BooleanValue(); + bufferOrigin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostOrigin = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostRowPitch = toUInt32(info.GetIsolate(), info[5], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostSlicePitch = toUInt32(info.GetIsolate(), info[6], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (V8ImageData::hasInstance(info[7], info.GetIsolate())) { + if (info.Length() > 7 && !V8ImageData::hasInstance(info[7], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 8 is not of type 'ImageData'."); + exceptionState.throwIfNeeded(); + return; + } + + imageData = V8ImageData::toImplWithTypeCheck(info.GetIsolate(), info[7]); + } else if (V8HTMLCanvasElement::hasInstance(info[7], info.GetIsolate())) { + if (info.Length() > 7 && !V8HTMLCanvasElement::hasInstance(info[7], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 8 is not of type 'HTMLCanvasElement'."); + exceptionState.throwIfNeeded(); + return; + } + + canvas = V8HTMLCanvasElement::toImplWithTypeCheck(info.GetIsolate(), info[7]); + } else if (V8HTMLImageElement::hasInstance(info[7], info.GetIsolate())) { + if (info.Length() > 7 && !V8HTMLImageElement::hasInstance(info[7], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 8 is not of type 'HTMLImageElement'."); + exceptionState.throwIfNeeded(); + return; + } + + image = V8HTMLImageElement::toImplWithTypeCheck(info.GetIsolate(), info[7]); + } + if (info.Length() > 8 && !isUndefinedOrNull(info[8])) { + eventWaitList = toRefPtrNativeArray(info[8], 9, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + + if (info.Length() > 9) { + if (!isUndefinedOrNull(info[9]) && !V8WebCLEvent::hasInstance(info[9], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 10 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[9]); + } + } + + if (V8ImageData::hasInstance(info[7], info.GetIsolate())) + impl->enqueueWriteBufferRect(buffer, blockingWrite, bufferOrigin, hostOrigin, region, hostRowPitch, hostSlicePitch, imageData, eventWaitList, event, exceptionState); + else if (V8HTMLCanvasElement::hasInstance(info[7], info.GetIsolate())) + impl->enqueueWriteBufferRect(buffer, blockingWrite, bufferOrigin, hostOrigin, region, hostRowPitch, hostSlicePitch, canvas, eventWaitList, event, exceptionState); + else if (V8HTMLImageElement::hasInstance(info[7], info.GetIsolate())) + impl->enqueueWriteBufferRect(buffer, blockingWrite, bufferOrigin, hostOrigin, region, hostRowPitch, hostSlicePitch, image, eventWaitList, event, exceptionState); + + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +static void enqueueWriteBufferRect2Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteBufferRect", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 10)) { + setMinimumArityTypeError(exceptionState, 10, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLBuffer* buffer; + bool blockingWrite; + Vector bufferOrigin; + Vector hostOrigin; + Vector region; + unsigned bufferRowPitch; + unsigned bufferSlicePitch; + unsigned hostRowPitch; + unsigned hostSlicePitch; + DOMArrayBufferView* hostPtr; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLBuffer::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLBuffer'."); + exceptionState.throwIfNeeded(); + return; + } + + buffer = V8WebCLBuffer::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingWrite = info[1]->BooleanValue(); + bufferOrigin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostOrigin = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + bufferRowPitch = toUInt32(info.GetIsolate(), info[5], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + bufferSlicePitch = toUInt32(info.GetIsolate(), info[6], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostRowPitch = toUInt32(info.GetIsolate(), info[7], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostSlicePitch = toUInt32(info.GetIsolate(), info[8], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 9 && !V8ArrayBufferView::hasInstance(info[9], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 10 is not of type 'ArrayBufferView'."); + exceptionState.throwIfNeeded(); + return; + } + + hostPtr = info[9]->IsArrayBufferView() ? V8ArrayBufferView::toImpl(v8::Handle::Cast(info[9])) : 0; + if (info.Length() > 10 && !isUndefinedOrNull(info[10])) { + eventWaitList = toRefPtrNativeArray(info[10], 11, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 11) { + if (!isUndefinedOrNull(info[11]) && !V8WebCLEvent::hasInstance(info[11], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 12 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[11]); + } + } + + impl->enqueueWriteBufferRect(buffer, blockingWrite, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, hostPtr, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueWriteBufferRectMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteBufferRect", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + switch (std::min(8, info.Length())) { + case 8: + if (V8ImageData::hasInstance(info[7], info.GetIsolate()) || V8HTMLCanvasElement::hasInstance(info[7], info.GetIsolate()) || V8HTMLImageElement::hasInstance(info[7], info.GetIsolate())) { + enqueueWriteBufferRect1Method(info); + return; + } + + enqueueWriteBufferRect2Method(info); + return; + default: + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(8, info.Length())); + exceptionState.throwIfNeeded(); + return; + } + + exceptionState.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + exceptionState.throwIfNeeded(); +} + +static void enqueueWriteImage3Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 5)) { + setMinimumArityTypeError(exceptionState, 5, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLImage* image; + bool blockingWrite; + Vector origin; + Vector region; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLImage::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + image = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingWrite = info[1]->BooleanValue(); + origin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + + if (V8ImageData::hasInstance(info[4], info.GetIsolate())) { + ImageData* imageData; + if (info.Length() > 4 && !V8ImageData::hasInstance(info[4], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 5 is not of type 'ImageData'."); + exceptionState.throwIfNeeded(); + return; + } + + imageData = V8ImageData::toImplWithTypeCheck(info.GetIsolate(), info[4]); + impl->enqueueWriteImage(image, blockingWrite, origin, region, imageData, eventWaitList, event, exceptionState); + } else if (V8HTMLCanvasElement::hasInstance(info[4], info.GetIsolate())) { + HTMLCanvasElement* canvas; + if (info.Length() > 4 && !V8HTMLCanvasElement::hasInstance(info[4], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 5 is not of type 'HTMLCanvasElement'."); + exceptionState.throwIfNeeded(); + return; + } + + canvas = V8HTMLCanvasElement::toImplWithTypeCheck(info.GetIsolate(), info[4]); + impl->enqueueWriteImage(image, blockingWrite, origin, region, canvas, eventWaitList, event, exceptionState); + } else if (V8HTMLImageElement::hasInstance(info[4], info.GetIsolate())) { + HTMLImageElement* imageElement; + if (info.Length() > 4 && !V8HTMLImageElement::hasInstance(info[4], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 5 is not of type 'HTMLImageElement'."); + exceptionState.throwIfNeeded(); + return; + } + + imageElement = V8HTMLImageElement::toImplWithTypeCheck(info.GetIsolate(), info[4]); + impl->enqueueWriteImage(image, blockingWrite, origin, region, imageElement, eventWaitList, event, exceptionState); + } + + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +static void enqueueWriteImage1Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 3)) { + setMinimumArityTypeError(exceptionState, 3, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLImage* image; + bool blockingWrite; + HTMLVideoElement* video; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLImage::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + image = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingWrite = info[1]->BooleanValue(); + if (info.Length() > 2 && !V8HTMLVideoElement::hasInstance(info[2], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 3 is not of type 'HTMLVideoElement'."); + exceptionState.throwIfNeeded(); + return; + } + + video = V8HTMLVideoElement::toImplWithTypeCheck(info.GetIsolate(), info[2]); + if (info.Length() > 3 && !isUndefinedOrNull(info[3])) { + eventWaitList = toRefPtrNativeArray(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 4) { + if (!isUndefinedOrNull(info[4]) && !V8WebCLEvent::hasInstance(info[4], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 5 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[4]); + } + } + + impl->enqueueWriteImage(image, blockingWrite, video, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) { + exceptionState.throwIfNeeded(); + } +} + +static void enqueueWriteImage2Method(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 6)) { + setMinimumArityTypeError(exceptionState, 6, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLImage* image; + bool blockingWrite; + Vector origin; + Vector region; + unsigned hostRowPitch; + DOMArrayBufferView* hostPtr; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLImage::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLImage'."); + exceptionState.throwIfNeeded(); + return; + } + + image = V8WebCLImage::toImplWithTypeCheck(info.GetIsolate(), info[0]); + blockingWrite = info[1]->BooleanValue(); + origin = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + region = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + hostRowPitch = toUInt32(info.GetIsolate(), info[4], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 5 && !V8ArrayBufferView::hasInstance(info[5], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 6 is not of type 'ArrayBufferView'."); + exceptionState.throwIfNeeded(); + return; + } + + hostPtr = info[5]->IsArrayBufferView() ? V8ArrayBufferView::toImpl(v8::Handle::Cast(info[5])) : 0; + if (info.Length() > 6 && !isUndefinedOrNull(info[6])) { + eventWaitList = toRefPtrNativeArray(info[6], 7, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 7) { + if (!isUndefinedOrNull(info[7]) && !V8WebCLEvent::hasInstance(info[7], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 8 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[7]); + } + } + + impl->enqueueWriteImage(image, blockingWrite, origin, region, hostRowPitch, hostPtr, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) { + exceptionState.throwIfNeeded(); + } +} + +void V8WebCLCommandQueue::enqueueWriteImageMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueWriteImage", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + switch (std::min(3, info.Length())) { + case 3: + if (V8HTMLVideoElement::hasInstance(info[2], info.GetIsolate())) { + enqueueWriteImage1Method(info); + return; + } + + if (info.Length() >= 5) { + if (V8ImageData::hasInstance(info[4], info.GetIsolate()) || V8HTMLCanvasElement::hasInstance(info[4], info.GetIsolate()) || V8HTMLImageElement::hasInstance(info[4], info.GetIsolate())) { + enqueueWriteImage3Method(info); + return; + } + enqueueWriteImage2Method(info); + return; + } + default: + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(3, info.Length())); + exceptionState.throwIfNeeded(); + return; + } + + exceptionState.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + exceptionState.throwIfNeeded(); +} + +void V8WebCLCommandQueue::enqueueNDRangeKernelMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "enqueueNDRangeKernel", "WebCLCommandQueue", info.Holder(), info.GetIsolate()); + if (UNLIKELY(info.Length() < 4)) { + setMinimumArityTypeError(exceptionState, 4, info.Length()); + exceptionState.throwIfNeeded(); + return; + } + + WebCLCommandQueue* impl = V8WebCLCommandQueue::toImpl(info.Holder()); + WebCLKernel* kernel; + unsigned workDim; + Vector offsets; + Vector globalWorkSize; + Vector localWorkSize; + Vector> eventWaitList; + WebCLEvent* event = nullptr; + { + if (info.Length() > 0 && !V8WebCLKernel::hasInstance(info[0], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 1 is not of type 'WebCLKernel'."); + exceptionState.throwIfNeeded(); + return; + } + + kernel = V8WebCLKernel::toImplWithTypeCheck(info.GetIsolate(), info[0]); + workDim = toUInt32(info.GetIsolate(), info[1], EnforceRange, exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 2 && !isUndefinedOrNull(info[2])){ + offsets = toImplArray>(info[2], 3, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + globalWorkSize = toImplArray>(info[3], 4, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + + if (info.Length() > 4 && !isUndefinedOrNull(info[4])) { + localWorkSize = toImplArray>(info[4], 5, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 5 && !isUndefinedOrNull(info[5])) { + eventWaitList = toRefPtrNativeArray(info[5], 6, info.GetIsolate(), exceptionState); + if(exceptionState.throwIfNeeded()) + return; + } + + if (info.Length() > 6) { + if (!isUndefinedOrNull(info[6]) && !V8WebCLEvent::hasInstance(info[6], info.GetIsolate())) { + exceptionState.throwTypeError("parameter 7 is not of type 'WebCLEvent'."); + exceptionState.throwIfNeeded(); + return; + } + + event = V8WebCLEvent::toImplWithTypeCheck(info.GetIsolate(), info[6]); + } + } + impl->enqueueNDRangeKernel(kernel, workDim, offsets, globalWorkSize, localWorkSize, eventWaitList, event, exceptionState); + if (exceptionState.hadException()) + exceptionState.throwIfNeeded(); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/bindings/modules/v8/custom/V8WebCLProgramCustom.cpp b/third_party/WebKit/Source/bindings/modules/v8/custom/V8WebCLProgramCustom.cpp new file mode 100644 index 0000000000000..0d96dd7b2b05a --- /dev/null +++ b/third_party/WebKit/Source/bindings/modules/v8/custom/V8WebCLProgramCustom.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) + +#include "bindings/modules/v8/V8WebCLCallback.h" +#include "bindings/modules/v8/V8WebCLDevice.h" +#include "bindings/modules/v8/V8WebCLProgram.h" + +namespace blink { + +void V8WebCLProgram::buildMethodCustom(const v8::FunctionCallbackInfo& info) +{ + ExceptionState es(ExceptionState::ExecutionContext, "build", "WebCLProgram", info.Holder(), info.GetIsolate()); + WebCLProgram* impl = V8WebCLProgram::toImpl(info.Holder()); + Vector> devices; + V8StringResource options; + WebCLCallback* whenFinished = nullptr; + { + if (info.Length() > 0 && !isUndefinedOrNull(info[0])) { + devices = toRefPtrNativeArray(info[0], 1, info.GetIsolate(), es); + if(es.throwIfNeeded()) + return; + } + + options = info[1]; + if(!options.prepare()) + return; + + if (!isUndefinedOrNull(info[2])) { + if (!info[2]->IsFunction()) { + es.throwTypeError("The callback provided as parameter 3 is not a function."); + es.throwIfNeeded(); + return; + } + + whenFinished = V8WebCLCallback::create(v8::Handle::Cast(info[2]), ScriptState::current(info.GetIsolate())); + } + } + + if (!devices.isEmpty()) + impl->build(devices, options, whenFinished, es); + else + impl->build(options, whenFinished, es); + + if (es.hadException()) + es.throwIfNeeded(); +} + +} +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gypi b/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gypi index 25d8daedb4029..293f574a08a37 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gypi +++ b/third_party/WebKit/Source/bindings/modules/v8/custom/custom.gypi @@ -9,6 +9,8 @@ 'V8CustomSQLStatementErrorCallback.cpp', 'V8DeviceMotionEventCustom.cpp', 'V8ServiceWorkerMessageEventCustom.cpp', + 'V8WebCLCommandQueueCustom.cpp', + 'V8WebCLProgramCustom.cpp', ], }, } diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi index 30eb8ca7eb7ba..25cfc82f1fa5f 100644 --- a/third_party/WebKit/Source/core/core.gypi +++ b/third_party/WebKit/Source/core/core.gypi @@ -381,6 +381,7 @@ 'timing/PerformanceResourceTiming.idl', 'timing/PerformanceTiming.idl', 'timing/WorkerPerformance.idl', + 'webcl/WebCLException.idl', 'workers/SharedWorker.idl', 'workers/Worker.idl', 'workers/WorkerConsole.idl', @@ -2007,6 +2008,8 @@ 'timing/WorkerGlobalScopePerformance.h', 'timing/WorkerPerformance.cpp', 'timing/WorkerPerformance.h', + 'webcl/WebCLException.cpp', + 'webcl/WebCLException.h', 'workers/AbstractWorker.cpp', 'workers/AbstractWorker.h', 'workers/DedicatedWorkerGlobalScope.cpp', diff --git a/third_party/WebKit/Source/core/webcl/WebCLException.cpp b/third_party/WebKit/Source/core/webcl/WebCLException.cpp new file mode 100644 index 0000000000000..425747da50c31 --- /dev/null +++ b/third_party/WebKit/Source/core/webcl/WebCLException.cpp @@ -0,0 +1,229 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) + +#include "core/webcl/WebCLException.h" +#include + +namespace blink { + +const char WebCLException::successMessage[] = "SUCCESS"; +const char WebCLException::deviceNotFoundMessage[] = "DEVICE_NOT_FOUND"; +const char WebCLException::deviceNotAvailableMessage[] = "DEVICE_NOT_AVAILABLE"; +const char WebCLException::compilerNotAvailableMessage[] = "COMPILER_NOT_AVAILABLE"; +const char WebCLException::memObjectAllocationFailureMessage[] = "MEM_OBJECT_ALLOCATION_FAILURE"; +const char WebCLException::outOfResourcesMessage[] = "OUT_OF_RESOURCES"; +const char WebCLException::outOfHostMemoryMessage[] = "OUT_OF_HOST_MEMORY"; +const char WebCLException::profilingInfoNotAvailableMessage[] = "PROFILING_INFO_NOT_AVAILABLE"; +const char WebCLException::memCopyOverlapMessage[] = "MEM_COPY_OVERLAP"; +const char WebCLException::imageFormatMismatchMessage[] = "IMAGE_FORMAT_MISMATCH"; +const char WebCLException::imageFormatNotSupportedMessage[] = "IMAGE_FORMAT_NOT_SUPPORTED"; +const char WebCLException::buildProgramFailureMessage[] = "BUILD_PROGRAM_FAILURE"; +const char WebCLException::mapFailureMessage[] = "MAP_FAILURE"; +const char WebCLException::misalignedSubBufferOffsetMessage[] = "MISALIGNED_SUB_BUFFER_OFFSET"; +const char WebCLException::execStatusErrorForEventsInWaitListMessage[] = "EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST"; +const char WebCLException::extensionNotEnabledMessage[] = "EXTENSION_NOT_ENABLED"; +const char WebCLException::invalidValueMessage[] = "INVALID_VALUE"; +const char WebCLException::invalidDeviceTypeMessage[] = "INVALID_DEVICE_TYPE"; +const char WebCLException::invalidPlatformMessage[] = "INVALID_PLATFORM"; +const char WebCLException::invalidDeviceMessage[] = "INVALID_DEVICE"; +const char WebCLException::invalidContextMessage[] = "INVALID_CONTEXT"; +const char WebCLException::invalidQueuePropertiesMessage[] = "INVALID_QUEUE_PROPERTIES"; +const char WebCLException::invalidCommandQueueMessage[] = "INVALID_COMMAND_QUEUE"; +const char WebCLException::invalidHostPTRMessage[] = "INVALID_HOST_PTR"; +const char WebCLException::invalidMemObjectMessage[] = "INVALID_MEM_OBJECT"; +const char WebCLException::invalidImageFormatDescriptorMessage[] = "INVALID_IMAGE_FORMAT_DESCRIPTOR"; +const char WebCLException::invalidImageSizeMessage[] = "INVALID_IMAGE_SIZE"; +const char WebCLException::invalidSamplerMessage[] = "INVALID_SAMPLER"; +const char WebCLException::invalidBinaryMessage[] = "INVALID_BINARY"; +const char WebCLException::invalidBuildOptionsMessage[] = "INVALID_BUILD_OPTIONS"; +const char WebCLException::invalidProgramMessage[] = "INVALID_PROGRAM"; +const char WebCLException::invalidProgramExecutableMessage[] = "INVALID_PROGRAM_EXECUTABLE"; +const char WebCLException::invalidKernelNameMessage[] = "INVALID_KERNEL_NAME"; +const char WebCLException::invalidKernelDefinitionMessage[] = "INVALID_KERNEL_DEFINITION"; +const char WebCLException::invalidKernelMessage[] = "INVALID_KERNEL"; +const char WebCLException::invalidArgIndexMessage[] = "INVALID_ARG_INDEX"; +const char WebCLException::invalidArgValueMessage[] = "INVALID_ARG_VALUE"; +const char WebCLException::invalidArgSizeMessage[] = "INVALID_ARG_SIZE"; +const char WebCLException::invalidKernelArgsMessage[] = "INVALID_KERNEL_ARGS"; +const char WebCLException::invalidWorkDimensionMessage[] = "INVALID_WORK_DIMENSION"; +const char WebCLException::invalidWorkGroupSizeMessage[] = "INVALID_WORK_GROUP_SIZE"; +const char WebCLException::invalidWorkItemSizeMessage[] = "INVALID_WORK_ITEM_SIZE"; +const char WebCLException::invalidGlobalOffsetMessage[] = "INVALID_GLOBAL_OFFSET"; +const char WebCLException::invalidEventWaitListMessage[] = "INVALID_EVENT_WAIT_LIST"; +const char WebCLException::invalidEventMessage[] = "INVALID_EVENT"; +const char WebCLException::invalidOperationMessage[] = "INVALID_OPERATION"; +const char WebCLException::invalidGLObjectMessage[] = "INVALID_GL_OBJECT"; +const char WebCLException::invalidBufferSizeMessage[] = "INVALID_BUFFER_SIZE"; +const char WebCLException::invalidMIPLevelMessage[] = "INVALID_MIP_LEVEL"; +const char WebCLException::invalidGlobalWorkSizeMessage[] = "INVALID_GLOBAL_WORK_SIZE"; +const char WebCLException::invalidPropertyMessage[] = "INVALID_PROPERTY"; +const char WebCLException::failureMessage[] = "FAILURE"; + +void WebCLException::throwException(int& code, ExceptionState& es) +{ + switch(code) { + case CL_DEVICE_NOT_FOUND: + es.throwWebCLException(WebCLException::DEVICE_NOT_FOUND, WebCLException::deviceNotFoundMessage); + break; + case CL_DEVICE_NOT_AVAILABLE: + es.throwWebCLException(WebCLException::DEVICE_NOT_AVAILABLE, WebCLException::deviceNotAvailableMessage); + break; + case CL_COMPILER_NOT_AVAILABLE: + es.throwWebCLException(WebCLException::COMPILER_NOT_AVAILABLE, WebCLException::compilerNotAvailableMessage); + break; + case CL_MEM_OBJECT_ALLOCATION_FAILURE: + es.throwWebCLException(WebCLException::MEM_OBJECT_ALLOCATION_FAILURE, WebCLException::memObjectAllocationFailureMessage); + break; + case CL_OUT_OF_RESOURCES: + es.throwWebCLException(WebCLException::OUT_OF_RESOURCES, WebCLException::outOfResourcesMessage); + break; + case CL_OUT_OF_HOST_MEMORY: + es.throwWebCLException(WebCLException::OUT_OF_HOST_MEMORY, WebCLException::outOfHostMemoryMessage); + break; + case CL_PROFILING_INFO_NOT_AVAILABLE: + es.throwWebCLException(WebCLException::PROFILING_INFO_NOT_AVAILABLE, WebCLException::profilingInfoNotAvailableMessage); + break; + case CL_MEM_COPY_OVERLAP: + es.throwWebCLException(WebCLException::MEM_OBJECT_ALLOCATION_FAILURE, WebCLException::memObjectAllocationFailureMessage); + break; + case CL_IMAGE_FORMAT_MISMATCH: + es.throwWebCLException(WebCLException::IMAGE_FORMAT_MISMATCH, WebCLException::imageFormatMismatchMessage); + break; + case CL_IMAGE_FORMAT_NOT_SUPPORTED: + es.throwWebCLException(WebCLException::IMAGE_FORMAT_NOT_SUPPORTED, WebCLException::imageFormatNotSupportedMessage); + break; + case CL_BUILD_PROGRAM_FAILURE: + es.throwWebCLException(WebCLException::BUILD_PROGRAM_FAILURE, WebCLException::buildProgramFailureMessage); + break; + case CL_MAP_FAILURE: + es.throwWebCLException(WebCLException::MAP_FAILURE, WebCLException::mapFailureMessage); + break; + case CL_MISALIGNED_SUB_BUFFER_OFFSET: + es.throwWebCLException(WebCLException::MISALIGNED_SUB_BUFFER_OFFSET, WebCLException::misalignedSubBufferOffsetMessage); + break; + case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST: + es.throwWebCLException(WebCLException::EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, WebCLException::execStatusErrorForEventsInWaitListMessage); + break; + case CL_INVALID_VALUE: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + break; + case CL_INVALID_DEVICE_TYPE: + es.throwWebCLException(WebCLException::INVALID_DEVICE_TYPE, WebCLException::invalidDeviceTypeMessage); + break; + case CL_INVALID_PLATFORM: + es.throwWebCLException(WebCLException::INVALID_PLATFORM, WebCLException::invalidPlatformMessage); + break; + case CL_INVALID_DEVICE: + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + break; + case CL_INVALID_CONTEXT: + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + break; + case CL_INVALID_QUEUE_PROPERTIES: + es.throwWebCLException(WebCLException::INVALID_QUEUE_PROPERTIES, WebCLException::invalidQueuePropertiesMessage); + break; + case CL_INVALID_COMMAND_QUEUE: + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + break; + case CL_INVALID_HOST_PTR: + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + break; + case CL_INVALID_MEM_OBJECT: + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidHostPTRMessage); + break; + case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: + es.throwWebCLException(WebCLException::INVALID_IMAGE_FORMAT_DESCRIPTOR, WebCLException::invalidImageFormatDescriptorMessage); + break; + case CL_INVALID_IMAGE_SIZE: + es.throwWebCLException(WebCLException::INVALID_IMAGE_SIZE, WebCLException::invalidImageSizeMessage); + break; + case CL_INVALID_SAMPLER: + es.throwWebCLException(WebCLException::INVALID_SAMPLER, WebCLException::invalidSamplerMessage); + break; + case CL_INVALID_BINARY: + es.throwWebCLException(WebCLException::INVALID_BINARY, WebCLException::invalidBinaryMessage); + break; + case CL_INVALID_BUILD_OPTIONS: + es.throwWebCLException(WebCLException::INVALID_BUILD_OPTIONS, WebCLException::invalidBuildOptionsMessage); + break; + case CL_INVALID_PROGRAM: + es.throwWebCLException(WebCLException::INVALID_PROGRAM, WebCLException::invalidProgramMessage); + break; + case CL_INVALID_PROGRAM_EXECUTABLE: + es.throwWebCLException(WebCLException::INVALID_PROGRAM_EXECUTABLE, WebCLException::invalidProgramExecutableMessage); + break; + case CL_INVALID_KERNEL_NAME: + es.throwWebCLException(WebCLException::INVALID_KERNEL_NAME, WebCLException::invalidKernelNameMessage); + break; + case CL_INVALID_KERNEL_DEFINITION: + es.throwWebCLException(WebCLException::INVALID_KERNEL_DEFINITION, WebCLException::invalidKernelDefinitionMessage); + break; + case CL_INVALID_KERNEL: + es.throwWebCLException(WebCLException::INVALID_KERNEL, WebCLException::invalidKernelMessage); + break; + case CL_INVALID_ARG_INDEX: + es.throwWebCLException(WebCLException::INVALID_ARG_INDEX, WebCLException::invalidKernelArgsMessage); + break; + case CL_INVALID_ARG_VALUE: + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + break; + case CL_INVALID_ARG_SIZE: + es.throwWebCLException(WebCLException::INVALID_ARG_SIZE, WebCLException::invalidArgSizeMessage); + break; + case CL_INVALID_KERNEL_ARGS: + es.throwWebCLException(WebCLException::INVALID_KERNEL_ARGS, WebCLException::invalidKernelArgsMessage); + break; + case CL_INVALID_WORK_DIMENSION: + es.throwWebCLException(WebCLException::INVALID_WORK_DIMENSION, WebCLException::invalidWorkDimensionMessage); + break; + case CL_INVALID_WORK_GROUP_SIZE: + es.throwWebCLException(WebCLException::INVALID_WORK_GROUP_SIZE, WebCLException::invalidWorkGroupSizeMessage); + break; + case CL_INVALID_WORK_ITEM_SIZE: + es.throwWebCLException(WebCLException::INVALID_WORK_ITEM_SIZE, WebCLException::invalidWorkItemSizeMessage); + break; + case CL_INVALID_GLOBAL_OFFSET: + es.throwWebCLException(WebCLException::INVALID_GLOBAL_OFFSET, WebCLException::invalidGlobalWorkSizeMessage); + break; + case CL_INVALID_EVENT_WAIT_LIST: + es.throwWebCLException(WebCLException::INVALID_EVENT_WAIT_LIST, WebCLException::invalidEventWaitListMessage); + break; + case CL_INVALID_EVENT: + es.throwWebCLException(WebCLException::INVALID_EVENT, WebCLException::invalidEventMessage); + break; + case CL_INVALID_OPERATION: + es.throwWebCLException(WebCLException::INVALID_OPERATION, WebCLException::invalidOperationMessage); + break; + case CL_INVALID_GL_OBJECT: + es.throwWebCLException(WebCLException::INVALID_GL_OBJECT, WebCLException::invalidGLObjectMessage); + break; + case CL_INVALID_BUFFER_SIZE: + es.throwWebCLException(WebCLException::INVALID_BUFFER_SIZE, WebCLException::invalidBufferSizeMessage); + break; + case CL_INVALID_MIP_LEVEL: + es.throwWebCLException(WebCLException::INVALID_MIP_LEVEL, WebCLException::invalidMIPLevelMessage); + break; + case CL_INVALID_GLOBAL_WORK_SIZE: + es.throwWebCLException(WebCLException::INVALID_GLOBAL_WORK_SIZE, WebCLException::invalidGlobalWorkSizeMessage); + break; + case CL_INVALID_PROPERTY: + es.throwWebCLException(WebCLException::INVALID_PROPERTY, WebCLException::invalidPropertyMessage); + break; + default: + es.throwWebCLException(WebCLException::FAILURE, WebCLException::failureMessage); + break; + } + + if (es.hadException()) + es.throwIfNeeded(); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/core/webcl/WebCLException.h b/third_party/WebKit/Source/core/webcl/WebCLException.h new file mode 100644 index 0000000000000..759ce8e823b03 --- /dev/null +++ b/third_party/WebKit/Source/core/webcl/WebCLException.h @@ -0,0 +1,153 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLException_h +#define WebCLException_h + +#include "bindings/core/v8/ExceptionState.h" +#include "bindings/core/v8/ScriptWrappable.h" +#include + +#define WEBCLEXCEPTIONOFFSET 0 + +namespace blink { + +class WebCLException : public ThreadSafeRefCounted, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + static PassRefPtr create(unsigned code, const String& name, const String& message) + { + return adoptRef(new WebCLException(code, name, message)); + } + + enum WebCLExceptionCode { + SUCCESS = WEBCLEXCEPTIONOFFSET, + DEVICE_NOT_FOUND = WEBCLEXCEPTIONOFFSET + 1, + DEVICE_NOT_AVAILABLE = WEBCLEXCEPTIONOFFSET + 2, + COMPILER_NOT_AVAILABLE = WEBCLEXCEPTIONOFFSET + 3, + MEM_OBJECT_ALLOCATION_FAILURE = WEBCLEXCEPTIONOFFSET + 4, + OUT_OF_RESOURCES = WEBCLEXCEPTIONOFFSET + 5, + OUT_OF_HOST_MEMORY = WEBCLEXCEPTIONOFFSET + 6, + PROFILING_INFO_NOT_AVAILABLE = WEBCLEXCEPTIONOFFSET + 7, + MEM_COPY_OVERLAP = WEBCLEXCEPTIONOFFSET + 8, + IMAGE_FORMAT_MISMATCH = WEBCLEXCEPTIONOFFSET + 9, + IMAGE_FORMAT_NOT_SUPPORTED = WEBCLEXCEPTIONOFFSET + 10, + BUILD_PROGRAM_FAILURE = WEBCLEXCEPTIONOFFSET + 11, + MAP_FAILURE = WEBCLEXCEPTIONOFFSET + 12, + MISALIGNED_SUB_BUFFER_OFFSET = WEBCLEXCEPTIONOFFSET + 13, + EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST = WEBCLEXCEPTIONOFFSET + 14, + EXTENSION_NOT_ENABLED = WEBCLEXCEPTIONOFFSET + 15, + + INVALID_VALUE = WEBCLEXCEPTIONOFFSET + 30, + INVALID_DEVICE_TYPE = WEBCLEXCEPTIONOFFSET + 31, + INVALID_PLATFORM = WEBCLEXCEPTIONOFFSET + 32, + INVALID_DEVICE = WEBCLEXCEPTIONOFFSET + 33, + INVALID_CONTEXT = WEBCLEXCEPTIONOFFSET + 34, + INVALID_QUEUE_PROPERTIES = WEBCLEXCEPTIONOFFSET + 35, + INVALID_COMMAND_QUEUE = WEBCLEXCEPTIONOFFSET + 36, + INVALID_HOST_PTR = WEBCLEXCEPTIONOFFSET + 37, + INVALID_MEM_OBJECT = WEBCLEXCEPTIONOFFSET + 38, + INVALID_IMAGE_FORMAT_DESCRIPTOR = WEBCLEXCEPTIONOFFSET + 39, + INVALID_IMAGE_SIZE = WEBCLEXCEPTIONOFFSET + 40, + INVALID_SAMPLER = WEBCLEXCEPTIONOFFSET + 41, + INVALID_BINARY = WEBCLEXCEPTIONOFFSET + 42, + INVALID_BUILD_OPTIONS = WEBCLEXCEPTIONOFFSET + 43, + INVALID_PROGRAM = WEBCLEXCEPTIONOFFSET + 44, + INVALID_PROGRAM_EXECUTABLE = WEBCLEXCEPTIONOFFSET + 45, + INVALID_KERNEL_NAME = WEBCLEXCEPTIONOFFSET + 46, + INVALID_KERNEL_DEFINITION = WEBCLEXCEPTIONOFFSET + 47, + INVALID_KERNEL = WEBCLEXCEPTIONOFFSET + 48, + INVALID_ARG_INDEX = WEBCLEXCEPTIONOFFSET + 49, + INVALID_ARG_VALUE = WEBCLEXCEPTIONOFFSET + 50, + INVALID_ARG_SIZE = WEBCLEXCEPTIONOFFSET + 51, + INVALID_KERNEL_ARGS = WEBCLEXCEPTIONOFFSET + 52, + INVALID_WORK_DIMENSION = WEBCLEXCEPTIONOFFSET + 53, + INVALID_WORK_GROUP_SIZE = WEBCLEXCEPTIONOFFSET + 54, + INVALID_WORK_ITEM_SIZE = WEBCLEXCEPTIONOFFSET + 55, + INVALID_GLOBAL_OFFSET = WEBCLEXCEPTIONOFFSET + 56, + INVALID_EVENT_WAIT_LIST = WEBCLEXCEPTIONOFFSET + 57, + INVALID_EVENT = WEBCLEXCEPTIONOFFSET + 58, + INVALID_OPERATION = WEBCLEXCEPTIONOFFSET + 59, + INVALID_GL_OBJECT = WEBCLEXCEPTIONOFFSET + 60, + INVALID_BUFFER_SIZE = WEBCLEXCEPTIONOFFSET + 61, + INVALID_MIP_LEVEL = WEBCLEXCEPTIONOFFSET + 62, + INVALID_GLOBAL_WORK_SIZE = WEBCLEXCEPTIONOFFSET + 63, + INVALID_PROPERTY = WEBCLEXCEPTIONOFFSET + 64, + FAILURE = WEBCLEXCEPTIONOFFSET + 65, + }; + + static const char successMessage[]; + static const char deviceNotFoundMessage[]; + static const char deviceNotAvailableMessage[]; + static const char compilerNotAvailableMessage[]; + static const char memObjectAllocationFailureMessage[]; + static const char outOfResourcesMessage[]; + static const char outOfHostMemoryMessage[]; + static const char profilingInfoNotAvailableMessage[]; + static const char memCopyOverlapMessage[]; + static const char imageFormatMismatchMessage[]; + static const char imageFormatNotSupportedMessage[]; + static const char buildProgramFailureMessage[]; + static const char mapFailureMessage[]; + static const char misalignedSubBufferOffsetMessage[]; + static const char execStatusErrorForEventsInWaitListMessage[]; + static const char extensionNotEnabledMessage[]; + static const char invalidValueMessage[]; + static const char invalidDeviceTypeMessage[]; + static const char invalidPlatformMessage[]; + static const char invalidDeviceMessage[]; + static const char invalidContextMessage[]; + static const char invalidQueuePropertiesMessage[]; + static const char invalidCommandQueueMessage[]; + static const char invalidHostPTRMessage[]; + static const char invalidMemObjectMessage[]; + static const char invalidImageFormatDescriptorMessage[]; + static const char invalidImageSizeMessage[]; + static const char invalidSamplerMessage[]; + static const char invalidBinaryMessage[]; + static const char invalidBuildOptionsMessage[]; + static const char invalidProgramMessage[]; + static const char invalidProgramExecutableMessage[]; + static const char invalidKernelNameMessage[]; + static const char invalidKernelDefinitionMessage[]; + static const char invalidKernelMessage[]; + static const char invalidArgIndexMessage[]; + static const char invalidArgValueMessage[]; + static const char invalidArgSizeMessage[]; + static const char invalidKernelArgsMessage[]; + static const char invalidWorkDimensionMessage[]; + static const char invalidWorkGroupSizeMessage[]; + static const char invalidWorkItemSizeMessage[]; + static const char invalidGlobalOffsetMessage[]; + static const char invalidEventWaitListMessage[]; + static const char invalidEventMessage[]; + static const char invalidOperationMessage[]; + static const char invalidGLObjectMessage[]; + static const char invalidBufferSizeMessage[]; + static const char invalidMIPLevelMessage[]; + static const char invalidGlobalWorkSizeMessage[]; + static const char invalidPropertyMessage[]; + static const char failureMessage[]; + + static void throwException(int& code, ExceptionState& es); + + String name() const { return m_name.isolatedCopy(); } + String message() const { return m_message.isolatedCopy(); } + +private: + WebCLException(unsigned code, const String& name, const String& message) + : m_code(code) + , m_name(name.isolatedCopy()) + , m_message(message.isolatedCopy()) + { + } + unsigned m_code; + String m_name; + String m_message; +}; + +} // namespace blink + +#endif // WebCLException_h diff --git a/third_party/WebKit/Source/core/webcl/WebCLException.idl b/third_party/WebKit/Source/core/webcl/WebCLException.idl new file mode 100644 index 0000000000000..6dadf726d1e00 --- /dev/null +++ b/third_party/WebKit/Source/core/webcl/WebCLException.idl @@ -0,0 +1,8 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +interface WebCLException { + readonly attribute DOMString name; + readonly attribute DOMString message; +}; diff --git a/third_party/WebKit/Source/modules/modules.gypi b/third_party/WebKit/Source/modules/modules.gypi index e0ce698cdcf0d..992667f64d240 100644 --- a/third_party/WebKit/Source/modules/modules.gypi +++ b/third_party/WebKit/Source/modules/modules.gypi @@ -229,6 +229,21 @@ 'webaudio/ScriptProcessorNode.idl', 'webaudio/StereoPannerNode.idl', 'webaudio/WaveShaperNode.idl', + 'webcl/WebCL.idl', + 'webcl/WebCLBuffer.idl', + 'webcl/WebCLCallback.idl', + 'webcl/WebCLCommandQueue.idl', + 'webcl/WebCLContext.idl', + 'webcl/WebCLDevice.idl', + 'webcl/WebCLEvent.idl', + 'webcl/WebCLImage.idl', + 'webcl/WebCLKernel.idl', + 'webcl/WebCLKernelArgInfo.idl', + 'webcl/WebCLMemoryObject.idl', + 'webcl/WebCLPlatform.idl', + 'webcl/WebCLProgram.idl', + 'webcl/WebCLSampler.idl', + 'webcl/WebCLUserEvent.idl', 'webdatabase/Database.idl', 'webdatabase/DatabaseCallback.idl', 'webdatabase/SQLError.idl', @@ -360,6 +375,7 @@ 'vibration/NavigatorVibration.idl', 'vr/NavigatorVRDevice.idl', 'webaudio/WindowWebAudio.idl', + 'webcl/WindowWebCL.idl', 'webdatabase/WindowWebDatabase.idl', 'webgl/WebGL2RenderingContextBase.idl', 'webgl/WebGLRenderingContextBase.idl', @@ -459,6 +475,7 @@ 'speech/SpeechRecognitionEventInit.idl', 'storage/StorageEventInit.idl', 'vr/VRFieldOfViewInit.idl', + 'webcl/WebCLImageDescriptor.idl', 'webgl/WebGLContextAttributes.idl', 'webgl/WebGLContextEventInit.idl', 'webmidi/MIDIConnectionEventInit.idl', @@ -588,6 +605,8 @@ '<(blink_modules_output_dir)/storage/StorageEventInit.h', '<(blink_modules_output_dir)/vr/VRFieldOfViewInit.cpp', '<(blink_modules_output_dir)/vr/VRFieldOfViewInit.h', + '<(blink_modules_output_dir)/webcl/WebCLImageDescriptor.cpp', + '<(blink_modules_output_dir)/webcl/WebCLImageDescriptor.h', '<(blink_modules_output_dir)/webgl/WebGLContextAttributes.cpp', '<(blink_modules_output_dir)/webgl/WebGLContextAttributes.h', '<(blink_modules_output_dir)/webgl/WebGLContextEventInit.cpp', @@ -1459,6 +1478,51 @@ 'webaudio/WaveShaperNode.h', 'webaudio/WaveShaperProcessor.cpp', 'webaudio/WaveShaperProcessor.h', + 'webcl/DOMWindowWebCL.cpp', + 'webcl/DOMWindowWebCL.h', + 'webcl/WebCL.cpp', + 'webcl/WebCL.h', + 'webcl/WebCLBuffer.cpp', + 'webcl/WebCLBuffer.h', + 'webcl/WebCLCallback.h', + 'webcl/WebCLCommandQueue.cpp', + 'webcl/WebCLCommandQueue.h', + 'webcl/WebCLConfig.h', + 'webcl/WebCLContext.cpp', + 'webcl/WebCLContext.h', + 'webcl/WebCLDevice.cpp', + 'webcl/WebCLDevice.h', + 'webcl/WebCLEvent.cpp', + 'webcl/WebCLEvent.h', + 'webcl/WebCLExtension.cpp', + 'webcl/WebCLExtension.h', + 'webcl/WebCLHTMLUtil.cpp', + 'webcl/WebCLHTMLUtil.h', + 'webcl/WebCLImage.cpp', + 'webcl/WebCLImage.h', + 'webcl/WebCLInputChecker.cpp', + 'webcl/WebCLInputChecker.h', + 'webcl/WebCLKernel.cpp', + 'webcl/WebCLKernel.h', + 'webcl/WebCLKernelArgInfo.h', + 'webcl/WebCLKernelArgInfoProvider.cpp', + 'webcl/WebCLKernelArgInfoProvider.h', + 'webcl/WebCLMemoryObject.cpp', + 'webcl/WebCLMemoryObject.h', + 'webcl/WebCLMemoryUtil.cpp', + 'webcl/WebCLMemoryUtil.h', + 'webcl/WebCLObject.cpp', + 'webcl/WebCLObject.h', + 'webcl/WebCLOpenCL.cpp', + 'webcl/WebCLOpenCL.h', + 'webcl/WebCLPlatform.cpp', + 'webcl/WebCLPlatform.h', + 'webcl/WebCLProgram.cpp', + 'webcl/WebCLProgram.h', + 'webcl/WebCLSampler.cpp', + 'webcl/WebCLSampler.h', + 'webcl/WebCLUserEvent.cpp', + 'webcl/WebCLUserEvent.h', 'webdatabase/ChangeVersionData.h', 'webdatabase/ChangeVersionWrapper.cpp', 'webdatabase/ChangeVersionWrapper.h', diff --git a/third_party/WebKit/Source/modules/webcl/DOMWindowWebCL.cpp b/third_party/WebKit/Source/modules/webcl/DOMWindowWebCL.cpp new file mode 100644 index 0000000000000..165fe20bda20f --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/DOMWindowWebCL.cpp @@ -0,0 +1,77 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#if ENABLE(WEBCL) + +#include "core/dom/Document.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/page/Page.h" +#include "DOMWindowWebCL.h" +#include "modules/webcl/WebCL.h" + +namespace blink { + +DOMWindowWebCL::DOMWindowWebCL(LocalDOMWindow& window) + : DOMWindowProperty(window.frame()) + , m_window(window) +{ +} + +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(DOMWindowWebCL); + +void DOMWindowWebCL::trace(Visitor* visitor) +{ + visitor->trace(m_webcl); + WillBeHeapSupplement::trace(visitor); + DOMWindowProperty::trace(visitor); +} + +DOMWindowWebCL& DOMWindowWebCL::from(LocalDOMWindow& window) +{ + DOMWindowWebCL* supplement = static_cast(WillBeHeapSupplement::from(window, supplementName())); + if (!supplement) { + supplement = new DOMWindowWebCL(window); + provideTo(window, supplementName(), adoptPtrWillBeNoop(supplement)); + } + + return *supplement; +} + +void DOMWindowWebCL::willDestroyGlobalObjectInFrame() +{ + m_webcl = nullptr; + DOMWindowProperty::willDestroyGlobalObjectInFrame(); +} + +void DOMWindowWebCL::willDetachGlobalObjectFromFrame() +{ + m_webcl = nullptr; + DOMWindowProperty::willDetachGlobalObjectFromFrame(); +} + +WebCL* DOMWindowWebCL::webcl(DOMWindow& window) +{ + return from(toLocalDOMWindow(window)).webcl(); +} + +WebCL* DOMWindowWebCL::webcl() +{ + if (!m_window.document() || !m_window.document()->page()) + return nullptr; + + if (!m_webcl) + m_webcl = WebCL::create(); + + return m_webcl.get(); +} + +const char* DOMWindowWebCL::supplementName() +{ + return "DOMWindowWebCL"; +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/DOMWindowWebCL.h b/third_party/WebKit/Source/modules/webcl/DOMWindowWebCL.h new file mode 100644 index 0000000000000..a0726eb007a16 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/DOMWindowWebCL.h @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DOMWindowWebCL_h +#define DOMWindowWebCL_h + +#if ENABLE(WEBCL) +#include "core/frame/DOMWindowProperty.h" +#include "platform/Supplementable.h" + +namespace blink { + +class LocalDOMWindow; +class WebCL; + +class DOMWindowWebCL : public NoBaseWillBeGarbageCollected, public WillBeHeapSupplement, public DOMWindowProperty { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(DOMWindowWebCL); + DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(DOMWindowWebCL); +public: + static DOMWindowWebCL& from(LocalDOMWindow&); + static WebCL* webcl(DOMWindow&); + + void willDestroyGlobalObjectInFrame() override; + void willDetachGlobalObjectFromFrame() override; + + void trace(Visitor*); + +private: + explicit DOMWindowWebCL(LocalDOMWindow&); + + WebCL* webcl(); + static const char* supplementName(); + + LocalDOMWindow& m_window; + RefPtr m_webcl; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // DOMWindowWebCL_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCL.cpp b/third_party/WebKit/Source/modules/webcl/WebCL.cpp new file mode 100644 index 0000000000000..68278f17cc534 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCL.cpp @@ -0,0 +1,413 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLCallback.h" +#include "modules/webcl/WebCLCommandQueue.h" +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLDevice.h" +#include "modules/webcl/WebCLExtension.h" +#include "modules/webcl/WebCLEvent.h" +#include "modules/webcl/WebCLImage.h" +#include "modules/webcl/WebCLInputChecker.h" +#include "modules/webcl/WebCLKernel.h" +#include "modules/webcl/WebCLMemoryObject.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLPlatform.h" +#include "modules/webcl/WebCLProgram.h" +#include "modules/webcl/WebCLSampler.h" +#include "platform/ThreadSafeFunctional.h" +#include "public/platform/Platform.h" +#include "public/platform/WebTraceLocation.h" +#include + +namespace blink { + +// The holder of WebCL. +class WebCLHolder { +public: + cl_event event; + cl_int type; + WeakPtr webcl; +}; + +static inline void getAllEnabledExtensions(WebCL* cl, PassRefPtr platform, const Vector>& devices, HashSet& enabledExtensions) +{ + cl->getEnabledExtensions(enabledExtensions); + platform->getEnabledExtensions(enabledExtensions); + + for (auto device : devices) + device->getEnabledExtensions(enabledExtensions); +} + +PassRefPtr WebCL::create() +{ + static bool libraryLoaded = false; + /* load libs in lib list. */ + if (!libraryLoaded) { + if (init(nullptr, 0)) + libraryLoaded = true; + } + + return libraryLoaded ? adoptRef(new WebCL()) : nullptr; +} + +WebCL::~WebCL() +{ + releaseAll(); +} + +Vector> WebCL::getPlatforms(ExceptionState& es) +{ + if (!m_platforms.size()) { + es.throwWebCLException(WebCLException::INVALID_PLATFORM, WebCLException::invalidPlatformMessage); + return Vector>(); + } + + return m_platforms; +} + +static void validateWebCLEventList(const Vector>& events, ExceptionState& es, bool isSyncCall) +{ + if (!events.size()) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + if (events[0]->isReleased() || (events[0]->isUserEvent() && isSyncCall)) { + es.throwWebCLException(WebCLException::INVALID_EVENT_WAIT_LIST, WebCLException::invalidEventWaitListMessage); + return; + } + + if ((!events[0]->isUserEvent() && events[0]->getStatus() == CL_INVALID_VALUE) || + (events[0]->isUserEvent() && events[0]->getStatus() < CL_SUCCESS)) { + es.throwWebCLException(WebCLException::EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, WebCLException::execStatusErrorForEventsInWaitListMessage); + return; + } + + WebCLContext* referenceContext = events[0]->context(); + + for (auto event : events) { + if (event->isReleased() || (event->isUserEvent() && isSyncCall)) { + es.throwWebCLException(WebCLException::INVALID_EVENT_WAIT_LIST, WebCLException::invalidEventWaitListMessage); + return; + } + + ASSERT(event->context()); + if (!WebCLInputChecker::compareContext(event->context(), referenceContext)) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if ((!event->isUserEvent() && event->getStatus() == CL_INVALID_VALUE) || + (event->isUserEvent() && event->getStatus() < CL_SUCCESS)) { + es.throwWebCLException(WebCLException::EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, WebCLException::execStatusErrorForEventsInWaitListMessage); + return; + } + } +} + +PassRefPtr WebCL::createContext(ExceptionState& es) +{ + return createContext(CL_DEVICE_TYPE_DEFAULT, es); +} + +PassRefPtr WebCL::createContext(unsigned deviceType, ExceptionState& es) +{ + if (!m_platforms.size()) + return nullptr; + + return createContext(m_platforms[0].get(), deviceType, es); +} + +PassRefPtr WebCL::createContext(WebCLPlatform* platform, ExceptionState& es) +{ + return createContext(platform, CL_DEVICE_TYPE_DEFAULT, es); +} + +PassRefPtr WebCL::createContext(WebCLPlatform* platform, unsigned deviceType, ExceptionState& es) +{ + if (!platform) { + es.throwWebCLException(WebCLException::INVALID_PLATFORM, WebCLException::invalidPlatformMessage); + return nullptr; + } + + if (!WebCLInputChecker::isValidDeviceType(deviceType)) { + es.throwWebCLException(WebCLException::INVALID_DEVICE_TYPE, WebCLException::invalidDeviceTypeMessage); + return nullptr; + } + + Vector> devices = platform->getDevices(deviceType, es); + Vector clDevices; + for (auto device : devices) + clDevices.append(device->getDeviceId()); + + if (!clDevices.size()) { + es.throwWebCLException(WebCLException::DEVICE_NOT_FOUND, WebCLException::deviceNotFoundMessage); + return nullptr; + } + + cl_int err = CL_SUCCESS; + cl_context clContextId = clCreateContext(nullptr, clDevices.size(), clDevices.data(), nullptr, nullptr, &err); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + + // Check all the enabled extensions and cache it to avoid enabling after context creation. + HashSet enabledExtensions; + getAllEnabledExtensions(this, platform, devices, enabledExtensions); + RefPtr context = WebCLContext::create(clContextId, this, devices, enabledExtensions); + if (!context) { + es.throwWebCLException(WebCLException::FAILURE, WebCLException::failureMessage); + return nullptr; + } + return context; +} + +PassRefPtr WebCL::createContext(WebCLDevice* device, ExceptionState& es) +{ + Vector> devices; + devices.append(device); + return createContext(devices, es); +} + +PassRefPtr WebCL::createContext(const Vector>& devices, ExceptionState& es) +{ + cl_int err = CL_SUCCESS; + cl_context clContextId = 0; + + if (!devices.size()) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + Vector clDeviceList; + for (auto device : devices) + clDeviceList.append(device->getDeviceId()); + + if (!clDeviceList.size()) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return nullptr; + } + + clContextId = clCreateContext(nullptr, clDeviceList.size(), clDeviceList.data(), nullptr, nullptr, &err); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + + // Check all the enabled extensions and cache it to avoid enabling after context creation. + HashSet enabledExtensions; + getAllEnabledExtensions(this, devices[0]->getPlatform(), devices, enabledExtensions); + RefPtr context = WebCLContext::create(clContextId, this, devices, enabledExtensions); + if (!context) { + es.throwWebCLException(WebCLException::FAILURE, WebCLException::failureMessage); + return nullptr; + } + + return context; +} + +void WebCL::waitForEvents(const Vector>& events, WebCLCallback* whenFinished, ExceptionState& es) +{ + validateWebCLEventList(events, es, !whenFinished); + if (es.hadException()) { + es.throwIfNeeded(); + return; + } + + waitForEventsImpl(events, whenFinished); +} + +void WebCL::releaseAll() +{ + if (m_webCLContexts.size()) { + for (int i = m_webCLContexts.size() - 1; i >= 0; i--) { + WebCLContext* context = m_webCLContexts[i].get(); + if (!context) + continue; + + context->releaseAll(); + } + m_webCLContexts.clear(); + } +} + +void WebCL::trackReleaseableWebCLContext(WeakPtr context) +{ + m_webCLContexts.append(context); +} + +bool WebCL::enableExtension(const String& name) +{ + return m_extension.enableExtension(name); +} + +Vector WebCL::getSupportedExtensions() +{ + return m_extension.getSupportedExtensions(); +} + +void WebCL::getEnabledExtensions(HashSet& extensions) +{ + m_extension.getEnabledExtensions(extensions); +} + +WebCL::WebCL() + : m_weakFactory(this) +{ + cachePlatforms(); + cacheSupportedExtensions(); +} + +Vector> WebCL::updateCallbacksFromCLEvent(cl_event event) +{ + Vector> callbacks; + if (m_callbackRegisterQueue.size()) { + for (int i = m_callbackRegisterQueue.size() - 1; i >= 0; i--) { + if (m_callbackRegisterQueue[i].first.size()) { + for (int j = m_callbackRegisterQueue[i].first.size() - 1; j >= 0; j--) { + WebCLEvent* webEvent = static_cast(m_callbackRegisterQueue[i].first[j].get()); + if (webEvent && event == webEvent->getEvent()) + m_callbackRegisterQueue[i].first.remove(j); + } + + if (!m_callbackRegisterQueue[i].first.size()) { + callbacks.append(m_callbackRegisterQueue[i].second); + m_callbackRegisterQueue.remove(i); + } + } + } + } + + return callbacks; +} + +void WebCL::callbackProxy(cl_event event, cl_int type, void* userData) +{ + OwnPtr holder = adoptPtr(static_cast(userData)); + holder->event = event; + holder->type = type; + + if (!isMainThread()) { + Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&WebCL::callbackProxyOnMainThread, holder.release())); + return; + } + + callbackProxyOnMainThread(holder.release()); +} + +void WebCL::callbackProxyOnMainThread(PassOwnPtr holder) +{ + ASSERT(isMainThread()); + RefPtr webcl(holder->webcl.get()); + cl_event event = holder->event; + cl_int type = holder->type; + + // Ignore the callback if the WebCL is destructed. + if (!webcl) + return; + + Vector> callbacks = webcl->updateCallbacksFromCLEvent(event); + // Ignore the callback if the OpenCL event is abnormally terminated. + if (type != CL_COMPLETE) { + return; + } + + for (auto callback : callbacks) { + if (callback) + callback->handleEvent(); + } +} + +void WebCL::waitForEventsImpl(const Vector>& events, WebCLCallback* callback) +{ + Vector clEvents; + Vector> webEvents; + WebCLHolder* holder = new WebCLHolder; + holder->webcl = m_weakFactory.createWeakPtr(); + + for (auto event : events) { + clEvents.append(event->getEvent()); + webEvents.append(event->createWeakPtr()); + } + + if (!callback) { + clWaitForEvents(clEvents.size(), clEvents.data()); + } else { + m_callbackRegisterQueue.append(std::make_pair(webEvents, adoptRef(callback))); + for (auto clEvent : clEvents) + clSetEventCallback(clEvent, CL_COMPLETE, &callbackProxy, holder); + } +} + +void WebCL::cachePlatforms() +{ + if (m_platforms.size() > 0) + return; + + cl_uint numPlatforms = 0; + cl_int err = clGetPlatformIDs(0, nullptr, &numPlatforms); + + if (err != CL_SUCCESS) + return; + + Vector clPlatforms; + clPlatforms.resize(numPlatforms); + err = clGetPlatformIDs(numPlatforms, clPlatforms.data(), nullptr); + if (err != CL_SUCCESS) + return; + + for (auto clPlatform : clPlatforms) { + RefPtr platform = WebCLPlatform::create(clPlatform); + if (platform) + m_platforms.append(platform); + } + clPlatforms.clear(); +} + +void WebCL::cacheSupportedExtensions() +{ + if (!m_platforms.size()) + return; + + Vector supportedExtensions = m_platforms[0]->getSupportedExtensions(); + if (m_platforms.size() == 1) { + // If there is only one platform, WebCL extensions is equal to this platform's extension. + return; + } + + for (auto platform : m_platforms) { + Vector temporary = platform->getSupportedExtensions(); + + Vector toBeRemoved; + for (auto supportedExtension : supportedExtensions) { + Vector::iterator iter = temporary.begin(); + for (; iter != temporary.end(); ++iter) { + if (supportedExtension == *iter) + break; + } + if (iter == temporary.end()) + toBeRemoved.append(supportedExtension); + } + + for (auto stringToBeRemoved : toBeRemoved) + supportedExtensions.remove(supportedExtensions.find(stringToBeRemoved)); + } + + for (auto supportedExtension : supportedExtensions) + m_extension.addSupportedCLExtension(supportedExtension); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCL.h b/third_party/WebKit/Source/modules/webcl/WebCL.h new file mode 100644 index 0000000000000..19e25a1abc939 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCL.h @@ -0,0 +1,84 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCL_h +#define WebCL_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLCallback.h" +#include "modules/webcl/WebCLCommandQueue.h" +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLDevice.h" +#include "modules/webcl/WebCLExtension.h" +#include "modules/webcl/WebCLEvent.h" +#include "modules/webcl/WebCLImage.h" +#include "modules/webcl/WebCLInputChecker.h" +#include "modules/webcl/WebCLKernel.h" +#include "modules/webcl/WebCLMemoryObject.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLPlatform.h" +#include "modules/webcl/WebCLProgram.h" +#include "modules/webcl/WebCLSampler.h" + +#include +#include +#include +#include +#include +#include + +namespace blink { + +typedef unsigned CLenum; +class ExceptionState; +class ExecutionContext; +class WebCLHolder; + +class WebCL : public RefCounted, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCL(); + static PassRefPtr create(); + + Vector> getPlatforms(ExceptionState&); + PassRefPtr createContext(ExceptionState&); + PassRefPtr createContext(unsigned, ExceptionState&); + PassRefPtr createContext(WebCLPlatform*, ExceptionState&); + PassRefPtr createContext(WebCLPlatform*, unsigned, ExceptionState&); + PassRefPtr createContext(WebCLDevice*, ExceptionState&); + PassRefPtr createContext(const Vector>&, ExceptionState&); + void waitForEvents(const Vector>&, WebCLCallback*, ExceptionState&); + void releaseAll(); + void trackReleaseableWebCLContext(WeakPtr); + bool enableExtension(const String& name); + Vector getSupportedExtensions(); + void getEnabledExtensions(HashSet& extensions); + +private: + WebCL(); + static void callbackProxy(cl_event, cl_int, void*); + static void callbackProxyOnMainThread(PassOwnPtr); + void waitForEventsImpl(const Vector>&, WebCLCallback*); + void cachePlatforms(); + void cacheSupportedExtensions(); + // Update the m_callbackRegisterQueue according to OpenCL event, and + // get the WebCLCallback list if OpenCL event becomes CL_COMPLETE. + Vector> updateCallbacksFromCLEvent(cl_event); + + Vector> m_platforms; + WebCLExtension m_extension; + Vector> m_webCLContexts; + + typedef Vector>, RefPtr>> WebCLCallbackRegisterQueue; + // It contains every un-triggered WebCLCallback and corresponding WebCLEvent list. + WebCLCallbackRegisterQueue m_callbackRegisterQueue; + WeakPtrFactory m_weakFactory; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCL_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCL.idl b/third_party/WebKit/Source/modules/webcl/WebCL.idl new file mode 100644 index 0000000000000..4590cd58ceb42 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCL.idl @@ -0,0 +1,347 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef boolean CLboolean; +typedef long CLint; // 32-bit signed integer +typedef unsigned long CLuint; // 32-bit unsigned integer +typedef long long CLlong; // 64-bit signed integer +typedef unsigned long long CLulong; // 64-bit unsigned integer +typedef unsigned long CLenum; // Used for enumerated types, such as WebCL.DEVICE_TYPE_GPU + +[ + Conditional=WEBCL, + NoInterfaceObject, + DoNotCheckConstants +] interface WebCL { + /* Error Codes */ + const CLint SUCCESS = 0; + const CLint DEVICE_NOT_FOUND = -1; + const CLint DEVICE_NOT_AVAILABLE = -2; + const CLint COMPILER_NOT_AVAILABLE = -3; + const CLint MEM_OBJECT_ALLOCATION_FAILURE = -4; + const CLint OUT_OF_RESOURCES = -5; + const CLint OUT_OF_HOST_MEMORY = -6; + const CLint PROFILING_INFO_NOT_AVAILABLE = -7; + const CLint MEM_COPY_OVERLAP = -8; + const CLint IMAGE_FORMAT_MISMATCH = -9; + const CLint IMAGE_FORMAT_NOT_SUPPORTED = -10; + const CLint BUILD_PROGRAM_FAILURE = -11; + const CLint MAP_FAILURE = -12; + const CLint MISALIGNED_SUB_BUFFER_OFFSET = -13; + const CLint EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST = -14; + + const CLint INVALID_VALUE = -30; + const CLint INVALID_DEVICE_TYPE = -31; + const CLint INVALID_PLATFORM = -32; + const CLint INVALID_DEVICE = -33; + const CLint INVALID_CONTEXT = -34; + const CLint INVALID_QUEUE_PROPERTIES = -35; + const CLint INVALID_COMMAND_QUEUE = -36; + const CLint INVALID_HOST_PTR = -37; + const CLint INVALID_MEM_OBJECT = -38; + const CLint INVALID_IMAGE_FORMAT_DESCRIPTOR = -39; + const CLint INVALID_IMAGE_SIZE = -40; + const CLint INVALID_SAMPLER = -41; + const CLint INVALID_BINARY = -42; + const CLint INVALID_BUILD_OPTIONS = -43; + const CLint INVALID_PROGRAM = -44; + const CLint INVALID_PROGRAM_EXECUTABLE = -45; + const CLint INVALID_KERNEL_NAME = -46; + const CLint INVALID_KERNEL_DEFINITION = -47; + const CLint INVALID_KERNEL = -48; + const CLint INVALID_ARG_INDEX = -49; + const CLint INVALID_ARG_VALUE = -50; + const CLint INVALID_ARG_SIZE = -51; + const CLint INVALID_KERNEL_ARGS = -52; + const CLint INVALID_WORK_DIMENSION = -53; + const CLint INVALID_WORK_GROUP_SIZE = -54; + const CLint INVALID_WORK_ITEM_SIZE = -55; + const CLint INVALID_GLOBAL_OFFSET = -56; + const CLint INVALID_EVENT_WAIT_LIST = -57; + const CLint INVALID_EVENT = -58; + const CLint INVALID_OPERATION = -59; + const CLint INVALID_BUFFER_SIZE = -61; + const CLint INVALID_GLOBAL_WORK_SIZE = -63; + const CLint INVALID_PROPERTY = -64; + + /* cl_bool */ + const CLenum FALSE = 0; + const CLenum TRUE = 1; + + /* cl_platform_info */ + const CLenum PLATFORM_PROFILE = 0x0900; + const CLenum PLATFORM_VERSION = 0x0901; + const CLenum PLATFORM_NAME = 0x0902; + const CLenum PLATFORM_VENDOR = 0x0903; + const CLenum PLATFORM_EXTENSIONS = 0x0904; + + /* cl_device_type - bitfield */ + const CLenum DEVICE_TYPE_DEFAULT = 0x1; // (1 << 0); + const CLenum DEVICE_TYPE_CPU = 0x2; // (1 << 1); + const CLenum DEVICE_TYPE_GPU = 0x4; // (1 << 2); + const CLenum DEVICE_TYPE_ACCELERATOR = 0x8; // (1 << 3); + const CLenum DEVICE_TYPE_ALL = 0xFFFFFFFF; + + /* cl_device_info */ + const CLenum DEVICE_TYPE = 0x1000; + const CLenum DEVICE_VENDOR_ID = 0x1001; + const CLenum DEVICE_MAX_COMPUTE_UNITS = 0x1002; + const CLenum DEVICE_MAX_WORK_ITEM_DIMENSIONS = 0x1003; + const CLenum DEVICE_MAX_WORK_GROUP_SIZE = 0x1004; + const CLenum DEVICE_MAX_WORK_ITEM_SIZES = 0x1005; + const CLenum DEVICE_PREFERRED_VECTOR_WIDTH_CHAR = 0x1006; + const CLenum DEVICE_PREFERRED_VECTOR_WIDTH_SHORT = 0x1007; + const CLenum DEVICE_PREFERRED_VECTOR_WIDTH_INT = 0x1008; + const CLenum DEVICE_PREFERRED_VECTOR_WIDTH_LONG = 0x1009; + const CLenum DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT = 0x100A; + const CLenum DEVICE_MAX_CLOCK_FREQUENCY = 0x100C; + const CLenum DEVICE_ADDRESS_BITS = 0x100D; + const CLenum DEVICE_MAX_READ_IMAGE_ARGS = 0x100E; + const CLenum DEVICE_MAX_WRITE_IMAGE_ARGS = 0x100F; + const CLenum DEVICE_MAX_MEM_ALLOC_SIZE = 0x1010; + const CLenum DEVICE_IMAGE2D_MAX_WIDTH = 0x1011; + const CLenum DEVICE_IMAGE2D_MAX_HEIGHT = 0x1012; + const CLenum DEVICE_IMAGE3D_MAX_WIDTH = 0x1013; + const CLenum DEVICE_IMAGE3D_MAX_HEIGHT = 0x1014; + const CLenum DEVICE_IMAGE3D_MAX_DEPTH = 0x1015; + const CLenum DEVICE_IMAGE_SUPPORT = 0x1016; + const CLenum DEVICE_MAX_PARAMETER_SIZE = 0x1017; + const CLenum DEVICE_MAX_SAMPLERS = 0x1018; + const CLenum DEVICE_MEM_BASE_ADDR_ALIGN = 0x1019; + const CLenum DEVICE_SINGLE_FP_CONFIG = 0x101B; + const CLenum DEVICE_GLOBAL_MEM_CACHE_TYPE = 0x101C; + const CLenum DEVICE_GLOBAL_MEM_CACHELINE_SIZE = 0x101D; + const CLenum DEVICE_GLOBAL_MEM_CACHE_SIZE = 0x101E; + const CLenum DEVICE_GLOBAL_MEM_SIZE = 0x101F; + const CLenum DEVICE_MAX_CONSTANT_BUFFER_SIZE = 0x1020; + const CLenum DEVICE_MAX_CONSTANT_ARGS = 0x1021; + const CLenum DEVICE_LOCAL_MEM_TYPE = 0x1022; + const CLenum DEVICE_LOCAL_MEM_SIZE = 0x1023; + const CLenum DEVICE_ERROR_CORRECTION_SUPPORT = 0x1024; + const CLenum DEVICE_PROFILING_TIMER_RESOLUTION = 0x1025; + const CLenum DEVICE_ENDIAN_LITTLE = 0x1026; + const CLenum DEVICE_AVAILABLE = 0x1027; + const CLenum DEVICE_COMPILER_AVAILABLE = 0x1028; + const CLenum DEVICE_EXECUTION_CAPABILITIES = 0x1029; + const CLenum DEVICE_QUEUE_PROPERTIES = 0x102A; + const CLenum DEVICE_NAME = 0x102B; + const CLenum DEVICE_VENDOR = 0x102C; + const CLenum DRIVER_VERSION = 0x102D; + const CLenum DEVICE_PROFILE = 0x102E; + const CLenum DEVICE_VERSION = 0x102F; + const CLenum DEVICE_EXTENSIONS = 0x1030; + const CLenum DEVICE_PLATFORM = 0x1031; + const CLenum DEVICE_HOST_UNIFIED_MEMORY = 0x1035; + const CLenum DEVICE_NATIVE_VECTOR_WIDTH_CHAR = 0x1036; + const CLenum DEVICE_NATIVE_VECTOR_WIDTH_SHORT = 0x1037; + const CLenum DEVICE_NATIVE_VECTOR_WIDTH_INT = 0x1038; + const CLenum DEVICE_NATIVE_VECTOR_WIDTH_LONG = 0x1039; + const CLenum DEVICE_NATIVE_VECTOR_WIDTH_FLOAT = 0x103A; + const CLenum DEVICE_OPENCL_C_VERSION = 0x103D; + + /* cl_device_fp_config - bitfield */ + const CLenum FP_DENORM = 0x01; // (1 << 0); + const CLenum FP_INF_NAN = 0x02; // (1 << 1); + const CLenum FP_ROUND_TO_NEAREST = 0x04; // (1 << 2); + const CLenum FP_ROUND_TO_ZERO = 0x08; // (1 << 3); + const CLenum FP_ROUND_TO_INF = 0x10; // (1 << 4); + const CLenum FP_FMA = 0x20; // (1 << 5); + const CLenum FP_SOFT_FLOAT = 0x40; // (1 << 6); + + /* cl_device_mem_cache_type */ + const CLenum NONE = 0x0; + const CLenum READ_ONLY_CACHE = 0x1; + const CLenum READ_WRITE_CACHE = 0x2; + + /* cl_device_local_mem_type */ + const CLenum LOCAL = 0x1; + const CLenum GLOBAL = 0x2; + + /* cl_device_exec_capabilities - bitfield */ + const CLenum EXEC_KERNEL = 0x1; // (1 << 0); + + /* cl_command_queue_properties - bitfield */ + const CLenum QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE = 0x1; // (1 << 0); + const CLenum QUEUE_PROFILING_ENABLE = 0x2; // (1 << 1); + + /* cl_context_info */ + const CLenum CONTEXT_DEVICES = 0x1081; + const CLenum CONTEXT_NUM_DEVICES = 0x1083; + const CLenum CONTEXT_PLATFORM = 0x1084; + + /* cl_context_info + cl_context_properties */ + + /* cl_command_queue_info */ + const CLenum QUEUE_CONTEXT = 0x1090; + const CLenum QUEUE_DEVICE = 0x1091; + const CLenum QUEUE_PROPERTIES = 0x1093; + + /* cl_mem_flags - bitfield */ + const CLenum MEM_READ_WRITE = 0x01; // (1 << 0); + const CLenum MEM_WRITE_ONLY = 0x02; // (1 << 1); + const CLenum MEM_READ_ONLY = 0x04; // (1 << 2); + + /* cl_channel_order */ + const CLenum R = 0x10B0; + const CLenum A = 0x10B1; + const CLenum RG = 0x10B2; + const CLenum RA = 0x10B3; + const CLenum RGB = 0x10B4; + const CLenum RGBA = 0x10B5; + const CLenum BGRA = 0x10B6; + const CLenum ARGB = 0x10B7; + const CLenum INTENSITY = 0x10B8; + const CLenum LUMINANCE = 0x10B9; + const CLenum Rx = 0x10BA; + const CLenum RGx = 0x10BB; + const CLenum RGBx = 0x10BC; + + /* cl_channel_type */ + const CLenum SNORM_INT8 = 0x10D0; + const CLenum SNORM_INT16 = 0x10D1; + const CLenum UNORM_INT8 = 0x10D2; + const CLenum UNORM_INT16 = 0x10D3; + const CLenum UNORM_SHORT_565 = 0x10D4; + const CLenum UNORM_SHORT_555 = 0x10D5; + const CLenum UNORM_INT_101010 = 0x10D6; + const CLenum SIGNED_INT8 = 0x10D7; + const CLenum SIGNED_INT16 = 0x10D8; + const CLenum SIGNED_INT32 = 0x10D9; + const CLenum UNSIGNED_INT8 = 0x10DA; + const CLenum UNSIGNED_INT16 = 0x10DB; + const CLenum UNSIGNED_INT32 = 0x10DC; + const CLenum HALF_FLOAT = 0x10DD; + const CLenum FLOAT = 0x10DE; + + /* cl_mem_object_type */ + const CLenum MEM_OBJECT_BUFFER = 0x10F0; + const CLenum MEM_OBJECT_IMAGE2D = 0x10F1; + + /* cl_mem_info */ + const CLenum MEM_TYPE = 0x1100; + const CLenum MEM_FLAGS = 0x1101; + const CLenum MEM_SIZE = 0x1102; + const CLenum MEM_CONTEXT = 0x1106; + const CLenum MEM_ASSOCIATED_MEMOBJECT = 0x1107; + const CLenum MEM_OFFSET = 0x1108; + + /* cl_image_info */ + const CLenum IMAGE_FORMAT = 0x1110; + const CLenum IMAGE_ELEMENT_SIZE = 0x1111; + const CLenum IMAGE_ROW_PITCH = 0x1112; + const CLenum IMAGE_WIDTH = 0x1114; + const CLenum IMAGE_HEIGHT = 0x1115; + + /* cl_addressing_mode */ + const CLenum ADDRESS_CLAMP_TO_EDGE = 0x1131; + const CLenum ADDRESS_CLAMP = 0x1132; + const CLenum ADDRESS_REPEAT = 0x1133; + const CLenum ADDRESS_MIRRORED_REPEAT = 0x1134; + + /* cl_filter_mode */ + const CLenum FILTER_NEAREST = 0x1140; + const CLenum FILTER_LINEAR = 0x1141; + + /* cl_sampler_info */ + const CLenum SAMPLER_CONTEXT = 0x1151; + const CLenum SAMPLER_NORMALIZED_COORDS = 0x1152; + const CLenum SAMPLER_ADDRESSING_MODE = 0x1153; + const CLenum SAMPLER_FILTER_MODE = 0x1154; + + const CLenum MAP_READ = 0x1; + const CLenum MAP_WRITE = 0x2; + + /* cl_program_info */ + const CLenum PROGRAM_CONTEXT = 0x1161; + const CLenum PROGRAM_NUM_DEVICES = 0x1162; + const CLenum PROGRAM_DEVICES = 0x1163; + const CLenum PROGRAM_SOURCE = 0x1164; + + /* cl_program_build_info */ + const CLenum PROGRAM_BUILD_STATUS = 0x1181; + const CLenum PROGRAM_BUILD_OPTIONS = 0x1182; + const CLenum PROGRAM_BUILD_LOG = 0x1183; + + /* cl_build_status */ + const CLint BUILD_SUCCESS = 0; + const CLint BUILD_NONE = -1; + const CLint BUILD_ERROR = -2; + const CLint BUILD_IN_PROGRESS = -3; + + /* cl_kernel_info */ + const CLenum KERNEL_FUNCTION_NAME = 0x1190; + const CLenum KERNEL_NUM_ARGS = 0x1191; + const CLenum KERNEL_CONTEXT = 0x1193; + const CLenum KERNEL_PROGRAM = 0x1194; + + /* cl_kernel_work_group_info */ + const CLenum KERNEL_WORK_GROUP_SIZE = 0x11B0; + const CLenum KERNEL_COMPILE_WORK_GROUP_SIZE = 0x11B1; + const CLenum KERNEL_LOCAL_MEM_SIZE = 0x11B2; + const CLenum KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE = 0x11B3; + const CLenum KERNEL_PRIVATE_MEM_SIZE = 0x11B4; + + /* cl_event_info */ + const CLenum EVENT_COMMAND_QUEUE = 0x11D0; + const CLenum EVENT_COMMAND_TYPE = 0x11D1; + const CLenum EVENT_COMMAND_EXECUTION_STATUS = 0x11D3; + const CLenum EVENT_CONTEXT = 0x11D4; + + /* cl_command_type */ + const CLenum COMMAND_NDRANGE_KERNEL = 0x11F0; + const CLenum COMMAND_TASK = 0x11F1; + const CLenum COMMAND_READ_BUFFER = 0x11F3; + const CLenum COMMAND_WRITE_BUFFER = 0x11F4; + const CLenum COMMAND_COPY_BUFFER = 0x11F5; + const CLenum COMMAND_READ_IMAGE = 0x11F6; + const CLenum COMMAND_WRITE_IMAGE = 0x11F7; + const CLenum COMMAND_COPY_IMAGE = 0x11F8; + const CLenum COMMAND_COPY_IMAGE_TO_BUFFER = 0x11F9; + const CLenum COMMAND_COPY_BUFFER_TO_IMAGE = 0x11FA; + const CLenum COMMAND_MARKER = 0x11FE; + const CLenum COMMAND_READ_BUFFER_RECT = 0x1201; + const CLenum COMMAND_WRITE_BUFFER_RECT = 0x1202; + const CLenum COMMAND_COPY_BUFFER_RECT = 0x1203; + const CLenum COMMAND_USER = 0x1204; + + /* command execution status */ + const CLenum COMPLETE = 0x0; + const CLenum RUNNING = 0x1; + const CLenum SUBMITTED = 0x2; + const CLenum QUEUED = 0x3; + + /* cl_buffer_create_type */ + const CLenum BUFFER_CREATE_TYPE_REGION = 0x1220; + + /* cl_profiling_info */ + const CLenum PROFILING_COMMAND_QUEUED = 0x1280; + const CLenum PROFILING_COMMAND_SUBMIT = 0x1281; + const CLenum PROFILING_COMMAND_START = 0x1282; + const CLenum PROFILING_COMMAND_END = 0x1283; + + /* extensions */ + const CLint INVALID_GL_OBJECT = -60; + const CLint INVALID_MIP_LEVEL = -62; + const CLenum DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE = 0x100B; + const CLenum DEVICE_DOUBLE_FP_CONFIG = 0x1032; + const CLenum DEVICE_HALF_FP_CONFIG = 0x1033; + const CLenum DEVICE_PREFERRED_VECTOR_WIDTH_HALF = 0x1034; + const CLenum DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE = 0x103B; + const CLenum DEVICE_NATIVE_VECTOR_WIDTH_HALF = 0x103C; + const CLenum COMMAND_ACQUIRE_GL_OBJECTS = 0x11FF; + const CLenum COMMAND_RELEASE_GL_OBJECTS = 0x1200; + + [RaisesException] WebCLContext createContext(sequence devices); + [RaisesException] WebCLContext createContext(WebCLDevice device); + [RaisesException] WebCLContext createContext(WebCLPlatform platform, CLenum deviceType); + [RaisesException] WebCLContext createContext(WebCLPlatform platform); + [RaisesException] WebCLContext createContext(CLenum deviceType); + [RaisesException] WebCLContext createContext(); + sequence? getSupportedExtensions(); + CLboolean enableExtension(DOMString extensionName); + [RaisesException] void waitForEvents(sequence eventWaitList, + optional WebCLCallback whenFinished); + [RaisesException] sequence getPlatforms(); + void releaseAll(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLBuffer.cpp b/third_party/WebKit/Source/modules/webcl/WebCLBuffer.cpp new file mode 100644 index 0000000000000..31636bc52c5f7 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLBuffer.cpp @@ -0,0 +1,128 @@ +// Copyright (C) 2011, 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) + +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLBuffer.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLMemoryObject.h" +#include "modules/webcl/WebCLOpenCL.h" + +namespace blink { + +namespace { + +struct CLBufferRegion { + unsigned origin; + unsigned size; +}; + +} // namespace anonymous + +WebCLBuffer::~WebCLBuffer() +{ +} + +PassRefPtr WebCLBuffer::create(WebCLContext* context, unsigned memoryFlags, unsigned sizeInBytes, void* data, ExceptionState& es) +{ + cl_context m_clContext = context->getContext(); + if (!m_clContext) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return nullptr; + } + + cl_int err = CL_SUCCESS; + cl_mem clMemObject = nullptr; + switch (memoryFlags) { + case CL_MEM_READ_ONLY: + clMemObject = data ? clCreateBuffer(m_clContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeInBytes, data, &err) : clCreateBuffer(m_clContext, CL_MEM_READ_ONLY, sizeInBytes, nullptr, &err); + break; + case CL_MEM_WRITE_ONLY: + clMemObject = data ? clCreateBuffer(m_clContext, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, sizeInBytes, data, &err) : clCreateBuffer(m_clContext, CL_MEM_WRITE_ONLY, sizeInBytes, nullptr , &err); + break; + case CL_MEM_READ_WRITE: + clMemObject = data ? clCreateBuffer(m_clContext, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeInBytes, data, &err) : clCreateBuffer(m_clContext, CL_MEM_READ_WRITE, sizeInBytes, nullptr, &err); + break; + default: + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + break; + } + + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + RefPtr buffer = adoptRef(new WebCLBuffer(clMemObject, context, memoryFlags, sizeInBytes)); + return buffer.release(); +} + +PassRefPtr WebCLBuffer::createSubBuffer(unsigned memoryFlags, unsigned origin, unsigned size, ExceptionState& es) +{ + CLBufferRegion bufferCreateInfo = {origin, size}; + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return nullptr; + } + + if (m_parentMemObject) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return nullptr; + } + + if (m_memoryFlags != CL_MEM_READ_WRITE && m_memoryFlags != memoryFlags) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + if (origin > sizeInBytes() || size > sizeInBytes()) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + if (!WebCLInputChecker::isValidMemoryObjectFlag(memoryFlags)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + cl_int err = CL_SUCCESS; + cl_mem clMemObject = 0; + switch (memoryFlags) { + case CL_MEM_READ_ONLY: + clMemObject = clCreateSubBuffer(m_clMem, CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, &bufferCreateInfo, &err); + break; + case CL_MEM_WRITE_ONLY: + clMemObject = clCreateSubBuffer(m_clMem, CL_MEM_WRITE_ONLY, CL_BUFFER_CREATE_TYPE_REGION, &bufferCreateInfo, &err); + break; + case CL_MEM_READ_WRITE: + clMemObject = clCreateSubBuffer(m_clMem, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, &bufferCreateInfo, &err); + break; + default: + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + break; + } + + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + + RefPtr buffer = adoptRef(new WebCLBuffer(clMemObject, context(), memoryFlags, size, this)); + return buffer.release(); +} + +WebCLBuffer::WebCLBuffer(cl_mem clMem, WebCLContext* context, unsigned memoryFlags, unsigned size, WebCLBuffer* parentBuffer) + : WebCLMemoryObject(clMem, size, context, parentBuffer) + , m_memoryFlags(memoryFlags) +{ +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLBuffer.h b/third_party/WebKit/Source/modules/webcl/WebCLBuffer.h new file mode 100644 index 0000000000000..d96115a657eee --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLBuffer.h @@ -0,0 +1,37 @@ +// Copyright (C) 2011, 2012, 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLBuffer_h +#define WebCLBuffer_h + +#if ENABLE(WEBCL) + +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLMemoryObject.h" + +namespace blink { + +class WebCL; +class WebCLContext; + +class WebCLBuffer : public WebCLMemoryObject { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLBuffer() override; + static PassRefPtr create(WebCLContext*, unsigned, unsigned, void*, ExceptionState&); + PassRefPtr createSubBuffer(unsigned, unsigned, unsigned, ExceptionState&); + + int type() override { return BUFFER; } + +private: + WebCLBuffer(cl_mem, WebCLContext*, unsigned, unsigned, WebCLBuffer* parentBuffer = nullptr); + + unsigned m_memoryFlags; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLBuffer_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLBuffer.idl b/third_party/WebKit/Source/modules/webcl/WebCLBuffer.idl new file mode 100644 index 0000000000000..9f387af903089 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLBuffer.idl @@ -0,0 +1,11 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef unsigned long CLuint; +typedef unsigned long CLenum; +[ + Conditional=WEBCL, +] interface WebCLBuffer : WebCLMemoryObject { + [RaisesException] WebCLBuffer createSubBuffer(CLenum memFlags, CLuint origin, CLuint sizeInBytes); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLCallback.h b/third_party/WebKit/Source/modules/webcl/WebCLCallback.h new file mode 100644 index 0000000000000..edae3c06fc06a --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLCallback.h @@ -0,0 +1,24 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLCallback_h +#define WebCLCallback_h + +#if ENABLE(WEBCL) +#include "platform/heap/Handle.h" +#include + +namespace blink { +class WebCLCallback : public RefCounted { +public: + virtual ~WebCLCallback() { } + DEFINE_INLINE_VIRTUAL_TRACE() { } + virtual bool handleEvent() = 0; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLCallback_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLCallback.idl b/third_party/WebKit/Source/modules/webcl/WebCLCallback.idl new file mode 100644 index 0000000000000..35e99909553ef --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLCallback.idl @@ -0,0 +1,9 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + Conditional=WEBCL +] callback interface WebCLCallback { + boolean handleEvent(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.cpp b/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.cpp new file mode 100644 index 0000000000000..90dac3e70e959 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.cpp @@ -0,0 +1,1313 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/modules/v8/V8WebCLContext.h" +#include "bindings/modules/v8/V8WebCLDevice.h" +#include "core/dom/DOMArrayBuffer.h" +#include "core/dom/DOMArrayBufferView.h" +#include "core/dom/DOMTypedArray.h" +#include "core/html/HTMLCanvasElement.h" +#include "core/html/ImageData.h" +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLBuffer.h" +#include "modules/webcl/WebCLCommandQueue.h" +#include "modules/webcl/WebCLEvent.h" +#include "modules/webcl/WebCLHTMLUtil.h" +#include "modules/webcl/WebCLImage.h" +#include "modules/webcl/WebCLImageDescriptor.h" +#include "modules/webcl/WebCLInputChecker.h" +#include "modules/webcl/WebCLKernel.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "public/platform/Platform.h" +#include "platform/ThreadSafeFunctional.h" + +namespace blink { + +// The holder of WebCLCommandQueue. +class WebCLCommandQueueHolder { +public: + cl_event event; + cl_int type; + WeakPtr commandQueue; +}; + +WebCLCommandQueue::~WebCLCommandQueue() +{ + release(); + ASSERT(!m_clCommandQueue); +} + +PassRefPtr WebCLCommandQueue::create(cl_command_queue commandQueue, WebCLContext* context, WebCLDevice* device) +{ + return adoptRef(new WebCLCommandQueue(commandQueue, context, device)); +} + +ScriptValue WebCLCommandQueue::getInfo(ScriptState* scriptState, int paramName, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_int err = CL_SUCCESS; + cl_command_queue_properties queueProperties = 0; + switch(paramName) { + case CL_QUEUE_CONTEXT: + return ScriptValue(scriptState, toV8(context(), creationContext, isolate)); + break; + case CL_QUEUE_DEVICE: + return ScriptValue(scriptState, toV8(m_device, creationContext, isolate)); + break; + case CL_QUEUE_PROPERTIES: + err = clGetCommandQueueInfo(m_clCommandQueue, CL_QUEUE_PROPERTIES, sizeof(cl_command_queue_properties), &queueProperties, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(queueProperties))); + break; + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); +} + +unsigned WebCLCommandQueue::getProperties() +{ + cl_command_queue_properties queueProperties; + cl_int err = clGetCommandQueueInfo(m_clCommandQueue, CL_QUEUE_PROPERTIES, sizeof(cl_command_queue_properties), &queueProperties, nullptr); + if (err == CL_SUCCESS) + return static_cast(queueProperties); + + return 0; +} + +void WebCLCommandQueue::finish(WebCLCallback* whenFinished, ExceptionState& es) +{ + if (isReleased() || m_whenFinishCallback) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + if (whenFinished) { + m_whenFinishCallback = adoptRef(whenFinished); + finishCommandQueues(ASYNC); + } else { + finishCommandQueues(SYNC); + } +} + +void WebCLCommandQueue::finishCommandQueues(SyncMethod method) +{ + if (method == ASYNC) { + cl_int err = clEnqueueMarker(m_clCommandQueue, &m_eventForCallback); + if (err != CL_SUCCESS || !m_eventForCallback) + return; + WebCLCommandQueueHolder* holder = new WebCLCommandQueueHolder; + holder->commandQueue = createWeakPtr(); + clSetEventCallback(m_eventForCallback, CL_COMPLETE, &callbackProxy, holder); + } else if (method == SYNC) { + clFinish(m_clCommandQueue); + } +} + +void WebCLCommandQueue::flush(ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_int err = clFlush(m_clCommandQueue); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::release() +{ + if (isReleased()) + return; + + // Wait for all the command queue to finish first. + finishCommandQueues(SYNC); + + cl_int err = clReleaseCommandQueue(m_clCommandQueue); + if (err != CL_SUCCESS) + ASSERT_NOT_REACHED(); + + m_clCommandQueue = 0; + + // Release the un-triggered callback and its associated event object. + resetEventAndCallback(); +} + +void WebCLCommandQueue::enqueueBarrier(ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_int err = clEnqueueBarrier(m_clCommandQueue); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueMarker(WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + if (event->isUserEvent()) { + es.throwWebCLException(WebCLException::INVALID_EVENT, WebCLException::invalidEventMessage); + return; + } + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = clEnqueueMarker(m_clCommandQueue, clEventId); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueWaitForEvents(const Vector>& events, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + if (!events.size()) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector clEvents = WebCLEventVectorToCLEventVector(false, events, es); + if (clEvents.size() != events.size()) + return; + + cl_int err = clEnqueueWaitForEvents(m_clCommandQueue, clEvents.size(), clEvents.data()); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueWriteBufferBase(WebCLBuffer* mem, bool blockingWrite, unsigned offset, unsigned bufferSize, void* ptr, size_t ptrLength, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_mem clMemId = nullptr; + if (mem) { + clMemId = mem->getMem(); + if (!clMemId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (!ptr) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + + if (!WebCLInputChecker::compareContext(context(), mem->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (ptrLength < bufferSize || mem->sizeInBytes() < (offset + bufferSize)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector clEvents = WebCLEventVectorToCLEventVector(blockingWrite, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = blockingWrite ? clEnqueueWriteBuffer(m_clCommandQueue, clMemId, CL_TRUE, offset, bufferSize, ptr, clEvents.size(), clEvents.data(), clEventId) : clEnqueueWriteBuffer(m_clCommandQueue, clMemId, CL_FALSE, offset, bufferSize, ptr, clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueWriteBuffer(WebCLBuffer* mem, bool blockingWrite, unsigned offset, unsigned bufferSize, DOMArrayBufferView* ptr, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!ptr || !WebCLInputChecker::isValidDataSizeForDOMArrayBufferView(bufferSize, ptr)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + enqueueWriteBufferBase(mem, blockingWrite, offset, bufferSize, ptr->baseAddress(), ptr->byteLength(), events, event, es); +} + +void WebCLCommandQueue::enqueueWriteBuffer(WebCLBuffer* buffer, bool blockingWrite, unsigned offset, ImageData* srcPixels, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + void* hostPtr = 0; + size_t pixelSize = 0; + if (!WebCLHTMLUtil::extractDataFromImageData(srcPixels, hostPtr, pixelSize, es)) + return; + + enqueueWriteBufferBase(buffer, blockingWrite, offset, pixelSize, hostPtr, pixelSize, events, event, es); +} + +void WebCLCommandQueue::enqueueWriteBuffer(WebCLBuffer* buffer, bool blockingWrite, unsigned offset, HTMLCanvasElement* srcCanvas, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t canvasSize = 0; + if (!WebCLHTMLUtil::extractDataFromCanvas(srcCanvas, data, canvasSize, es)) + return; + + void* hostPtr = data.data(); + enqueueWriteBufferBase(buffer, blockingWrite, offset, canvasSize, hostPtr, canvasSize, events, event, es); +} + +void WebCLCommandQueue::enqueueWriteBuffer(WebCLBuffer* buffer, bool blockingWrite, unsigned offset, HTMLImageElement* srcImage, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t imageSize = 0; + if (!WebCLHTMLUtil::extractDataFromImage(srcImage, data, imageSize, es)) + return; + + void* hostPtr = data.data(); + enqueueWriteBufferBase(buffer, blockingWrite, offset, imageSize, hostPtr, imageSize, events, event, es); +} + +void WebCLCommandQueue::enqueueWriteBufferRectBase(WebCLBuffer* mem, bool blockingWrite, const Vector& bufferOrigin, const Vector& hostOrigin, const Vector& region, unsigned bufferRowPitch, unsigned bufferSlicePitch, unsigned hostRowPitch, unsigned hostSlicePitch, void* ptr, size_t ptrLength, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_mem clMemId = nullptr; + if (mem) { + clMemId = mem->getMem(); + if (!clMemId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (!ptr) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + + if (!WebCLInputChecker::compareContext(context(), mem->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (bufferOrigin.size() != 3 || hostOrigin.size() != 3 || region.size() != 3) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector bufferOriginCopy, hostOriginCopy, regionCopy; + bufferOriginCopy.appendVector(bufferOrigin); + hostOriginCopy.appendVector(hostOrigin); + regionCopy.appendVector(region); + + if (!WebCLInputChecker::isValidRegionForMemoryObject(bufferOriginCopy, regionCopy, bufferRowPitch, bufferSlicePitch, mem->sizeInBytes()) || !WebCLInputChecker::isValidRegionForMemoryObject(hostOriginCopy, regionCopy, hostRowPitch, hostSlicePitch, ptrLength)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector clEvents = WebCLEventVectorToCLEventVector(blockingWrite, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = blockingWrite? clEnqueueWriteBufferRect(m_clCommandQueue, clMemId, CL_TRUE, bufferOriginCopy.data(), hostOriginCopy.data(), regionCopy.data(), bufferRowPitch, bufferSlicePitch, hostRowPitch, 0, ptr, clEvents.size(), clEvents.data(), clEventId) : clEnqueueWriteBufferRect(m_clCommandQueue, clMemId, CL_FALSE, bufferOriginCopy.data(), hostOriginCopy.data(), regionCopy.data(), bufferRowPitch, bufferSlicePitch, hostRowPitch, 0, ptr, clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueWriteBufferRect(WebCLBuffer* mem, bool blockingWrite, const Vector& bufferOrigin, const Vector& hostOrigin, const Vector& region, unsigned bufferRowPitch, unsigned bufferSlicePitch, unsigned hostRowPitch, unsigned hostSlicePitch, DOMArrayBufferView* ptr, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!ptr || !WebCLInputChecker::isValidDataSizeForDOMArrayBufferView(hostRowPitch, ptr) || !WebCLInputChecker::isValidDataSizeForDOMArrayBufferView(hostSlicePitch, ptr)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + enqueueWriteBufferRectBase(mem, blockingWrite, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, ptr->baseAddress(), ptr->byteLength(), events, event, es); +} + +void WebCLCommandQueue::enqueueWriteBufferRect(WebCLBuffer* buffer, bool blockingWrite, const Vector& bufferOrigin, const Vector& hostOrigin, const Vector& region, unsigned bufferRowPitch, unsigned bufferSlicePitch, ImageData* srcPixels, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + void* hostPtr = 0; + size_t pixelSize = 0; + if (!WebCLHTMLUtil::extractDataFromImageData(srcPixels, hostPtr, pixelSize, es)) + return; + + enqueueWriteBufferRectBase(buffer, blockingWrite, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, 0, 0, hostPtr, pixelSize, events, event, es); +} + +void WebCLCommandQueue::enqueueWriteBufferRect(WebCLBuffer* buffer, bool blockingWrite, const Vector& bufferOrigin, const Vector& hostOrigin, const Vector& region, unsigned bufferRowPitch, unsigned bufferSlicePitch, HTMLCanvasElement* srcCanvas, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t canvasSize = 0; + if (!WebCLHTMLUtil::extractDataFromCanvas(srcCanvas, data, canvasSize, es)) + return; + + void* hostPtr = data.data(); + enqueueWriteBufferRectBase(buffer, blockingWrite, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, 0, 0, hostPtr, canvasSize, events, event, es); +} + +void WebCLCommandQueue::enqueueWriteBufferRect(WebCLBuffer* buffer, bool blockingWrite, const Vector& bufferOrigin, const Vector& hostOrigin, const Vector& region, unsigned bufferRowPitch, unsigned bufferSlicePitch, HTMLImageElement* srcImage, const Vector>& eventWaitlist, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t imageSize = 0; + if (!WebCLHTMLUtil::extractDataFromImage(srcImage, data, imageSize, es)) + return; + + void* hostPtr = data.data(); + enqueueWriteBufferRectBase(buffer, blockingWrite, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, 0, 0, hostPtr, imageSize, eventWaitlist, event, es); +} + +void WebCLCommandQueue::enqueueReadBufferBase(WebCLBuffer* mem, bool blockingRead, unsigned offset, unsigned bufferSize, void* ptr, size_t ptrLength, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + if (!WebCLInputChecker::compareContext(context(), mem->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + cl_mem clMemId = nullptr; + if (mem) { + clMemId = mem->getMem(); + if (!clMemId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (ptrLength < bufferSize || mem->sizeInBytes() < (offset + bufferSize)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector clEvents = WebCLEventVectorToCLEventVector(blockingRead, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = blockingRead ? clEnqueueReadBuffer(m_clCommandQueue, clMemId, CL_TRUE, offset, bufferSize, ptr, clEvents.size(), clEvents.data(), clEventId) : clEnqueueReadBuffer(m_clCommandQueue, clMemId, CL_FALSE, offset, bufferSize, ptr, clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueReadBuffer(WebCLBuffer* mem, bool blockingRead, unsigned offset, unsigned bufferSize, DOMArrayBufferView* ptr, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!ptr || !WebCLInputChecker::isValidDataSizeForDOMArrayBufferView(bufferSize, ptr)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + enqueueReadBufferBase(mem, blockingRead, offset, bufferSize, ptr->baseAddress(), ptr->byteLength(), events, event, es); +} + +void WebCLCommandQueue::enqueueReadBuffer(WebCLBuffer* buffer, bool blockingRead, unsigned offset, unsigned numBytes, HTMLCanvasElement* dstCanvas, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t canvasSize = 0; + if (!WebCLHTMLUtil::extractDataFromCanvas(dstCanvas, data, canvasSize, es)) + return; + + void* hostPtr = data.data(); + enqueueReadBufferBase(buffer, blockingRead, offset, numBytes, hostPtr, canvasSize, events, event, es); +} + +void WebCLCommandQueue::enqueueReadBufferRectBase(WebCLBuffer* mem, bool blockingRead, const Vector& bufferOrigin, const Vector& hostOrigin, const Vector& region, unsigned bufferRowPitch, unsigned bufferSlicePitch, unsigned hostRowPitch, unsigned hostSlicePitch, void* ptr, size_t ptrLength, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + if (!WebCLInputChecker::compareContext(context(), mem->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + cl_mem clMemId = nullptr; + if (mem) { + clMemId = mem->getMem(); + if (!clMemId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (!ptr) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + + if (bufferOrigin.size() != 3 || hostOrigin.size() != 3 || region.size() != 3) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector bufferOriginCopy, hostOriginCopy, regionCopy; + bufferOriginCopy.appendVector(bufferOrigin); + hostOriginCopy.appendVector(hostOrigin); + regionCopy.appendVector(region); + + if (!WebCLInputChecker::isValidRegionForMemoryObject(hostOriginCopy, regionCopy, hostRowPitch, hostSlicePitch, ptrLength) || !WebCLInputChecker::isValidRegionForMemoryObject(bufferOriginCopy, regionCopy, bufferRowPitch, bufferSlicePitch, mem->sizeInBytes())) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector clEvents = WebCLEventVectorToCLEventVector(blockingRead, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = blockingRead ? clEnqueueReadBufferRect(m_clCommandQueue, clMemId, CL_TRUE, bufferOriginCopy.data(), hostOriginCopy.data(), regionCopy.data(), bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, ptr, clEvents.size(), clEvents.data(), clEventId) : clEnqueueReadBufferRect(m_clCommandQueue, clMemId, CL_FALSE, bufferOriginCopy.data(), hostOriginCopy.data(), regionCopy.data(), bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, ptr, clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueReadBufferRect(WebCLBuffer* mem, bool blockingRead, const Vector& bufferOrigin, const Vector& hostOrigin, const Vector& region, unsigned bufferRowPitch, unsigned bufferSlicePitch, unsigned hostRowPitch, unsigned hostSlicePitch, DOMArrayBufferView* ptr, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!ptr || !WebCLInputChecker::isValidDataSizeForDOMArrayBufferView(hostRowPitch, ptr) || !WebCLInputChecker::isValidDataSizeForDOMArrayBufferView(hostSlicePitch, ptr)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + enqueueReadBufferRectBase(mem, blockingRead, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, hostRowPitch, hostSlicePitch, ptr->baseAddress(), ptr->byteLength(), events, event, es); +} + +void WebCLCommandQueue::enqueueReadBufferRect(WebCLBuffer* buffer, bool blockingRead, const Vector& bufferOrigin, const Vector& hostOrigin, const Vector& region, unsigned bufferRowPitch, unsigned bufferSlicePitch, HTMLCanvasElement* dstCanvas, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t canvasSize = 0; + if (!WebCLHTMLUtil::extractDataFromCanvas(dstCanvas, data, canvasSize, es)) + return; + + void* hostPtr = data.data(); + enqueueReadBufferRectBase(buffer, blockingRead, bufferOrigin, hostOrigin, region, bufferRowPitch, bufferSlicePitch, 0, 0, hostPtr, canvasSize, events, event, es); +} + +void WebCLCommandQueue::enqueueReadImageBase(WebCLImage* image, bool blockingRead, const Vector& origin, const Vector& region, unsigned hostRowPitch, void* ptr, size_t ptrLength, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + if (!WebCLInputChecker::compareContext(context(), image->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + cl_mem clMemId = nullptr; + if (image) { + clMemId = image->getMem(); + if (!clMemId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (origin.size() != 2 || region.size() != 2) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + if (!WebCLInputChecker::isValidRegionForImage(image->imageDescriptor(), origin, region) || !WebCLInputChecker::isValidRegionForHostPtr(region, hostRowPitch, image->imageDescriptor(), ptrLength)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector originCopy, regionCopy; + originCopy.appendVector(origin); + regionCopy.appendVector(region); + // No support for 3D-images, so set default values of 0 for all origin & region arrays at 3rd index. + originCopy.append(0); + regionCopy.append(1); + + Vector clEvents = WebCLEventVectorToCLEventVector(blockingRead, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = blockingRead ? clEnqueueReadImage(m_clCommandQueue, clMemId, CL_TRUE, originCopy.data(), regionCopy.data(), hostRowPitch, 0, ptr, clEvents.size(), clEvents.data(), clEventId) : clEnqueueReadImage(m_clCommandQueue, clMemId, CL_FALSE, originCopy.data(), regionCopy.data(), hostRowPitch, 0, ptr, clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueReadImage(WebCLImage* image, bool blockingRead, const Vector& origin, const Vector& region, unsigned hostRowPitch, DOMArrayBufferView* ptr, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!ptr || !WebCLInputChecker::isValidDataSizeForDOMArrayBufferView(hostRowPitch, ptr)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + enqueueReadImageBase(image, blockingRead, origin, region, hostRowPitch, ptr->baseAddress(), ptr->byteLength(), events, event, es); +} + +void WebCLCommandQueue::enqueueReadImage(WebCLImage* image, bool blockingRead, const Vector& origin, const Vector& region, HTMLCanvasElement* dstCanvas, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t canvasSize = 0; + if (!WebCLHTMLUtil::extractDataFromCanvas(dstCanvas, data, canvasSize, es)) + return; + + void* hostPtr = data.data(); + enqueueReadImageBase(image, blockingRead, origin, region, 0, hostPtr, canvasSize, events, event, es); +} + +void WebCLCommandQueue::enqueueNDRangeKernel(WebCLKernel* kernel, unsigned dim, const Vector& offsets, const Vector& globalWorkSize, const Vector& localWorkSize, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_kernel clKernelId = nullptr; + if (kernel) { + clKernelId = kernel->getKernel(); + if (!clKernelId) { + es.throwWebCLException(WebCLException::INVALID_KERNEL, WebCLException::invalidKernelMessage); + return; + } + } + + if (!WebCLInputChecker::compareContext(context(), kernel->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (dim > 3) { + es.throwWebCLException(WebCLException::INVALID_WORK_DIMENSION, WebCLException::invalidWorkDimensionMessage); + return; + } + + if (dim != globalWorkSize.size()) { + es.throwWebCLException(WebCLException::INVALID_GLOBAL_WORK_SIZE, WebCLException::invalidGlobalWorkSizeMessage); + return; + } + + if (offsets.size() && dim != offsets.size()) { + es.throwWebCLException(WebCLException::INVALID_GLOBAL_OFFSET, WebCLException::invalidGlobalOffsetMessage); + return; + } + if (localWorkSize.size() && dim != localWorkSize.size()) { + es.throwWebCLException(WebCLException::INVALID_WORK_GROUP_SIZE, WebCLException::invalidWorkGroupSizeMessage); + return; + } + + const Vector& required = kernel->requiredArguments(); + if (!localWorkSize.size() && required.size()) { + es.throwWebCLException(WebCLException::INVALID_WORK_GROUP_SIZE, WebCLException::invalidWorkGroupSizeMessage); + return; + } + + if (localWorkSize.size() && required.size()) { + for (unsigned i = 0; i < localWorkSize.size(); i ++) { + if (localWorkSize[i] != required[i]) { + es.throwWebCLException(WebCLException::INVALID_WORK_GROUP_SIZE, WebCLException::invalidWorkGroupSizeMessage); + return; + } + } + } + + const unsigned long long maxWorkSizeValue = (1ULL << 32) - 1; + for (unsigned i = 0; i < globalWorkSize.size(); i ++) { + if (globalWorkSize[i] > maxWorkSizeValue) { + es.throwWebCLException(WebCLException::INVALID_GLOBAL_WORK_SIZE, WebCLException::invalidGlobalWorkSizeMessage); + return; + } + if (offsets.size() && globalWorkSize[i] + offsets[i] > maxWorkSizeValue) { + es.throwWebCLException(WebCLException::INVALID_GLOBAL_OFFSET, WebCLException::invalidGlobalOffsetMessage); + return; + } + if (localWorkSize.size() && ((unsigned)localWorkSize[i] && (unsigned)globalWorkSize[i] % (unsigned)localWorkSize[i] != 0)) { + es.throwWebCLException(WebCLException::INVALID_WORK_GROUP_SIZE, WebCLException::invalidWorkGroupSizeMessage); + return; + } + } + + unsigned maxWorkGroupSize = m_device->getMaxWorkGroup(); + Vector maxWorkItemSizes = m_device->getMaxWorkItem(); + unsigned total = 1; + for (unsigned i = 0; maxWorkItemSizes.size() == localWorkSize.size() && i < localWorkSize.size(); i ++) { + if (localWorkSize[i] > maxWorkItemSizes[i]) { + es.throwWebCLException(WebCLException::INVALID_WORK_ITEM_SIZE, WebCLException::invalidWorkItemSizeMessage); + return; + } + total = total * localWorkSize[i]; + } + + if (maxWorkGroupSize && total > maxWorkGroupSize) { + es.throwWebCLException(WebCLException::INVALID_WORK_GROUP_SIZE, WebCLException::invalidWorkGroupSizeMessage); + return; + } + + if (kernel->numberOfArguments() != kernel->associatedArguments()) { + es.throwWebCLException(WebCLException::INVALID_KERNEL_ARGS, WebCLException::invalidKernelArgsMessage); + return; + } + + Vector gWorkSizeCopy, lWorkSizeCopy, gWorkOffsetCopy; + gWorkSizeCopy.appendVector(globalWorkSize); + gWorkOffsetCopy.appendVector(offsets); + lWorkSizeCopy.appendVector(localWorkSize); + + Vector clEvents = WebCLEventVectorToCLEventVector(false, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = clEnqueueNDRangeKernel(m_clCommandQueue, clKernelId, dim, gWorkOffsetCopy.data(), gWorkSizeCopy.data(), lWorkSizeCopy.data(), clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueWriteImageBase(WebCLImage* image, bool blockingWrite, const Vector& origin, const Vector& region, unsigned hostRowPitch, void* ptr, size_t ptrLength, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_mem clMemId = nullptr; + if (image) { + clMemId = image->getMem(); + if (!clMemId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (!WebCLInputChecker::compareContext(context(), image->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (!ptr) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + + if (origin.size() != 2 || region.size() != 2) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + if (!WebCLInputChecker::isValidRegionForImage(image->imageDescriptor(), origin, region) || !WebCLInputChecker::isValidRegionForHostPtr(region, hostRowPitch, image->imageDescriptor(), ptrLength)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector originCopy, regionCopy; + originCopy.appendVector(origin); + regionCopy.appendVector(region); + // WebCL doesn't support 3D-images as OpenCL, so set default values of 0 for all origin & region arrays at 3rd index. + originCopy.append(0); + regionCopy.append(1); + + Vector clEvents = WebCLEventVectorToCLEventVector(blockingWrite, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = blockingWrite ? clEnqueueWriteImage(m_clCommandQueue, clMemId, CL_TRUE, originCopy.data(), regionCopy.data(), hostRowPitch, 0, ptr, clEvents.size(), clEvents.data(), clEventId) : clEnqueueWriteImage(m_clCommandQueue, clMemId, CL_FALSE, originCopy.data(), regionCopy.data(), hostRowPitch, 0, ptr, clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueWriteImage(WebCLImage* image, bool blockingWrite, const Vector& origin, const Vector& region, unsigned hostRowPitch, DOMArrayBufferView* ptr, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!ptr || !WebCLInputChecker::isValidDataSizeForDOMArrayBufferView(hostRowPitch, ptr)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + enqueueWriteImageBase(image, blockingWrite, origin, region, hostRowPitch, ptr->baseAddress(), ptr->byteLength(), events, event, es); +} + +void WebCLCommandQueue::enqueueWriteImage(WebCLImage* image, bool blockingWrite, const Vector& origin, const Vector& region, ImageData* srcPixels, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + void* hostPtr = 0; + size_t pixelSize = 0; + if (!WebCLHTMLUtil::extractDataFromImageData(srcPixels, hostPtr, pixelSize, es)) + return; + + enqueueWriteImageBase(image, blockingWrite, origin, region, 0, hostPtr, pixelSize, events, event, es); +} + +void WebCLCommandQueue::enqueueWriteImage(WebCLImage* image, bool blockingWrite, const Vector& origin, const Vector& region, HTMLCanvasElement* srcCanvas, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t canvasSize = 0; + if (!WebCLHTMLUtil::extractDataFromCanvas(srcCanvas, data, canvasSize, es)) + return; + + void* hostPtr = data.data(); + enqueueWriteImageBase(image, blockingWrite, origin, region, 0, hostPtr, canvasSize, events, event, es); +} + +void WebCLCommandQueue::enqueueWriteImage(WebCLImage* image, bool blockingWrite, const Vector& origin, const Vector& region, HTMLImageElement* srcImage, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t imageSize = 0; + if (!WebCLHTMLUtil::extractDataFromImage(srcImage, data, imageSize, es)) + return; + + void* hostPtr = data.data(); + enqueueWriteImageBase(image, blockingWrite, origin, region, 0, hostPtr, imageSize, events, event, es); +} + +void WebCLCommandQueue::enqueueWriteImage(WebCLImage* image, bool blockingWrite, HTMLVideoElement* srcVideo, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (!isExtensionEnabled(context(), "WEBCL_html_video")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return; + } + + Vector data; + size_t videoSize = 0; + if (!context()->getHTMLUtil()->extractDataFromVideo(srcVideo, data, videoSize, es)) + return; + void* hostPtr = data.data(); + + Vector origin; + origin.reserveCapacity(2); + origin.append(0); + origin.append(0); + + Vector region; + region.reserveCapacity(2); + region.append(image->imageDescriptor().width()); + region.append(image->imageDescriptor().height()); + + enqueueWriteImageBase(image, blockingWrite, origin, region, 0, hostPtr, videoSize, events, event, es); +} + +void WebCLCommandQueue::enqueueCopyBuffer(WebCLBuffer* srcBuffer, WebCLBuffer* dstBuffer, unsigned srcOffset, unsigned dstOffset, unsigned cb, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_mem clSrcBufferId = nullptr; + if (srcBuffer) { + clSrcBufferId = srcBuffer->getMem(); + if (!clSrcBufferId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + cl_mem clDstBufferId = nullptr; + if (dstBuffer) { + clDstBufferId = dstBuffer->getMem(); + if (!clDstBufferId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (!WebCLInputChecker::compareContext(context(), srcBuffer->context()) || !WebCLInputChecker::compareContext(context(), dstBuffer->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (WebCLInputChecker::isRegionOverlapping(srcBuffer, dstBuffer, srcOffset, dstOffset, cb)) { + es.throwWebCLException(WebCLException::MEM_COPY_OVERLAP, WebCLException::memCopyOverlapMessage); + return; + } + + if ((srcOffset + cb) > srcBuffer->sizeInBytes() + || (dstOffset + cb) > dstBuffer->sizeInBytes()) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector clEvents = WebCLEventVectorToCLEventVector(false, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = clEnqueueCopyBuffer(m_clCommandQueue, clSrcBufferId, clDstBufferId, srcOffset, dstOffset, cb, clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueCopyBufferRect(WebCLBuffer* srcBuffer, WebCLBuffer* dstBuffer, const Vector& srcOrigin, const Vector& dstOrigin, const Vector& region, unsigned srcRowPitch, unsigned srcSlicePitch, unsigned dstRowPitch, unsigned dstSlicePitch, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_mem clSrcBufferId = nullptr; + if (srcBuffer) { + clSrcBufferId = srcBuffer->getMem(); + if (!clSrcBufferId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + cl_mem clDstBufferId = nullptr; + if (dstBuffer) { + clDstBufferId = dstBuffer->getMem(); + if (!clDstBufferId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (!WebCLInputChecker::compareContext(context(), srcBuffer->context()) || !WebCLInputChecker::compareContext(context(), dstBuffer->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (srcOrigin.size() != 3 || dstOrigin.size() != 3 || region.size() != 3) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + size_t srcOffset = srcOrigin[2] * srcSlicePitch + srcOrigin[1] * srcRowPitch + srcOrigin[0]; + size_t dstOffset = dstOrigin[2] * dstSlicePitch + dstOrigin[1] * dstRowPitch + dstOrigin[0]; + size_t numBytes = region[2] * region[1] * region[0]; + if (WebCLInputChecker::isRegionOverlapping(srcBuffer, dstBuffer, srcOffset, dstOffset, numBytes)) { + es.throwWebCLException(WebCLException::MEM_COPY_OVERLAP, WebCLException::memCopyOverlapMessage); + return; + } + + Vector srcOriginCopy, dstOriginCopy, regionCopy; + srcOriginCopy.appendVector(srcOrigin); + dstOriginCopy.appendVector(dstOrigin); + regionCopy.appendVector(region); + + if (!WebCLInputChecker::isValidRegionForMemoryObject(srcOriginCopy, regionCopy, srcRowPitch, srcSlicePitch, srcBuffer->sizeInBytes()) || !WebCLInputChecker::isValidRegionForMemoryObject(dstOriginCopy, regionCopy, dstRowPitch, dstSlicePitch, dstBuffer->sizeInBytes())) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector clEvents = WebCLEventVectorToCLEventVector(false, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = clEnqueueCopyBufferRect(m_clCommandQueue, clSrcBufferId, clDstBufferId, srcOriginCopy.data(), dstOriginCopy.data(), regionCopy.data(), srcRowPitch, srcSlicePitch, dstRowPitch, dstSlicePitch, clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueCopyImage(WebCLImage* srcImage, WebCLImage* dstImage, const Vector& srcOrigin, const Vector& dstOrigin, const Vector& region, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_mem clSrcImageId = nullptr; + if (srcImage) { + clSrcImageId = srcImage->getMem(); + if (!clSrcImageId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + cl_mem clDstImageId = nullptr; + if (dstImage) { + clDstImageId = dstImage->getMem(); + if (!clDstImageId) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_SIZE, WebCLException::invalidImageSizeMessage); + return; + } + } + + if (!WebCLInputChecker::compareContext(context(), srcImage->context()) || !WebCLInputChecker::compareContext(context(), dstImage->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (!WebCLInputChecker::compareImageFormat(srcImage->imageDescriptor(), dstImage->imageDescriptor())) { + es.throwWebCLException(WebCLException::IMAGE_FORMAT_MISMATCH, WebCLException::imageFormatMismatchMessage); + return; + } + + if (srcOrigin.size() != 2 || dstOrigin.size() != 2 || region.size() != 2) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + if (!WebCLInputChecker::isValidRegionForImage(srcImage->imageDescriptor(), srcOrigin, region) || !WebCLInputChecker::isValidRegionForImage(dstImage->imageDescriptor(), dstOrigin, region)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector srcOriginCopy, dstOriginCopy, regionCopy; + srcOriginCopy.appendVector(srcOrigin); + dstOriginCopy.appendVector(dstOrigin); + regionCopy.appendVector(region); + + // No support for 3D-images, so set default values of 0 for all origin & region arrays at 3rd index. + srcOriginCopy.append(0); + dstOriginCopy.append(0); + regionCopy.append(1); + + Vector clEvents = WebCLEventVectorToCLEventVector(false, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = clEnqueueCopyImage(m_clCommandQueue, clSrcImageId, clDstImageId, srcOriginCopy.data(), dstOriginCopy.data(), regionCopy.data(), clEvents.size(), clEvents.data(), clEventId); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueCopyImageToBuffer(WebCLImage* srcImage, WebCLBuffer* dstBuffer, const Vector& srcOrigin, const Vector& region, unsigned offset, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_mem clSrcImageId = nullptr; + if (srcImage) { + clSrcImageId = srcImage->getMem(); + if (!clSrcImageId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + cl_mem clDstBufferId = nullptr; + if (dstBuffer) { + clDstBufferId = dstBuffer->getMem(); + if (!clDstBufferId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (!WebCLInputChecker::compareContext(context(), srcImage->context()) || !WebCLInputChecker::compareContext(context(), dstBuffer->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (srcOrigin.size() != 2 || region.size() != 2) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + if (!WebCLInputChecker::isValidRegionForBuffer(dstBuffer->sizeInBytes(), region, offset, srcImage->imageDescriptor()) || !WebCLInputChecker::isValidRegionForImage(srcImage->imageDescriptor(), srcOrigin, region)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector srcOriginCopy, regionCopy; + srcOriginCopy.appendVector(srcOrigin); + regionCopy.appendVector(region); + // No support for 3D-images, so set default values of 0 for all origin & region arrays at 3rd index. + srcOriginCopy.append(0); + regionCopy.append(1); + + Vector clEvents = WebCLEventVectorToCLEventVector(false, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = clEnqueueCopyImageToBuffer(m_clCommandQueue, clSrcImageId, clDstBufferId, srcOriginCopy.data(), regionCopy.data(), offset, clEvents.size(), clEvents.data(), clEventId); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLCommandQueue::enqueueCopyBufferToImage(WebCLBuffer* srcBuffer, WebCLImage* dstImage, unsigned offset, const Vector& dstOrigin, const Vector& region, const Vector>& events, WebCLEvent* event, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return; + } + + cl_mem clSrcBufferId = nullptr; + if (srcBuffer) { + clSrcBufferId = srcBuffer->getMem(); + if (!clSrcBufferId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + cl_mem clDstImageId = nullptr; + if (dstImage) { + clDstImageId = dstImage->getMem(); + if (!clDstImageId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + if (!WebCLInputChecker::compareContext(context(), srcBuffer->context()) || !WebCLInputChecker::compareContext(context(), dstImage->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return; + } + + if (dstOrigin.size() != 2 || region.size() != 2) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + if (!WebCLInputChecker::isValidRegionForBuffer(srcBuffer->sizeInBytes(), region, offset, dstImage->imageDescriptor()) || !WebCLInputChecker::isValidRegionForImage(dstImage->imageDescriptor(), dstOrigin, region)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + Vector targetOriginCopy, regionCopy; + targetOriginCopy.appendVector(dstOrigin); + regionCopy.appendVector(region); + + // No support for 3D-images, so set default values of 0 for all origin & region arrays at 3rd index. + targetOriginCopy.append(0); + regionCopy.append(1); + + Vector clEvents = WebCLEventVectorToCLEventVector(false, events, es); + if (events.size() && clEvents.size() != events.size()) + return; + + cl_event* clEventId = WebCLEventPtrToCLEventPtr(event, es); + if (event && !clEventId) + return; + + cl_int err = clEnqueueCopyBufferToImage(m_clCommandQueue, clSrcBufferId, clDstImageId, offset, targetOriginCopy.data(), regionCopy.data(), clEvents.size(), clEvents.data(), clEventId); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +WebCLCommandQueue::WebCLCommandQueue(cl_command_queue commandQueue, WebCLContext* context, WebCLDevice* device) + : WebCLObject(context) + , m_whenFinishCallback(nullptr) + , m_eventForCallback(0) + , m_device(device) + , m_clCommandQueue(commandQueue) +{ +} + +Vector WebCLCommandQueue::WebCLEventVectorToCLEventVector(bool blocking, Vector> events, ExceptionState& es) +{ + Vector clEvents; + for (auto event : events) { + if (event->isReleased()) { + es.throwWebCLException(WebCLException::INVALID_EVENT_WAIT_LIST, WebCLException::invalidEventWaitListMessage); + break; + } + if (!WebCLInputChecker::compareContext(context(), event->context())) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + break; + } + if (blocking && events[0]->getStatus() == CL_INVALID_VALUE) { + es.throwWebCLException(WebCLException::EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, WebCLException::execStatusErrorForEventsInWaitListMessage); + break; + } + if (blocking && (event->isUserEvent() || !event->setAssociatedCommandQueue(this))) { + es.throwWebCLException(WebCLException::INVALID_EVENT_WAIT_LIST, WebCLException::invalidEventWaitListMessage); + break; + } + + clEvents.append(event->getEvent()); + } + return clEvents; +} + +cl_event* WebCLCommandQueue::WebCLEventPtrToCLEventPtr(WebCLEvent* event, ExceptionState& es) +{ + cl_event* clEventId = nullptr; + if (event) { + clEventId = event->getEventPtr(); + if (!clEventId || !event->setAssociatedCommandQueue(this)) { + es.throwWebCLException(WebCLException::INVALID_EVENT, WebCLException::invalidEventMessage); + return nullptr; + } + } + return clEventId; +} + +bool WebCLCommandQueue::isExtensionEnabled(WebCLContext* context, const String& name) const +{ + return context->isExtensionEnabled(name); +} + +void WebCLCommandQueue::callbackProxy(cl_event event, cl_int type, void* userData) +{ + OwnPtr holder = adoptPtr(static_cast(userData)); + holder->event = event; + holder->type = type; + + if (!isMainThread()) { + Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&WebCLCommandQueue::callbackProxyOnMainThread, holder.release())); + return; + } + + callbackProxyOnMainThread(holder.release()); +} + +void WebCLCommandQueue::callbackProxyOnMainThread(PassOwnPtr holder) +{ + ASSERT(isMainThread()); + RefPtr webCommandQueue(static_cast(holder->commandQueue.get())); + cl_event event = holder->event; + cl_int type = holder->type; + + if (!webCommandQueue) + return; + + // Ignore the callback if the WebCLCommandQueue is released or OpenCL event is abnormally terminated. + // It's possible for its OpenCL object to not be released yet. + if (type != CL_COMPLETE || webCommandQueue->isReleased()) { + webCommandQueue->resetEventAndCallback(); + return; + } + + cl_event clEvent = webCommandQueue->m_eventForCallback; + if (event == clEvent) { + if (webCommandQueue->m_whenFinishCallback) { + webCommandQueue->m_whenFinishCallback->handleEvent(); + } + + webCommandQueue->resetEventAndCallback(); + } +} + +void WebCLCommandQueue::resetEventAndCallback() +{ + if (m_eventForCallback) + clReleaseEvent(m_eventForCallback); + + m_eventForCallback = 0; + m_whenFinishCallback.clear(); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.h b/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.h new file mode 100644 index 0000000000000..beee06a0f65a8 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.h @@ -0,0 +1,117 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLCommandQueue_h +#define WebCLCommandQueue_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLCallback.h" +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLObject.h" + +#include +#include +#include + +namespace blink { + +class DOMArrayBufferView; +class ExceptionState; +class HTMLCanvasElement; +class HTMLImageElement; +class HTMLVideoElement; +class ImageData; +class WebCL; +class WebCLBuffer; +class WebCLCommandQueueHolder; +class WebCLDevice; +class WebCLEvent; +class WebCLEventList; +class WebCLImage; +class WebCLKernel; +class WebCLMemoryObject; +class WebCLProgram; +class WebCLSampler; + +class WebCLCommandQueue : public WebCLObject, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLCommandQueue() override; + static PassRefPtr create(cl_command_queue, WebCLContext*, WebCLDevice*); + + ScriptValue getInfo(ScriptState*, int, ExceptionState&); + void enqueueWriteBuffer(WebCLBuffer*, bool, unsigned, unsigned, DOMArrayBufferView*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteBuffer(WebCLBuffer*, bool, unsigned, ImageData*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteBuffer(WebCLBuffer*, bool, unsigned, HTMLCanvasElement*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteBuffer(WebCLBuffer*, bool, unsigned, HTMLImageElement*, const Vector>&, WebCLEvent*, ExceptionState&); + + void enqueueWriteBufferRect(WebCLBuffer*, bool, const Vector&, const Vector&, const Vector&, unsigned, unsigned, unsigned, unsigned, DOMArrayBufferView*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteBufferRect(WebCLBuffer*, bool, const Vector&, const Vector&, const Vector&, unsigned, unsigned, ImageData*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteBufferRect(WebCLBuffer*, bool, const Vector&, const Vector&, const Vector&, unsigned, unsigned, HTMLCanvasElement*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteBufferRect(WebCLBuffer*, bool, const Vector&, const Vector&, const Vector&, unsigned, unsigned, HTMLImageElement*, const Vector>&, WebCLEvent*, ExceptionState&); + + void enqueueReadBuffer(WebCLBuffer*, bool, unsigned, unsigned, DOMArrayBufferView*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueReadBuffer(WebCLBuffer*, bool, unsigned, unsigned, HTMLCanvasElement*, const Vector>&, WebCLEvent*, ExceptionState&); + + void enqueueReadBufferRect(WebCLBuffer*, bool, const Vector&, const Vector&, const Vector&, unsigned, unsigned, unsigned, unsigned, DOMArrayBufferView*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueReadBufferRect(WebCLBuffer*, bool, const Vector&, const Vector&, const Vector&, unsigned, unsigned, HTMLCanvasElement*, const Vector>&, WebCLEvent*, ExceptionState&); + + void enqueueReadImage(WebCLImage*, bool, const Vector&, const Vector&, unsigned, DOMArrayBufferView*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueReadImage(WebCLImage*, bool, const Vector&, const Vector&, HTMLCanvasElement*, const Vector>&, WebCLEvent*, ExceptionState&); + + void enqueueNDRangeKernel(WebCLKernel*, unsigned, const Vector&, const Vector&, const Vector&, const Vector>&, WebCLEvent*, ExceptionState&); + + void enqueueWriteImage(WebCLImage*, bool, const Vector&, const Vector&, unsigned, DOMArrayBufferView*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteImage(WebCLImage*, bool, const Vector&, const Vector&, ImageData*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteImage(WebCLImage*, bool, const Vector&, const Vector&, HTMLCanvasElement*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteImage(WebCLImage*, bool, const Vector&, const Vector&, HTMLImageElement*, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteImage(WebCLImage*, bool blockingWrite, HTMLVideoElement*, const Vector>&, WebCLEvent*, ExceptionState&); + + void enqueueCopyBuffer(WebCLBuffer*, WebCLBuffer*, unsigned, unsigned, unsigned, const Vector>& events, WebCLEvent* event, ExceptionState&); + void enqueueCopyBufferRect(WebCLBuffer*, WebCLBuffer*, const Vector&, const Vector&, const Vector&, unsigned, unsigned, unsigned, unsigned, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueCopyImage(WebCLImage*, WebCLImage*, const Vector&, const Vector&, const Vector&, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueCopyImageToBuffer(WebCLImage*, WebCLBuffer*, const Vector&, const Vector&, unsigned, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueCopyBufferToImage(WebCLBuffer*, WebCLImage*, unsigned, const Vector&, const Vector&, const Vector>&, WebCLEvent*, ExceptionState&); + + void finish(WebCLCallback* whenFinished, ExceptionState&); + void flush(ExceptionState&); + void release() override; + void enqueueBarrier(ExceptionState&); + void enqueueMarker(WebCLEvent*, ExceptionState&); + void enqueueWaitForEvents(const Vector>&, ExceptionState&); + + enum SyncMethod { + ASYNC, + SYNC + }; + void finishCommandQueues(SyncMethod); + unsigned getProperties(); + bool isReleased() const { return !m_clCommandQueue; } + +private: + void enqueueWriteBufferBase(WebCLBuffer*, bool, unsigned, unsigned, void*, size_t, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueReadBufferBase(WebCLBuffer*, bool, unsigned, unsigned, void*, size_t, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueReadBufferRectBase(WebCLBuffer*, bool, const Vector&, const Vector&, const Vector&, unsigned, unsigned, unsigned, unsigned, void*, size_t, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueReadImageBase(WebCLImage*, bool, const Vector&, const Vector&, unsigned, void*, size_t, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteBufferRectBase(WebCLBuffer*, bool, const Vector&, const Vector&, const Vector&, unsigned, unsigned, unsigned, unsigned, void*, size_t, const Vector>&, WebCLEvent*, ExceptionState&); + void enqueueWriteImageBase(WebCLImage*, bool, const Vector&, const Vector&, unsigned, void*, size_t, const Vector>&, WebCLEvent*, ExceptionState&); + WebCLCommandQueue(cl_command_queue, WebCLContext*, WebCLDevice*); + Vector WebCLEventVectorToCLEventVector(bool, Vector>, ExceptionState&); + cl_event* WebCLEventPtrToCLEventPtr(WebCLEvent*, ExceptionState&); + bool isExtensionEnabled(WebCLContext*, const String& name) const; + static void callbackProxy(cl_event, cl_int, void*); + static void callbackProxyOnMainThread(PassOwnPtr); + void resetEventAndCallback(); + + RefPtr m_whenFinishCallback; + cl_event m_eventForCallback; + WebCLDevice* m_device; + cl_command_queue m_clCommandQueue; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLCommandQueue_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.idl b/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.idl new file mode 100644 index 0000000000000..44f88e2ee5808 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLCommandQueue.idl @@ -0,0 +1,239 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file + +typedef unsigned long CLenum; +typedef boolean CLboolean; +typedef unsigned long CLuint; +[ + Conditional=WEBCL, +] interface WebCLCommandQueue { + // TODO(junmin-zhu) Because WebIDL doesn't support "optional<>" as null. + // So all the function here are implemented through custom binding. Will revisit here when it's supported. + [Custom, RaisesException] void enqueueCopyBuffer(WebCLBuffer srcBuffer, + WebCLBuffer dstBuffer, + CLuint srcOffset, + CLuint dstOffset, + CLuint numBytes, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueCopyBufferRect(WebCLBuffer srcBuffer, + WebCLBuffer dstBuffer, + sequence srcOrigin, + sequence dstOrigin, + sequence region, + CLuint srcRowPitch, + CLuint srcSlicePitch, + CLuint dstRowPitch, + CLuint dstSlicePitch, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueCopyImage(WebCLImage srcImage, + WebCLImage dstImage, + sequence srcOrigin, + sequence dstOrigin, + sequence region, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueCopyImageToBuffer(WebCLImage srcImage, + WebCLBuffer dstBuffer, + sequence srcOrigin, + sequence srcRegion, + CLuint dstOffset, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueCopyBufferToImage(WebCLBuffer srcBuffer, + WebCLImage dstImage, + CLuint srcOffset, + sequence dstOrigin, + sequence dstRegion, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueReadBuffer(WebCLBuffer buffer, + CLboolean blockingRead, + CLuint bufferOffset, + CLuint numBytes, + ArrayBufferView hostPtr, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + // WebIDL doesn't support the same function with different argument with "Custom" keyword, + // Separate them throught argument checking in the manual binding code. + /*[Custom, RaisesException] void enqueueReadBuffer(WebCLBuffer buffer, + CLboolean blockingRead, + CLuint bufferOffset, + CLuint numBytes, + HTMLCanvasElement dstCanvas, + optional sequence? eventWaitList, + optional WebCLEvent? event = null);*/ + + [Custom, RaisesException] void enqueueReadBufferRect(WebCLBuffer buffer, + CLboolean blockingRead, + sequence bufferOrigin, + sequence hostOrigin, + sequence region, + CLuint bufferRowPitch, + CLuint bufferSlicePitch, + CLuint hostRowPitch, + CLuint hostSlicePitch, + ArrayBufferView hostPtr, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + // The same as above comment. + /*[Custom, RaisesException] void enqueueReadBufferRect(WebCLBuffer buffer, + CLboolean blockingRead, + sequence bufferOrigin, + sequence dstOrigin, + sequence region, + CLuint bufferRowPitch, + CLuint bufferSlicePitch, + HTMLCanvasElement dstCanvas, + optional sequence? eventWaitList, + optional WebCLEvent? event = null);*/ + + [Custom, RaisesException] void enqueueReadImage(WebCLImage image, + CLboolean blockingRead, + sequence origin, + sequence region, + CLuint hostRowPitch, + ArrayBufferView hostPtr, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + // The same as above comment. + /*[Custom, RaisesException] void enqueueReadImage(WebCLImage image, + CLboolean blockingRead, + sequence origin, + sequence region, + HTMLCanvasElement dstCanvas, + optional sequence? eventWaitList, + optional WebCLEvent? event = null);*/ + + [Custom, RaisesException] void enqueueWriteBuffer(WebCLBuffer bufferId, + CLboolean blockingWrite, + CLuint bufferOffset, + CLuint numBytes, + ArrayBufferView hostPtr, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + // The same as above comment. + /*[Custom, RaisesException] void enqueueWriteBuffer(WebCLBuffer buffer, + CLboolean blockingWrite, + CLuint bufferOffset, + ImageData srcPixels, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueWriteBuffer(WebCLBuffer buffer, + CLboolean blockingWrite, + CLuint bufferOffset, + HTMLCanvasElement srcCanvas, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueWriteBuffer(WebCLBuffer buffer, + CLboolean blockingWrite, + CLuint bufferOffset, + HTMLImageElement srcImage, + optional sequence? eventWaitList, + optional WebCLEvent? event = null);*/ + + [Custom, RaisesException] void enqueueWriteBufferRect(WebCLBuffer buffer, + CLboolean blockingWrite, + sequence bufferOrigin, + sequence hostOrigin, + sequence region, + CLuint bufferRowPitch, + CLuint bufferSlicePitch, + CLuint hostRowPitch, + CLuint hostSlicePitch, + ArrayBufferView hostPtr, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + // The same as above comment. + /*[Custom, RaisesException] void enqueueWriteBufferRect(WebCLBuffer buffer, + CLboolean blockingWrite, + sequence bufferOrigin, + sequence srcOrigin, + sequence region, + CLuint bufferRowPitch, + CLuint bufferSlicePitch, + ImageData srcPixels, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueWriteBufferRect(WebCLBuffer buffer, + CLboolean blockingWrite, + sequence bufferOrigin, + sequence srcOrigin, + sequence region, + CLuint bufferRowPitch, + CLuint bufferSlicePitch, + HTMLCanvasElement srcCanvas, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueWriteBufferRect(WebCLBuffer buffer, + CLboolean blockingWrite, + sequence bufferOrigin, + sequence srcOrigin, + sequence region, + CLuint bufferRowPitch, + CLuint bufferSlicePitch, + HTMLImageElement srcImage, + optional sequence? eventWaitList, + optional WebCLEvent? event = null);*/ + + [Custom, RaisesException] void enqueueWriteImage(WebCLImage image, + CLboolean blockingWrite, + sequence origin, + sequence region, + CLuint hostRowPitch, + ArrayBufferView hostPtr, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + // The same as above comment. + /*[Custom, RaisesException] void enqueueWriteImage(WebCLImage image, + CLboolean blockingWrite, + sequence origin, + sequence region, + ImageData srcPixels, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueWriteImage(WebCLImage image, + CLboolean blockingWrite, + sequence origin, + sequence region, + HTMLCanvasElement srcCanvas, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [Custom, RaisesException] void enqueueWriteImage(WebCLImage image, + CLboolean blockingWrite, + sequence origin, + sequence region, + HTMLImageElement srcImage, + optional sequence? eventWaitList, + optional WebCLEvent? event = null);*/ + + [Custom, RaisesException] void enqueueNDRangeKernel(WebCLKernel kernel, + CLuint workDim, + sequence? offsets, + sequence globalWorkSize, + optional sequence? localWorkSize, + optional sequence? eventWaitList, + optional WebCLEvent? event = null); + + [RaisesException] void enqueueMarker(WebCLEvent event); + [RaisesException] void enqueueBarrier(); + [RaisesException] void enqueueWaitForEvents(sequence events); + [RaisesException] void finish(optional WebCLCallback whenFinished); + [RaisesException] void flush() ; + [CallWith=ScriptState, RaisesException] any getInfo(CLenum queuenfo); + void release(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLConfig.h b/third_party/WebKit/Source/modules/webcl/WebCLConfig.h new file mode 100644 index 0000000000000..8220afa1b4f88 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLConfig.h @@ -0,0 +1,30 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBCL_CONFIG_H__ +#define WEBCL_CONFIG_H__ + +#if ENABLE(WEBCL) + +#include "bindings/core/v8/ScriptWrappable.h" +#include "bindings/core/v8/ScriptState.h" +#include "platform/Logging.h" +#include +#include +#include +#include +#include +#include +#include +#include + +typedef cl_int GLint; +typedef cl_uint GLuint; +typedef cl_uint GLenum; + +#define MULTI_EXTENSIONS_LENGTH 1024 +#define SINGLE_EXTENSION_LENGTH 64 + +#endif // ENABLE(WEBCL) +#endif // WebCLConfig_H diff --git a/third_party/WebKit/Source/modules/webcl/WebCLContext.cpp b/third_party/WebKit/Source/modules/webcl/WebCLContext.cpp new file mode 100644 index 0000000000000..d3125be541238 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLContext.cpp @@ -0,0 +1,728 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/modules/v8/V8WebCLDevice.h" +#include "core/html/HTMLCanvasElement.h" +#include "core/html/HTMLImageElement.h" +#include "core/html/HTMLVideoElement.h" +#include "core/html/ImageData.h" +#include "core/webcl/WebCLException.h" +#include "platform/graphics/Image.h" +#include "platform/graphics/ImageBuffer.h" +#include "bindings/core/v8/V8Binding.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLBuffer.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLCommandQueue.h" +#include "modules/webcl/WebCLDevice.h" +#include "modules/webcl/WebCLHTMLUtil.h" +#include "modules/webcl/WebCLImage.h" +#include "modules/webcl/WebCLImageDescriptor.h" +#include "modules/webcl/WebCLInputChecker.h" +#include "modules/webcl/WebCLKernel.h" +#include "modules/webcl/WebCLMemoryObject.h" +#include "modules/webcl/WebCLMemoryUtil.h" +#include "modules/webcl/WebCLObject.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLSampler.h" +#include "modules/webcl/WebCLUserEvent.h" + +namespace blink { + +WebCLContext::~WebCLContext() +{ + releaseAll(); + ASSERT(!m_clContext); +} + +PassRefPtr WebCLContext::create(cl_context contextId, WebCL* webCL, const Vector>& devices, HashSet& enabledExtensions) +{ + return adoptRef(new WebCLContext(contextId, webCL, devices, enabledExtensions)); +} + +ScriptValue WebCLContext::getInfo(ScriptState* scriptState, int paramName, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_int err = CL_SUCCESS; + cl_uint uintUnits = 0; + Vector> result; + switch(paramName) { + case CL_CONTEXT_NUM_DEVICES: + err = clGetContextInfo(m_clContext,CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); + case CL_CONTEXT_DEVICES: + return ScriptValue(scriptState, toV8(m_devices, creationContext, isolate)); + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } +} + +PassRefPtr WebCLContext::createCommandQueue(WebCLDevice* device, unsigned commandQueueProp, ExceptionState& es) +{ + if (!WebCLInputChecker::isValidCommandQueueProperty(commandQueueProp)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + cl_device_id clDevice = nullptr; + // NOTE: if device is null, it will be selected by any WebCLDevice that matches Properties + if (!device) { + for (auto deviceItem : m_devices) { + unsigned properties = deviceItem->getQueueProperties(); + if (!commandQueueProp || (properties && (properties & commandQueueProp))) { + device = deviceItem.get(); + clDevice = deviceItem->getDeviceId(); + break; + } else { + es.throwWebCLException(WebCLException::INVALID_QUEUE_PROPERTIES, WebCLException::invalidQueuePropertiesMessage); + return nullptr; + } + } + } else { + clDevice = device->getDeviceId(); + size_t i = 0; + for (i = 0; i < m_devices.size(); ++i) { + if (m_devices[i]->getDeviceId() == clDevice) + break; + } + if (i == m_devices.size()) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return nullptr; + } + } + + cl_int err = CL_SUCCESS; + cl_command_queue clCommandQueueId = nullptr; + switch (commandQueueProp) { + case CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE: + clCommandQueueId = clCreateCommandQueue(m_clContext, clDevice, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err); + break; + case CL_QUEUE_PROFILING_ENABLE: + clCommandQueueId = clCreateCommandQueue(m_clContext, clDevice, CL_QUEUE_PROFILING_ENABLE, &err); + break; + default: + clCommandQueueId = clCreateCommandQueue(m_clContext, clDevice, 0, &err); + break; + } + + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + + RefPtr commandQueue = WebCLCommandQueue::create(clCommandQueueId, this, device); + if (!commandQueue) { + es.throwWebCLException(WebCLException::INVALID_COMMAND_QUEUE, WebCLException::invalidCommandQueueMessage); + return nullptr; + } + + if (commandQueue) + m_memoryUtil->commandQueueCreated(commandQueue.get(), es); + + return commandQueue.release(); +} + +PassRefPtr WebCLContext::createCommandQueue(int properties,ExceptionState& es) +{ + return createCommandQueue(nullptr, properties, es); +} + +PassRefPtr WebCLContext::createCommandQueue(WebCLDevice* device, ExceptionState& es) +{ + return createCommandQueue(device, 0, es); +} + +PassRefPtr WebCLContext::createCommandQueue(ExceptionState& es) +{ + return createCommandQueue(nullptr, 0, es); +} + +PassRefPtr WebCLContext::createProgram(const String& kernelSource, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return nullptr; + } + + if (!kernelSource.length()) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + const char* source = strdup(kernelSource.utf8().data()); + cl_int err = CL_SUCCESS; + cl_program clProgramId = clCreateProgramWithSource(m_clContext, 1, (const char**)&source, nullptr, &err); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + + RefPtr program = WebCLProgram::create(clProgramId, this, kernelSource); + if (!program) { + es.throwWebCLException(WebCLException::INVALID_PROGRAM, WebCLException::invalidProgramMessage); + return nullptr; + } + + return program.release(); +} + +PassRefPtr WebCLContext::createSampler(bool normCords, unsigned addrMode, unsigned fltrMode, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return nullptr; + } + + if (!WebCLInputChecker::isValidAddressingMode(addrMode) || !WebCLInputChecker::isValidFilterMode(fltrMode)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + if (!normCords && (addrMode == CL_ADDRESS_REPEAT || addrMode == CL_ADDRESS_MIRRORED_REPEAT)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + cl_bool normalizedCoords = CL_FALSE; + if (normCords) + normalizedCoords = CL_TRUE; + + cl_addressing_mode addressingMode; + switch(addrMode) { + case CL_ADDRESS_CLAMP_TO_EDGE: + addressingMode = CL_ADDRESS_CLAMP_TO_EDGE; + break; + case CL_ADDRESS_CLAMP: + addressingMode = CL_ADDRESS_CLAMP; + break; + case CL_ADDRESS_REPEAT: + addressingMode = CL_ADDRESS_REPEAT; + break; + case CL_ADDRESS_MIRRORED_REPEAT: + addressingMode = CL_ADDRESS_MIRRORED_REPEAT; + break; + default: + es.throwWebCLException(WebCLException::FAILURE, WebCLException::failureMessage); + return nullptr; + } + + cl_filter_mode filterMode = CL_FILTER_NEAREST; + switch(fltrMode) { + case CL_FILTER_LINEAR: + filterMode = CL_FILTER_LINEAR; + break; + case CL_FILTER_NEAREST : + filterMode = CL_FILTER_NEAREST ; + break; + default: + es.throwWebCLException(WebCLException::FAILURE, WebCLException::failureMessage); + return nullptr; + } + + cl_int err = CL_SUCCESS; + cl_sampler clSamplerId = clCreateSampler(m_clContext, normalizedCoords, addressingMode, filterMode, &err); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + + RefPtr sampler = WebCLSampler::create(clSamplerId, normCords, addrMode, fltrMode, this); + if (!sampler) { + es.throwWebCLException(WebCLException::FAILURE, WebCLException::failureMessage); + return nullptr; + } + + return sampler.release(); +} + +PassRefPtr WebCLContext::createUserEvent(ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return nullptr; + } + + RefPtr event = WebCLUserEvent::create(this, es); + return event.release(); +} + +PassRefPtr WebCLContext::createBufferBase(unsigned memFlags, unsigned sizeInBytes, void* hostPtr, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return nullptr; + } + + if (!WebCLInputChecker::isValidMemoryObjectFlag(memFlags)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + unsigned num = 0 ; + for (size_t i = 0; i < m_devices.size(); ++i) { + unsigned maxMemAllocSize = m_devices[i]->getMaxMemAllocSize(); + if (maxMemAllocSize && maxMemAllocSize < sizeInBytes) { + num++; + } + } + + if (num != 0 && num == m_devices.size()) { + es.throwWebCLException(WebCLException::INVALID_BUFFER_SIZE, WebCLException::invalidBufferSizeMessage); + return nullptr; + } + + if (sizeInBytes == 0) { + es.throwWebCLException(WebCLException::INVALID_BUFFER_SIZE, WebCLException::invalidBufferSizeMessage); + return nullptr; + } + RefPtr buffer = WebCLBuffer::create(this, memFlags, sizeInBytes, hostPtr, es); + if (!hostPtr && buffer) + m_memoryUtil->bufferCreated(buffer.get(), es); + + return buffer.release(); +} + +PassRefPtr WebCLContext::createBuffer(unsigned memFlags, unsigned sizeInBytes, DOMArrayBufferView* hostPtr, ExceptionState& es) +{ + RefPtr buffer; + if (hostPtr) { + if (hostPtr->byteLength() < sizeInBytes) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return nullptr; + } + + if (!hostPtr->buffer()) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return nullptr; + } + buffer = hostPtr->buffer(); + } + + return createBufferBase(memFlags, sizeInBytes, buffer ? buffer->data() : nullptr, es); +} + +PassRefPtr WebCLContext::createBuffer(unsigned memFlags, unsigned sizeInBytes, ExceptionState& es) +{ + return createBuffer(memFlags, sizeInBytes, nullptr, es); +} + +PassRefPtr WebCLContext::createBuffer(unsigned memoryFlags, ImageData* srcPixels, ExceptionState& es) +{ + if (!isExtensionEnabled("WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return nullptr; + } + + void* hostPtr = 0; + size_t pixelSize = 0; + if (!WebCLHTMLUtil::extractDataFromImageData(srcPixels, hostPtr, pixelSize, es)) + return nullptr; + + return createBufferBase(memoryFlags, pixelSize, hostPtr, es); +} + +PassRefPtr WebCLContext::createBuffer(unsigned memoryFlags, HTMLCanvasElement* srcCanvas, ExceptionState& es) +{ + if (!isExtensionEnabled("WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return nullptr; + } + + Vector data; + size_t canvasSize = 0; + if (!WebCLHTMLUtil::extractDataFromCanvas(srcCanvas, data, canvasSize, es)) + return nullptr; + + void* hostPtr = data.data(); + return createBufferBase(memoryFlags, canvasSize, hostPtr, es); +} + +PassRefPtr WebCLContext::createBuffer(unsigned memoryFlags, HTMLImageElement* srcImage, ExceptionState& es) +{ + if (!isExtensionEnabled("WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return nullptr; + } + + Vector data; + size_t bufferSize = 0; + if (!WebCLHTMLUtil::extractDataFromImage(srcImage, data, bufferSize, es)) + return nullptr; + + void* hostPtr = data.data(); + return createBufferBase(memoryFlags, bufferSize, hostPtr, es); +} + +PassRefPtr WebCLContext::createImage2DBase(unsigned flags, unsigned width, unsigned height, unsigned rowPitch, unsigned channelOrder, unsigned channelType, void* data, ExceptionState& es) +{ + if (!width || !height) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_FORMAT_DESCRIPTOR, WebCLException::invalidImageFormatDescriptorMessage); + return nullptr; + } + + if (!WebCLInputChecker::isValidMemoryObjectFlag(flags)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + ASSERT(data); + flags |= CL_MEM_COPY_HOST_PTR; + WebCLImageDescriptor imageDescriptor; + imageDescriptor.setWidth(width); + imageDescriptor.setHeight(height); + imageDescriptor.setRowPitch(rowPitch); + imageDescriptor.setChannelOrder(channelOrder); + imageDescriptor.setChannelType(channelType); + cl_image_format image_format = {channelOrder, channelType}; + + cl_int err = CL_SUCCESS; + cl_mem clMemId = clCreateImage2D(m_clContext, flags, &image_format, width, height, rowPitch, data, &err); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + + RefPtr image = WebCLImage::create(clMemId, imageDescriptor, this); + return image.release(); +} + +PassRefPtr WebCLContext::createImage(unsigned flags, const WebCLImageDescriptor& descriptor, DOMArrayBufferView* hostPtr, ExceptionState& es) +{ + if (!WebCLInputChecker::isValidMemoryObjectFlag(flags)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + unsigned width = descriptor.width(); + unsigned height = descriptor.height(); + unsigned rowPitch = descriptor.rowPitch(); + unsigned channelOrder = descriptor.channelOrder(); + unsigned channelType = descriptor.channelType(); + unsigned numberOfChannels = WebCLContext::numberOfChannelsForChannelOrder(channelOrder); + unsigned bytesPerChannel = WebCLContext::bytesPerChannelType(channelType); + + if (!WebCLInputChecker::isValidChannelOrder(channelOrder) || !WebCLInputChecker::isValidChannelType(channelType)) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_FORMAT_DESCRIPTOR, WebCLException::invalidImageFormatDescriptorMessage); + return nullptr; + } + + if ((!hostPtr && rowPitch) || (hostPtr && rowPitch > 0 && rowPitch < (width * numberOfChannels * bytesPerChannel))) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_SIZE, WebCLException::invalidImageSizeMessage); + return nullptr; + } + + if (!supportsWidthHeight(width, height, es)) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_SIZE, WebCLException::invalidImageSizeMessage); + return nullptr; + } + RefPtr buffer; + if (hostPtr) { + unsigned byteLength = hostPtr->byteLength(); + if ((rowPitch && byteLength < (rowPitch * height)) || byteLength < (width * height * numberOfChannels * bytesPerChannel)) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return nullptr; + } + buffer = hostPtr->buffer(); + } else { + buffer = DOMArrayBuffer::create(width * height * numberOfChannels * bytesPerChannel, 1); + } + + return createImage2DBase(flags, width, height, rowPitch, channelOrder, channelType, buffer->data(), es); +} + +PassRefPtr WebCLContext::createImage(unsigned memFlags, const WebCLImageDescriptor& descriptor, ExceptionState& es) +{ + return createImage(memFlags, descriptor, nullptr, es); +} + +PassRefPtr WebCLContext::createImage(unsigned flags, HTMLCanvasElement* srcCanvas, ExceptionState& es) +{ + if (!isExtensionEnabled("WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return nullptr; + } + + unsigned width = srcCanvas->width(); + unsigned height = srcCanvas->height(); + if (!supportsWidthHeight(width, height, es)) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_SIZE, WebCLException::invalidImageSizeMessage); + return nullptr; + } + + Vector data; + size_t canvasSize = 0; + if (!WebCLHTMLUtil::extractDataFromCanvas(srcCanvas, data, canvasSize, es)) + return nullptr; + void* hostPtr = data.data(); + return createImage2DBase(flags, width, height, 0, CL_RGBA, CL_UNORM_INT8, hostPtr, es); +} + +PassRefPtr WebCLContext::createImage(unsigned flags, HTMLImageElement* srcImage, ExceptionState& es) +{ + if (!isExtensionEnabled("WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return nullptr; + } + + unsigned width = srcImage->width(); + unsigned height = srcImage->height(); + if (!supportsWidthHeight(width, height, es)) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_SIZE, WebCLException::invalidImageSizeMessage); + return nullptr; + } + + Vector data; + size_t bufferSize = 0; + if (!WebCLHTMLUtil::extractDataFromImage(srcImage, data, bufferSize, es)) + return nullptr; + + void* hostPtr = data.data(); + return createImage2DBase(flags, width, height, 0, CL_RGBA, CL_UNORM_INT8, hostPtr, es); +} + +PassRefPtr WebCLContext::createImage(unsigned flags, HTMLVideoElement* video, ExceptionState& es) +{ + if (!isExtensionEnabled("WEBCL_html_video")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return nullptr; + } + + if (CL_MEM_READ_ONLY != flags) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return nullptr; + } + + unsigned width = video->clientWidth(); + unsigned height = video->clientHeight(); + if (!supportsWidthHeight(width, height, es)) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_SIZE, WebCLException::invalidImageSizeMessage); + return nullptr; + } + + Vector data; + size_t videoSize = 0; + if (!m_HTMLUtil->extractDataFromVideo(video, data, videoSize, es)) + return nullptr; + + void* hostPtr = data.data(); + return createImage2DBase(flags, width, height, 0, CL_RGBA, CL_UNORM_INT8, hostPtr, es); +} + +PassRefPtr WebCLContext::createImage(unsigned flags, ImageData* srcPixels, ExceptionState& es) +{ + if (!isExtensionEnabled("WEBCL_html_image")) { + es.throwWebCLException(WebCLException::EXTENSION_NOT_ENABLED, WebCLException::extensionNotEnabledMessage); + return nullptr; + } + + void* hostPtr = 0; + size_t pixelSize = 0; + if(!WebCLHTMLUtil::extractDataFromImageData(srcPixels, hostPtr, pixelSize, es)) + return nullptr; + + unsigned width = srcPixels->width(); + unsigned height = srcPixels->height(); + return createImage2DBase(flags, width, height, 0, CL_RGBA, CL_UNORM_INT8, hostPtr, es); +} + +Nullable> WebCLContext::getSupportedImageFormats(ExceptionState& es) +{ + return getSupportedImageFormats(CL_MEM_READ_WRITE, es); +} + +Nullable> WebCLContext::getSupportedImageFormats(unsigned memFlags, ExceptionState& es) +{ + HeapVector supportedImageDescriptor; + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_CONTEXT, WebCLException::invalidContextMessage); + return supportedImageDescriptor; + } + + if (!WebCLInputChecker::isValidMemoryObjectFlag(memFlags)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return supportedImageDescriptor; + } + + cl_uint numberOfSupportedImageFormats = 0; + cl_int err = clGetSupportedImageFormats(m_clContext, memFlags, CL_MEM_OBJECT_IMAGE2D, 0, 0, &numberOfSupportedImageFormats); + + if (err != CL_SUCCESS) { + es.throwWebCLException(WebCLException::INVALID_IMAGE_SIZE, WebCLException::invalidImageSizeMessage); + return supportedImageDescriptor; + } + + Vector supportedImages; + supportedImages.reserveCapacity(numberOfSupportedImageFormats); + supportedImages.resize(numberOfSupportedImageFormats); + + err = clGetSupportedImageFormats(m_clContext, memFlags, CL_MEM_OBJECT_IMAGE2D, numberOfSupportedImageFormats, supportedImages.data(), 0); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + } else { + for (size_t i = 0; i < static_cast(numberOfSupportedImageFormats); ++i) { + if (WebCLInputChecker::isValidChannelOrder(supportedImages[i].image_channel_order) && WebCLInputChecker::isValidChannelType(supportedImages[i].image_channel_data_type)) { + WebCLImageDescriptor des; + des.setChannelOrder(supportedImages[i].image_channel_order); + des.setChannelType(supportedImages[i].image_channel_data_type); + supportedImageDescriptor.append(des); + } + } + } + + return supportedImageDescriptor; +} + +void WebCLContext::release() +{ + if (isReleased()) + return; + + cl_int err = clReleaseContext(m_clContext); + if (err != CL_SUCCESS) + ASSERT_NOT_REACHED(); + + m_clContext = 0; +} + +void WebCLContext::releaseAll() +{ + if (isReleased()) + return; + + if (m_webCLObjects.size()) { + for (int i = m_webCLObjects.size() - 1; i >= 0; i--) { + WebCLObject* object = m_webCLObjects[i].get(); + if (!object) + continue; + object->release(); + } + m_webCLObjects.clear(); + } + + release(); +} + +void WebCLContext::trackReleaseableWebCLObject(WeakPtr object) +{ + m_webCLObjects.append(object); +} + +void WebCLContext::untrackReleaseableWebCLObject(WeakPtr object) +{ + unsigned int i = m_webCLObjects.find(object); + if (i != kNotFound) + m_webCLObjects.remove(i); +} + +unsigned WebCLContext::bytesPerChannelType(unsigned channelType) +{ + switch(channelType) { + case CL_SNORM_INT8: + case CL_UNORM_INT8: + case CL_SIGNED_INT8: + case CL_UNSIGNED_INT8: + return 1; + case CL_SNORM_INT16: + case CL_UNORM_INT16: + case CL_SIGNED_INT16: + case CL_UNSIGNED_INT16: + case CL_HALF_FLOAT: + return 2; + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT32: + case CL_FLOAT: + return 4; + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + case CL_UNORM_INT_101010: + break; + } + + return 0; +} + +unsigned WebCLContext::numberOfChannelsForChannelOrder(unsigned order) +{ + switch (order) { + case CL_R: + case CL_A: + case CL_INTENSITY: + case CL_LUMINANCE: + return 1; + case CL_RG: + case CL_RA: + case CL_Rx: + return 2; + case CL_RGB: + case CL_RGx: + return 3; + case CL_RGBA: + case CL_BGRA: + case CL_ARGB: + case CL_RGBx: + return 4; + } + + return 0; +} + +WebCLContext::WebCLContext(cl_context context, WebCL* webCL, const Vector>& devices, HashSet& enabledExtensions) + : m_devices(devices) + , m_enabledExtensions(enabledExtensions) + , m_weakFactory(this) + , m_clContext(context) +{ + if (isExtensionEnabled("WEBCL_html_video")) + m_HTMLUtil = adoptPtr(new WebCLHTMLUtil()); + else + m_HTMLUtil = nullptr; + + m_memoryUtil = adoptPtr(new WebCLMemoryUtil(this)); + webCL->trackReleaseableWebCLContext(m_weakFactory.createWeakPtr()); +} + +// Private method to check if {width, height} can be accomodated in any of the context devices. +bool WebCLContext::supportsWidthHeight(unsigned width, unsigned height, ExceptionState& es) +{ + if (m_devices.size() && !m_deviceMaxValues.size()) { + unsigned deviceMaxWidth = 0, deviceMaxHeight = 0; + for (auto device : m_devices) { + deviceMaxWidth = device->getImage2DMaxWidth(); + deviceMaxHeight = device->getImage2DMaxHeight(); + if (deviceMaxWidth && deviceMaxHeight) + m_deviceMaxValues.add(device.get(), std::make_pair(deviceMaxWidth, deviceMaxHeight)); + } + } + + for (auto it : m_deviceMaxValues) { + if (width <= it.value.first && height <= it.value.second) + return true; + } + + return false; +} + +bool WebCLContext::isExtensionEnabled(const String& name) const +{ + return m_enabledExtensions.contains(name); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLContext.h b/third_party/WebKit/Source/modules/webcl/WebCLContext.h new file mode 100644 index 0000000000000..0067542f5a1cc --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLContext.h @@ -0,0 +1,102 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLContext_h +#define WebCLContext_h + +#if ENABLE(WEBCL) +#include "bindings/core/v8/Nullable.h" +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLDevice.h" +#include +#include +#include +#include + +namespace blink { + +class ExceptionState; +class DOMArrayBufferView; +class HTMLCanvasElement; +class HTMLImageElement; +class HTMLVideoElement; +class ImageBuffer; +class ImageData; +class IntSize; +class WebCL; +class WebCLBuffer; +class WebCLCommandQueue; +class WebCLHTMLUtil; +class WebCLImage; +class WebCLImageDescriptor; +class WebCLMemoryUtil; +class WebCLObject; +class WebCLProgram; +class WebCLSampler; +class WebCLUserEvent; + +class WebCLContext : public RefCounted, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLContext(); + static PassRefPtr create(cl_context, WebCL*, const Vector>&, HashSet&); + + ScriptValue getInfo(ScriptState*, int, ExceptionState&); + PassRefPtr createCommandQueue(WebCLDevice*, unsigned, ExceptionState&); + PassRefPtr createCommandQueue(int, ExceptionState&); + PassRefPtr createCommandQueue(WebCLDevice*, ExceptionState&); + PassRefPtr createCommandQueue(ExceptionState& es); + PassRefPtr createProgram(const String&, ExceptionState&); + PassRefPtr createSampler(bool, unsigned, unsigned, ExceptionState&); + PassRefPtr createUserEvent(ExceptionState&); + PassRefPtr createBuffer(unsigned, unsigned, DOMArrayBufferView*, ExceptionState&); + PassRefPtr createBuffer(unsigned, unsigned, ExceptionState&); + PassRefPtr createBuffer(unsigned, ImageData*, ExceptionState&); + PassRefPtr createBuffer(unsigned, HTMLCanvasElement*, ExceptionState&); + PassRefPtr createBuffer(unsigned, HTMLImageElement*, ExceptionState&); + PassRefPtr createImage(unsigned, const WebCLImageDescriptor&, DOMArrayBufferView*, ExceptionState&); + PassRefPtr createImage(unsigned, const WebCLImageDescriptor&, ExceptionState&); + PassRefPtr createImage(unsigned, ImageData*, ExceptionState&); + PassRefPtr createImage(unsigned, HTMLCanvasElement*, ExceptionState&); + PassRefPtr createImage(unsigned, HTMLImageElement*, ExceptionState&); + PassRefPtr createImage(unsigned, HTMLVideoElement*, ExceptionState&); + Nullable> getSupportedImageFormats(ExceptionState&); + Nullable> getSupportedImageFormats(unsigned, ExceptionState&); + void release(); + void releaseAll(); + + void trackReleaseableWebCLObject(WeakPtr); + void untrackReleaseableWebCLObject(WeakPtr); + static unsigned bytesPerChannelType(unsigned); + static unsigned numberOfChannelsForChannelOrder(unsigned); + bool isExtensionEnabled(const String& name) const; + const Vector>& getDevices() { return m_devices; } + void setDevices(const Vector>& deviceList) { m_devices = deviceList; } + WebCLHTMLUtil* getHTMLUtil() const { return m_HTMLUtil.get(); } + cl_context getContext() const { return m_clContext; } + +private: + WebCLContext(cl_context, WebCL*, const Vector>&, HashSet&); + bool isReleased() const { return !m_clContext; } + + typedef HashMap> MaximumWidthAndHeightForDevice; + PassRefPtr createImage2DBase(unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, void*, ExceptionState&); + PassRefPtr createBufferBase(unsigned memoryFlags, unsigned size, void* data, ExceptionState&); + bool supportsWidthHeight(unsigned width, unsigned height, ExceptionState&); + + Vector> m_devices; + HashSet m_enabledExtensions; + MaximumWidthAndHeightForDevice m_deviceMaxValues; + OwnPtr m_memoryUtil; + OwnPtr m_HTMLUtil; + Vector> m_webCLObjects; + WeakPtrFactory m_weakFactory; + cl_context m_clContext; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLContext_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLContext.idl b/third_party/WebKit/Source/modules/webcl/WebCLContext.idl new file mode 100644 index 0000000000000..643593e466697 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLContext.idl @@ -0,0 +1,29 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef unsigned long CLenum; +typedef unsigned long CLuint; +typedef boolean CLboolean; +[ + Conditional=WEBCL, +] interface WebCLContext { + [RaisesException] WebCLBuffer createBuffer(CLenum memFlags, ImageData hostPtr); + [RaisesException] WebCLBuffer createBuffer(CLenum memFlags, HTMLCanvasElement hostPtr); + [RaisesException] WebCLBuffer createBuffer(CLenum memFlags, HTMLImageElement hostPtr); + [RaisesException] WebCLBuffer createBuffer(CLenum memFlags, CLuint sizeInBytes, optional ArrayBufferView hostPtr); + [RaisesException] WebCLCommandQueue createCommandQueue(optional WebCLDevice? device, optional CLenum properties); + [RaisesException] WebCLImage createImage(CLenum memFlags, ImageData hostPtr); + [RaisesException] WebCLImage createImage(CLenum memFlags, HTMLCanvasElement hostPtr); + [RaisesException] WebCLImage createImage(CLenum memFlags, HTMLImageElement hostPtr); + [RaisesException] WebCLImage createImage(CLenum memFlags, HTMLVideoElement hostPtr); + [RaisesException] WebCLImage createImage(CLenum memFlags, [PermissiveDictionaryConversion] WebCLImageDescriptor descriptor, optional ArrayBufferView hostPtr); + [RaisesException] WebCLProgram createProgram(DOMString source); + [RaisesException] WebCLSampler createSampler(CLboolean normalizedCoords, CLenum addressingMode, CLenum filterMode); + [RaisesException] WebCLUserEvent createUserEvent(); + [CallWith=ScriptState, RaisesException] any getInfo(CLenum name); + [RaisesException] sequence? getSupportedImageFormats(CLenum memFlags); + [RaisesException] sequence? getSupportedImageFormats(); + void release(); + void releaseAll(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLDevice.cpp b/third_party/WebKit/Source/modules/webcl/WebCLDevice.cpp new file mode 100644 index 0000000000000..f6a02cbc56130 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLDevice.cpp @@ -0,0 +1,472 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/modules/v8/V8WebCLPlatform.h" +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLDevice.h" +#include "modules/webcl/WebCLOpenCL.h" + +namespace blink { + +WebCLDevice::~WebCLDevice() +{ + // Unlike WebCLContext / WebCLCommandQueue / WebCLProgram / ..., + // WebCLDevice does not need to call a release() method here: + // 1) OpenCL 1.1 runtime has no clReleaseDevice() or an alternative, so + // there's no need to release the device. + // 2) The OpenCL 1.2 (or above) spec implies that clReleaseDevice() is only + // meaningful for sub devices, but no sub device is created in our WebCL + // 1.0 implementation. +} + +PassRefPtr WebCLDevice::create(cl_device_id deviceId) +{ + return adoptRef(new WebCLDevice(deviceId, nullptr)); +} + +PassRefPtr WebCLDevice::create(cl_device_id deviceId, WebCLPlatform* platform) +{ + return adoptRef(new WebCLDevice(deviceId, platform)); +} + +unsigned WebCLDevice::getQueueProperties() +{ + cl_command_queue_properties queueProperties = 0; + clGetDeviceInfo(m_clDeviceId, CL_DEVICE_QUEUE_PROPERTIES, sizeof(cl_command_queue_properties), &queueProperties, nullptr); + return static_cast(queueProperties); +} + +unsigned long long WebCLDevice::getMaxMemAllocSize() +{ + cl_ulong ulongUnits = 0; + clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &ulongUnits, nullptr); + return static_cast(ulongUnits); +} + +unsigned WebCLDevice::getImage2DMaxWidth() +{ + size_t sizetUnits = 0; + clGetDeviceInfo(m_clDeviceId, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &sizetUnits, nullptr); + return static_cast(sizetUnits); +} + +unsigned WebCLDevice::getImage2DMaxHeight() +{ + size_t sizetUnits = 0; + clGetDeviceInfo(m_clDeviceId, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &sizetUnits, nullptr); + return static_cast(sizetUnits); +} + +unsigned WebCLDevice::getMaxWorkGroup() +{ + size_t sizetUnits = 0; + clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &sizetUnits, nullptr); + return static_cast(sizetUnits); +} + +Vector WebCLDevice::getMaxWorkItem() +{ + size_t sizetUnits = 0; + size_t sizetArray[3] = {0}; + cl_int err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) { + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(sizetArray), &sizetArray, nullptr); + if (err == CL_SUCCESS) { + Vector values; + for (unsigned i = 0; i < static_cast(sizetUnits); ++i) + values.append(static_cast(sizetArray[i])); + return values; + } + } + return Vector(); +} + +ScriptValue WebCLDevice::getInfo(ScriptState* scriptState, unsigned deviceType, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (!m_clDeviceId) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + if (!WebCLInputChecker::isValidDeviceInfoType(deviceType)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_int err = CL_SUCCESS; + char deviceString[1024]; + cl_uint uintUnits = 0; + size_t sizetUnits = 0; + cl_ulong ulongUnits = 0; + cl_uint infoValue = 0; + cl_bool boolUnits = false; + cl_device_type type = 0; + cl_device_fp_config deviceFPConfig = 0; + cl_device_mem_cache_type globalType = 0; + cl_device_exec_capabilities exec = 0; + cl_device_local_mem_type localType = 0; + + switch(deviceType) { + case CL_DEVICE_PROFILE: + return ScriptValue(scriptState, v8String(isolate, String("WEBCL_PROFILE"))); + case CL_DEVICE_VERSION: + return ScriptValue(scriptState, v8String(isolate, String("WebCL 1.0"))); + case CL_DEVICE_OPENCL_C_VERSION: + return ScriptValue(scriptState, v8String(isolate, String("WebCL C 1.0"))); + case CL_DEVICE_EXTENSIONS: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_EXTENSIONS, sizeof(deviceString), &deviceString, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8String(isolate, String(deviceString))); + break; + case CL_DEVICE_NAME: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_NAME, sizeof(deviceString), &deviceString, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8String(isolate, String(deviceString))); + break; + case CL_DEVICE_VENDOR: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_VENDOR, sizeof(deviceString), &deviceString, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8String(isolate, String(deviceString))); + break; + case CL_DRIVER_VERSION: + err = clGetDeviceInfo(m_clDeviceId, CL_DRIVER_VERSION, sizeof(deviceString), &deviceString, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8String(isolate, String(deviceString))); + break; + case CL_DEVICE_ADDRESS_BITS: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_ADDRESS_BITS, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_MAX_CLOCK_FREQUENCY: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_MAX_CONSTANT_ARGS: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_CONSTANT_ARGS, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_MAX_READ_IMAGE_ARGS: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_MAX_SAMPLERS: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_SAMPLERS, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_MEM_BASE_ADDR_ALIGN: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_VENDOR_ID: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_VENDOR_ID, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_MAX_COMPUTE_UNITS: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_DEVICE_IMAGE2D_MAX_HEIGHT: { + unsigned result = getImage2DMaxHeight(); + if (result) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, result)); + break; + } + case CL_DEVICE_IMAGE2D_MAX_WIDTH: { + unsigned result = getImage2DMaxWidth(); + if (result) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, result)); + break; + } + case CL_DEVICE_IMAGE3D_MAX_DEPTH: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_DEVICE_IMAGE3D_MAX_HEIGHT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_DEVICE_IMAGE3D_MAX_WIDTH: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_DEVICE_MAX_PARAMETER_SIZE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_DEVICE_MAX_WORK_GROUP_SIZE: { + unsigned result = getMaxWorkGroup(); + if (result) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, result)); + break; + } + case CL_DEVICE_MAX_WORK_ITEM_SIZES: { + Vector result = getMaxWorkItem(); + if (result.size()) + return ScriptValue(scriptState, toV8(result, creationContext, isolate)); + break; + } + case CL_DEVICE_PROFILING_TIMER_RESOLUTION: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_PROFILING_TIMER_RESOLUTION, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_DEVICE_LOCAL_MEM_SIZE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(ulongUnits))); + break; + case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(ulongUnits))); + break; + case CL_DEVICE_MAX_MEM_ALLOC_SIZE: { + unsigned long long result = getMaxMemAllocSize(); + if (result) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, result)); + break; + } + case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(ulongUnits))); + break; + case CL_DEVICE_GLOBAL_MEM_SIZE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(ulongUnits))); + break; + case CL_DEVICE_AVAILABLE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_AVAILABLE, sizeof(cl_bool), &boolUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Boolean::New(isolate, static_cast(boolUnits))); + break; + case CL_DEVICE_COMPILER_AVAILABLE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_COMPILER_AVAILABLE, sizeof(cl_bool), &boolUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Boolean::New(isolate, static_cast(boolUnits))); + break; + case CL_DEVICE_HOST_UNIFIED_MEMORY: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(cl_bool), &boolUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Boolean::New(isolate, static_cast(boolUnits))); + break; + case CL_DEVICE_ENDIAN_LITTLE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_ENDIAN_LITTLE, sizeof(cl_bool), &boolUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Boolean::New(isolate, static_cast(boolUnits))); + break; + case CL_DEVICE_ERROR_CORRECTION_SUPPORT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof(cl_bool), &boolUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Boolean::New(isolate, static_cast(boolUnits))); + break; + case CL_DEVICE_IMAGE_SUPPORT: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &boolUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Boolean::New(isolate, static_cast(boolUnits))); + break; + case CL_DEVICE_TYPE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_TYPE, sizeof(type), &type, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(type))); + break; + case CL_DEVICE_SINGLE_FP_CONFIG: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(deviceFPConfig), &deviceFPConfig, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(deviceFPConfig))); + break; + case CL_DEVICE_QUEUE_PROPERTIES: { + unsigned result = getQueueProperties(); + if (result) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, result)); + break; + } + case CL_DEVICE_PLATFORM: + return ScriptValue(scriptState, toV8(m_platform, creationContext, isolate)); + case CL_DEVICE_EXECUTION_CAPABILITIES: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_EXECUTION_CAPABILITIES, sizeof(cl_device_exec_capabilities), &exec, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(exec))); + break; + case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, sizeof(cl_device_mem_cache_type), &globalType, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(globalType))); + break; + case CL_DEVICE_LOCAL_MEM_TYPE: + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(cl_device_local_mem_type), &localType, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(localType))); + break; + case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: + if (!m_extension.isEnabledExtension("KHR_fp64")) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, 0)); + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &infoValue, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(infoValue))); + break; + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: + if (!m_extension.isEnabledExtension("KHR_fp64")) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, 0)); + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &infoValue, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(infoValue))); + break; + case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: + if (!m_extension.isEnabledExtension("KHR_fp16")) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, 0)); + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, sizeof(cl_uint), &infoValue, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(infoValue))); + break; + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: + if (!m_extension.isEnabledExtension("KHR_fp16")) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, 0)); + err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, sizeof(cl_uint), &infoValue, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(infoValue))); + break; + default: + es.throwWebCLException(WebCLException::FAILURE, WebCLException::failureMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); +} + +void WebCLDevice::cacheDeviceExtensions() +{ + char deviceString[MULTI_EXTENSIONS_LENGTH] = ""; + Vector extensions; + + if (!m_clDeviceId) + return; + + cl_int err = clGetDeviceInfo(m_clDeviceId, CL_DEVICE_EXTENSIONS, sizeof(deviceString), &deviceString, nullptr); + + if (err != CL_SUCCESS) + return; + + String temp = String(deviceString); + temp.split(' ', extensions); + + for (auto extension : extensions) { + if (!extension.containsOnlyWhitespace()) + m_extension.addSupportedCLExtension(String(extension)); + } +} + +bool WebCLDevice::enableExtension(const String& name) +{ + return m_extension.enableExtension(name); +} + +Vector WebCLDevice::getSupportedExtensions() +{ + return m_extension.getSupportedExtensions(); +} + +void WebCLDevice::getEnabledExtensions(HashSet& extensions) +{ + m_extension.getEnabledExtensions(extensions); +} + +WebCLDevice::WebCLDevice(cl_device_id device, WebCLPlatform* platform) + : m_platform(platform) + , m_clDeviceId(device) +{ + cacheDeviceExtensions(); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLDevice.h b/third_party/WebKit/Source/modules/webcl/WebCLDevice.h new file mode 100644 index 0000000000000..5de04aaa564ba --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLDevice.h @@ -0,0 +1,57 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLDevice_h +#define WebCLDevice_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLExtension.h" +#include "modules/webcl/WebCLPlatform.h" + +#include +#include + +namespace blink { + +class ExceptionState; +class WebCL; +class WebCLGetInfo; +class WebCLPlatform; + +class WebCLDevice : public RefCounted, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLDevice(); + static PassRefPtr create(cl_device_id); + static PassRefPtr create(cl_device_id, WebCLPlatform* platform); + + ScriptValue getInfo(ScriptState*, unsigned, ExceptionState&); + + void cacheDeviceExtensions(); + bool enableExtension(const String& name); + void getEnabledExtensions(HashSet& extensions); + Vector getSupportedExtensions(); + unsigned getQueueProperties(); + unsigned long long getMaxMemAllocSize(); + unsigned getImage2DMaxWidth(); + unsigned getImage2DMaxHeight(); + unsigned getMaxWorkGroup(); + Vector getMaxWorkItem(); + PassRefPtr getPlatform() const { return m_platform; } + cl_device_id getDeviceId() { return m_clDeviceId; } + +private: + WebCLDevice(cl_device_id, WebCLPlatform* platform); + + WebCLPlatform* m_platform; + WebCLExtension m_extension; + cl_device_id m_clDeviceId; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLDevice_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLDevice.idl b/third_party/WebKit/Source/modules/webcl/WebCLDevice.idl new file mode 100644 index 0000000000000..c2839c487c373 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLDevice.idl @@ -0,0 +1,14 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef unsigned long CLenum; +typedef boolean CLboolean; + +[ + Conditional=WEBCL, +] interface WebCLDevice { + [CallWith=ScriptState, RaisesException] any getInfo(CLenum deviceType); + sequence? getSupportedExtensions(); + CLboolean enableExtension(DOMString extensionName); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLEvent.cpp b/third_party/WebKit/Source/modules/webcl/WebCLEvent.cpp new file mode 100644 index 0000000000000..4c68d9614a470 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLEvent.cpp @@ -0,0 +1,239 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/modules/v8/V8WebCLCommandQueue.h" +#include "bindings/modules/v8/V8WebCLContext.h" +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLEvent.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "platform/ThreadSafeFunctional.h" +#include "public/platform/Platform.h" +#include "public/platform/WebTraceLocation.h" + +namespace blink { + +// The holder of WebCLEvent. +class WebCLEventHolder { +public: + WeakPtr event; + cl_int type; + cl_event event2; + cl_int type2; +}; + +WebCLEvent::~WebCLEvent() +{ + release(); + ASSERT(!m_clEvent); +} + +PassRefPtr WebCLEvent::create() +{ + return adoptRef(new WebCLEvent(0)); +} + +ScriptValue WebCLEvent::getInfo(ScriptState* scriptState, unsigned paramName, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_EVENT, WebCLException::invalidEventMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_int err = CL_SUCCESS; + cl_int intUnits = 0; + cl_command_type commandType = 0; + switch(paramName) { + case CL_EVENT_COMMAND_EXECUTION_STATUS: + err = clGetEventInfo(m_clEvent, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &intUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::New(isolate, static_cast(intUnits))); + break; + case CL_EVENT_COMMAND_TYPE: + err = clGetEventInfo(m_clEvent, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(commandType))); + break; + case CL_EVENT_CONTEXT: + ASSERT(!isUserEvent()); + return ScriptValue(scriptState, toV8(context(), creationContext, isolate)); + case CL_EVENT_COMMAND_QUEUE: + ASSERT(m_commandQueue); + ASSERT(!isUserEvent()); + return ScriptValue(scriptState, toV8(m_commandQueue, creationContext, isolate)); + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); +} + +int WebCLEvent::getStatus() +{ + cl_int intUnits = 0; + cl_int err = clGetEventInfo(m_clEvent, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &intUnits, nullptr); + if (err == CL_SUCCESS) + return static_cast(intUnits); + return CL_INVALID_VALUE; +} + +unsigned WebCLEvent::getProfilingInfo(int paramName, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_EVENT, WebCLException::invalidEventMessage); + return 0; + } + + int status = getStatus(); + unsigned properties = m_commandQueue ? m_commandQueue->getProperties() : 0; + if (isUserEvent() || status != CL_COMPLETE || !(properties & CL_QUEUE_PROFILING_ENABLE)) { + es.throwWebCLException(WebCLException::PROFILING_INFO_NOT_AVAILABLE, WebCLException::profilingInfoNotAvailableMessage); + return 0; + } + + cl_int err = CL_SUCCESS; + cl_ulong ulongUnits = 0; + switch(paramName) { + case CL_PROFILING_COMMAND_QUEUED: + err = clGetEventProfilingInfo(m_clEvent, CL_PROFILING_COMMAND_QUEUED, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return static_cast(ulongUnits); + break; + case CL_PROFILING_COMMAND_SUBMIT: + err = clGetEventProfilingInfo(m_clEvent, CL_PROFILING_COMMAND_SUBMIT, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return static_cast(ulongUnits); + break; + case CL_PROFILING_COMMAND_START: + err = clGetEventProfilingInfo(m_clEvent, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return static_cast(ulongUnits); + break; + case CL_PROFILING_COMMAND_END: + err = clGetEventProfilingInfo(m_clEvent, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return static_cast(ulongUnits); + break; + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return 0; + } + + WebCLException::throwException(err, es); + return 0; +} + +void WebCLEvent::setCallback(unsigned commandExecCallbackType, WebCLCallback* callback, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_EVENT, WebCLException::invalidEventMessage); + return; + } + + if (commandExecCallbackType != CL_COMPLETE) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + ASSERT(callback); + if (m_callbacks.size()) { + m_callbacks.append(adoptRef(callback)); + return; + } + + m_callbacks.clear(); + m_callbacks.append(adoptRef(callback)); + WebCLEventHolder* holder = new WebCLEventHolder; + holder->event = createWeakPtr(); + holder->type = commandExecCallbackType; + cl_int err = clSetEventCallback(m_clEvent, commandExecCallbackType, &callbackProxy, holder); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +void WebCLEvent::release() +{ + if (isReleased()) + return; + + cl_int err = clReleaseEvent(m_clEvent); + if (err != CL_SUCCESS) + ASSERT_NOT_REACHED(); + + m_clEvent = 0; + + // Release un-triggered callbacks. + m_callbacks.clear(); +} + +bool WebCLEvent::setAssociatedCommandQueue(WebCLCommandQueue* commandQueue) +{ + if (m_commandQueue) + return false; + + m_commandQueue = commandQueue; + setContext(m_commandQueue->context()); + return true; +} + +WebCLEvent::WebCLEvent(cl_event clEvent) + : WebCLObject() + , m_commandQueue(nullptr) + , m_clEvent(clEvent) +{ +} + +void WebCLEvent::callbackProxy(cl_event event, cl_int type, void* userData) +{ + OwnPtr holder = adoptPtr(static_cast(userData)); + holder->event2 = event; + holder->type2 = type; + + if (!isMainThread()) { + Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&WebCLEvent::callbackProxyOnMainThread, holder.release())); + return; + } + + callbackProxyOnMainThread(holder.release()); +} + +void WebCLEvent::callbackProxyOnMainThread(PassOwnPtr holder) +{ + ASSERT(isMainThread()); + RefPtr webEvent(static_cast(holder->event.get())); +#ifndef NDEBUG + cl_event event = holder->event2; +#endif + cl_int type = holder->type2; + + if (!webEvent) + return; + + // Ignore the callback if the WebCLEvent is released or OpenCL event is abnormally terminated. + if (webEvent->isReleased() || type != holder->type) { + webEvent->m_callbacks.clear(); + return; + } + + ASSERT(event == webEvent->getEvent()); + Vector> callbacks = webEvent->m_callbacks; + ASSERT(callbacks.size()); + for (auto callback : callbacks) + callback->handleEvent(); + + webEvent->m_callbacks.clear(); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLEvent.h b/third_party/WebKit/Source/modules/webcl/WebCLEvent.h new file mode 100644 index 0000000000000..9a210a0c530fd --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLEvent.h @@ -0,0 +1,56 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLEvent_h +#define WebCLEvent_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLCallback.h" +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLObject.h" + +#include +#include + +namespace blink { + +class WebCL; +class WebCLCommandQueue; +class WebCLEventHolder; +class ExceptionState; + +class WebCLEvent : public WebCLObject, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLEvent() override; + static PassRefPtr create(); + + virtual ScriptValue getInfo(ScriptState*, unsigned, ExceptionState&); + unsigned getProfilingInfo(int, ExceptionState&); + void setCallback(unsigned, WebCLCallback*, ExceptionState&); + void release() override; + + virtual bool isUserEvent() const { return false; } + virtual int getStatus(); + bool setAssociatedCommandQueue(WebCLCommandQueue* commandQueue); + cl_event* getEventPtr() { return &m_clEvent; } + cl_event getEvent() { return m_clEvent; } + bool isReleased() const { return !m_clEvent; } + +protected: + WebCLEvent(cl_event); + + static void callbackProxy(cl_event, cl_int, void*); + static void callbackProxyOnMainThread(PassOwnPtr); + + Vector> m_callbacks; + WebCLCommandQueue* m_commandQueue; + cl_event m_clEvent; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLEvent_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLEvent.idl b/third_party/WebKit/Source/modules/webcl/WebCLEvent.idl new file mode 100644 index 0000000000000..4c594eb45af04 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLEvent.idl @@ -0,0 +1,16 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef unsigned long CLenum; +typedef unsigned long long CLulong; +[ + Conditional=WEBCL, + Constructor, +] interface WebCLEvent { + [CallWith=ScriptState, RaisesException] any getInfo(CLenum name); + [RaisesException] CLulong getProfilingInfo(CLenum name); + [RaisesException] void setCallback(CLenum commandExecCallbackType, + WebCLCallback notify); + void release(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLExtension.cpp b/third_party/WebKit/Source/modules/webcl/WebCLExtension.cpp new file mode 100644 index 0000000000000..6a485f9025bea --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLExtension.cpp @@ -0,0 +1,78 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "config.h" + +#if ENABLE(WEBCL) + +#include "modules/webcl/WebCLExtension.h" + +namespace blink { + +bool WebCLExtension::enableExtension(const String& name) +{ + if (equalIgnoringCase(name, "WEBCL_html_image")) { + m_enabledExtensions.append("WEBCL_html_image"); + return true; + } + + if (equalIgnoringCase(name, "WEBCL_html_video")) { + m_enabledExtensions.append("WEBCL_html_video"); + return true; + } + + if (equalIgnoringCase(name, "KHR_fp64")) { + bool khrFP64 = m_supportedCLExtensions.contains("cl_khr_fp64"); + if (khrFP64) + m_enabledExtensions.append("KHR_fp64"); + return khrFP64; + } + + if (equalIgnoringCase(name, "KHR_fp16")) { + bool khrFP16 = m_supportedCLExtensions.contains("cl_khr_fp16"); + if (khrFP16) + m_enabledExtensions.append("KHR_fp16"); + return khrFP16; + } + + return false; +} + +Vector WebCLExtension::getSupportedExtensions() +{ + // Filter the opencl supported extension. + Vector result; + result.append("WEBCL_html_image"); + result.append("WEBCL_html_video"); + if (m_supportedCLExtensions.contains("cl_khr_fp64")) + result.append("KHR_fp64"); + + if (m_supportedCLExtensions.contains("cl_khr_fp16")) + result.append("KHR_fp16"); + + return result; +} + +bool WebCLExtension::isEnabledExtension(const String& name) const +{ + return m_enabledExtensions.contains(name); +} + +void WebCLExtension::getEnabledExtensions(HashSet& extensions) +{ + for (auto enabledExtension : m_enabledExtensions) { + const String& extensionString = enabledExtension; + if (!extensionString.isEmpty()) + extensions.add(extensionString); + } +} + +void WebCLExtension::addSupportedCLExtension(const String& name) +{ + m_supportedCLExtensions.append(name); +} + +} // blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLExtension.h b/third_party/WebKit/Source/modules/webcl/WebCLExtension.h new file mode 100644 index 0000000000000..cc0d88e2ac30c --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLExtension.h @@ -0,0 +1,35 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLExtension_h +#define WebCLExtension_h + +#if ENABLE(WEBCL) + +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCLConfig.h" + +namespace blink { + +class WebCLExtension { +public: + ~WebCLExtension() {} + WebCLExtension() {} + + bool enableExtension(const String& name); + Vector getSupportedExtensions(); + bool isEnabledExtension(const String& name) const; + void getEnabledExtensions(HashSet&); + void addSupportedCLExtension(const String& name); + +private: + Vector m_enabledExtensions; + Vector m_supportedCLExtensions; +}; + +} // blink + +#endif // ENABLE(WEBCL) +#endif // WebCLExtension_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLHTMLUtil.cpp b/third_party/WebKit/Source/modules/webcl/WebCLHTMLUtil.cpp new file mode 100644 index 0000000000000..99fdf9e3b4b93 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLHTMLUtil.cpp @@ -0,0 +1,187 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) + +#include "core/html/HTMLCanvasElement.h" +#include "core/html/HTMLImageElement.h" +#include "core/html/HTMLVideoElement.h" +#include "core/html/ImageData.h" +#include "core/webcl/WebCLException.h" +#include "platform/graphics/gpu/WebGLImageConversion.h" +#include "platform/graphics/ImageBuffer.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLHTMLUtil.h" + +namespace blink { + +bool packImageData(Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, unsigned width, unsigned height, Vector& data) { + WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, false, false); + if (!imageExtractor.extractSucceeded()) + return false; + + WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); + WebGLImageConversion::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); + const void* imagePixelData = imageExtractor.imagePixelData(); + unsigned imageSourceUnpackAlignment = imageExtractor.imageSourceUnpackAlignment(); + + return WebGLImageConversion::packImageData(image, imagePixelData, GL_RGBA, GL_UNSIGNED_BYTE, false, alphaOp, sourceDataFormat, width, height, imageSourceUnpackAlignment, data); +} + +bool WebCLHTMLUtil::extractDataFromCanvas(HTMLCanvasElement* canvas, Vector& data, size_t& canvasSize, ExceptionState& es) +{ + // Currently the data is read back from gpu to cpu, and uploaded from cpu to gpu + // when OpenCL kernel funtion is assigned to run on GPU device. + // TODO(junmin-zhu): should directly copy or share gpu memory in that case. + if (!canvas) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + if (!packImageData(canvas->copiedImage(BackBuffer).get(), WebGLImageConversion::HtmlDomCanvas, canvas->width(), canvas->height(), data)) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + canvasSize = data.size(); + if (!data.data() || !canvasSize) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + return true; +} + +bool WebCLHTMLUtil::extractDataFromImage(HTMLImageElement* image, Vector& data, size_t& imageSize, ExceptionState& es) +{ + if (!image || !image->cachedImage()) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + if (!packImageData(image->cachedImage()->image(), WebGLImageConversion::HtmlDomImage, image->width(), image->height(), data)) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + imageSize = data.size(); + if (!data.data() || !imageSize) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + return true; +} + +bool WebCLHTMLUtil::extractDataFromImageData(ImageData* srcPixels, void*& hostPtr, size_t& pixelSize, ExceptionState& es) +{ + if (!srcPixels && !srcPixels->data() && !srcPixels->data()->data()) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + pixelSize = srcPixels->data()->length(); + hostPtr = static_cast(srcPixels->data()->data()); + if (!hostPtr || !pixelSize) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + return true; +} + +bool WebCLHTMLUtil::extractDataFromVideo(HTMLVideoElement* video, Vector& data, size_t& videoSize, ExceptionState& es) +{ + // Currently the data is read back from gpu to cpu, and uploaded from cpu to gpu + // when OpenCL kernel funtion is assigned to run on GPU device. + // TODO(junmin-zhu): should directly copy or share gpu memory in that case. + if (!video) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + RefPtr image = videoFrameToImage(video); + if (!image) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + + if (!packImageData(image.get(), WebGLImageConversion::HtmlDomVideo, video->clientWidth(), video->clientHeight(), data)) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + videoSize = data.size(); + + if (!data.data() || !videoSize) { + es.throwWebCLException(WebCLException::INVALID_HOST_PTR, WebCLException::invalidHostPTRMessage); + return false; + } + return true; +} + +PassRefPtr WebCLHTMLUtil::videoFrameToImage(HTMLVideoElement* video) +{ + if (!video || !video->clientWidth() || !video->clientHeight()) + return nullptr; + + IntSize size(video->clientWidth(), video->clientHeight()); + ImageBuffer* imageBufferObject = m_generatedImageCache.imageBuffer(size); + if (!imageBufferObject) + return nullptr; + + IntRect destRect(0, 0, size.width(), size.height()); + video->paintCurrentFrame(imageBufferObject->canvas(), destRect, nullptr); + return imageBufferObject->copyImage(); +} + +WebCLHTMLUtil::WebCLHTMLUtil(unsigned capacity) + : m_generatedImageCache(capacity) +{ +} + +WebCLHTMLUtil::ImageBufferCache::ImageBufferCache(unsigned capacity) + : m_capacity(capacity) +{ + m_buffers.reserveCapacity(capacity); +} + +// Get the imageBuffer with the same size as input argument, and swtich it to front for reusing. +ImageBuffer* WebCLHTMLUtil::ImageBufferCache::imageBuffer(const IntSize& size) +{ + unsigned i; + for (i = 0; i < m_buffers.size(); ++i) { + ImageBuffer* buf = m_buffers[i].get(); + if (buf->size() != size) + continue; + + if (i > 0) + m_buffers[i].swap(m_buffers[0]); + + return buf; + } + + OwnPtr temp = ImageBuffer::create(size); + if (!temp) + return nullptr; + + if (i < m_capacity - 1) { + m_buffers.append(temp.release()); + } else { + m_buffers[m_capacity - 1] = temp.release(); + i = m_capacity - 1; + } + + ImageBuffer* buf = m_buffers[i].get(); + if (i > 0) + m_buffers[i].swap(m_buffers[0]); + + return buf; +} + +} // blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLHTMLUtil.h b/third_party/WebKit/Source/modules/webcl/WebCLHTMLUtil.h new file mode 100644 index 0000000000000..094e8263cf996 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLHTMLUtil.h @@ -0,0 +1,45 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLHTMLUtil_h +#define WebCLHTMLUtil_h + +#if ENABLE(WEBCL) +#include + +namespace blink { + +class ExceptionState; +class HTMLCanvasElement; +class HTMLImageElement; +class HTMLVideoElement; +class ImageData; + +class WebCLHTMLUtil { +public: + explicit WebCLHTMLUtil(unsigned capacity = 4); + static bool extractDataFromCanvas(HTMLCanvasElement*, Vector& data, size_t& canvasSize, ExceptionState&); + static bool extractDataFromImage(HTMLImageElement*, Vector& data, size_t& canvasSize, ExceptionState&); + static bool extractDataFromImageData(ImageData*, void*& hostPtr, size_t& pixelSize, ExceptionState&); + bool extractDataFromVideo(HTMLVideoElement*, Vector& data, size_t& videoSize, ExceptionState&); +private: + PassRefPtr videoFrameToImage(HTMLVideoElement*); + + // Fixed-size cache of reusable image buffers for extractDataFromVideo calls. + class ImageBufferCache { + public: + ImageBufferCache(unsigned capacity); + ImageBuffer* imageBuffer(const IntSize&); + private: + Vector> m_buffers; + unsigned m_capacity; + }; + ImageBufferCache m_generatedImageCache; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLHTMLUtil_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLImage.cpp b/third_party/WebKit/Source/modules/webcl/WebCLImage.cpp new file mode 100644 index 0000000000000..3a41727964734 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLImage.cpp @@ -0,0 +1,57 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLImage.h" +#include "modules/webcl/WebCLOpenCL.h" + +namespace blink { + +WebCLImage::~WebCLImage() +{ +} + +PassRefPtr WebCLImage::create(cl_mem image, const WebCLImageDescriptor& imageDescriptor, WebCLContext* context) +{ + return adoptRef(new WebCLImage(image, imageDescriptor, context)); +} + +void WebCLImage::getInfo(ExceptionState& es, WebCLImageDescriptor& descriptor) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + + descriptor.setWidth(m_imageDescriptor.width()); + descriptor.setHeight(m_imageDescriptor.height()); + descriptor.setRowPitch(m_imageDescriptor.rowPitch()); + descriptor.setChannelOrder(m_imageDescriptor.channelOrder()); + descriptor.setChannelType(m_imageDescriptor.channelType()); +} + +WebCLImage::WebCLImage(cl_mem image, const WebCLImageDescriptor& imageDescriptor, WebCLContext* context) + : WebCLMemoryObject(image, 0, context) + , m_imageDescriptor(imageDescriptor) +{ + size_t memorySizeValue = 0; + cl_int err = clGetMemObjectInfo(image, CL_MEM_SIZE, sizeof(size_t), &memorySizeValue, nullptr); + if (err == CL_SUCCESS) + m_sizeInBytes = memorySizeValue; + + size_t actualRowPitch = 0; + err = clGetImageInfo(image, CL_IMAGE_ROW_PITCH, sizeof(size_t), &actualRowPitch, nullptr); + if (err == CL_SUCCESS) + m_imageDescriptor.setRowPitch(actualRowPitch); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLImage.h b/third_party/WebKit/Source/modules/webcl/WebCLImage.h new file mode 100644 index 0000000000000..5a28ed28b04a9 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLImage.h @@ -0,0 +1,41 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLImage_h +#define WebCLImage_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLImageDescriptor.h" +#include "modules/webcl/WebCLMemoryObject.h" + +#include +#include + +namespace blink { + +class ExceptionState; +class WebCL; + +class WebCLImage : public WebCLMemoryObject { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLImage() override; + static PassRefPtr create(cl_mem, const WebCLImageDescriptor&, WebCLContext*); + + void getInfo(ExceptionState&, WebCLImageDescriptor&); + const WebCLImageDescriptor& imageDescriptor() { return m_imageDescriptor; } + int type() override { return IMAGE; } + +private: + WebCLImage(cl_mem, const WebCLImageDescriptor&, WebCLContext*); + + WebCLImageDescriptor m_imageDescriptor; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLImage_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLImage.idl b/third_party/WebKit/Source/modules/webcl/WebCLImage.idl new file mode 100644 index 0000000000000..96fd5b95f09db --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLImage.idl @@ -0,0 +1,9 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + Conditional=WEBCL, +] interface WebCLImage : WebCLMemoryObject { + [RaisesException] WebCLImageDescriptor getInfo(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLImageDescriptor.idl b/third_party/WebKit/Source/modules/webcl/WebCLImageDescriptor.idl new file mode 100644 index 0000000000000..ae667b6b82f7a --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLImageDescriptor.idl @@ -0,0 +1,14 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + Conditional=WEBCL, + PermissiveDictionaryConversion +] dictionary WebCLImageDescriptor { + unsigned long channelOrder = 0x10B5; //WebCL.RGBA; + unsigned long channelType = 0x10D2; //WebCL.UNORM_INT8; + unsigned long width = 0; + unsigned long height = 0; + unsigned long rowPitch = 0; +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLInputChecker.cpp b/third_party/WebKit/Source/modules/webcl/WebCLInputChecker.cpp new file mode 100644 index 0000000000000..9fd8f44a65117 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLInputChecker.cpp @@ -0,0 +1,364 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) + +#include "modules/webcl/WebCLBuffer.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLImage.h" +#include "modules/webcl/WebCLImageDescriptor.h" +#include "modules/webcl/WebCLInputChecker.h" +#include "modules/webcl/WebCLKernel.h" + +namespace blink { +namespace WebCLInputChecker { + +bool isValidDeviceType(unsigned deviceType) +{ + switch (deviceType) { + case CL_DEVICE_TYPE_CPU: + case CL_DEVICE_TYPE_GPU: + case CL_DEVICE_TYPE_ACCELERATOR: + case CL_DEVICE_TYPE_DEFAULT: + case CL_DEVICE_TYPE_ALL: + return true; + } + + return false; +} + +bool isValidDeviceInfoType(unsigned infoType) +{ + switch (infoType) { + case CL_DEVICE_EXTENSIONS: + case CL_DEVICE_PROFILE: + case CL_DEVICE_NAME: + case CL_DEVICE_VENDOR: + case CL_DEVICE_VENDOR_ID: + case CL_DEVICE_VERSION: + case CL_DRIVER_VERSION: + case CL_DEVICE_OPENCL_C_VERSION: + case CL_DEVICE_ADDRESS_BITS: + case CL_DEVICE_MAX_CONSTANT_ARGS: + case CL_DEVICE_MAX_READ_IMAGE_ARGS: + case CL_DEVICE_MAX_SAMPLERS: + case CL_DEVICE_MAX_WRITE_IMAGE_ARGS: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: + case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: + case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: + case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: + case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: + case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: + case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: + case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: + case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: + case CL_DEVICE_MAX_CLOCK_FREQUENCY: + case CL_DEVICE_IMAGE2D_MAX_HEIGHT: + case CL_DEVICE_IMAGE2D_MAX_WIDTH: + case CL_DEVICE_IMAGE3D_MAX_HEIGHT: + case CL_DEVICE_IMAGE3D_MAX_WIDTH: + case CL_DEVICE_IMAGE3D_MAX_DEPTH: + case CL_DEVICE_MAX_PARAMETER_SIZE: + case CL_DEVICE_MAX_WORK_GROUP_SIZE: + case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: + case CL_DEVICE_LOCAL_MEM_SIZE: + case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: + case CL_DEVICE_MAX_MEM_ALLOC_SIZE: + case CL_DEVICE_AVAILABLE: + case CL_DEVICE_ENDIAN_LITTLE: + case CL_DEVICE_HOST_UNIFIED_MEMORY: + case CL_DEVICE_IMAGE_SUPPORT: + case CL_DEVICE_TYPE: + case CL_DEVICE_QUEUE_PROPERTIES: + case CL_DEVICE_PLATFORM: + case CL_DEVICE_LOCAL_MEM_TYPE: + case CL_DEVICE_MAX_WORK_ITEM_SIZES: + case CL_DEVICE_MAX_COMPUTE_UNITS: + case CL_DEVICE_GLOBAL_MEM_SIZE: + case CL_DEVICE_MEM_BASE_ADDR_ALIGN: + case CL_DEVICE_SINGLE_FP_CONFIG: + case CL_DEVICE_COMPILER_AVAILABLE: + case CL_DEVICE_EXECUTION_CAPABILITIES: + case CL_DEVICE_ERROR_CORRECTION_SUPPORT: + case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: + case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: + case CL_DEVICE_PROFILING_TIMER_RESOLUTION: + case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: + return true; + } + + return false; +} + +bool isValidMemoryObjectFlag(unsigned memoryObjectFlag) +{ + switch (memoryObjectFlag) { + case CL_MEM_READ_ONLY: + case CL_MEM_WRITE_ONLY: + case CL_MEM_READ_WRITE: + return true; + } + + return false; +} + +bool isValidAddressingMode(unsigned value) +{ + switch(value) { + case CL_ADDRESS_CLAMP_TO_EDGE: + case CL_ADDRESS_CLAMP: + case CL_ADDRESS_REPEAT: + case CL_ADDRESS_MIRRORED_REPEAT: + return true; + } + + return false; +} + +bool isValidFilterMode(unsigned value) +{ + switch(value) { + case CL_FILTER_NEAREST: + case CL_FILTER_LINEAR: + return true; + } + + return false; +} + +bool isValidChannelOrder(unsigned value) +{ + switch (value) { + case CL_R: + case CL_A: + case CL_RG: + case CL_RA: + case CL_RGB: + case CL_RGBA: + case CL_BGRA: + case CL_ARGB: + case CL_INTENSITY: + case CL_LUMINANCE: + case CL_Rx: + case CL_RGx: + case CL_RGBx: + return true; + } + + return false; +} + +bool isValidChannelType(unsigned value) +{ + switch (value) { + case CL_SNORM_INT8: + case CL_SNORM_INT16: + case CL_UNORM_INT8: + case CL_UNORM_INT16: + case CL_UNORM_SHORT_565: + case CL_UNORM_SHORT_555: + case CL_UNORM_INT_101010: + case CL_SIGNED_INT8: + case CL_SIGNED_INT16: + case CL_SIGNED_INT32: + case CL_UNSIGNED_INT8: + case CL_UNSIGNED_INT16: + case CL_UNSIGNED_INT32: + case CL_HALF_FLOAT: + case CL_FLOAT: + return true; + } + + return false; +} + +bool isValidCommandQueueProperty(unsigned value) +{ + switch (value) { + case 0: // 0 as integer value CommandQueueProperty is optional. + case CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE: + case CL_QUEUE_PROFILING_ENABLE: + return true; + } + + return false; +} + +bool isValidKernelArgIndex(WebCLKernel* kernel, unsigned index) +{ + ASSERT(kernel); + return index < kernel->numberOfArguments(); +} + +bool isValidDataSizeForDOMArrayBufferView(unsigned size, DOMArrayBufferView* arrayBufferView) +{ + ASSERT(arrayBufferView); + + unsigned bytesPerElement = 1; + switch (arrayBufferView->type()) { + case DOMArrayBufferView::TypeInt8: + case DOMArrayBufferView::TypeUint8: + case DOMArrayBufferView::TypeUint8Clamped: + bytesPerElement = 1; + break; + case DOMArrayBufferView::TypeInt16: + case DOMArrayBufferView::TypeUint16: + bytesPerElement = 2; + break; + case DOMArrayBufferView::TypeInt32: + case DOMArrayBufferView::TypeUint32: + case DOMArrayBufferView::TypeFloat32: + bytesPerElement = 4; + break; + case DOMArrayBufferView::TypeFloat64: + bytesPerElement = 8; + break; + default: + ASSERT_NOT_REACHED(); + return false; + } + + return !(size % bytesPerElement); +} + +bool isValidRegionForMemoryObject(const Vector& origin, const Vector& region, size_t rowPitch, size_t slicePitch, size_t length) +{ + size_t regionArea = region[0] * region[1] * region[2]; + if (!regionArea) + return false; + + if (rowPitch) { + // Validate User given rowPitch, region read = rowPitch * number of rows * number of slices. + // The rowPitch is used to move the pointer to the next read the next row. By default its set to + // row width. With user sent values we must ensure the read is within the bounds. + size_t maximumReadPtrValue = rowPitch * region[1] * region[2]; + if (maximumReadPtrValue > length) + return false; + } + + if (slicePitch) { + // Validate User given slicePitch , region read = slicePitch * number of slices. + // The slicePitch is used to move the pointer for the next slice. Default value is size of slice + // in bytes ( region[1] * rowPitch). Must be validated identical to rowPitch to avoid out of bound memory access. + size_t maximumReadPtrValue = slicePitch * region[2]; + if (maximumReadPtrValue > length) + return false; + } + + // If row_pitch is 0, row_pitch is computed as region[0]. + rowPitch = rowPitch ? rowPitch : region[0]; + if (rowPitch < region[0]) + return false; + + // If slice_pitch is 0, slice_pitch is computed as region[1] * row_pitch. + slicePitch = slicePitch ? slicePitch : (region[1] * rowPitch); + if (slicePitch < rowPitch * region[1]) + return false; + + // The offset in bytes is computed as origin[2] * host_slice_pitch + origin[1] * rowPitch + origin[0]. + size_t offset = origin[2] * slicePitch + origin[1] * rowPitch + origin[0]; + + return (regionArea + offset) <= length; +} + +bool isValidRegionForImage(const WebCLImageDescriptor& descriptor, const Vector& origin, const Vector& region) +{ + size_t regionArea = region[0] * region[1]; + if (!regionArea) + return false; + + size_t height = descriptor.height(); + size_t width = descriptor.width(); + size_t offsetFromOrigin = origin[1] * height + origin[0]; + return (offsetFromOrigin + regionArea) <= (height * width); +} + +bool isValidRegionForBuffer(const size_t bufferLength, const Vector& region, const size_t offset, const WebCLImageDescriptor& descriptor) +{ + // The size in bytes of the region to be copied from buffer is width * height * bytes/image element. + size_t bytesCopied = region[0] * region[1] + * WebCLContext::bytesPerChannelType(descriptor.channelType()) + * WebCLContext::numberOfChannelsForChannelOrder(descriptor.channelOrder()); + + return (offset+ bytesCopied) <= bufferLength; +} + +bool isValidRegionForHostPtr(const Vector& region, size_t rowPitch, const WebCLImageDescriptor& descriptor, size_t length) +{ + /* + * Validate the hostPtr length passed to enqueue*Image* API's. Since hostPtr are not validated by OpenCL + * Out of Bound access may cause crashes. So validating with rowPitch & region being read. + * rowPitch is used to move the pointer to next row for write/read. + */ + size_t imageBytesPerPixel = WebCLContext::bytesPerChannelType(descriptor.channelType()) + * WebCLContext::numberOfChannelsForChannelOrder(descriptor.channelOrder()); + rowPitch = rowPitch ? rowPitch : region[0] * imageBytesPerPixel; + if (rowPitch * region[1] > length) + return false; + + size_t regionArea = region[0] * region[1]; + if (!regionArea) + return false; + + return (regionArea <= length); +} + +static bool valueInRange(size_t value, size_t minimum, size_t maximum) +{ + return ((value >= minimum) && (value <= maximum)); +} + +bool isRegionOverlapping(WebCLImage* source, WebCLImage* destination, const Vector& sourceOrigin, const Vector& destinationOrigin, const Vector& region) +{ + if (!source || !destination) + return false; + + if (sourceOrigin.size() != 2 || destinationOrigin.size() != 2 || region.size() != 2) + return false; + + if (source->getMem() != destination->getMem()) + return false; + + bool xOverlap = valueInRange(destinationOrigin[0], sourceOrigin[0], (region[0] + sourceOrigin[0])) || valueInRange(sourceOrigin[0], destinationOrigin[0], (destinationOrigin[0] + region[0])); + bool yOverlap = valueInRange(destinationOrigin[1], sourceOrigin[1], (region[1] + sourceOrigin[1])) || valueInRange(sourceOrigin[1], destinationOrigin[1], (destinationOrigin[1] + region[1])); + + return xOverlap && yOverlap; +} + +bool isRegionOverlapping(WebCLBuffer* srcBuffer, WebCLBuffer* destBuffer, const unsigned srcOffset, const unsigned dstOffset, const unsigned numBytes) +{ + if (!srcBuffer || !destBuffer) + return false; + + if (srcBuffer->getMem() != destBuffer->getMem()) + return false; + + return valueInRange(dstOffset, srcOffset, (srcOffset + numBytes)) || valueInRange(srcOffset, dstOffset, (dstOffset + numBytes)); +} + +bool compareContext(WebCLContext* context1, WebCLContext* context2) +{ + if (!context1 || !context2) + return false; + + return context1->getContext() == context2->getContext(); +} + +bool compareImageFormat(const WebCLImageDescriptor& srcDescriptor, const WebCLImageDescriptor& dstDescriptor) +{ + return (srcDescriptor.channelOrder() == dstDescriptor.channelOrder()) && (srcDescriptor.channelType() == dstDescriptor.channelType()); +} + +} // namespace WebCLInputChecker +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLInputChecker.h b/third_party/WebKit/Source/modules/webcl/WebCLInputChecker.h new file mode 100644 index 0000000000000..a4be38b6dd6ae --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLInputChecker.h @@ -0,0 +1,45 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLInputChecker_h +#define WebCLInputChecker_h + +#if ENABLE(WEBCL) +#include "core/dom/DOMArrayBufferView.h" +#include "modules/webcl/WebCLConfig.h" + +namespace blink { + +class WebCLBuffer; +class WebCLContext; +class WebCLImage; +class WebCLImageDescriptor; +class WebCLKernel; + +namespace WebCLInputChecker { + +bool isValidDeviceType(unsigned); +bool isValidDeviceInfoType(unsigned); +bool isValidMemoryObjectFlag(unsigned); +bool isValidAddressingMode(unsigned); +bool isValidFilterMode(unsigned); +bool isValidChannelType(unsigned); +bool isValidChannelOrder(unsigned); +bool isValidCommandQueueProperty(unsigned); +bool isValidKernelArgIndex(WebCLKernel*, unsigned index); +bool isValidDataSizeForDOMArrayBufferView(unsigned size, DOMArrayBufferView*); +bool isValidRegionForMemoryObject(const Vector& origin, const Vector& region, size_t rowPitch, size_t slicePitch, size_t length); +bool isValidRegionForHostPtr(const Vector& region, size_t rowPitch, const WebCLImageDescriptor&, size_t length); +bool isValidRegionForImage(const WebCLImageDescriptor&, const Vector& origin, const Vector& region); +bool isValidRegionForBuffer(const size_t bufferLength, const Vector& region, const size_t offset, const WebCLImageDescriptor&); +bool isRegionOverlapping(WebCLImage*, WebCLImage*, const Vector& srcOrigin, const Vector& dstOrigin, const Vector& region); +bool isRegionOverlapping(WebCLBuffer*, WebCLBuffer*, const unsigned srcOffset, const unsigned dstOffset, const unsigned numBytes); +bool compareContext(WebCLContext*, WebCLContext*); +bool compareImageFormat(const WebCLImageDescriptor&, const WebCLImageDescriptor&); +} // namespace WebCLInputChecker + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLInputChecker_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLKernel.cpp b/third_party/WebKit/Source/modules/webcl/WebCLKernel.cpp new file mode 100644 index 0000000000000..8fcd081b02bcf --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLKernel.cpp @@ -0,0 +1,449 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/core/v8/V8ArrayBufferView.h" +#include "bindings/modules/v8/V8WebCLContext.h" +#include "bindings/modules/v8/V8WebCLMemoryObject.h" +#include "bindings/modules/v8/V8WebCLProgram.h" +#include "bindings/modules/v8/V8WebCLSampler.h" +#include "core/dom/DOMArrayBufferView.h" +#include "core/dom/DOMTypedArray.h" +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLBuffer.h" +#include "modules/webcl/WebCLDevice.h" +#include "modules/webcl/WebCLImage.h" +#include "modules/webcl/WebCLKernel.h" +#include "modules/webcl/WebCLKernelArgInfo.h" +#include "modules/webcl/WebCLOpenCL.h" + +namespace blink { + +WebCLKernel::~WebCLKernel() +{ + release(); + ASSERT(!m_clKernel); +} + +PassRefPtr WebCLKernel::create(cl_kernel kernel, WebCLContext* context, WebCLProgram* program, const String& kernelName) +{ + return adoptRef(new WebCLKernel(kernel, context, program, kernelName)); +} + +ScriptValue WebCLKernel::getInfo(ScriptState* scriptState, int kernelInfo, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_KERNEL, WebCLException::invalidKernelMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_int err = CL_SUCCESS; + cl_uint uintUnits = 0; + switch (kernelInfo) { + case CL_KERNEL_FUNCTION_NAME: + return ScriptValue(scriptState, v8String(isolate, m_kernelName)); + case CL_KERNEL_NUM_ARGS: + err = clGetKernelInfo(m_clKernel, CL_KERNEL_NUM_ARGS, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + break; + case CL_KERNEL_PROGRAM: + return ScriptValue(scriptState, toV8(m_program, creationContext, isolate)); + break; + case CL_KERNEL_CONTEXT: + return ScriptValue(scriptState, toV8(context(), creationContext, isolate)); + break; + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); +} + +ScriptValue WebCLKernel::getWorkGroupInfo(ScriptState* scriptState, WebCLDevice* device, int paramName, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_KERNEL, WebCLException::invalidKernelMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_device_id clDevice = nullptr; + Vector> deviceList = context()->getDevices(); + if (device) { + clDevice = device->getDeviceId(); + if (!clDevice) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + size_t i; + for (i = 0; i < deviceList.size(); i ++) { + if (clDevice == deviceList[i]->getDeviceId()) + break; + } + + if (i == deviceList.size()) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + } + + if (!device && deviceList.size() != 1) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_int err = CL_SUCCESS; + size_t sizetUnits = 0; + size_t workGroupSize[3] = {0}; + cl_ulong ulongUnits = 0; + switch (paramName) { + case CL_KERNEL_WORK_GROUP_SIZE: + err = clGetKernelWorkGroupInfo(m_clKernel, clDevice, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_KERNEL_PRIVATE_MEM_SIZE: + err = clGetKernelWorkGroupInfo(m_clKernel, clDevice, CL_KERNEL_PRIVATE_MEM_SIZE, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(ulongUnits))); + break; + case CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE: + err = clGetKernelWorkGroupInfo(m_clKernel, clDevice, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_KERNEL_COMPILE_WORK_GROUP_SIZE: + err = clGetKernelWorkGroupInfo(m_clKernel, clDevice, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, sizeof(workGroupSize), &workGroupSize, nullptr); + if (err == CL_SUCCESS) { + Vector values; + for (unsigned i = 0; i < 3; ++i) + values.append((unsigned)workGroupSize[i]); + return ScriptValue(scriptState, toV8(values, creationContext, isolate)); + } + break; + case CL_KERNEL_LOCAL_MEM_SIZE: + err = clGetKernelWorkGroupInfo(m_clKernel, clDevice, CL_KERNEL_LOCAL_MEM_SIZE, sizeof(cl_ulong), &ulongUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(ulongUnits))); + break; + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); +} + +#if CPU(BIG_ENDIAN) +inline void swapElementsForBigEndian(size_t& arrayLength, DOMArrayBufferView* bufferView, Vector& uLongBuffer) { + for (size_t i = 0; i < arrayLength * 2; i += 2) { + unsigned low, high; + low = static_cast(bufferView->view())->item(i); + high = static_cast(bufferView->view())->item(i + 1); + uLongBuffer[i / 2] = ((unsigned)low << 32) | high; + } +} +#endif + +WebCLKernelArgInfo* WebCLKernel::getArgInfo(unsigned index, ExceptionState& es) +{ + if (!WebCLInputChecker::isValidKernelArgIndex(this, index)) { + es.throwWebCLException(WebCLException::INVALID_ARG_INDEX, WebCLException::invalidArgIndexMessage); + return nullptr; + } + + return m_argumentInfoProvider.argumentsInfo().at(index).get(); +} + +void WebCLKernel::setArg(unsigned index, const ScriptValue& value, ExceptionState& es) +{ + v8::Isolate* isolate = value.isolate(); + v8::Handle object(value.v8Value()); + if (V8WebCLMemoryObject::hasInstance(object, isolate)) { + WebCLMemoryObject* memoryObject; + memoryObject = V8WebCLMemoryObject::toImplWithTypeCheck(isolate, object); + setArg(index, memoryObject, es); + return; + } + + if (V8WebCLSampler::hasInstance(object, isolate)) { + WebCLSampler* sampler; + sampler = V8WebCLSampler::toImplWithTypeCheck(isolate, object); + setArg(index, sampler, es); + return; + } + + if (V8ArrayBufferView::hasInstance(object, isolate)) { + DOMArrayBufferView* arrayBufferView; + arrayBufferView = object->IsArrayBufferView() ? V8ArrayBufferView::toImpl(v8::Handle::Cast(object)) : 0; + setArg(index, arrayBufferView, es); + return; + } + + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); +} + +void WebCLKernel::setArg(unsigned index, WebCLMemoryObject* object, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_KERNEL, WebCLException::invalidKernelMessage); + return; + } + + cl_mem clObject = nullptr; + if (object) { + clObject = object->getMem(); + if (!clObject) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + WebCLKernelArgInfo* argInfo = getArgInfo(index, es); + if (!argInfo || (object->type() == WebCLMemoryObject::IMAGE && argInfo->type() != WebCLKernelArgInfo::IMAGE) || (object->type() == WebCLMemoryObject::BUFFER && (argInfo->addressQualifier().isEmpty() || argInfo->type() != WebCLKernelArgInfo::BUFFER))) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgIndexMessage); + return; + } + + cl_int err = clSetKernelArg(m_clKernel, index, sizeof(cl_mem), &clObject); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); + else + argInfo->setAssociated(true); +} + +void WebCLKernel::setArg(unsigned index, WebCLSampler* sampler, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_KERNEL, WebCLException::invalidKernelMessage); + return; + } + + cl_sampler clSamplerId = nullptr; + if (sampler) { + clSamplerId = sampler->getSampler(); + if (!clSamplerId) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return; + } + } + + WebCLKernelArgInfo* argInfo = getArgInfo(index, es); + if (!argInfo || argInfo->type() != WebCLKernelArgInfo::SAMPLER) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgIndexMessage); + return; + } + cl_int err = clSetKernelArg(m_clKernel, index, sizeof(cl_sampler), &clSamplerId); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); + else + argInfo->setAssociated(true); +} + +void WebCLKernel::setArg(unsigned index, DOMArrayBufferView* data, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_KERNEL, WebCLException::invalidKernelMessage); + return; + } + + if (!WebCLInputChecker::isValidKernelArgIndex(this, index)) { + es.throwWebCLException(WebCLException::INVALID_ARG_INDEX, WebCLException::invalidArgIndexMessage); + return; + } + + cl_int err = CL_SUCCESS; + WebCLKernelArgInfo* argInfo = getArgInfo(index, es); + const String& accessQualifier = argInfo->addressQualifier(); + bool hasLocalQualifier = accessQualifier == "local"; + if (hasLocalQualifier) { + if (data->type() != DOMArrayBufferView::TypeUint32) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + + Uint32Array* typedArray = static_cast(data->view()); + if (typedArray->length() != 1) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + + unsigned* value = static_cast(data->view())->data(); + err = clSetKernelArg(m_clKernel, index, static_cast(value[0]), 0); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); + else + argInfo->setAssociated(true); + + return; + } + + void* bufferData = 0; + size_t arrayLength = 0; + Vector uLongBuffer; + int type = argInfo->type(); + switch(data->type()) { + case (DOMArrayBufferView::TypeFloat64): // DOUBLE + if (type != WebCLKernelArgInfo::DOUBLE) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + bufferData = static_cast(data->view())->data(); + arrayLength = data->byteLength() / 8; + break; + case (DOMArrayBufferView::TypeFloat32): // FLOAT + if (type != WebCLKernelArgInfo::FLOAT) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + bufferData = static_cast(data->view())->data(); + arrayLength = data->byteLength() / 4; + break; + case (DOMArrayBufferView::TypeUint32): // UINT + if (!(type == WebCLKernelArgInfo::UINT || type == WebCLKernelArgInfo::ULONG)) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + bufferData = static_cast(data->view())->data(); + arrayLength = data->byteLength() / 4; + if (type == WebCLKernelArgInfo::LONG) { + arrayLength = arrayLength / 2; +#if CPU(BIG_ENDIAN) + uLongBuffer.resize(arrayLength); + swapElementsForBigEndian(arrayLength, bufferView, uLongBuffer); + bufferData = uLongBuffer.data(); +#endif + } + break; + case (DOMArrayBufferView::TypeInt32): // INT + if (!(type == WebCLKernelArgInfo::INT || type == WebCLKernelArgInfo::LONG)) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + bufferData = static_cast(data->view())->data(); + arrayLength = data->byteLength() / 4; + + if (type == WebCLKernelArgInfo::LONG) + arrayLength = arrayLength / 2; + break; + case (DOMArrayBufferView::TypeUint16): // USHORT + if (type != WebCLKernelArgInfo::USHORT) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + bufferData = static_cast(data->view())->data(); + arrayLength = data->byteLength() / 2; + break; + case (DOMArrayBufferView::TypeInt16): // SHORT + if (type != WebCLKernelArgInfo::SHORT) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + bufferData = static_cast(data->view())->data(); + arrayLength = data->byteLength() / 2; + break; + case (DOMArrayBufferView::TypeUint8): // UCHAR + if (type != WebCLKernelArgInfo::UCHAR) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + bufferData = static_cast(data->view())->data(); + arrayLength = data->byteLength() / 1; + break; + case (DOMArrayBufferView::TypeInt8): // CHAR + if (type != WebCLKernelArgInfo::CHAR) { + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + bufferData = static_cast(data->view())->data(); + arrayLength = data->byteLength() / 1; + break; + default: + es.throwWebCLException(WebCLException::INVALID_ARG_VALUE, WebCLException::invalidArgValueMessage); + return; + } + + size_t bufferDataSize = data->byteLength(); + err = clSetKernelArg(m_clKernel, index, bufferDataSize, bufferData); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); + else + argInfo->setAssociated(true); +} + +void WebCLKernel::setArg(unsigned index, size_t argSize, const void* argValue, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_KERNEL, WebCLException::invalidKernelMessage); + return; + } + + if (!WebCLInputChecker::isValidKernelArgIndex(this, index)) { + es.throwWebCLException(WebCLException::INVALID_ARG_INDEX, WebCLException::invalidArgIndexMessage); + return; + } + + cl_int err = CL_SUCCESS; + WebCLKernelArgInfo* argInfo = getArgInfo(index, es); + err = clSetKernelArg(m_clKernel, index, argSize, argValue); + + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); + else + argInfo->setAssociated(true); +} + +void WebCLKernel::release() +{ + if (isReleased()) + return; + + cl_int err = clReleaseKernel(m_clKernel); + if (err != CL_SUCCESS) + ASSERT_NOT_REACHED(); + + m_clKernel = 0; +} + +unsigned WebCLKernel::numberOfArguments() +{ + return m_argumentInfoProvider.numberOfArguments(); +} + +unsigned WebCLKernel::associatedArguments() +{ + unsigned count = 0; + for (unsigned i = 0; i < m_argumentInfoProvider.numberOfArguments(); i ++) { + if (m_argumentInfoProvider.argumentsInfo()[i]->isAssociated()) + count ++; + } + return count; +} + +WebCLKernel::WebCLKernel(cl_kernel kernel, WebCLContext* context, WebCLProgram* program, const String& kernelName) + : WebCLObject(context) + , m_program(program) + , m_kernelName(kernelName) + , m_argumentInfoProvider(this) + , m_clKernel(kernel) +{ +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLKernel.h b/third_party/WebKit/Source/modules/webcl/WebCLKernel.h new file mode 100644 index 0000000000000..d7423daf15cab --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLKernel.h @@ -0,0 +1,64 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLKernel_h +#define WebCLKernel_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLKernelArgInfoProvider.h" +#include "modules/webcl/WebCLProgram.h" + +#include +#include + +namespace blink { + +class DOMArrayBufferView; +class ExceptionState; +class WebCL; +class WebCLCommandQueue; +class WebCLDevice; +class WebCLKernelArgInfo; +class WebCLMemoryObject; +class WebCLPlatform; +class WebCLSampler; + +class WebCLKernel : public WebCLObject, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLKernel() override; + static PassRefPtr create(cl_kernel, WebCLContext*, WebCLProgram*, const String&); + + ScriptValue getInfo(ScriptState*, int, ExceptionState&); + ScriptValue getWorkGroupInfo(ScriptState*, WebCLDevice*, int, ExceptionState&); + WebCLKernelArgInfo* getArgInfo(unsigned index, ExceptionState&); + void setArg(unsigned, const ScriptValue&, ExceptionState&); + void setArg(unsigned, WebCLMemoryObject*, ExceptionState&); + void setArg(unsigned, WebCLSampler*, ExceptionState&); + void setArg(unsigned, DOMArrayBufferView*, ExceptionState&); + void setArg(unsigned, size_t, const void*, ExceptionState&); + void release() override; + + unsigned numberOfArguments(); + unsigned associatedArguments(); + WebCLProgram* program() const { return m_program; } + const String& kernelName() const { return m_kernelName; } + const Vector& requiredArguments() { return m_argumentInfoProvider.requiredArguments(); } + cl_kernel getKernel() const { return m_clKernel; } + +private: + WebCLKernel(cl_kernel, WebCLContext*, WebCLProgram*, const String&); + bool isReleased() const { return !m_clKernel; } + + WebCLProgram* m_program; + String m_kernelName; + WebCLKernelArgInfoProvider m_argumentInfoProvider; + cl_kernel m_clKernel; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLKernel_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLKernel.idl b/third_party/WebKit/Source/modules/webcl/WebCLKernel.idl new file mode 100644 index 0000000000000..5a5e9be8eaec1 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLKernel.idl @@ -0,0 +1,16 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef unsigned long CLenum; +typedef unsigned long CLuint; + +[ + Conditional=WEBCL, +] interface WebCLKernel { + [CallWith=ScriptState, RaisesException] any getInfo(CLenum name); + [CallWith=ScriptState, RaisesException] any getWorkGroupInfo(WebCLDevice? device, CLenum name); + [RaisesException] WebCLKernelArgInfo getArgInfo(CLuint index); + [RaisesException] void setArg(CLuint index, any value); + void release(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfo.h b/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfo.h new file mode 100644 index 0000000000000..a9ac520df95b1 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfo.h @@ -0,0 +1,125 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLKernelArgInfo_h +#define WebCLKernelArgInfo_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLConfig.h" + +#include + +namespace blink { + +class WebCLKernelArgInfo : public RefCounted, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + enum { + CHAR, + UCHAR, + SHORT, + USHORT, + INT, + UINT, + LONG, + ULONG, + FLOAT, + DOUBLE, + BUFFER, + SAMPLER, + IMAGE, + UNKNOWN + }; + + static PassRefPtr create(const String& addressQualifier, const String& accessQualifier, const String& type, const String& name, const bool isPointerType = false) { + return adoptRef(new WebCLKernelArgInfo(addressQualifier, accessQualifier, type, name, isPointerType)); + } + + const String& name() const { return m_name; } + const String& typeName() const { return m_type; } + const String& addressQualifier() const { return m_addressQualifier; } + const String& accessQualifier() const { return m_accessQualifier; } + int type() const { return extractTypeEnum(m_type, m_isPointerType); } + bool hasLocalAddressQualifier() const { return m_hasLocalAddressQualifier; } + void setAssociated(bool value) { m_associated = value; } + bool isAssociated() const { return m_associated; } + +private: + WebCLKernelArgInfo(const String& addressQualifier, const String& accessQualifier, const String& type, const String& name, const bool isPointerType) + : m_addressQualifier(addressQualifier) + , m_accessQualifier(accessQualifier) + , m_type(type) + , m_name(name) + , m_associated(false) + , m_isPointerType(isPointerType) + { + m_hasLocalAddressQualifier = (m_addressQualifier == "local"); + } + + String m_addressQualifier; + String m_accessQualifier; + String m_type; + String m_name; + bool m_hasLocalAddressQualifier; + bool m_associated; + bool m_isPointerType; + + static inline int extractTypeEnum(const String& typeName, bool isPointerType) + { + if (isPointerType) + return BUFFER; + + static String image2d_t("image2d_t"); + if (typeName == image2d_t) + return IMAGE; + + static String sampler_t("sampler_t"); + if (typeName == sampler_t) + return SAMPLER; + + static String ucharLiteral("uchar"); + if (typeName.contains(ucharLiteral)) + return UCHAR; + static String charLiteral("char"); + if (typeName.contains(charLiteral)) + return CHAR; + + static String ushortLiteral("ushort"); + if (typeName.contains(ushortLiteral)) + return USHORT; + static String shortLiteral("short"); + if (typeName.contains(shortLiteral)) + return SHORT; + + static String uintLiteral("uint"); + if (typeName.contains(uintLiteral)) + return UINT; + static String intLiteral("int"); + if (typeName.contains(intLiteral)) + return INT; + + static String ulongLiteral("ulong"); + if (typeName.contains(ulongLiteral)) + return ULONG; + static String longLiteral("long"); + if (typeName.contains(longLiteral)) + return LONG; + + static String floatLiteral("float"); + if (typeName.contains(floatLiteral)) + return FLOAT; + + static String doubleLiteral("double"); + if (typeName.contains(doubleLiteral)) + return DOUBLE; + + return UNKNOWN; + } +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLKernelArgInfo_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfo.idl b/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfo.idl new file mode 100644 index 0000000000000..cfa63489b4dff --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfo.idl @@ -0,0 +1,14 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO(junmin-zhu): Blink does not support WebIDL dictionary definitions currently. +// Implement as a WebIDL dictionary type. +[ + Conditional=WEBCL, +] interface WebCLKernelArgInfo { + readonly attribute DOMString name; + readonly attribute DOMString typeName; + readonly attribute DOMString addressQualifier; + readonly attribute DOMString accessQualifier; +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfoProvider.cpp b/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfoProvider.cpp new file mode 100644 index 0000000000000..b178e3b5ae9a3 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfoProvider.cpp @@ -0,0 +1,246 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCLKernel.h" +#include "modules/webcl/WebCLKernelArgInfoProvider.h" +#include "modules/webcl/WebCLProgram.h" + +namespace blink { + +const size_t notFound = static_cast(-1); + +static bool isASCIILineBreakCharacter(UChar c) +{ + return c == '\r' || c == '\n'; +} + +inline bool isEmptySpace(UChar c) +{ + return c <= ' ' && (c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f'); +} + +inline bool isStarCharacter(UChar c) +{ + return c == '*'; +} + +inline bool isPrecededByUnderscores(const String& string, size_t index) +{ + size_t start = index - 2; + return (start >= 0 && string[start + 1] == '_' && string[start] == '_'); +} + +WebCLKernelArgInfoProvider::WebCLKernelArgInfoProvider(WebCLKernel* kernel) + : m_kernel(kernel) +{ + ASSERT(kernel); + ensureInfo(); +} + +void WebCLKernelArgInfoProvider::ensureInfo() +{ + if (m_argumentInfoVector.size()) + return; + + const String& source = m_kernel->program()->sourceWithCommentsStripped(); + // 0) find "kernel" string. + // 1) Check if it is a valid kernel declaration. + // 2) find the first open braces past "kernel". + // 3) reverseFind the given kernel name string. + // 4) if not found go back to (1) + // 5) if found, parse its argument list. + + size_t kernelNameIndex = 0; + size_t kernelDeclarationIndex = 0; + for (size_t startIndex = 0; ; startIndex = kernelDeclarationIndex + 6) { + kernelDeclarationIndex = source.find("kernel", startIndex); + if (kernelDeclarationIndex == notFound) { + return; + } + + // Check if "kernel" is not a substring of a valid token, + // e.g. "akernel" or "__kernel_": + // 1) After "kernel" there has to be an empty space. + // 2) Before "kernel" there has to be either: + // 2.1) two underscore characters or + // 2.2) none, i.e. "kernel" is the first string in the program source or + // 2.3) an empty space. + if (!isEmptySpace(source[kernelDeclarationIndex + 6])) + continue; + + // If the kernel declaration is not at the beginning of the program. + bool hasTwoUnderscores = isPrecededByUnderscores(source, kernelDeclarationIndex); + bool isKernelDeclarationAtBeginning = hasTwoUnderscores ? (kernelDeclarationIndex == 2) : (kernelDeclarationIndex == 0); + + if (!isKernelDeclarationAtBeginning) { + size_t firstPrecedingIndex = kernelDeclarationIndex - (hasTwoUnderscores ? 3 : 1); + if (!isEmptySpace(source[firstPrecedingIndex])) + continue; + } + + size_t openBrace = source.find("{", kernelDeclarationIndex + 6); + kernelNameIndex = source.reverseFind(m_kernel->kernelName(), openBrace); + + if (kernelNameIndex < kernelDeclarationIndex) + continue; + + if (kernelNameIndex != notFound) + break; + } + + ASSERT(kernelNameIndex); + size_t requiredIndex = source.reverseFind("required_work_group_size", kernelNameIndex); + if (requiredIndex != notFound) { + size_t requiredOpenBracket = source.find("(", requiredIndex); + size_t requiredCloseBracket = source.find(")", requiredOpenBracket); + const String& requiredArgumentListStr = source.substring(requiredOpenBracket + 1, requiredCloseBracket - requiredOpenBracket - 1); + + Vector requiredArgumentStrVector; + requiredArgumentListStr.split(",", requiredArgumentStrVector); + for (auto requiredArgument : requiredArgumentStrVector) { + requiredArgument = requiredArgument.removeCharacters(isASCIILineBreakCharacter); + requiredArgument = requiredArgument.stripWhiteSpace(); + m_requiredArgumentVector.append(requiredArgument.toUInt()); + } + } + + size_t openBracket = source.find("(", kernelNameIndex); + size_t closeBracket = source.find(")", openBracket); + const String& argumentListStr = source.substring(openBracket + 1, closeBracket - openBracket - 1); + + Vector argumentStrVector; + argumentListStr.split(",", argumentStrVector); + for (auto argument : argumentStrVector) { + argument = argument.removeCharacters(isASCIILineBreakCharacter); + argument = argument.stripWhiteSpace(); + parseAndAppendDeclaration(argument); + } +} + +static void prependUnsignedIfNeeded(Vector& declarationStrVector, String& type) +{ + for (size_t i = 0; i < declarationStrVector.size(); i++) { + static AtomicString& Unsigned = *new AtomicString("unsigned", AtomicString::ConstructFromLiteral); + if (declarationStrVector[i] == Unsigned) { + type = "u" + type; + declarationStrVector.remove(i); + return; + } + } +} + +void WebCLKernelArgInfoProvider::parseAndAppendDeclaration(const String& argumentDeclaration) +{ + // "*" is used to indicate pointer data type, setting isPointerType flag if "*" is present in argumentDeclaration. + // Since we parse only valid & buildable OpenCL kernels, * in argumentDeclaration must be associated with type only. + bool isPointerType = false; + if (argumentDeclaration.contains("*")) + isPointerType = true; + + Vector declarationStrVector; + argumentDeclaration.removeCharacters(isStarCharacter).split(" ", declarationStrVector); + + const String& name = extractName(declarationStrVector); + const String& addressQualifier = extractAddressQualifier(declarationStrVector); + String type = extractType(declarationStrVector); + + static AtomicString& image2d_t = *new AtomicString("image2d_t", AtomicString::ConstructFromLiteral); + const String& accessQualifier = (type == image2d_t) ? extractAccessQualifier(declarationStrVector) : "none"; + prependUnsignedIfNeeded(declarationStrVector, type); + + m_argumentInfoVector.append(WebCLKernelArgInfo::create(addressQualifier, accessQualifier, type, name, isPointerType)); +} + +String WebCLKernelArgInfoProvider::extractAddressQualifier(Vector& declarationStrVector) +{ + static AtomicString* __Private = new AtomicString("__private", AtomicString::ConstructFromLiteral); + static AtomicString* Private = new AtomicString("private", AtomicString::ConstructFromLiteral); + + static AtomicString* __Global = new AtomicString("__global", AtomicString::ConstructFromLiteral); + static AtomicString* Global = new AtomicString("global", AtomicString::ConstructFromLiteral); + + static AtomicString* __Constant = new AtomicString("__constant", AtomicString::ConstructFromLiteral); + static AtomicString* Constant = new AtomicString("constant", AtomicString::ConstructFromLiteral); + + static AtomicString* __Local = new AtomicString("__local", AtomicString::ConstructFromLiteral); + static AtomicString* Local = new AtomicString("local", AtomicString::ConstructFromLiteral); + + String address = *Private; + size_t i = 0; + for (; i < declarationStrVector.size(); i++) { + const String& candidate = declarationStrVector[i]; + if (candidate == *__Private || candidate == *Private) { + break; + } else if (candidate == *__Global || candidate == *Global) { + address = *Global; + break; + } else if (candidate == *__Constant || candidate == *Constant) { + address = *Constant; + break; + } else if (candidate == *__Local || candidate == *Local) { + address = *Local; + break; + } + } + + if (i < declarationStrVector.size()) + declarationStrVector.remove(i); + + return address; +} + +String WebCLKernelArgInfoProvider::extractAccessQualifier(Vector& declarationStrVector) +{ + static AtomicString* __read_only = new AtomicString("__read_only", AtomicString::ConstructFromLiteral); + static AtomicString* read_only = new AtomicString("read_only", AtomicString::ConstructFromLiteral); + + static AtomicString* __write_only = new AtomicString("__read_only", AtomicString::ConstructFromLiteral); + static AtomicString* write_only = new AtomicString("write_only", AtomicString::ConstructFromLiteral); + + static AtomicString* __read_write = new AtomicString("__read_write", AtomicString::ConstructFromLiteral); + static AtomicString* read_write = new AtomicString("read_write", AtomicString::ConstructFromLiteral); + + String access = *read_only; + size_t i = 0; + for (; i < declarationStrVector.size(); i++) { + const String& candidate = declarationStrVector[i]; + if (candidate == *__read_only || candidate == *read_only) { + break; + } else if (candidate == *__write_only || candidate == *write_only) { + access = *write_only; + break; + } else if (candidate == *__read_write || candidate == *read_write) { + access = *read_write; + break; + } + } + + if (i < declarationStrVector.size()) + declarationStrVector.remove(i); + + return access; +} + +String WebCLKernelArgInfoProvider::extractName(Vector& declarationStrVector) +{ + String last = declarationStrVector.last(); + declarationStrVector.removeLast(); + return last; +} + +String WebCLKernelArgInfoProvider::extractType(Vector& declarationStrVector) +{ + String type = declarationStrVector.last(); + declarationStrVector.removeLast(); + return type; +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfoProvider.h b/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfoProvider.h new file mode 100644 index 0000000000000..2d665bdd83f83 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLKernelArgInfoProvider.h @@ -0,0 +1,44 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLKernelArgInfoProvider_h +#define WebCLKernelArgInfoProvider_h + +#if ENABLE(WEBCL) + +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLKernelArgInfo.h" + +#include + +namespace blink { + +class WebCLKernel; + +class WebCLKernelArgInfoProvider { +public: + explicit WebCLKernelArgInfoProvider(WebCLKernel*); + const Vector>& argumentsInfo() { return m_argumentInfoVector; }; + + unsigned numberOfArguments() { return m_argumentInfoVector.size(); } + const Vector& requiredArguments() { return m_requiredArgumentVector; } + +private: + void ensureInfo(); + void parseAndAppendDeclaration(const String& argumentDeclaration); + String extractAddressQualifier(Vector& declaration); + String extractAccessQualifier(Vector& declaration); + String extractType(Vector& declaration); + String extractName(Vector& declaration); + + WebCLKernel* m_kernel; + Vector> m_argumentInfoVector; + Vector m_requiredArgumentVector; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLKernelArgInfoProvider_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.cpp b/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.cpp new file mode 100644 index 0000000000000..e8ccb203e4a79 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.cpp @@ -0,0 +1,104 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/modules/v8/V8WebCLContext.h" +#include "bindings/modules/v8/V8WebCLMemoryObject.h" +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLMemoryObject.h" +#include "modules/webcl/WebCLOpenCL.h" + +namespace blink { + +WebCLMemoryObject::~WebCLMemoryObject() +{ + release(); + ASSERT(!m_clMem); +} + +PassRefPtr WebCLMemoryObject::create(cl_mem mem, unsigned sizeInBytes, WebCLContext* context) +{ + return adoptRef(new WebCLMemoryObject(mem, sizeInBytes, context)); +} + +ScriptValue WebCLMemoryObject::getInfo(ScriptState* scriptState, int paramName, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_MEM_OBJECT, WebCLException::invalidMemObjectMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_int err = CL_SUCCESS; + size_t sizetUnits = 0; + size_t memorySizeValue = 0; + cl_mem_object_type memType = 0; + cl_mem_flags memFlags = 0; + unsigned memCopyHostPtrMask = 0x07; + + switch(paramName) { + case CL_MEM_SIZE: + err = clGetMemObjectInfo(m_clMem, CL_MEM_SIZE, sizeof(size_t), &sizetUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(sizetUnits))); + break; + case CL_MEM_FLAGS: + err = clGetMemObjectInfo(m_clMem, CL_MEM_FLAGS, sizeof(cl_mem_flags), &memFlags, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(memFlags & memCopyHostPtrMask))); + break; + case CL_MEM_OFFSET: + err = clGetMemObjectInfo(m_clMem, CL_MEM_OFFSET, sizeof(size_t), &memorySizeValue, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(memorySizeValue))); + break; + case CL_MEM_TYPE: + err = clGetMemObjectInfo(m_clMem, CL_MEM_TYPE, sizeof(cl_mem_object_type), &memType, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(memType))); + break; + case CL_MEM_CONTEXT: + return ScriptValue(scriptState, toV8(context(), creationContext, isolate)); + case CL_MEM_ASSOCIATED_MEMOBJECT: + if (m_parentMemObject) + return ScriptValue(scriptState, toV8(m_parentMemObject, creationContext, isolate)); + return ScriptValue(scriptState, v8::Null(isolate)); + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); +} + +void WebCLMemoryObject::release() +{ + if (isReleased()) + return; + + cl_int err = clReleaseMemObject(m_clMem); + if (err != CL_SUCCESS) + ASSERT_NOT_REACHED(); + + m_clMem = 0; +} + +WebCLMemoryObject::WebCLMemoryObject(cl_mem mem, unsigned sizeInBytes, WebCLContext* context, WebCLMemoryObject* parentBuffer) + : WebCLObject(context) + , m_parentMemObject(parentBuffer) + , m_sizeInBytes(sizeInBytes) + , m_clMem(mem) +{ +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.h b/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.h new file mode 100644 index 0000000000000..ba3d968ba1d1e --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.h @@ -0,0 +1,54 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLMemoryObject_h +#define WebCLMemoryObject_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLObject.h" + +#include +#include + +namespace blink { + +class ExceptionState; +class WebCL; +class WebCLContext; + +class WebCLMemoryObject : public WebCLObject, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + enum { + MEMORY, + BUFFER, + IMAGE, + UNKNOWN + }; + + ~WebCLMemoryObject() override; + static PassRefPtr create(cl_mem, unsigned, WebCLContext*); + + virtual ScriptValue getInfo(ScriptState*, int, ExceptionState&); + void release() override; + + size_t sizeInBytes() const { return m_sizeInBytes; } + virtual int type() { return MEMORY; } + cl_mem getMem() const { return m_clMem; } + bool isReleased() const { return !m_clMem; } + +protected: + WebCLMemoryObject(cl_mem, unsigned, WebCLContext*, WebCLMemoryObject* parentBuffer = nullptr); + + WebCLMemoryObject* m_parentMemObject; + size_t m_sizeInBytes; + cl_mem m_clMem; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLMemoryObject_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.idl b/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.idl new file mode 100644 index 0000000000000..0bc2301df0e50 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLMemoryObject.idl @@ -0,0 +1,11 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef unsigned long CLenum; +[ + Conditional=WEBCL, +] interface WebCLMemoryObject { + [CallWith=ScriptState, RaisesException] any getInfo(CLenum name); + void release(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLMemoryUtil.cpp b/third_party/WebKit/Source/modules/webcl/WebCLMemoryUtil.cpp new file mode 100644 index 0000000000000..fb842c15e4670 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLMemoryUtil.cpp @@ -0,0 +1,182 @@ +// Copyright (C) 2014 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) + +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLBuffer.h" +#include "modules/webcl/WebCLCommandQueue.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLDevice.h" +#include "modules/webcl/WebCLKernel.h" +#include "modules/webcl/WebCLMemoryObject.h" +#include "modules/webcl/WebCLMemoryUtil.h" +#include "modules/webcl/WebCLObject.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLProgram.h" + +namespace blink { + +const char* programSource = \ + "__kernel void init(__global char* buffer, unsigned offset, unsigned count) "\ + "{ "\ + " unsigned i = get_global_id(0); "\ + " unsigned displacedI = i + offset; "\ + " if (displacedI < count) "\ + " buffer[displacedI] = (char)(0); "\ + "} "\ + "__kernel void init16(__global char16* buffer, unsigned count) "\ + "{ "\ + " unsigned i = get_global_id(0); "\ + " if (i < count) "\ + " buffer[i] = (char16)(0); "\ + "} "; + +WebCLMemoryUtil::WebCLMemoryUtil(WebCLContext* context) + : m_context(context) +{ +} + +WebCLMemoryUtil::~WebCLMemoryUtil() +{ +} + +void WebCLMemoryUtil::ensureMemory(WebCLMemoryObject* memoryObject, WebCLCommandQueue* commandQueue, ExceptionState& es) +{ + cl_int err = CL_SUCCESS; + // The program and kernels are used to intialize OpenCL memory to 0. + // Every created OpenCL memory should call this function to intialize. + // TODO(junmin-zhu): Move intialization from buffer creation to buffer operations, such as: enqueueRead/Write/Copy* and enqueueNDRangeKernel function + // after the third_party WebCL-validator integrated. + if (!m_program) { + cl_program clProgramId = clCreateProgramWithSource(m_context->getContext(), 1, (const char**)&programSource, nullptr, &err); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return; + } + + m_program = WebCLProgram::create(clProgramId, m_context, String(programSource)); + m_program->build(m_context->getDevices(), emptyString(), nullptr, es); + + cl_kernel clKernelId16 = clCreateKernel(clProgramId, "init16", &err); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return; + } + + m_kernelChar16 = WebCLKernel::create(clKernelId16, m_context, m_program.get(), String("init16")); + cl_kernel clKernelId = clCreateKernel(clProgramId, "init", &err); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return; + } + + m_kernelChar = WebCLKernel::create(clKernelId, m_context, m_program.get(), String("init")); + } + + unsigned count = memoryObject->sizeInBytes() / 16; + if (count) { + m_kernelChar16->setArg(0, memoryObject, es); + if (es.hadException()) + return; + + m_kernelChar16->setArg(1, sizeof(unsigned), &count, es); + if (es.hadException()) + return; + + Vector globalWorkSize; + globalWorkSize.append(count); + Vector globalWorkOffset; + Vector localWorkSize; + + commandQueue->enqueueNDRangeKernel(m_kernelChar16.get(), globalWorkSize.size(), globalWorkOffset, globalWorkSize, localWorkSize, Vector>(), nullptr, es); + } + + unsigned remainingBytes = memoryObject->sizeInBytes() % 16; + if (remainingBytes) { + m_kernelChar->setArg(0, memoryObject, es); + if (es.hadException()) + return; + + unsigned offset = count * 16; + m_kernelChar->setArg(1, sizeof(unsigned), &offset, es); + if (es.hadException()) + return; + + unsigned totalSize = memoryObject->sizeInBytes(); + m_kernelChar->setArg(2, sizeof(unsigned), &totalSize, es); + if (es.hadException()) + return; + + Vector globalWorkSize; + globalWorkSize.append(remainingBytes); + Vector globalWorkOffset; + Vector localWorkSize; + + commandQueue->enqueueNDRangeKernel(m_kernelChar.get(), globalWorkSize.size(), globalWorkOffset, globalWorkSize, localWorkSize, Vector>(), nullptr, es); + } + + commandQueue->finishCommandQueues(WebCLCommandQueue::SyncMethod::SYNC); +} + +void WebCLMemoryUtil::commandQueueCreated(WebCLCommandQueue* queue, ExceptionState& es) +{ + if (!queue) + return; + + m_queues.append(queue->createWeakPtr()); + processPendingMemoryList(es); +} + +void WebCLMemoryUtil::bufferCreated(WebCLBuffer* buffer, ExceptionState& es) +{ + if (!buffer) + return; + + initializeOrQueueMemoryObject(buffer, es); +} + +void WebCLMemoryUtil::processPendingMemoryList(ExceptionState& es) +{ + if (!m_pendingBuffers.size()) + return; + + WebCLCommandQueue* queue = validCommandQueue(); + if (queue) { + for (auto bufferObject : m_pendingBuffers) { + WebCLBuffer* buffer = static_cast(bufferObject.get()); + if (buffer && !buffer->getMem()) + ensureMemory(buffer, queue, es); + } + } + m_pendingBuffers.clear(); +} + +WebCLCommandQueue* WebCLMemoryUtil::validCommandQueue() const +{ + for (auto queueObject : m_queues) { + WebCLCommandQueue* queue = static_cast(queueObject.get()); + if (queue && !queue->isReleased()) + return queue; + } + return nullptr; +} + +void WebCLMemoryUtil::initializeOrQueueMemoryObject(WebCLBuffer* buffer, ExceptionState& es) +{ + WebCLCommandQueue* queue = validCommandQueue(); + if (!queue) { + m_pendingBuffers.append(buffer->createWeakPtr()); + return; + } + + ensureMemory(buffer, queue, es); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLMemoryUtil.h b/third_party/WebKit/Source/modules/webcl/WebCLMemoryUtil.h new file mode 100644 index 0000000000000..2651b06a22419 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLMemoryUtil.h @@ -0,0 +1,54 @@ +// Copyright (C) 2014 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLMemoryUtil_h +#define WebCLMemoryUtil_h + +#if ENABLE(WEBCL) + +#include "core/webcl/WebCLException.h" +#include +#include +#include + +namespace blink { + +class WebCLBuffer; +class WebCLCommandQueue; +class WebCLContext; +class WebCLMemoryObject; +class WebCLKernel; +class WebCLObject; +class WebCLProgram; + +// WebCLMemoryUtil is a helper class to intialize the OpenCL memory to 0. +// It leverages the OpenCL kernel function to do it. +class WebCLMemoryUtil { +public: + explicit WebCLMemoryUtil(WebCLContext*); + ~WebCLMemoryUtil(); + + void bufferCreated(WebCLBuffer*, ExceptionState&); + void commandQueueCreated(WebCLCommandQueue*, ExceptionState&); + +private: + void ensureMemory(WebCLMemoryObject*, WebCLCommandQueue*, ExceptionState&); + void processPendingMemoryList(ExceptionState&); + WebCLCommandQueue* validCommandQueue() const; + void initializeOrQueueMemoryObject(WebCLBuffer*, ExceptionState&); + + WebCLContext* m_context; + RefPtr m_program; + RefPtr m_kernelChar; + RefPtr m_kernelChar16; + + Vector> m_pendingBuffers; + Vector> m_queues; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLMemoryUtil_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLObject.cpp b/third_party/WebKit/Source/modules/webcl/WebCLObject.cpp new file mode 100644 index 0000000000000..ba9e05b979b71 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLObject.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLObject.h" + +namespace blink { + +WebCLObject::~WebCLObject() +{ + if (m_context) + m_context->untrackReleaseableWebCLObject(createWeakPtr()); +} + +WebCLObject::WebCLObject(WebCLContext* context) + : m_weakFactory(this) + , m_context(context) +{ + ASSERT(m_context); + m_context->trackReleaseableWebCLObject(createWeakPtr()); +} + +WebCLObject::WebCLObject() + : m_weakFactory(this) + , m_context(nullptr) +{ +} + +WebCLContext* WebCLObject::context() +{ + ASSERT(m_context); + return m_context; +} + +void WebCLObject::setContext(WebCLContext* context) +{ + m_context = context; + m_context->trackReleaseableWebCLObject(createWeakPtr()); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLObject.h b/third_party/WebKit/Source/modules/webcl/WebCLObject.h new file mode 100644 index 0000000000000..be5b25dc8a61c --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLObject.h @@ -0,0 +1,45 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLObject_h +#define WebCLObject_h + +#if ENABLE(WEBCL) + +#include "core/webcl/WebCLException.h" + +#include +#include + +namespace blink { +class ExceptionState; +class WebCLContext; + +// WebCLObject is the base class of WebCommandQueue, WebCLProgram, WebCLKernel, +// WebCLMemoryObject/WebCLBuffer/WebCLImage, WebCLEvent/WebCLUserEvent, WebCLSampler. +// They are owned by WebCLContext through weakptr for lifecycle tracking. +class WebCLObject : public RefCounted { +public: + virtual ~WebCLObject(); + WeakPtr createWeakPtr() { return m_weakFactory.createWeakPtr(); } + WebCLContext* context(); + + void setContext(WebCLContext* context); + virtual void release() { ASSERT_NOT_REACHED(); } + +protected: + explicit WebCLObject(WebCLContext* context); + // Some object isn't associated with WebContext in constructor by developer. + // but at runtime by OpenCL. Such as: WebCLEvent + WebCLObject(); + + WeakPtrFactory m_weakFactory; + WebCLContext* m_context; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLObject_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLOpenCL.cpp b/third_party/WebKit/Source/modules/webcl/WebCLOpenCL.cpp new file mode 100644 index 0000000000000..fbf8fca0736bb --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLOpenCL.cpp @@ -0,0 +1,389 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLOpenCL.h" + +#if defined(WTF_OS_LINUX) || OS(ANDROID) +#include +#endif +#include +#include +#include + +// Track different opencl libs. +#if defined(WTF_OS_LINUX) || OS(ANDROID) +#if defined(WTF_CPU_ARM) +#define LIBS {"libOpenCL.so"} +#define SO_LEN 1 + +// After the byt, IA devices are shipped with "libOpenCL.so" +// by default. Before that, IA devices are shipped with +// "libPVROCL.so" to leverage PowerVR GPU for OpenCL. +// +// Note that there are some IA devices have "libOpenCL.so.1" +// but not "libOpenCL.so", such as: Asus Memo. So add "libOpenCL.so.1" +// to the OpenCL library list. +#elif defined(WTF_CPU_X86) +#define LIBS {"libOpenCL.so", "libOpenCL.so.1", "libPVROCL.so"} +#define SO_LEN 3 + +#else +#define LIBS {} +#define SO_LEN 0 + +#endif // defined(WTF_CPU_ARM) || defined(WTF_CPU_X86) +#endif // defined(WTF_OS_LINUX) || OS(ANDROID) + +/* Platform APIs */ +cl_int (CL_API_CALL *web_clGetPlatformIDs)(cl_uint num_entries, cl_platform_id* platforms, cl_uint* num_platforms); + +cl_int (CL_API_CALL *web_clGetPlatformInfo)(cl_platform_id platform, cl_platform_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clUnloadCompiler)(cl_platform_id platform); + +cl_int (CL_API_CALL *web_clUnloadPlatformCompiler)(cl_platform_id platform); + +/* Device APIs */ +cl_int (CL_API_CALL *web_clGetDeviceInfo)(cl_device_id device, cl_device_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clGetDeviceIDs)(cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, cl_device_id* devices, cl_uint* num_devices); + +cl_int (CL_API_CALL *web_clReleaseDevice)(cl_device_id device); + +/* Context APIs */ +cl_int (CL_API_CALL *web_clGetContextInfo)(cl_context context, cl_context_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clReleaseContext)(cl_context context); + +cl_context (CL_API_CALL *web_clCreateContext)(const cl_context_properties* properties, cl_uint num_devices, const cl_device_id* devices, void (CL_API_CALL* pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data), void* user_data, cl_int* errcode_ret); + +cl_context (CL_API_CALL *web_clCreateContextFromType)(const cl_context_properties* properties, cl_device_type device_type, void (CL_API_CALL *pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data), void* user_data, cl_int* errcode_ret); + +/* CommandQueue APIs */ +cl_int (CL_API_CALL *web_clGetCommandQueueInfo)(cl_command_queue command_queue, cl_command_queue_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clReleaseCommandQueue)(cl_command_queue command_queue); + +cl_command_queue (CL_API_CALL *web_clCreateCommandQueue)(cl_context context, cl_device_id device, cl_command_queue_properties properties, cl_int* errcode_ret); + +/* Memory Object APIs */ +cl_mem (CL_API_CALL *web_clCreateBuffer)(cl_context context, cl_mem_flags flags, size_t size, void* host_ptr, cl_int* errcode_ret); + +cl_mem (CL_API_CALL *web_clCreateSubBuffer)(cl_mem buffer, cl_mem_flags flags, cl_buffer_create_type buffer_create_type, const void* buffer_create_info, cl_int* errcode_ret); + +cl_int (CL_API_CALL *web_clGetMemObjectInfo)(cl_mem memobj, cl_mem_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clReleaseMemObject)(cl_mem memobj); + +cl_int (CL_API_CALL *web_clGetImageInfo)(cl_mem image, cl_image_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_mem (CL_API_CALL *web_clCreateImage2D)(cl_context context, cl_mem_flags flags, const cl_image_format* image_format, size_t image_width, size_t image_height, size_t image_row_pitch, void* host_ptr, cl_int* errcode_ret); + +cl_mem (CL_API_CALL *web_clCreateImage)(cl_context context, cl_mem_flags flags, const cl_image_format* image_format, const cl_image_desc* image_desc, void* host_ptr, cl_int* errcode_ret); + +cl_int (CL_API_CALL *web_clGetSupportedImageFormats)(cl_context context, cl_mem_flags flags, cl_mem_object_type image_type, cl_uint num_entries, cl_image_format* image_formats, cl_uint* num_image_formats); + +/* Sampler APIs */ +cl_sampler (CL_API_CALL *web_clCreateSampler)(cl_context context, cl_bool normalized_coords, cl_addressing_mode addressing_mode, cl_filter_mode filter_mode, cl_int* errcode_ret); + +cl_int (CL_API_CALL *web_clGetSamplerInfo)(cl_sampler sampler, cl_sampler_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clReleaseSampler)(cl_sampler sampler); + +/* Program Object APIs */ +cl_int (CL_API_CALL *web_clGetProgramInfo)(cl_program program, cl_program_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clGetProgramBuildInfo)(cl_program program, cl_device_id device, cl_program_build_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clBuildProgram)(cl_program program, cl_uint num_devices, const cl_device_id* device_list, const char* options, void (CL_API_CALL *pfn_notify)(cl_program program, void* user_data), void* user_data); + +cl_int (CL_API_CALL *web_clReleaseProgram)(cl_program program); + +cl_program (CL_API_CALL *web_clCreateProgramWithSource)(cl_context context, cl_uint const, const char** strings, const size_t* lengths, cl_int* errcode_ret); + +/* Kernel Object APIs */ +cl_int (CL_API_CALL *web_clGetKernelInfo)(cl_kernel kernel, cl_kernel_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clGetKernelWorkGroupInfo)(cl_kernel kernel, cl_device_id device, cl_kernel_work_group_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clSetKernelArg)(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void* arg_value); + +cl_int (CL_API_CALL *web_clReleaseKernel)(cl_kernel kernel); + +cl_kernel (CL_API_CALL *web_clCreateKernel)(cl_program program, const char* kernel_name, cl_int* errcode_ret); + +cl_int (CL_API_CALL *web_clCreateKernelsInProgram)(cl_program program, cl_uint num_kernels, cl_kernel* kernels, cl_uint* num_kernels_ret); + +/* Event Object APIs */ +cl_event (CL_API_CALL *web_clCreateUserEvent)(cl_context context, cl_int* errcode_ret); + +cl_int (CL_API_CALL *web_clWaitForEvents)(cl_uint num_events, const cl_event* event_list); + +cl_int (CL_API_CALL *web_clGetEventInfo)(cl_event event, cl_event_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +cl_int (CL_API_CALL *web_clSetUserEventStatus)(cl_event event, cl_int execution_status); + +cl_int (CL_API_CALL *web_clReleaseEvent)(cl_event event); + +cl_int (CL_API_CALL *web_clSetEventCallback)(cl_event event, cl_int command_exec_callback_type, void (CL_API_CALL* pfn_event_notify)(cl_event event, cl_int event_command_exec_status, void* user_data), void* user_data); + +cl_int (CL_API_CALL *web_clGetEventProfilingInfo)(cl_event event, cl_profiling_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +/* Flush and Finish APIs */ +cl_int (CL_API_CALL *web_clFlush)(cl_command_queue command_queue); + +cl_int (CL_API_CALL *web_clFinish)(cl_command_queue command_queue); + +/* enqueue commands APIs */ +cl_int (CL_API_CALL *web_clEnqueueReadBuffer)(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, size_t size, void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueWriteBuffer)(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t offset, size_t size, const void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueReadImage)(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t* origin, const size_t* region, size_t row_pitch, size_t slice_pitch, void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueWriteImage)(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t* origin, const size_t* region, size_t input_row_pitch, size_t input_slice_pitch, const void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueCopyBuffer)(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, size_t src_offset, size_t dst_offset, size_t size, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueBarrier)(cl_command_queue command_queue); + +cl_int (CL_API_CALL *web_clEnqueueBarrierWithWaitList)(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueMarker)(cl_command_queue command_queue, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueMarkerWithWaitList)(cl_command_queue command_queue, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueTask)(cl_command_queue command_queue, cl_kernel kernel, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueReadBufferRect)(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t* buffer_origin, const size_t* host_origin, const size_t* region, size_t buffer_row_pitch, size_t buffer_slice_pitch, size_t host_row_pitch, size_t host_slice_pitch, void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueWriteBufferRect)(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t* buffer_origin, const size_t* host_origin, const size_t* region, size_t buffer_row_pitch, size_t buffer_slice_pitch, size_t host_row_pitch, size_t host_slice_pitch, const void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueNDRangeKernel)(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t* global_work_offset, const size_t* global_work_size, const size_t* local_work_size, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueCopyBufferRect)(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t* src_origin, const size_t* dst_origin, const size_t* region, size_t src_row_pitch, size_t src_slice_pitch, size_t dst_row_pitch, size_t dst_slice_pitch, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueCopyImage)(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t* src_origin, const size_t* dst_origin, const size_t* region, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueCopyImageToBuffer)(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t* src_origin, const size_t* region, size_t dst_offset, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueCopyBufferToImage)(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, const size_t* dst_origin, const size_t* region, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueWaitForEvents)(cl_command_queue command_queue, cl_uint num_events, const cl_event* event_list); + +/* OpenCL Extention */ +cl_int (CL_API_CALL *web_clEnqueueAcquireGLObjects)(cl_command_queue command_queue, cl_uint num_objects, const cl_mem* mem_objects, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_int (CL_API_CALL *web_clEnqueueReleaseGLObjects)(cl_command_queue command_queue, cl_uint num_objects, const cl_mem* mem_objects, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +cl_mem (CL_API_CALL *web_clCreateFromGLBuffer)(cl_context context, cl_mem_flags flags, GLuint bufobj, cl_int* errcode_ret); + +cl_mem (CL_API_CALL *web_clCreateFromGLRenderbuffer)(cl_context context, cl_mem_flags flags, GLuint renderbuffer, cl_int* errcode_ret); + +cl_mem (CL_API_CALL *web_clCreateFromGLTexture2D)(cl_context context, cl_mem_flags flags, GLenum texture_target, GLint miplevel, GLuint texture, cl_int* errcode_ret); + +cl_mem (CL_API_CALL *web_clCreateFromGLTexture)(cl_context context, cl_mem_flags flags, GLenum texture_target, GLint miplevel, GLuint texture, cl_int* errcode_ret); + +cl_int (CL_API_CALL *web_clGetGLTextureInfo)(cl_mem, cl_gl_texture_info, size_t, void *, size_t *); + +// These aliases are missing from WebCLOpenCL.h. Put them here for internal use only. +#define clReleaseDevice web_clReleaseDevice +#define clCreateImage web_clCreateImage +#define clUnloadPlatformCompiler web_clUnloadPlatformCompiler +#define clEnqueueMarkerWithWaitList web_clEnqueueMarkerWithWaitList +#define clEnqueueBarrierWithWaitList web_clEnqueueBarrierWithWaitList +#define clCreateFromGLTexture web_clCreateFromGLTexture + +#if defined(WTF_OS_LINUX) || OS(ANDROID) +#define MAP_FUNC(fn) { *(void**)(&fn) = dlsym(handle, #fn); } +#define MAP_FUNC_OR_BAIL(fn) { *(void**)(&fn) = dlsym(handle, #fn); if(!fn) return false; } +// In case `fn' is not defined or deprecated in the OpenCL spec tagged by +// `major' and `minor', map `fn' to a wrapper implemented with APIs defined +// by this spec. +#define MAP_FUNC_TO_WRAPPER(fn, major, minor) { *(void**)(&fn) = (void*)fn##Impl##major##minor; } + +static const char* DEFAULT_SO[] = LIBS; +static const int DEFAULT_SO_LEN = SO_LEN; +static void* handle = nullptr; +static bool getCLHandle(const char** libs, int length) +{ + for (int i = 0; i < length; ++i) { + handle = dlopen(libs[i], RTLD_LAZY); + if (handle) + return true; + } + + /* FAILURE: COULD NOT OPEN .SO */ + return false; +} +#endif // defined(WTF_OS_LINUX) || OS(ANDROID) + +// In OpenCL 1.1 spec, no release opertion is needed for device. +static cl_int CL_API_CALL clReleaseDeviceImpl11(cl_device_id device) +{ + return CL_SUCCESS; +} + +static cl_mem CL_API_CALL clCreateImage2DImpl12(cl_context context, cl_mem_flags flags, const cl_image_format* format, size_t width, size_t height, size_t rowPitch, void* hostPtr, cl_int* err) +{ + cl_image_desc desc = {CL_MEM_OBJECT_IMAGE2D, static_cast(width), static_cast(height), 0, 0, static_cast(rowPitch), 0, 0, 0, 0}; + ASSERT(clCreateImage); + return clCreateImage(context, flags, format, &desc, hostPtr, err); +} + +static cl_int CL_API_CALL clUnloadCompilerImpl12(cl_platform_id platform) +{ + ASSERT(clUnloadPlatformCompiler); + return clUnloadPlatformCompiler(platform); +} + +static cl_int CL_API_CALL clEnqueueMarkerImpl12(cl_command_queue queue, cl_event* event) +{ + ASSERT(clEnqueueMarkerWithWaitList); + return clEnqueueMarkerWithWaitList(queue, 0, nullptr, event); +} + +static cl_int CL_API_CALL clEnqueueBarrierImpl12(cl_command_queue queue) +{ + ASSERT(clEnqueueBarrierWithWaitList); + return clEnqueueBarrierWithWaitList(queue, 0, nullptr, nullptr); +} + +static cl_int CL_API_CALL clEnqueueWaitForEventsImpl12(cl_command_queue queue, cl_uint numEvents, const cl_event* eventList) +{ + ASSERT(clEnqueueBarrierWithWaitList); + return clEnqueueBarrierWithWaitList(queue, numEvents, eventList, nullptr); +} + +static cl_mem CL_API_CALL clCreateFromGLTexture2DImpl12(cl_context context, cl_mem_flags flags, GLenum textureTarget, GLint miplevel, GLuint texture, cl_int* err) +{ + ASSERT(clCreateFromGLTexture); + return clCreateFromGLTexture(context, flags, textureTarget, miplevel, texture, err); +} + +bool init(const char** libs, int length) +{ + const char** mLibs = (libs == 0 ? DEFAULT_SO : libs); + int mLength = (libs == 0 ? DEFAULT_SO_LEN: length); + + if (!getCLHandle(mLibs, mLength)) + return false; + + MAP_FUNC_OR_BAIL(clBuildProgram); + MAP_FUNC_OR_BAIL(clCreateBuffer); + MAP_FUNC_OR_BAIL(clCreateCommandQueue); + MAP_FUNC_OR_BAIL(clCreateContext); + MAP_FUNC_OR_BAIL(clCreateContextFromType); + MAP_FUNC_OR_BAIL(clCreateKernel); + MAP_FUNC_OR_BAIL(clCreateKernelsInProgram); + MAP_FUNC_OR_BAIL(clCreateProgramWithSource); + MAP_FUNC_OR_BAIL(clCreateSampler); + MAP_FUNC_OR_BAIL(clCreateSubBuffer); + MAP_FUNC_OR_BAIL(clCreateUserEvent); + + MAP_FUNC_OR_BAIL(clEnqueueCopyBuffer); + MAP_FUNC_OR_BAIL(clEnqueueReadBuffer); + MAP_FUNC_OR_BAIL(clEnqueueWriteBuffer); + MAP_FUNC_OR_BAIL(clEnqueueCopyImage); + MAP_FUNC_OR_BAIL(clEnqueueReadImage); + MAP_FUNC_OR_BAIL(clEnqueueWriteImage); + MAP_FUNC_OR_BAIL(clEnqueueCopyBufferRect); + MAP_FUNC_OR_BAIL(clEnqueueCopyBufferToImage); + MAP_FUNC_OR_BAIL(clEnqueueCopyImageToBuffer); + MAP_FUNC_OR_BAIL(clEnqueueReadBufferRect); + MAP_FUNC_OR_BAIL(clEnqueueWriteBufferRect); + MAP_FUNC_OR_BAIL(clEnqueueNDRangeKernel); + MAP_FUNC_OR_BAIL(clEnqueueTask); + + MAP_FUNC_OR_BAIL(clFinish); + MAP_FUNC_OR_BAIL(clFlush); + + MAP_FUNC_OR_BAIL(clGetContextInfo); + MAP_FUNC_OR_BAIL(clGetCommandQueueInfo); + MAP_FUNC_OR_BAIL(clGetDeviceIDs); + MAP_FUNC_OR_BAIL(clGetDeviceInfo); + MAP_FUNC_OR_BAIL(clGetEventInfo); + MAP_FUNC_OR_BAIL(clGetEventProfilingInfo); + MAP_FUNC_OR_BAIL(clGetImageInfo); + MAP_FUNC_OR_BAIL(clGetKernelInfo); + MAP_FUNC_OR_BAIL(clGetKernelWorkGroupInfo); + MAP_FUNC_OR_BAIL(clGetPlatformIDs); + MAP_FUNC_OR_BAIL(clGetSamplerInfo); + MAP_FUNC_OR_BAIL(clGetSupportedImageFormats); + + MAP_FUNC_OR_BAIL(clGetMemObjectInfo); + MAP_FUNC_OR_BAIL(clGetPlatformInfo); + MAP_FUNC_OR_BAIL(clGetProgramBuildInfo); + MAP_FUNC_OR_BAIL(clGetProgramInfo); + + MAP_FUNC_OR_BAIL(clReleaseCommandQueue); + MAP_FUNC_OR_BAIL(clReleaseContext); + MAP_FUNC_OR_BAIL(clReleaseEvent); + MAP_FUNC_OR_BAIL(clReleaseKernel); + MAP_FUNC_OR_BAIL(clReleaseMemObject); + MAP_FUNC_OR_BAIL(clReleaseProgram); + MAP_FUNC_OR_BAIL(clReleaseSampler); + + MAP_FUNC_OR_BAIL(clSetEventCallback); + MAP_FUNC_OR_BAIL(clSetKernelArg); + MAP_FUNC_OR_BAIL(clSetUserEventStatus); + + MAP_FUNC_OR_BAIL(clWaitForEvents); + + // They depends on whether OpenCL library support gl_sharing extension. + // which aren't required mandatorily for OpenCL spec. + MAP_FUNC(clEnqueueAcquireGLObjects); + MAP_FUNC(clEnqueueReleaseGLObjects); + MAP_FUNC(clCreateFromGLBuffer); + MAP_FUNC(clCreateFromGLRenderbuffer); + MAP_FUNC(clGetGLTextureInfo); + + // The following APIs are not available in all versions of the OpenCL + // spec, so wrappers may be needed if they are not exported by the OpenCL + // runtime library. + MAP_FUNC(clReleaseDevice) + if (!clReleaseDevice) + MAP_FUNC_TO_WRAPPER(clReleaseDevice, 1, 1) + + MAP_FUNC(clCreateImage) + if (clCreateImage) + MAP_FUNC_TO_WRAPPER(clCreateImage2D, 1, 2) + else + MAP_FUNC_OR_BAIL(clCreateImage2D) + + MAP_FUNC(clUnloadPlatformCompiler) + if (clUnloadPlatformCompiler) + MAP_FUNC_TO_WRAPPER(clUnloadCompiler, 1, 2) + else + MAP_FUNC_OR_BAIL(clUnloadCompiler) + + MAP_FUNC(clEnqueueMarkerWithWaitList) + if (clEnqueueMarkerWithWaitList) + MAP_FUNC_TO_WRAPPER(clEnqueueMarker, 1, 2) + else + MAP_FUNC_OR_BAIL(clEnqueueMarker) + + MAP_FUNC(clEnqueueBarrierWithWaitList) + if (clEnqueueBarrierWithWaitList) + MAP_FUNC_TO_WRAPPER(clEnqueueBarrier, 1, 2) + else + MAP_FUNC_OR_BAIL(clEnqueueBarrier) + + MAP_FUNC(clEnqueueWaitForEvents) + if (!clEnqueueWaitForEvents) + MAP_FUNC_TO_WRAPPER(clEnqueueWaitForEvents, 1, 2) + + MAP_FUNC(clCreateFromGLTexture) + if (clCreateFromGLTexture) + MAP_FUNC_TO_WRAPPER(clCreateFromGLTexture2D, 1, 2) + else + MAP_FUNC(clCreateFromGLTexture2D) + + return true; +} + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLOpenCL.h b/third_party/WebKit/Source/modules/webcl/WebCLOpenCL.h new file mode 100644 index 0000000000000..d298d8c2be1a0 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLOpenCL.h @@ -0,0 +1,226 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLOpenCL_h +#define WebCLOpenCL_h + +#include "modules/webcl/WebCLConfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool init(const char** libs, int len); /* load libs in lib list. */ + +/* Platform APIs */ +extern cl_int (CL_API_CALL *web_clGetPlatformIDs)(cl_uint num_entries, cl_platform_id* platforms, cl_uint* num_platforms); + +extern cl_int (CL_API_CALL *web_clGetPlatformInfo)(cl_platform_id platform, cl_platform_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clUnloadCompiler)(cl_platform_id platform); + +/* Device APIs */ +extern cl_int (CL_API_CALL *web_clGetDeviceInfo)(cl_device_id device, cl_device_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clGetDeviceIDs)(cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, cl_device_id* devices, cl_uint* num_devices); + +/* Context APIs */ +extern cl_int (CL_API_CALL *web_clGetContextInfo)(cl_context context, cl_context_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clReleaseContext)(cl_context context); + +extern cl_context (CL_API_CALL *web_clCreateContext)(const cl_context_properties* properties, cl_uint num_devices, const cl_device_id* devices, void (CL_API_CALL* pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data), void* user_data, cl_int* errcode_ret); + +extern cl_context (CL_API_CALL *web_clCreateContextFromType)(const cl_context_properties* properties, cl_device_type device_type, void (CL_API_CALL *pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data), void* user_data, cl_int* errcode_ret); + +/* CommandQueue APIs */ +extern cl_int (CL_API_CALL *web_clGetCommandQueueInfo)(cl_command_queue command_queue, cl_command_queue_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clReleaseCommandQueue)(cl_command_queue command_queue); + +extern cl_command_queue (CL_API_CALL *web_clCreateCommandQueue)(cl_context context, cl_device_id device, cl_command_queue_properties properties, cl_int* errcode_ret); + +/* Memory Object APIs */ +extern cl_mem (CL_API_CALL *web_clCreateBuffer)(cl_context context, cl_mem_flags flags, size_t size, void* host_ptr, cl_int* errcode_ret); + +extern cl_mem (CL_API_CALL *web_clCreateSubBuffer)(cl_mem buffer, cl_mem_flags flags, cl_buffer_create_type buffer_create_type, const void* buffer_create_info, cl_int* errcode_ret); + +extern cl_int (CL_API_CALL *web_clGetMemObjectInfo)(cl_mem memobj, cl_mem_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clReleaseMemObject)(cl_mem memobj); + +extern cl_int (CL_API_CALL *web_clGetImageInfo)(cl_mem image, cl_image_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_mem (CL_API_CALL *web_clCreateImage2D)(cl_context context, cl_mem_flags flags, const cl_image_format* image_format, size_t image_width, size_t image_height, size_t image_row_pitch, void* host_ptr, cl_int* errcode_ret); + +extern cl_int (CL_API_CALL *web_clGetSupportedImageFormats)(cl_context context, cl_mem_flags flags, cl_mem_object_type image_type, cl_uint num_entries, cl_image_format* image_formats, cl_uint* num_image_formats); + +/* Sampler APIs */ +extern cl_sampler (CL_API_CALL *web_clCreateSampler)(cl_context context, cl_bool normalized_coords, cl_addressing_mode addressing_mode, cl_filter_mode filter_mode, cl_int* errcode_ret); + +extern cl_int (CL_API_CALL *web_clGetSamplerInfo)(cl_sampler sampler, cl_sampler_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clReleaseSampler)(cl_sampler sampler); + +/* Program Object APIs */ +extern cl_int (CL_API_CALL *web_clGetProgramInfo)(cl_program program, cl_program_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clGetProgramBuildInfo)(cl_program program, cl_device_id device, cl_program_build_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clBuildProgram)(cl_program program, cl_uint num_devices, const cl_device_id* device_list, const char* options, void (CL_API_CALL *pfn_notify)(cl_program program, void* user_data), void* user_data); + +extern cl_int (CL_API_CALL *web_clReleaseProgram)(cl_program program); + +extern cl_program (CL_API_CALL *web_clCreateProgramWithSource)(cl_context context, cl_uint const, const char** strings, const size_t* lengths, cl_int* errcode_ret); + +/* Kernel Object APIs */ +extern cl_int (CL_API_CALL *web_clGetKernelInfo)(cl_kernel kernel, cl_kernel_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clGetKernelWorkGroupInfo)(cl_kernel kernel, cl_device_id device, cl_kernel_work_group_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clSetKernelArg)(cl_kernel kernel, cl_uint arg_index, size_t arg_size, const void* arg_value); + +extern cl_int (CL_API_CALL *web_clReleaseKernel)(cl_kernel kernel); + +extern cl_kernel (CL_API_CALL *web_clCreateKernel)(cl_program program, const char* kernel_name, cl_int* errcode_ret); + +extern cl_int (CL_API_CALL *web_clCreateKernelsInProgram)(cl_program program, cl_uint num_kernels, cl_kernel* kernels, cl_uint* num_kernels_ret); + +/* Event Object APIs */ +extern cl_event (CL_API_CALL *web_clCreateUserEvent)(cl_context context, cl_int* errcode_ret); + +extern cl_int (CL_API_CALL *web_clWaitForEvents)(cl_uint num_events, const cl_event* event_list); + +extern cl_int (CL_API_CALL *web_clGetEventInfo)(cl_event event, cl_event_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +extern cl_int (CL_API_CALL *web_clSetUserEventStatus)(cl_event event, cl_int execution_status); + +extern cl_int (CL_API_CALL *web_clReleaseEvent)(cl_event event); + +extern cl_int (CL_API_CALL *web_clSetEventCallback)(cl_event event, cl_int command_exec_callback_type, void (CL_API_CALL* pfn_event_notify)(cl_event event, cl_int event_command_exec_status, void* user_data), void* user_data); + +extern cl_int (CL_API_CALL *web_clGetEventProfilingInfo)(cl_event event, cl_profiling_info param_name, size_t param_value_size, void* param_value, size_t* param_value_size_ret); + +/* Flush and Finish APIs */ +extern cl_int (CL_API_CALL *web_clFlush)(cl_command_queue command_queue); + +extern cl_int (CL_API_CALL *web_clFinish)(cl_command_queue command_queue); + +/* enqueue commands APIs */ +extern cl_int (CL_API_CALL *web_clEnqueueReadBuffer)(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, size_t size, void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueWriteBuffer)(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, size_t offset, size_t size, const void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueReadImage)(cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, const size_t* origin, const size_t* region, size_t row_pitch, size_t slice_pitch, void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueWriteImage)(cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, const size_t* origin, const size_t* region, size_t input_row_pitch, size_t input_slice_pitch, const void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueCopyBuffer)(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, size_t src_offset, size_t dst_offset, size_t size, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueBarrier)(cl_command_queue command_queue); + +extern cl_int (CL_API_CALL *web_clEnqueueMarker)(cl_command_queue command_queue, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueTask)(cl_command_queue command_queue, cl_kernel kernel, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueReadBufferRect)(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, const size_t* buffer_origin, const size_t* host_origin, const size_t* region, size_t buffer_row_pitch, size_t buffer_slice_pitch, size_t host_row_pitch, size_t host_slice_pitch, void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueWriteBufferRect)(cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, const size_t* buffer_origin, const size_t* host_origin, const size_t* region, size_t buffer_row_pitch, size_t buffer_slice_pitch, size_t host_row_pitch, size_t host_slice_pitch, const void* ptr, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueNDRangeKernel)(cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, const size_t* global_work_offset, const size_t* global_work_size, const size_t* local_work_size, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueCopyBufferRect)(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, const size_t* src_origin, const size_t* dst_origin, const size_t* region, size_t src_row_pitch, size_t src_slice_pitch, size_t dst_row_pitch, size_t dst_slice_pitch, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueCopyImage)(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, const size_t* src_origin, const size_t* dst_origin, const size_t* region, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueCopyImageToBuffer)(cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, const size_t* src_origin, const size_t* region, size_t dst_offset, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueCopyBufferToImage)(cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_image, size_t src_offset, const size_t* dst_origin, const size_t* region, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueWaitForEvents)(cl_command_queue command_queue, cl_uint num_events, const cl_event* event_list); + +/* OpenCL Extention */ +extern cl_int (CL_API_CALL *web_clEnqueueAcquireGLObjects)(cl_command_queue command_queue, cl_uint num_objects, const cl_mem* mem_objects, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_int (CL_API_CALL *web_clEnqueueReleaseGLObjects)(cl_command_queue command_queue, cl_uint num_objects, const cl_mem* mem_objects, cl_uint num_events_in_wait_list, const cl_event* event_wait_list, cl_event* event); + +extern cl_mem (CL_API_CALL *web_clCreateFromGLBuffer)(cl_context context, cl_mem_flags flags, GLuint bufobj, cl_int* errcode_ret); + +extern cl_mem (CL_API_CALL *web_clCreateFromGLRenderbuffer)(cl_context context, cl_mem_flags flags, GLuint renderbuffer, cl_int* errcode_ret); + +extern cl_mem (CL_API_CALL *web_clCreateFromGLTexture2D)(cl_context context, cl_mem_flags flags, GLenum texture_target, GLint miplevel, GLuint texture, cl_int* errcode_ret); + +extern cl_int (CL_API_CALL *web_clGetGLTextureInfo)(cl_mem, cl_gl_texture_info, size_t, void *, size_t *); + +#ifdef __cplusplus +} +#endif + +// Mapping real OpenCL function to the function pointer. +#define clGetImageInfo web_clGetImageInfo +#define clCreateBuffer web_clCreateBuffer +#define clCreateSubBuffer web_clCreateSubBuffer +#define clGetCommandQueueInfo web_clGetCommandQueueInfo +#define clEnqueueWriteBuffer web_clEnqueueWriteBuffer +#define clFinish web_clFinish +#define clFlush web_clFlush +#define clEnqueueReadBuffer web_clEnqueueReadBuffer +#define clReleaseCommandQueue web_clReleaseCommandQueue +#define clEnqueueWriteImage web_clEnqueueWriteImage +#define clEnqueueAcquireGLObjects web_clEnqueueAcquireGLObjects +#define clEnqueueReleaseGLObjects web_clEnqueueReleaseGLObjects +#define clEnqueueCopyBuffer web_clEnqueueCopyBuffer +#define clEnqueueBarrier web_clEnqueueBarrier +#define clEnqueueMarker web_clEnqueueMarker +#define clEnqueueTask web_clEnqueueTask +#define clEnqueueWriteBufferRect web_clEnqueueWriteBufferRect +#define clEnqueueReadBufferRect web_clEnqueueReadBufferRect +#define clEnqueueReadImage web_clEnqueueReadImage +#define clEnqueueNDRangeKernel web_clEnqueueNDRangeKernel +#define clEnqueueCopyBufferRect web_clEnqueueCopyBufferRect +#define clEnqueueCopyImage web_clEnqueueCopyImage +#define clEnqueueCopyImageToBuffer web_clEnqueueCopyImageToBuffer +#define clEnqueueCopyBufferToImage web_clEnqueueCopyBufferToImage +#define clEnqueueWaitForEvents web_clEnqueueWaitForEvents +#define clCreateCommandQueue web_clCreateCommandQueue +#define clGetContextInfo web_clGetContextInfo +#define clCreateProgramWithSource web_clCreateProgramWithSource +#define clCreateImage2D web_clCreateImage2D +#define clCreateFromGLBuffer web_clCreateFromGLBuffer +#define clCreateFromGLRenderbuffer web_clCreateFromGLRenderbuffer +#define clCreateSampler web_clCreateSampler +#define clCreateFromGLTexture2D web_clCreateFromGLTexture2D +#define clCreateUserEvent web_clCreateUserEvent +#define clWaitForEvents web_clWaitForEvents +#define clReleaseContext web_clReleaseContext +#define clGetSupportedImageFormats web_clGetSupportedImageFormats +#define clCreateContext web_clCreateContext +#define clCreateContextFromType web_clCreateContextFromType +#define clGetPlatformIDs web_clGetPlatformIDs +#define clUnloadCompiler web_clUnloadCompiler +#define clGetDeviceIDs web_clGetDeviceIDs +#define clGetDeviceInfo web_clGetDeviceInfo +#define clGetEventInfo web_clGetEventInfo +#define clSetUserEventStatus web_clSetUserEventStatus +#define clReleaseEvent web_clReleaseEvent +#define clSetEventCallback web_clSetEventCallback +#define clGetEventProfilingInfo web_clGetEventProfilingInfo +#define clGetGLTextureInfo web_clGetGLTextureInfo +#define clGetKernelInfo web_clGetKernelInfo +#define clGetKernelWorkGroupInfo web_clGetKernelWorkGroupInfo +#define clSetKernelArg web_clSetKernelArg +#define clReleaseKernel web_clReleaseKernel +#define clGetMemObjectInfo web_clGetMemObjectInfo +#define clReleaseMemObject web_clReleaseMemObject +#define clGetPlatformInfo web_clGetPlatformInfo +#define clGetProgramInfo web_clGetProgramInfo +#define clCreateKernel web_clCreateKernel +#define clGetProgramBuildInfo web_clGetProgramBuildInfo +#define clCreateKernelsInProgram web_clCreateKernelsInProgram +#define clBuildProgram web_clBuildProgram +#define clReleaseProgram web_clReleaseProgram +#define clGetSamplerInfo web_clGetSamplerInfo +#define clReleaseSampler web_clReleaseSampler + +#endif // WebCLOpenCL_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLPlatform.cpp b/third_party/WebKit/Source/modules/webcl/WebCLPlatform.cpp new file mode 100644 index 0000000000000..6122af5990cd9 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLPlatform.cpp @@ -0,0 +1,186 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/core/v8/V8Binding.h" +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLPlatform.h" + +namespace blink { + +WebCLPlatform::~WebCLPlatform() +{ +} + +PassRefPtr WebCLPlatform::create(cl_platform_id m_clPlatformId) +{ + return adoptRef(new WebCLPlatform(m_clPlatformId)); +} + +Vector> WebCLPlatform::getDevices(ExceptionState& es) +{ + return getDevices(CL_DEVICE_TYPE_ALL, es); +} + +Vector> WebCLPlatform::getDevices(unsigned deviceType, ExceptionState& es) +{ + if (!m_clPlatformId) { + es.throwWebCLException(WebCLException::INVALID_PLATFORM, WebCLException::invalidPlatformMessage); + return Vector>(); + } + + if (deviceType && !WebCLInputChecker::isValidDeviceType(deviceType)) { + es.throwWebCLException(WebCLException::INVALID_DEVICE_TYPE, WebCLException::invalidDeviceTypeMessage); + return Vector>(); + } + + if (!deviceType) + deviceType = CL_DEVICE_TYPE_ALL; + + if (m_cachedDeviceType == deviceType && m_devices.size()) + return m_devices; + + cl_int err = CL_SUCCESS; + cl_uint numDevices = 0; + switch(deviceType) { + case CL_DEVICE_TYPE_GPU: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_GPU, 0, nullptr, &numDevices); + break; + case CL_DEVICE_TYPE_CPU: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_CPU, 0, nullptr, &numDevices); + break; + case CL_DEVICE_TYPE_ACCELERATOR: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_ACCELERATOR, 0, nullptr, &numDevices); + break; + case CL_DEVICE_TYPE_DEFAULT: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_DEFAULT, 0, nullptr, &numDevices); + break; + case CL_DEVICE_TYPE_ALL: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_ALL, 0, nullptr, &numDevices); + break; + default: + ASSERT_NOT_REACHED(); + } + + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return Vector>(); + } + + Vector clDevices; + clDevices.resize(numDevices); + + switch (deviceType) { + case CL_DEVICE_TYPE_GPU: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_GPU, numDevices, clDevices.data(), nullptr); + break; + case CL_DEVICE_TYPE_CPU: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_CPU, numDevices, clDevices.data(), nullptr); + break; + case CL_DEVICE_TYPE_ACCELERATOR: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_ACCELERATOR, numDevices, clDevices.data(), nullptr); + break; + case CL_DEVICE_TYPE_DEFAULT: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_DEFAULT, numDevices, clDevices.data(), nullptr ); + break; + case CL_DEVICE_TYPE_ALL: + err = clGetDeviceIDs(m_clPlatformId, CL_DEVICE_TYPE_ALL, numDevices, clDevices.data(), nullptr); + break; + default: + ASSERT_NOT_REACHED(); + } + + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return Vector>(); + } + + m_devices.clear(); + for (auto clDevice : clDevices) { + RefPtr device = WebCLDevice::create(clDevice, this); + if (device) + m_devices.append(device); + } + + clDevices.clear(); + m_cachedDeviceType = deviceType; + return m_devices; +} + +ScriptValue WebCLPlatform::getInfo(ScriptState* scriptState, int platformInfo, ExceptionState& es) +{ + v8::Isolate* isolate = scriptState->isolate(); + + if (!m_clPlatformId) { + es.throwWebCLException(WebCLException::INVALID_PLATFORM, WebCLException::invalidPlatformMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + switch (platformInfo) { + case CL_PLATFORM_PROFILE: + return ScriptValue(scriptState, v8String(isolate, String("WEBCL_PROFILE"))); + case CL_PLATFORM_VERSION: + return ScriptValue(scriptState, v8String(isolate, String("WebCL 1.0"))); + case CL_PLATFORM_NAME: + case CL_PLATFORM_VENDOR: + case CL_PLATFORM_EXTENSIONS: + return ScriptValue(scriptState, v8String(isolate, emptyString())); + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } +} + +void WebCLPlatform::cachePlatformExtensions() +{ + char platformString[MULTI_EXTENSIONS_LENGTH] = ""; + Vector extensions; + + if (!m_clPlatformId) + return; + + cl_int err = clGetPlatformInfo(m_clPlatformId, CL_PLATFORM_EXTENSIONS, sizeof(platformString), &platformString, nullptr); + + if (err != CL_SUCCESS) + return; + + String temp = String(platformString); + temp.split(' ', extensions); + + for (auto extension : extensions) { + if (!extension.containsOnlyWhitespace()) + m_extension.addSupportedCLExtension(String(extension)); + } +} + +bool WebCLPlatform::enableExtension(const String& name) +{ + return m_extension.enableExtension(name); +} + +Vector WebCLPlatform::getSupportedExtensions() +{ + return m_extension.getSupportedExtensions(); +} + +void WebCLPlatform::getEnabledExtensions(HashSet& extensions) +{ + m_extension.getEnabledExtensions(extensions); +} + +WebCLPlatform::WebCLPlatform(cl_platform_id platform) + : m_cachedDeviceType(0) + , m_clPlatformId(platform) +{ + cachePlatformExtensions(); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLPlatform.h b/third_party/WebKit/Source/modules/webcl/WebCLPlatform.h new file mode 100644 index 0000000000000..cdbcbf8921c8a --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLPlatform.h @@ -0,0 +1,51 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLPlatform_h +#define WebCLPlatform_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLExtension.h" + +#include +#include + +namespace blink { + +class ExceptionState; +class WebCLCommandQueue; +class WebCLImage; + +class WebCLPlatform : public RefCounted, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLPlatform(); + static PassRefPtr create(cl_platform_id); + + Vector> getDevices(unsigned, ExceptionState&); + Vector> getDevices(ExceptionState&); + ScriptValue getInfo(ScriptState*, int, ExceptionState&); + + void cachePlatformExtensions(); + bool enableExtension(const String& name); + Vector getSupportedExtensions(); + void getEnabledExtensions(HashSet& extensions); + cl_platform_id getPlatformId() { return m_clPlatformId; } + +private: + WebCLPlatform(cl_platform_id); + + Vector> m_devices; + unsigned m_cachedDeviceType; + WebCLExtension m_extension; + cl_platform_id m_clPlatformId; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLPlatform_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLPlatform.idl b/third_party/WebKit/Source/modules/webcl/WebCLPlatform.idl new file mode 100644 index 0000000000000..2ab006acd11b8 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLPlatform.idl @@ -0,0 +1,14 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef boolean CLboolean; +typedef unsigned long CLenum; +[ + Conditional=WEBCL, +] interface WebCLPlatform { + [CallWith=ScriptState, RaisesException] any getInfo(CLenum platformInfo); + [RaisesException] sequence getDevices(optional CLenum deviceType); + sequence? getSupportedExtensions(); + CLboolean enableExtension(DOMString extensionName); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLProgram.cpp b/third_party/WebKit/Source/modules/webcl/WebCLProgram.cpp new file mode 100644 index 0000000000000..476ee239e5fca --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLProgram.cpp @@ -0,0 +1,510 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/modules/v8/V8WebCLContext.h" +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLKernel.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLProgram.h" +#include "platform/ThreadSafeFunctional.h" +#include "public/platform/Platform.h" +#include "public/platform/WebTraceLocation.h" + +namespace blink { + +// The holder of WebCLProgram. +class WebCLProgramHolder { +public: + WeakPtr program; + cl_program program2; +}; + +static bool isASCIILineBreakOrWhiteSpaceCharacter(UChar c) +{ + return c == '\r' || c == '\n' || c == ' '; +} + +WebCLProgram::~WebCLProgram() +{ + release(); + ASSERT(!m_clProgram); +} + +PassRefPtr WebCLProgram::create(cl_program program, WebCLContext* context, const String& kernelSource) +{ + return adoptRef(new WebCLProgram(program, context, kernelSource)); +} + +bool WebCLProgram::isExtensionEnabled(RefPtr context, const String& name) +{ + return context->isExtensionEnabled(name); +} + +static void removeComments(const String& inSource, String& outSource) +{ + enum Mode { DEFAULT, BLOCK_COMMENT, LINE_COMMENT }; + Mode currentMode = DEFAULT; + + ASSERT(!inSource.isNull()); + ASSERT(!inSource.isEmpty()); + + outSource = inSource; + for (unsigned i = 0; i < outSource.length(); ++i) { + if (currentMode == BLOCK_COMMENT) { + if (outSource[i] == '*' && outSource[i + 1] == '/') { + outSource.replace(i++, 2, " "); + currentMode = DEFAULT; + continue; + } + outSource.replace(i, 1, " "); + continue; + } + + if (currentMode == LINE_COMMENT) { + if (outSource[i] == '\n' || outSource[i] == '\r') { + currentMode = DEFAULT; + continue; + } + outSource.replace(i, 1, " "); + continue; + } + + if (outSource[i] == '/') { + if (outSource[i + 1] == '*') { + outSource.replace(i++, 2, " "); + currentMode = BLOCK_COMMENT; + continue; + } + + if (outSource[i + 1] == '/') { + outSource.replace(i++, 2, " "); + currentMode = LINE_COMMENT; + continue; + } + } + } +} + +ScriptValue WebCLProgram::getInfo(ScriptState* scriptState, int paramName, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_PROGRAM, WebCLException::invalidProgramMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_int err = CL_SUCCESS; + cl_uint uintUnits = 0; + Vector> result = context()->getDevices(); + + switch(paramName) { + case CL_PROGRAM_NUM_DEVICES: + err = clGetProgramInfo(m_clProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &uintUnits, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(uintUnits))); + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); + case CL_PROGRAM_SOURCE: + return ScriptValue(scriptState, v8String(isolate, m_programSource)); + case CL_PROGRAM_CONTEXT: + return ScriptValue(scriptState, toV8(context(), creationContext, isolate)); + case CL_PROGRAM_DEVICES: + return ScriptValue(scriptState, toV8(result, creationContext, isolate)); + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } +} + +ScriptValue WebCLProgram::getBuildInfo(ScriptState* scriptState, WebCLDevice* device, int paramName, ExceptionState& es) +{ + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_PROGRAM, WebCLException::invalidProgramMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + cl_device_id clDevice = nullptr; + if (device) { + clDevice = device->getDeviceId(); + if (!clDevice) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + size_t i = 0; + Vector> deviceList = context()->getDevices(); + for (; i < deviceList.size(); i ++) { + if (clDevice == deviceList[i]->getDeviceId()) + break; + } + if (i == deviceList.size()) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + } + + cl_int err = CL_SUCCESS; + char *buffer; + size_t len = 0; + switch (paramName) { + case CL_PROGRAM_BUILD_LOG: { + err = clGetProgramBuildInfo(m_clProgram, clDevice, CL_PROGRAM_BUILD_LOG, 0, nullptr, &len); + if (err != CL_SUCCESS) + break; + buffer = new char[len + 1]; + err = clGetProgramBuildInfo(m_clProgram, clDevice, CL_PROGRAM_BUILD_LOG, len, buffer, nullptr); + if (err != CL_SUCCESS) + break; + String result(buffer); + delete [] buffer; + return ScriptValue(scriptState, v8String(isolate, result)); + } + case CL_PROGRAM_BUILD_OPTIONS: { + err = clGetProgramBuildInfo(m_clProgram, clDevice, CL_PROGRAM_BUILD_OPTIONS, 0, nullptr, &len); + if (err != CL_SUCCESS) + break; + buffer = new char[len + 1]; + err = clGetProgramBuildInfo(m_clProgram, clDevice, CL_PROGRAM_BUILD_OPTIONS, len, buffer, nullptr); + if (err != CL_SUCCESS) + break; + String result(buffer); + delete [] buffer; + return ScriptValue(scriptState, v8String(isolate, result)); + } + case CL_PROGRAM_BUILD_STATUS: + cl_build_status buildStatus; + err = clGetProgramBuildInfo(m_clProgram, clDevice, CL_PROGRAM_BUILD_STATUS, sizeof(cl_build_status), &buildStatus, nullptr); + if (err == CL_SUCCESS) + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(buildStatus))); + break; + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + WebCLException::throwException(err, es); + return ScriptValue(scriptState, v8::Null(isolate)); +} + +PassRefPtr WebCLProgram::createKernel(const String& kernelName, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_PROGRAM, WebCLException::invalidProgramMessage); + return nullptr; + } + + if (!m_isProgramBuilt) { + es.throwWebCLException(WebCLException::INVALID_PROGRAM_EXECUTABLE, WebCLException::invalidProgramExecutableMessage); + return nullptr; + } + + if (!m_programSource.contains(kernelName)) { + es.throwWebCLException(WebCLException::INVALID_KERNEL_NAME, WebCLException::invalidKernelNameMessage); + return nullptr; + } + + cl_int err = CL_SUCCESS; + const char* kernelNameStr = strdup(kernelName.utf8().data()); + cl_kernel clKernelId = clCreateKernel(m_clProgram, kernelNameStr, &err); + + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return nullptr; + } + RefPtr kernel = WebCLKernel::create(clKernelId, context(), this, kernelName); + return kernel; +} + +Vector> WebCLProgram::createKernelsInProgram(ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_PROGRAM, WebCLException::invalidProgramMessage); + return Vector>(); + } + + if (!m_isProgramBuilt) { + es.throwWebCLException(WebCLException::INVALID_PROGRAM_EXECUTABLE, WebCLException::invalidProgramExecutableMessage); + return Vector>(); + } + + cl_uint num = 0; + cl_int err = clCreateKernelsInProgram(m_clProgram, 0, nullptr, &num); + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return Vector>(); + } + + if (num == 0) { + es.throwWebCLException(WebCLException::FAILURE, WebCLException::failureMessage); + return Vector>(); + } + + cl_kernel* kernelBuf = (cl_kernel*)malloc (sizeof(cl_kernel) * num); + if (!kernelBuf) { + return Vector>(); + } + + err = clCreateKernelsInProgram(m_clProgram, num, kernelBuf, nullptr); + + if (err != CL_SUCCESS) { + WebCLException::throwException(err, es); + return Vector>(); + } + + Vector kernelName; + size_t bytesOfKernelName = 0; + Vector> m_kernelList; + for (size_t i = 0 ; i < num; i++) { + err = clGetKernelInfo(kernelBuf[i], CL_KERNEL_FUNCTION_NAME, 0, nullptr, &bytesOfKernelName); + if (err != CL_SUCCESS) { + continue; + } + + kernelName.reserveCapacity(bytesOfKernelName); + kernelName.resize(bytesOfKernelName); + + err = clGetKernelInfo(kernelBuf[i], CL_KERNEL_FUNCTION_NAME, bytesOfKernelName, kernelName.data(), 0); + + if (err != CL_SUCCESS) { + continue; + } + + RefPtr kernel = WebCLKernel::create(kernelBuf[i], context(), this, static_cast(kernelName.data())); + + if (kernel) + m_kernelList.append(kernel); + kernelName.clear(); + bytesOfKernelName = 0; + } + + return m_kernelList; +} + +void WebCLProgram::build(const Vector>& devices, const String& buildOptions, WebCLCallback* callback, ExceptionState& es) +{ + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_PROGRAM, WebCLException::invalidProgramMessage); + return; + } + + size_t kernel_label = m_programSource.find("__kernel ", 0); + while (kernel_label != WTF::kNotFound) { + size_t openBrace = m_programSource.find("{", kernel_label); + size_t openBraket = m_programSource.reverseFind("(", openBrace); + size_t space = m_programSource.reverseFind(" ", openBraket); + String kernelName = m_programSource.substring(space + 1, openBraket - space - 1); + if (kernelName.length() > 254) { + // Kernel Name length isn't allowed larger than 255. + es.throwWebCLException(WebCLException::BUILD_PROGRAM_FAILURE, WebCLException::buildProgramFailureMessage); + return; + } + + size_t closeBraket = m_programSource.find(")", openBraket); + String arguments = m_programSource.substring(openBraket + 1, closeBraket - openBraket - 1); + if (arguments.contains("struct ") || arguments.contains("image1d_array_t ") || arguments.contains("image1d_buffer_t ") || arguments.contains("image1d_t ") || arguments.contains("image2d_array_t ")) { + // 1. Kernel structure parameters aren't allowed; + // 2. Kernel argument "image1d_t", "image1d_array_t", "image2d_array_t" and "image1d_buffer_t" aren't allowed; + es.throwWebCLException(WebCLException::BUILD_PROGRAM_FAILURE, WebCLException::buildProgramFailureMessage); + return; + } + + size_t closeBrace = m_programSource.find("}", openBrace); + String codeString = m_programSource.substring(openBrace + 1, closeBrace - openBrace - 1).removeCharacters(isASCIILineBreakOrWhiteSpaceCharacter); + if (codeString.isEmpty()) { + // Kernel code isn't empty; + es.throwWebCLException(WebCLException::BUILD_PROGRAM_FAILURE, WebCLException::buildProgramFailureMessage); + return; + } + + kernel_label = m_programSource.find("__kernel ", closeBrace); + } + + if (buildOptions.length() > 0) { + static AtomicString& buildOptionDashD = *new AtomicString("-D", AtomicString::ConstructFromLiteral); + static HashSet& webCLSupportedBuildOptions = *new HashSet(); + if (webCLSupportedBuildOptions.isEmpty()) { + webCLSupportedBuildOptions.add(AtomicString("-cl-opt-disable", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-cl-single-precision-constant", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-cl-denorms-are-zero", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-cl-mad-enable", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-cl-no-signed-zeros", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-cl-unsafe-math-optimizations", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-cl-finite-math-only", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-cl-fast-relaxed-math", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-w", AtomicString::ConstructFromLiteral)); + webCLSupportedBuildOptions.add(AtomicString("-Werror", AtomicString::ConstructFromLiteral)); + } + + Vector webCLBuildOptionsVector; + buildOptions.split(" ", false, webCLBuildOptionsVector); + + for (size_t i = 0; i < webCLBuildOptionsVector.size(); i++) { + // Every build option must start with a hyphen. + if (!webCLBuildOptionsVector[i].startsWith("-")) { + es.throwWebCLException(WebCLException::INVALID_BUILD_OPTIONS, WebCLException::invalidBuildOptionsMessage); + return; + } + + if (webCLSupportedBuildOptions.contains(AtomicString(webCLBuildOptionsVector[i]))) + continue; + + if (webCLBuildOptionsVector[i].startsWith(buildOptionDashD)) { + size_t j; + for (j = i + 1; j < webCLBuildOptionsVector.size() && !webCLBuildOptionsVector[j].startsWith("-"); ++j) {} + if (webCLBuildOptionsVector[i].stripWhiteSpace() == buildOptionDashD && j == i + 1) { + es.throwWebCLException(WebCLException::INVALID_BUILD_OPTIONS, WebCLException::invalidBuildOptionsMessage); + return; + } + + i = --j; + continue; + } + + es.throwWebCLException(WebCLException::INVALID_BUILD_OPTIONS, WebCLException::invalidBuildOptionsMessage); + return; + } + } + + pfnNotify callbackProxyPtr = nullptr; + WebCLProgramHolder* holder = nullptr; + if (callback) { + if (m_buildCallback) { + es.throwWebCLException(WebCLException::INVALID_OPERATION, WebCLException::invalidOperationMessage); + return; + } + + // Store the callback, eventList to HashTable and call callbackProxy. + m_buildCallback = adoptRef(callback); + callbackProxyPtr = &callbackProxy; + holder = new WebCLProgramHolder; + holder->program = createWeakPtr(); + } + + cl_int err = CL_SUCCESS; + Vector clDevices; + Vector> contextDevices = context()->getDevices(); + if (devices.size()) { + Vector inputDevices; + for (auto device : devices) + inputDevices.append(device->getDeviceId()); + + size_t contextDevicesLength = contextDevices.size(); + for (size_t z, i = 0; i < inputDevices.size(); i++) { + // Check if the inputDevices[i] is part of programs WebCLContext. + for (z = 0; z < contextDevicesLength; z++) { + if (contextDevices[z]->getDeviceId() == inputDevices[i]) { + break; + } + } + + if (z == contextDevicesLength) { + es.throwWebCLException(WebCLException::INVALID_DEVICE, WebCLException::invalidDeviceMessage); + return; + } + + clDevices.append(inputDevices[i]); + } + } else { + for (auto contextDevice : contextDevices) + clDevices.append(contextDevice->getDeviceId()); + } + + if (!clDevices.size()) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + m_isProgramBuilt = true; + err = clBuildProgram(m_clProgram, clDevices.size(), clDevices.data(), buildOptions.utf8().data(), callbackProxyPtr, holder); + + if (err != CL_SUCCESS) + es.throwWebCLException(WebCLException::BUILD_PROGRAM_FAILURE, WebCLException::buildProgramFailureMessage); +} + +void WebCLProgram::build(const String& options, WebCLCallback* callback, ExceptionState& es) +{ + Vector> devices; + build(devices, options, callback, es); +} + +void WebCLProgram::release() +{ + if (isReleased()) + return; + + cl_int err = clReleaseProgram(m_clProgram); + if (err != CL_SUCCESS) + ASSERT_NOT_REACHED(); + + m_clProgram = 0; + + // Release the un-triggered callback. + m_buildCallback.clear(); +} + +const String& WebCLProgram::sourceWithCommentsStripped() +{ + if (m_programSourceWithCommentsStripped.isNull()) + removeComments(m_programSource, m_programSourceWithCommentsStripped); + + return m_programSourceWithCommentsStripped; +} + +WebCLProgram::WebCLProgram(cl_program program, WebCLContext* context, const String& kernelSource) + : WebCLObject(context) + , m_buildCallback(nullptr) + , m_programSource(kernelSource) + , m_isProgramBuilt(false) + , m_clProgram(program) +{ +} + +void WebCLProgram::callbackProxy(cl_program program, void* userData) +{ + OwnPtr holder = adoptPtr(static_cast(userData)); + holder->program2 = program; + + if (isMainThread()) { + callbackProxyOnMainThread(holder.release()); + return; + } + + Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&WebCLProgram::callbackProxyOnMainThread, holder.release())); +} + +void WebCLProgram::callbackProxyOnMainThread(PassOwnPtr holder) +{ + ASSERT(isMainThread()); + RefPtr webProgram(static_cast(holder->program.get())); +#ifndef NDEBUG + cl_program program = holder->program2; +#endif + + if (!webProgram) + return; + + if (webProgram->isReleased()) { + webProgram->m_buildCallback.clear(); + return; + } + + ASSERT(program == webProgram->getProgram()); + + if (webProgram->m_buildCallback) { + webProgram->m_buildCallback->handleEvent(); + webProgram->m_buildCallback.clear(); + } +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLProgram.h b/third_party/WebKit/Source/modules/webcl/WebCLProgram.h new file mode 100644 index 0000000000000..43511cae10f64 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLProgram.h @@ -0,0 +1,63 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLProgram_h +#define WebCLProgram_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLCallback.h" +#include "modules/webcl/WebCLObject.h" + +#include +#include +#include + +namespace blink { + +class ExceptionState; +class WebCL; +class WebCLContext; +class WebCLDevice; +class WebCLKernel; +class WebCLProgramHolder; + +class WebCLProgram : public WebCLObject, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLProgram() override; + static PassRefPtr create(cl_program, WebCLContext*, const String&); + + ScriptValue getInfo(ScriptState*, int, ExceptionState&); + ScriptValue getBuildInfo(ScriptState* scriptState, WebCLDevice*, int, ExceptionState&); + PassRefPtr createKernel(const String&, ExceptionState&); + Vector> createKernelsInProgram(ExceptionState&); + void build(const Vector>&, const String&, WebCLCallback*, ExceptionState&); + void build(const String&, WebCLCallback*, ExceptionState&); + void release() override; + + const String& sourceWithCommentsStripped(); + const String& getProgramSource() const { return m_programSource; } + +private: + WebCLProgram(cl_program, WebCLContext*, const String&); + bool isReleased() const { return !m_clProgram; } + bool isExtensionEnabled(RefPtr, const String&); + typedef void (*pfnNotify)(cl_program, void*); + static void callbackProxy(cl_program, void*); + static void callbackProxyOnMainThread(PassOwnPtr); + cl_program getProgram() { return m_clProgram; } + + RefPtr m_buildCallback; + String m_programSource; + String m_programSourceWithCommentsStripped; + bool m_isProgramBuilt; + cl_program m_clProgram; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLProgram_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLProgram.idl b/third_party/WebKit/Source/modules/webcl/WebCLProgram.idl new file mode 100644 index 0000000000000..09b76f40a3154 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLProgram.idl @@ -0,0 +1,19 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef unsigned long CLenum; +[ + Conditional=WEBCL, +] interface WebCLProgram { + [CallWith=ScriptState, RaisesException] any getInfo(CLenum name); + [CallWith=ScriptState, RaisesException] any getBuildInfo(WebCLDevice device, CLenum name); + // TODO(junmin-zhu) Because WebIDL doesn't support "optional<>" as null. + // So all the function here are implemented through custom binding. Will revisit here when it's supported. + [Custom, RaisesException] void build(optional sequence? devices, + optional DOMString? options, + optional WebCLCallback whenFinished); + [RaisesException] WebCLKernel createKernel(DOMString kernelName); + [RaisesException] sequence createKernelsInProgram(); + void release(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLSampler.cpp b/third_party/WebKit/Source/modules/webcl/WebCLSampler.cpp new file mode 100644 index 0000000000000..556e49bf4b1e5 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLSampler.cpp @@ -0,0 +1,82 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/modules/v8/V8WebCLContext.h" +#include "core/webcl/WebCLException.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLSampler.h" + +namespace blink { + +WebCLSampler::~WebCLSampler() +{ + release(); + ASSERT(!m_clSampler); +} + +PassRefPtr WebCLSampler::create(cl_sampler sampler, bool normCoords, unsigned addressingMode, unsigned filterMode, WebCLContext* context) +{ + return adoptRef(new WebCLSampler(sampler, normCoords, addressingMode, filterMode, context)); +} + +ScriptValue WebCLSampler::getInfo(ScriptState* scriptState, cl_sampler_info paramName, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_SAMPLER, WebCLException::invalidSamplerMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + switch (paramName) { + case CL_SAMPLER_NORMALIZED_COORDS: + return ScriptValue(scriptState, v8::Boolean::New(isolate, m_normCoords)); + break; + case CL_SAMPLER_CONTEXT: + return ScriptValue(scriptState, toV8(context(), creationContext, isolate)); + break; + case CL_SAMPLER_ADDRESSING_MODE: + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(m_addressingMode))); + break; + case CL_SAMPLER_FILTER_MODE: + return ScriptValue(scriptState, v8::Integer::NewFromUnsigned(isolate, static_cast(m_filterMode))); + break; + default: + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + return ScriptValue(scriptState, v8::Null(isolate)); +} + +void WebCLSampler::release() +{ + if (isReleased()) + return; + + cl_int err = clReleaseSampler(m_clSampler); + if (err != CL_SUCCESS) + ASSERT_NOT_REACHED(); + + m_clSampler = 0; +} + +WebCLSampler::WebCLSampler(cl_sampler sampler, bool normCoords, unsigned addressingMode, unsigned filterMode, WebCLContext* context) + : WebCLObject(context) + , m_normCoords(normCoords) + , m_addressingMode(addressingMode) + , m_filterMode(filterMode) + , m_clSampler(sampler) +{ +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLSampler.h b/third_party/WebKit/Source/modules/webcl/WebCLSampler.h new file mode 100644 index 0000000000000..16af4e54dc549 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLSampler.h @@ -0,0 +1,45 @@ +// Copyright (C) 2011 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLSampler_h +#define WebCLSampler_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLObject.h" + +#include +#include + +namespace blink { + +class ExceptionState; +class WebCL; + +class WebCLSampler : public WebCLObject, public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLSampler() override; + static PassRefPtr create(cl_sampler, bool, unsigned, unsigned, WebCLContext*); + + ScriptValue getInfo(ScriptState*, cl_sampler_info, ExceptionState&); + void release() override; + + cl_sampler getSampler() const { return m_clSampler; } + +private: + WebCLSampler(cl_sampler, bool, unsigned, unsigned, WebCLContext*); + bool isReleased() const { return !m_clSampler; } + + bool m_normCoords; + unsigned m_addressingMode; + unsigned m_filterMode; + cl_sampler m_clSampler; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLSampler_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLSampler.idl b/third_party/WebKit/Source/modules/webcl/WebCLSampler.idl new file mode 100644 index 0000000000000..791a6d4c5420a --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLSampler.idl @@ -0,0 +1,11 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef unsigned long CLenum; +[ + Conditional=WEBCL, +] interface WebCLSampler { + [CallWith=ScriptState, RaisesException] any getInfo(CLenum name); + void release(); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.cpp b/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.cpp new file mode 100644 index 0000000000000..b7f0388a99b7c --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.cpp @@ -0,0 +1,90 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#if ENABLE(WEBCL) +#include "bindings/modules/v8/V8WebCLContext.h" +#include "modules/webcl/WebCL.h" +#include "modules/webcl/WebCLContext.h" +#include "modules/webcl/WebCLCommandQueue.h" +#include "modules/webcl/WebCLOpenCL.h" +#include "modules/webcl/WebCLUserEvent.h" + +namespace blink { + +WebCLUserEvent::~WebCLUserEvent() +{ +} + +PassRefPtr WebCLUserEvent::create(WebCLContext* context, ExceptionState& es) +{ + cl_int userEventError = 0; + cl_event userEvent = clCreateUserEvent(context->getContext(), &userEventError); + if (userEventError != CL_SUCCESS) { + WebCLException::throwException(userEventError, es); + return nullptr; + } + + return adoptRef(new WebCLUserEvent(userEvent, context)); +} + +void WebCLUserEvent::setStatus(cl_int executionStatus, ExceptionState& es) +{ + ASSERT(isUserEvent()); + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_EVENT, WebCLException::invalidEventMessage); + return; + } + + if (!(executionStatus < 0 || executionStatus == CL_COMPLETE)) { + es.throwWebCLException(WebCLException::INVALID_VALUE, WebCLException::invalidValueMessage); + return; + } + + if (m_eventStatusSituation == StatusSet) { + es.throwWebCLException(WebCLException::INVALID_OPERATION, WebCLException::invalidOperationMessage); + return; + } + + m_eventStatusSituation = StatusSet; + m_executionStatus = executionStatus; + + cl_int err = clSetUserEventStatus(m_clEvent, executionStatus); + if (err != CL_SUCCESS) + WebCLException::throwException(err, es); +} + +ScriptValue WebCLUserEvent::getInfo(ScriptState* scriptState, unsigned name, ExceptionState& es) +{ + v8::Handle creationContext = scriptState->context()->Global(); + v8::Isolate* isolate = scriptState->isolate(); + + if (isReleased()) { + es.throwWebCLException(WebCLException::INVALID_EVENT, WebCLException::invalidEventMessage); + return ScriptValue(scriptState, v8::Null(isolate)); + } + + switch (name) { + case CL_EVENT_CONTEXT: + return ScriptValue(scriptState, toV8(context(), creationContext, isolate)); + case CL_EVENT_COMMAND_QUEUE: + return ScriptValue(scriptState, v8::Null(isolate)); + } + + return WebCLEvent::getInfo(scriptState, name, es); +} + +WebCLUserEvent::WebCLUserEvent(cl_event event, WebCLContext* context) + : WebCLEvent(event) + , m_eventStatusSituation(StatusUnset) + , m_executionStatus(0) +{ + setContext(context); +} + +} // namespace blink + +#endif // ENABLE(WEBCL) diff --git a/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.h b/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.h new file mode 100644 index 0000000000000..e7266209ebdbf --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.h @@ -0,0 +1,39 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebCLUserEvent_h +#define WebCLUserEvent_h + +#if ENABLE(WEBCL) +#include "modules/webcl/WebCLConfig.h" +#include "modules/webcl/WebCLEvent.h" + +namespace blink { + +class WebCLContext; + +class WebCLUserEvent : public WebCLEvent { + DEFINE_WRAPPERTYPEINFO(); +public: + ~WebCLUserEvent() override; + static PassRefPtr create(WebCLContext*, ExceptionState&); + + void setStatus(cl_int, ExceptionState&); + ScriptValue getInfo(ScriptState* scriptState, unsigned, ExceptionState&) override; + + enum EventStatusSituation { StatusUnset, StatusSet }; + bool isUserEvent() const override { return true; } + int getStatus() override { return m_executionStatus; } + +private: + WebCLUserEvent(cl_event event, WebCLContext*); + enum EventStatusSituation m_eventStatusSituation; + int m_executionStatus; +}; + +} // namespace blink + +#endif // ENABLE(WEBCL) +#endif // WebCLUserEvent_h diff --git a/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.idl b/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.idl new file mode 100644 index 0000000000000..9fc6107020f44 --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WebCLUserEvent.idl @@ -0,0 +1,12 @@ +// Copyright (C) 2013 Samsung Electronics Corporation. All rights reserved. +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +typedef long CLint; + +[ + Conditional=WEBCL, +] interface WebCLUserEvent : WebCLEvent { + [RaisesException] void setStatus(CLint executionStatus); +}; diff --git a/third_party/WebKit/Source/modules/webcl/WindowWebCL.idl b/third_party/WebKit/Source/modules/webcl/WindowWebCL.idl new file mode 100644 index 0000000000000..94fb795f667dd --- /dev/null +++ b/third_party/WebKit/Source/modules/webcl/WindowWebCL.idl @@ -0,0 +1,10 @@ +// Copyright (C) 2015 Intel Corporation All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + Conditional=WEBCL, + ImplementedAs=DOMWindowWebCL +] partial interface Window { + readonly attribute WebCL webcl; +};