/platform/external/webkit/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp

https://github.com/aharish/totoro-gb-opensource-update2 · C++ · 1072 lines · 866 code · 90 blank · 116 comment · 156 complexity · 1486a8d8bd5a6c03ac96fd83f463c691 MD5 · raw file

  1. /*
  2. * Copyright (C) 2009 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions areV8ClassIndex::WEBGL
  6. * met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above
  11. * copyright notice, this list of conditions and the following disclaimer
  12. * in the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Google Inc. nor the names of its
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "config.h"
  31. #if ENABLE(3D_CANVAS)
  32. #include "V8WebGLRenderingContext.h"
  33. #include "ExceptionCode.h"
  34. #include "NotImplemented.h"
  35. #include <wtf/FastMalloc.h>
  36. #include "V8Binding.h"
  37. #include "V8WebGLArray.h"
  38. #include "V8WebGLBuffer.h"
  39. #include "V8WebGLByteArray.h"
  40. #include "V8WebGLFloatArray.h"
  41. #include "V8WebGLFramebuffer.h"
  42. #include "V8WebGLIntArray.h"
  43. #include "V8WebGLProgram.h"
  44. #include "V8WebGLRenderbuffer.h"
  45. #include "V8WebGLShader.h"
  46. #include "V8WebGLShortArray.h"
  47. #include "V8WebGLTexture.h"
  48. #include "V8WebGLUniformLocation.h"
  49. #include "V8WebGLUnsignedByteArray.h"
  50. #include "V8WebGLUnsignedIntArray.h"
  51. #include "V8WebGLUnsignedShortArray.h"
  52. #include "V8HTMLCanvasElement.h"
  53. #include "V8HTMLImageElement.h"
  54. #include "V8HTMLVideoElement.h"
  55. #include "V8ImageData.h"
  56. #include "V8Proxy.h"
  57. #include "WebGLRenderingContext.h"
  58. namespace WebCore {
  59. // Allocates new storage via tryFastMalloc.
  60. // Returns NULL if array failed to convert for any reason.
  61. static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len)
  62. {
  63. // Convert the data element-by-element.
  64. float* data;
  65. if (!tryFastMalloc(len * sizeof(float)).getValue(data))
  66. return 0;
  67. for (uint32_t i = 0; i < len; i++) {
  68. v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
  69. if (!val->IsNumber()) {
  70. fastFree(data);
  71. return 0;
  72. }
  73. data[i] = toFloat(val);
  74. }
  75. return data;
  76. }
  77. // Allocates new storage via tryFastMalloc.
  78. // Returns NULL if array failed to convert for any reason.
  79. static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len)
  80. {
  81. // Convert the data element-by-element.
  82. int* data;
  83. if (!tryFastMalloc(len * sizeof(int)).getValue(data))
  84. return 0;
  85. for (uint32_t i = 0; i < len; i++) {
  86. v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
  87. bool ok;
  88. int ival = toInt32(val, ok);
  89. if (!ok) {
  90. fastFree(data);
  91. return 0;
  92. }
  93. data[i] = ival;
  94. }
  95. return data;
  96. }
  97. v8::Handle<v8::Value> V8WebGLRenderingContext::bufferDataCallback(const v8::Arguments& args)
  98. {
  99. INC_STATS("DOM.WebGLRenderingContext.bufferData()");
  100. // Forms:
  101. // * bufferData(GLenum target, WebGLArray data, GLenum usage);
  102. // - Sets the buffer's data from the given WebGLArray
  103. // * bufferData(GLenum target, GLsizeiptr size, GLenum usage);
  104. // - Sets the size of the buffer to the given size in bytes
  105. if (args.Length() != 3) {
  106. V8Proxy::setDOMException(SYNTAX_ERR);
  107. return notHandledByInterceptor();
  108. }
  109. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  110. bool ok;
  111. int target = toInt32(args[0], ok);
  112. if (!ok) {
  113. V8Proxy::setDOMException(SYNTAX_ERR);
  114. return notHandledByInterceptor();
  115. }
  116. int usage = toInt32(args[2], ok);
  117. if (!ok) {
  118. V8Proxy::setDOMException(SYNTAX_ERR);
  119. return notHandledByInterceptor();
  120. }
  121. if (args[1]->IsInt32()) {
  122. int size = toInt32(args[1]);
  123. ExceptionCode exceptionCode;
  124. context->bufferData(target, size, usage, exceptionCode);
  125. } else if (V8WebGLArray::HasInstance(args[1])) {
  126. WebGLArray* array = V8WebGLArray::toNative(args[1]->ToObject());
  127. ExceptionCode exceptionCode;
  128. context->bufferData(target, array, usage, exceptionCode);
  129. } else {
  130. V8Proxy::setDOMException(SYNTAX_ERR);
  131. return notHandledByInterceptor();
  132. }
  133. return v8::Undefined();
  134. }
  135. v8::Handle<v8::Value> V8WebGLRenderingContext::bufferSubDataCallback(const v8::Arguments& args)
  136. {
  137. INC_STATS("DOM.WebGLRenderingContext.bufferSubData()");
  138. // Forms:
  139. // * bufferSubData(GLenum target, GLintptr offset, WebGLArray data);
  140. if (args.Length() != 3) {
  141. V8Proxy::setDOMException(SYNTAX_ERR);
  142. return notHandledByInterceptor();
  143. }
  144. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  145. bool ok;
  146. int target = toInt32(args[0], ok);
  147. if (!ok) {
  148. V8Proxy::setDOMException(SYNTAX_ERR);
  149. return notHandledByInterceptor();
  150. }
  151. int offset = toInt32(args[1], ok);
  152. if (!ok) {
  153. V8Proxy::setDOMException(SYNTAX_ERR);
  154. return notHandledByInterceptor();
  155. }
  156. if (!V8WebGLArray::HasInstance(args[2])) {
  157. V8Proxy::setDOMException(SYNTAX_ERR);
  158. return notHandledByInterceptor();
  159. }
  160. WebGLArray* array = V8WebGLArray::toNative(args[2]->ToObject());
  161. ExceptionCode exceptionCode;
  162. context->bufferSubData(target, offset, array, exceptionCode);
  163. return v8::Undefined();
  164. }
  165. static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& info)
  166. {
  167. switch (info.getType()) {
  168. case WebGLGetInfo::kTypeBool:
  169. return v8::Boolean::New(info.getBool());
  170. case WebGLGetInfo::kTypeFloat:
  171. return v8::Number::New(info.getFloat());
  172. case WebGLGetInfo::kTypeLong:
  173. return v8::Integer::New(info.getLong());
  174. case WebGLGetInfo::kTypeNull:
  175. return v8::Null();
  176. case WebGLGetInfo::kTypeString:
  177. return v8::String::New(fromWebCoreString(info.getString()), info.getString().length());
  178. case WebGLGetInfo::kTypeUnsignedLong:
  179. return v8::Integer::NewFromUnsigned(info.getUnsignedLong());
  180. case WebGLGetInfo::kTypeWebGLBuffer:
  181. return toV8(info.getWebGLBuffer());
  182. case WebGLGetInfo::kTypeWebGLFloatArray:
  183. return toV8(info.getWebGLFloatArray());
  184. case WebGLGetInfo::kTypeWebGLFramebuffer:
  185. return toV8(info.getWebGLFramebuffer());
  186. case WebGLGetInfo::kTypeWebGLIntArray:
  187. return toV8(info.getWebGLIntArray());
  188. // FIXME: implement WebGLObjectArray
  189. // case WebGLGetInfo::kTypeWebGLObjectArray:
  190. case WebGLGetInfo::kTypeWebGLProgram:
  191. return toV8(info.getWebGLProgram());
  192. case WebGLGetInfo::kTypeWebGLRenderbuffer:
  193. return toV8(info.getWebGLRenderbuffer());
  194. case WebGLGetInfo::kTypeWebGLTexture:
  195. return toV8(info.getWebGLTexture());
  196. case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
  197. return toV8(info.getWebGLUnsignedByteArray());
  198. default:
  199. notImplemented();
  200. return v8::Undefined();
  201. }
  202. }
  203. enum ObjectType {
  204. kBuffer, kRenderbuffer, kTexture, kVertexAttrib
  205. };
  206. static v8::Handle<v8::Value> getObjectParameter(const v8::Arguments& args, ObjectType objectType)
  207. {
  208. if (args.Length() != 2) {
  209. V8Proxy::setDOMException(SYNTAX_ERR);
  210. return notHandledByInterceptor();
  211. }
  212. ExceptionCode ec = 0;
  213. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  214. bool ok;
  215. unsigned target = toInt32(args[0], ok);
  216. if (!ok) {
  217. V8Proxy::setDOMException(SYNTAX_ERR);
  218. return notHandledByInterceptor();
  219. }
  220. unsigned pname = toInt32(args[1], ok);
  221. if (!ok) {
  222. V8Proxy::setDOMException(SYNTAX_ERR);
  223. return notHandledByInterceptor();
  224. }
  225. WebGLGetInfo info;
  226. switch (objectType) {
  227. case kBuffer:
  228. info = context->getBufferParameter(target, pname, ec);
  229. break;
  230. case kRenderbuffer:
  231. info = context->getRenderbufferParameter(target, pname, ec);
  232. break;
  233. case kTexture:
  234. info = context->getTexParameter(target, pname, ec);
  235. break;
  236. case kVertexAttrib:
  237. // target => index
  238. info = context->getVertexAttrib(target, pname, ec);
  239. break;
  240. default:
  241. notImplemented();
  242. break;
  243. }
  244. if (ec) {
  245. V8Proxy::setDOMException(ec);
  246. return v8::Undefined();
  247. }
  248. return toV8Object(info);
  249. }
  250. static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok)
  251. {
  252. ok = false;
  253. WebGLUniformLocation* location = 0;
  254. if (V8WebGLUniformLocation::HasInstance(value)) {
  255. location = V8WebGLUniformLocation::toNative(value->ToObject());
  256. ok = true;
  257. }
  258. return location;
  259. }
  260. enum WhichProgramCall {
  261. kProgramParameter, kUniform
  262. };
  263. v8::Handle<v8::Value> V8WebGLRenderingContext::getBufferParameterCallback(const v8::Arguments& args)
  264. {
  265. INC_STATS("DOM.WebGLRenderingContext.getBufferParameter()");
  266. return getObjectParameter(args, kBuffer);
  267. }
  268. v8::Handle<v8::Value> V8WebGLRenderingContext::getFramebufferAttachmentParameterCallback(const v8::Arguments& args)
  269. {
  270. INC_STATS("DOM.WebGLRenderingContext.getFramebufferAttachmentParameter()");
  271. if (args.Length() != 3) {
  272. V8Proxy::setDOMException(SYNTAX_ERR);
  273. return notHandledByInterceptor();
  274. }
  275. ExceptionCode ec = 0;
  276. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  277. bool ok;
  278. unsigned target = toInt32(args[0], ok);
  279. if (!ok) {
  280. V8Proxy::setDOMException(SYNTAX_ERR);
  281. return notHandledByInterceptor();
  282. }
  283. unsigned attachment = toInt32(args[1], ok);
  284. if (!ok) {
  285. V8Proxy::setDOMException(SYNTAX_ERR);
  286. return notHandledByInterceptor();
  287. }
  288. unsigned pname = toInt32(args[2], ok);
  289. if (!ok) {
  290. V8Proxy::setDOMException(SYNTAX_ERR);
  291. return notHandledByInterceptor();
  292. }
  293. WebGLGetInfo info = context->getFramebufferAttachmentParameter(target, attachment, pname, ec);
  294. if (ec) {
  295. V8Proxy::setDOMException(ec);
  296. return v8::Undefined();
  297. }
  298. return toV8Object(info);
  299. }
  300. v8::Handle<v8::Value> V8WebGLRenderingContext::getParameterCallback(const v8::Arguments& args)
  301. {
  302. INC_STATS("DOM.WebGLRenderingContext.getParameter()");
  303. if (args.Length() != 1) {
  304. V8Proxy::setDOMException(SYNTAX_ERR);
  305. return notHandledByInterceptor();
  306. }
  307. ExceptionCode ec = 0;
  308. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  309. bool ok;
  310. unsigned pname = toInt32(args[0], ok);
  311. if (!ok) {
  312. V8Proxy::setDOMException(SYNTAX_ERR);
  313. return notHandledByInterceptor();
  314. }
  315. WebGLGetInfo info = context->getParameter(pname, ec);
  316. if (ec) {
  317. V8Proxy::setDOMException(ec);
  318. return v8::Undefined();
  319. }
  320. return toV8Object(info);
  321. }
  322. v8::Handle<v8::Value> V8WebGLRenderingContext::getProgramParameterCallback(const v8::Arguments& args)
  323. {
  324. INC_STATS("DOM.WebGLRenderingContext.getProgramParameter()");
  325. if (args.Length() != 2) {
  326. V8Proxy::setDOMException(SYNTAX_ERR);
  327. return notHandledByInterceptor();
  328. }
  329. ExceptionCode ec = 0;
  330. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  331. WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
  332. bool ok;
  333. unsigned pname = toInt32(args[1], ok);
  334. if (!ok) {
  335. V8Proxy::setDOMException(SYNTAX_ERR);
  336. return notHandledByInterceptor();
  337. }
  338. WebGLGetInfo info = context->getProgramParameter(program, pname, ec);
  339. if (ec) {
  340. V8Proxy::setDOMException(ec);
  341. return v8::Undefined();
  342. }
  343. return toV8Object(info);
  344. }
  345. v8::Handle<v8::Value> V8WebGLRenderingContext::getRenderbufferParameterCallback(const v8::Arguments& args)
  346. {
  347. INC_STATS("DOM.WebGLRenderingContext.getRenderbufferParameter()");
  348. return getObjectParameter(args, kRenderbuffer);
  349. }
  350. v8::Handle<v8::Value> V8WebGLRenderingContext::getShaderParameterCallback(const v8::Arguments& args)
  351. {
  352. INC_STATS("DOM.WebGLRenderingContext.getShaderParameter()");
  353. if (args.Length() != 2) {
  354. V8Proxy::setDOMException(SYNTAX_ERR);
  355. return notHandledByInterceptor();
  356. }
  357. ExceptionCode ec = 0;
  358. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  359. WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
  360. bool ok;
  361. unsigned pname = toInt32(args[1], ok);
  362. if (!ok) {
  363. V8Proxy::setDOMException(SYNTAX_ERR);
  364. return notHandledByInterceptor();
  365. }
  366. WebGLGetInfo info = context->getShaderParameter(shader, pname, ec);
  367. if (ec) {
  368. V8Proxy::setDOMException(ec);
  369. return v8::Undefined();
  370. }
  371. return toV8Object(info);
  372. }
  373. v8::Handle<v8::Value> V8WebGLRenderingContext::getTexParameterCallback(const v8::Arguments& args)
  374. {
  375. INC_STATS("DOM.WebGLRenderingContext.getTexParameter()");
  376. return getObjectParameter(args, kTexture);
  377. }
  378. v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Arguments& args)
  379. {
  380. INC_STATS("DOM.WebGLRenderingContext.getUniform()");
  381. if (args.Length() != 2) {
  382. V8Proxy::setDOMException(SYNTAX_ERR);
  383. return notHandledByInterceptor();
  384. }
  385. ExceptionCode ec = 0;
  386. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  387. WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0;
  388. bool ok = false;
  389. WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok);
  390. if (!ok) {
  391. V8Proxy::setDOMException(SYNTAX_ERR);
  392. return notHandledByInterceptor();
  393. }
  394. WebGLGetInfo info = context->getUniform(program, location, ec);
  395. if (ec) {
  396. V8Proxy::setDOMException(ec);
  397. return v8::Undefined();
  398. }
  399. return toV8Object(info);
  400. }
  401. v8::Handle<v8::Value> V8WebGLRenderingContext::getVertexAttribCallback(const v8::Arguments& args)
  402. {
  403. INC_STATS("DOM.WebGLRenderingContext.getVertexAttrib()");
  404. return getObjectParameter(args, kVertexAttrib);
  405. }
  406. v8::Handle<v8::Value> V8WebGLRenderingContext::texImage2DCallback(const v8::Arguments& args)
  407. {
  408. INC_STATS("DOM.WebGLRenderingContext.texImage2D()");
  409. // Currently supported forms:
  410. // * void texImage2D(in GLenum target, in GLint level,
  411. // in GLint internalformat,
  412. // in GLsizei width, in GLsizei height, in GLint border,
  413. // in GLenum format, in GLenum type, in WebGLArray pixels);
  414. // * void texImage2D(in GLenum target, in GLint level, in ImageData pixels,
  415. // [Optional] in GLboolean flipY, [Optional] in GLboolean premulitplyAlpha);
  416. // * void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image,
  417. // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha);
  418. // * void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement image,
  419. // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha);
  420. // * void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement image,
  421. // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha);
  422. if (args.Length() != 3 &&
  423. args.Length() != 4 &&
  424. args.Length() != 5 &&
  425. args.Length() != 9) {
  426. V8Proxy::setDOMException(SYNTAX_ERR);
  427. return notHandledByInterceptor();
  428. }
  429. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  430. bool ok;
  431. int target = toInt32(args[0], ok);
  432. if (!ok) {
  433. V8Proxy::setDOMException(SYNTAX_ERR);
  434. return notHandledByInterceptor();
  435. }
  436. int level = toInt32(args[1], ok);
  437. if (!ok) {
  438. V8Proxy::setDOMException(SYNTAX_ERR);
  439. return notHandledByInterceptor();
  440. }
  441. ExceptionCode ec = 0;
  442. if (args.Length() == 3 ||
  443. args.Length() == 4 ||
  444. args.Length() == 5) {
  445. bool flipY = false;
  446. bool premultiplyAlpha = false;
  447. if (args.Length() >= 4)
  448. flipY = args[3]->BooleanValue();
  449. if (args.Length() >= 5)
  450. premultiplyAlpha = args[4]->BooleanValue();
  451. v8::Handle<v8::Value> arg = args[2];
  452. if (V8HTMLImageElement::HasInstance(arg)) {
  453. HTMLImageElement* element = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg));
  454. context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
  455. } else if (V8HTMLCanvasElement::HasInstance(arg)) {
  456. HTMLCanvasElement* element = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg));
  457. context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
  458. } else if(V8ImageData::HasInstance(arg)) {
  459. ImageData* imageElement = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(arg));
  460. context->texImage2D(target, level, imageElement, flipY, premultiplyAlpha, ec);
  461. } else if (V8HTMLVideoElement::HasInstance(arg)) {
  462. HTMLVideoElement* element = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg));
  463. context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec);
  464. }
  465. else {
  466. // FIXME: consider different / better exception type.
  467. V8Proxy::setDOMException(SYNTAX_ERR);
  468. return notHandledByInterceptor();
  469. }
  470. // Fall through
  471. } else if (args.Length() == 9) {
  472. int internalformat = toInt32(args[2], ok);
  473. if (!ok) {
  474. V8Proxy::setDOMException(SYNTAX_ERR);
  475. return notHandledByInterceptor();
  476. }
  477. int width = toInt32(args[3], ok);
  478. if (!ok) {
  479. V8Proxy::setDOMException(SYNTAX_ERR);
  480. return notHandledByInterceptor();
  481. }
  482. int height = toInt32(args[4], ok);
  483. if (!ok) {
  484. V8Proxy::setDOMException(SYNTAX_ERR);
  485. return notHandledByInterceptor();
  486. }
  487. int border = toInt32(args[5], ok);
  488. if (!ok) {
  489. V8Proxy::setDOMException(SYNTAX_ERR);
  490. return notHandledByInterceptor();
  491. }
  492. int format = toInt32(args[6], ok);
  493. if (!ok) {
  494. V8Proxy::setDOMException(SYNTAX_ERR);
  495. return notHandledByInterceptor();
  496. }
  497. int type = toInt32(args[7], ok);
  498. if (!ok) {
  499. V8Proxy::setDOMException(SYNTAX_ERR);
  500. return notHandledByInterceptor();
  501. }
  502. v8::Handle<v8::Value> arg = args[8];
  503. if (!arg->IsObject())
  504. // Assume that the user is passing null for texture
  505. context->texImage2D(target,
  506. level,
  507. internalformat,
  508. width,
  509. height,
  510. border,
  511. format,
  512. type,
  513. 0,
  514. ec);
  515. else if (V8WebGLArray::HasInstance(arg)) {
  516. WebGLArray* array = V8WebGLArray::toNative(arg->ToObject());
  517. context->texImage2D(target,
  518. level,
  519. internalformat,
  520. width,
  521. height,
  522. border,
  523. format,
  524. type,
  525. array,
  526. ec);
  527. // Fall through
  528. } else {
  529. V8Proxy::setDOMException(SYNTAX_ERR);
  530. return notHandledByInterceptor();
  531. }
  532. } else {
  533. ASSERT_NOT_REACHED();
  534. V8Proxy::setDOMException(SYNTAX_ERR);
  535. return notHandledByInterceptor();
  536. }
  537. if (ec) {
  538. V8Proxy::setDOMException(ec);
  539. return v8::Handle<v8::Value>();
  540. }
  541. return v8::Undefined();
  542. }
  543. v8::Handle<v8::Value> V8WebGLRenderingContext::texSubImage2DCallback(const v8::Arguments& args)
  544. {
  545. INC_STATS("DOM.WebGLRenderingContext.texSubImage2D()");
  546. // Currently supported forms:
  547. // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
  548. // in GLsizei width, in GLsizei height,
  549. // in GLenum format, in GLenum type, in WebGLArray pixels);
  550. // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
  551. // in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
  552. // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
  553. // in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
  554. // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
  555. // in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
  556. // * void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
  557. // in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha);
  558. if (args.Length() != 5 &&
  559. args.Length() != 6 &&
  560. args.Length() != 7 &&
  561. args.Length() != 9) {
  562. V8Proxy::setDOMException(SYNTAX_ERR);
  563. return notHandledByInterceptor();
  564. }
  565. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  566. bool ok;
  567. int target = toInt32(args[0], ok);
  568. if (!ok) {
  569. V8Proxy::setDOMException(SYNTAX_ERR);
  570. return notHandledByInterceptor();
  571. }
  572. int level = toInt32(args[1], ok);
  573. if (!ok) {
  574. V8Proxy::setDOMException(SYNTAX_ERR);
  575. return notHandledByInterceptor();
  576. }
  577. int xoff = toInt32(args[2], ok);
  578. if (!ok) {
  579. V8Proxy::setDOMException(SYNTAX_ERR);
  580. return notHandledByInterceptor();
  581. }
  582. int yoff = toInt32(args[3], ok);
  583. if (!ok) {
  584. V8Proxy::setDOMException(SYNTAX_ERR);
  585. return notHandledByInterceptor();
  586. }
  587. ExceptionCode ec = 0;
  588. if (args.Length() == 5 ||
  589. args.Length() == 6 ||
  590. args.Length() == 7) {
  591. bool flipY = false;
  592. bool premultiplyAlpha = false;
  593. if (args.Length() >= 6)
  594. flipY = args[5]->BooleanValue();
  595. if (args.Length() >= 7)
  596. premultiplyAlpha = args[6]->BooleanValue();
  597. v8::Handle<v8::Value> arg = args[4];
  598. if (V8HTMLImageElement::HasInstance(arg)) {
  599. HTMLImageElement* element = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg));
  600. context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
  601. } else if (V8HTMLCanvasElement::HasInstance(arg)) {
  602. HTMLCanvasElement* element = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg));
  603. context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
  604. } else if(V8ImageData::HasInstance(arg)) {
  605. ImageData* imageElement = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(arg));
  606. context->texSubImage2D(target, level, xoff, yoff, imageElement, flipY, premultiplyAlpha, ec);
  607. } else if (V8HTMLVideoElement::HasInstance(arg)) {
  608. HTMLVideoElement* element = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg));
  609. context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec);
  610. }
  611. else {
  612. // FIXME: consider different / better exception type.
  613. V8Proxy::setDOMException(SYNTAX_ERR);
  614. return notHandledByInterceptor();
  615. }
  616. // Fall through
  617. } else if (args.Length() == 9) {
  618. int width = toInt32(args[4], ok);
  619. if (!ok) {
  620. V8Proxy::setDOMException(SYNTAX_ERR);
  621. return notHandledByInterceptor();
  622. }
  623. int height = toInt32(args[5], ok);
  624. if (!ok) {
  625. V8Proxy::setDOMException(SYNTAX_ERR);
  626. return notHandledByInterceptor();
  627. }
  628. int format = toInt32(args[6], ok);
  629. if (!ok) {
  630. V8Proxy::setDOMException(SYNTAX_ERR);
  631. return notHandledByInterceptor();
  632. }
  633. int type = toInt32(args[7], ok);
  634. if (!ok) {
  635. V8Proxy::setDOMException(SYNTAX_ERR);
  636. return notHandledByInterceptor();
  637. }
  638. v8::Handle<v8::Value> arg = args[8];
  639. if (!arg->IsObject())
  640. // Assume that the user is passing null for texture
  641. context->texSubImage2D(target,
  642. level,
  643. xoff,
  644. yoff,
  645. width,
  646. height,
  647. format,
  648. type,
  649. 0,
  650. ec);
  651. else if (V8WebGLArray::HasInstance(arg)) {
  652. WebGLArray* array = V8WebGLArray::toNative(arg->ToObject());
  653. context->texSubImage2D(target,
  654. level,
  655. xoff,
  656. yoff,
  657. width,
  658. height,
  659. format,
  660. type,
  661. array,
  662. ec);
  663. // Fall through
  664. } else {
  665. V8Proxy::setDOMException(SYNTAX_ERR);
  666. return notHandledByInterceptor();
  667. }
  668. } else {
  669. ASSERT_NOT_REACHED();
  670. V8Proxy::setDOMException(SYNTAX_ERR);
  671. return notHandledByInterceptor();
  672. }
  673. if (ec) {
  674. V8Proxy::setDOMException(ec);
  675. return v8::Handle<v8::Value>();
  676. }
  677. return v8::Undefined();
  678. }
  679. enum FunctionToCall {
  680. kUniform1v, kUniform2v, kUniform3v, kUniform4v,
  681. kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v
  682. };
  683. bool isFunctionToCallForAttribute(FunctionToCall functionToCall)
  684. {
  685. switch (functionToCall) {
  686. case kVertexAttrib1v:
  687. case kVertexAttrib2v:
  688. case kVertexAttrib3v:
  689. case kVertexAttrib4v:
  690. return true;
  691. default:
  692. break;
  693. }
  694. return false;
  695. }
  696. static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& args,
  697. FunctionToCall functionToCall) {
  698. // Forms:
  699. // * glUniform1fv(WebGLUniformLocation location, Array data);
  700. // * glUniform1fv(WebGLUniformLocation location, WebGLFloatArray data);
  701. // * glUniform2fv(WebGLUniformLocation location, Array data);
  702. // * glUniform2fv(WebGLUniformLocation location, WebGLFloatArray data);
  703. // * glUniform3fv(WebGLUniformLocation location, Array data);
  704. // * glUniform3fv(WebGLUniformLocation location, WebGLFloatArray data);
  705. // * glUniform4fv(WebGLUniformLocation location, Array data);
  706. // * glUniform4fv(WebGLUniformLocation location, WebGLFloatArray data);
  707. // * glVertexAttrib1fv(GLint index, Array data);
  708. // * glVertexAttrib1fv(GLint index, WebGLFloatArray data);
  709. // * glVertexAttrib2fv(GLint index, Array data);
  710. // * glVertexAttrib2fv(GLint index, WebGLFloatArray data);
  711. // * glVertexAttrib3fv(GLint index, Array data);
  712. // * glVertexAttrib3fv(GLint index, WebGLFloatArray data);
  713. // * glVertexAttrib4fv(GLint index, Array data);
  714. // * glVertexAttrib4fv(GLint index, WebGLFloatArray data);
  715. if (args.Length() != 2) {
  716. V8Proxy::setDOMException(SYNTAX_ERR);
  717. return notHandledByInterceptor();
  718. }
  719. bool ok = false;
  720. int index = -1;
  721. WebGLUniformLocation* location = 0;
  722. if (isFunctionToCallForAttribute(functionToCall))
  723. index = toInt32(args[0], ok);
  724. else
  725. location = toWebGLUniformLocation(args[0], ok);
  726. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  727. if (!ok) {
  728. V8Proxy::setDOMException(SYNTAX_ERR);
  729. return notHandledByInterceptor();
  730. }
  731. if (V8WebGLFloatArray::HasInstance(args[1])) {
  732. WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[1]->ToObject());
  733. ASSERT(array != NULL);
  734. ExceptionCode ec = 0;
  735. switch (functionToCall) {
  736. case kUniform1v: context->uniform1fv(location, array, ec); break;
  737. case kUniform2v: context->uniform2fv(location, array, ec); break;
  738. case kUniform3v: context->uniform3fv(location, array, ec); break;
  739. case kUniform4v: context->uniform4fv(location, array, ec); break;
  740. case kVertexAttrib1v: context->vertexAttrib1fv(index, array); break;
  741. case kVertexAttrib2v: context->vertexAttrib2fv(index, array); break;
  742. case kVertexAttrib3v: context->vertexAttrib3fv(index, array); break;
  743. case kVertexAttrib4v: context->vertexAttrib4fv(index, array); break;
  744. default: ASSERT_NOT_REACHED(); break;
  745. }
  746. if (ec)
  747. V8Proxy::setDOMException(ec);
  748. return v8::Undefined();
  749. }
  750. v8::Handle<v8::Array> array =
  751. v8::Local<v8::Array>::Cast(args[1]);
  752. if (array.IsEmpty()) {
  753. V8Proxy::setDOMException(SYNTAX_ERR);
  754. return notHandledByInterceptor();
  755. }
  756. uint32_t len = array->Length();
  757. float* data = jsArrayToFloatArray(array, len);
  758. if (!data) {
  759. // FIXME: consider different / better exception type.
  760. V8Proxy::setDOMException(SYNTAX_ERR);
  761. return notHandledByInterceptor();
  762. }
  763. ExceptionCode ec = 0;
  764. switch (functionToCall) {
  765. case kUniform1v: context->uniform1fv(location, data, len, ec); break;
  766. case kUniform2v: context->uniform2fv(location, data, len, ec); break;
  767. case kUniform3v: context->uniform3fv(location, data, len, ec); break;
  768. case kUniform4v: context->uniform4fv(location, data, len, ec); break;
  769. case kVertexAttrib1v: context->vertexAttrib1fv(index, data, len); break;
  770. case kVertexAttrib2v: context->vertexAttrib2fv(index, data, len); break;
  771. case kVertexAttrib3v: context->vertexAttrib3fv(index, data, len); break;
  772. case kVertexAttrib4v: context->vertexAttrib4fv(index, data, len); break;
  773. default: ASSERT_NOT_REACHED(); break;
  774. }
  775. fastFree(data);
  776. if (ec)
  777. V8Proxy::setDOMException(ec);
  778. return v8::Undefined();
  779. }
  780. static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args,
  781. FunctionToCall functionToCall) {
  782. // Forms:
  783. // * glUniform1iv(GLUniformLocation location, Array data);
  784. // * glUniform1iv(GLUniformLocation location, WebGLIntArray data);
  785. // * glUniform2iv(GLUniformLocation location, Array data);
  786. // * glUniform2iv(GLUniformLocation location, WebGLIntArray data);
  787. // * glUniform3iv(GLUniformLocation location, Array data);
  788. // * glUniform3iv(GLUniformLocation location, WebGLIntArray data);
  789. // * glUniform4iv(GLUniformLocation location, Array data);
  790. // * glUniform4iv(GLUniformLocation location, WebGLIntArray data);
  791. if (args.Length() != 2) {
  792. V8Proxy::setDOMException(SYNTAX_ERR);
  793. return notHandledByInterceptor();
  794. }
  795. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  796. bool ok = false;
  797. WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
  798. if (!ok) {
  799. V8Proxy::setDOMException(SYNTAX_ERR);
  800. return notHandledByInterceptor();
  801. }
  802. if (V8WebGLIntArray::HasInstance(args[1])) {
  803. WebGLIntArray* array = V8WebGLIntArray::toNative(args[1]->ToObject());
  804. ASSERT(array != NULL);
  805. ExceptionCode ec = 0;
  806. switch (functionToCall) {
  807. case kUniform1v: context->uniform1iv(location, array, ec); break;
  808. case kUniform2v: context->uniform2iv(location, array, ec); break;
  809. case kUniform3v: context->uniform3iv(location, array, ec); break;
  810. case kUniform4v: context->uniform4iv(location, array, ec); break;
  811. default: ASSERT_NOT_REACHED(); break;
  812. }
  813. if (ec)
  814. V8Proxy::setDOMException(ec);
  815. return v8::Undefined();
  816. }
  817. v8::Handle<v8::Array> array =
  818. v8::Local<v8::Array>::Cast(args[1]);
  819. if (array.IsEmpty()) {
  820. V8Proxy::setDOMException(SYNTAX_ERR);
  821. return notHandledByInterceptor();
  822. }
  823. uint32_t len = array->Length();
  824. int* data = jsArrayToIntArray(array, len);
  825. if (!data) {
  826. // FIXME: consider different / better exception type.
  827. V8Proxy::setDOMException(SYNTAX_ERR);
  828. return notHandledByInterceptor();
  829. }
  830. ExceptionCode ec = 0;
  831. switch (functionToCall) {
  832. case kUniform1v: context->uniform1iv(location, data, len, ec); break;
  833. case kUniform2v: context->uniform2iv(location, data, len, ec); break;
  834. case kUniform3v: context->uniform3iv(location, data, len, ec); break;
  835. case kUniform4v: context->uniform4iv(location, data, len, ec); break;
  836. default: ASSERT_NOT_REACHED(); break;
  837. }
  838. fastFree(data);
  839. if (ec)
  840. V8Proxy::setDOMException(ec);
  841. return v8::Undefined();
  842. }
  843. v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1fvCallback(const v8::Arguments& args)
  844. {
  845. INC_STATS("DOM.WebGLRenderingContext.uniform1fv()");
  846. return vertexAttribAndUniformHelperf(args, kUniform1v);
  847. }
  848. v8::Handle<v8::Value> V8WebGLRenderingContext::uniform1ivCallback(const v8::Arguments& args)
  849. {
  850. INC_STATS("DOM.WebGLRenderingContext.uniform1iv()");
  851. return uniformHelperi(args, kUniform1v);
  852. }
  853. v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2fvCallback(const v8::Arguments& args)
  854. {
  855. INC_STATS("DOM.WebGLRenderingContext.uniform2fv()");
  856. return vertexAttribAndUniformHelperf(args, kUniform2v);
  857. }
  858. v8::Handle<v8::Value> V8WebGLRenderingContext::uniform2ivCallback(const v8::Arguments& args)
  859. {
  860. INC_STATS("DOM.WebGLRenderingContext.uniform2iv()");
  861. return uniformHelperi(args, kUniform2v);
  862. }
  863. v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3fvCallback(const v8::Arguments& args)
  864. {
  865. INC_STATS("DOM.WebGLRenderingContext.uniform3fv()");
  866. return vertexAttribAndUniformHelperf(args, kUniform3v);
  867. }
  868. v8::Handle<v8::Value> V8WebGLRenderingContext::uniform3ivCallback(const v8::Arguments& args)
  869. {
  870. INC_STATS("DOM.WebGLRenderingContext.uniform3iv()");
  871. return uniformHelperi(args, kUniform3v);
  872. }
  873. v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4fvCallback(const v8::Arguments& args)
  874. {
  875. INC_STATS("DOM.WebGLRenderingContext.uniform4fv()");
  876. return vertexAttribAndUniformHelperf(args, kUniform4v);
  877. }
  878. v8::Handle<v8::Value> V8WebGLRenderingContext::uniform4ivCallback(const v8::Arguments& args)
  879. {
  880. INC_STATS("DOM.WebGLRenderingContext.uniform4iv()");
  881. return uniformHelperi(args, kUniform4v);
  882. }
  883. static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args,
  884. int matrixSize)
  885. {
  886. // Forms:
  887. // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data);
  888. // * glUniformMatrix2fv(GLint location, GLboolean transpose, WebGLFloatArray data);
  889. // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data);
  890. // * glUniformMatrix3fv(GLint location, GLboolean transpose, WebGLFloatArray data);
  891. // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data);
  892. // * glUniformMatrix4fv(GLint location, GLboolean transpose, WebGLFloatArray data);
  893. //
  894. // FIXME: need to change to accept WebGLFloatArray as well.
  895. if (args.Length() != 3) {
  896. V8Proxy::setDOMException(SYNTAX_ERR);
  897. return notHandledByInterceptor();
  898. }
  899. WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder());
  900. bool ok = false;
  901. WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok);
  902. if (!ok) {
  903. V8Proxy::setDOMException(SYNTAX_ERR);
  904. return notHandledByInterceptor();
  905. }
  906. bool transpose = args[1]->BooleanValue();
  907. if (V8WebGLFloatArray::HasInstance(args[2])) {
  908. WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[2]->ToObject());
  909. ASSERT(array != NULL);
  910. ExceptionCode ec = 0;
  911. switch (matrixSize) {
  912. case 2: context->uniformMatrix2fv(location, transpose, array, ec); break;
  913. case 3: context->uniformMatrix3fv(location, transpose, array, ec); break;
  914. case 4: context->uniformMatrix4fv(location, transpose, array, ec); break;
  915. default: ASSERT_NOT_REACHED(); break;
  916. }
  917. if (ec)
  918. V8Proxy::setDOMException(ec);
  919. return v8::Undefined();
  920. }
  921. v8::Handle<v8::Array> array =
  922. v8::Local<v8::Array>::Cast(args[2]);
  923. if (array.IsEmpty()) {
  924. V8Proxy::setDOMException(SYNTAX_ERR);
  925. return notHandledByInterceptor();
  926. }
  927. uint32_t len = array->Length();
  928. float* data = jsArrayToFloatArray(array, len);
  929. if (!data) {
  930. // FIXME: consider different / better exception type.
  931. V8Proxy::setDOMException(SYNTAX_ERR);
  932. return notHandledByInterceptor();
  933. }
  934. ExceptionCode ec = 0;
  935. switch (matrixSize) {
  936. case 2: context->uniformMatrix2fv(location, transpose, data, len, ec); break;
  937. case 3: context->uniformMatrix3fv(location, transpose, data, len, ec); break;
  938. case 4: context->uniformMatrix4fv(location, transpose, data, len, ec); break;
  939. default: ASSERT_NOT_REACHED(); break;
  940. }
  941. fastFree(data);
  942. if (ec)
  943. V8Proxy::setDOMException(ec);
  944. return v8::Undefined();
  945. }
  946. v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix2fvCallback(const v8::Arguments& args)
  947. {
  948. INC_STATS("DOM.WebGLRenderingContext.uniformMatrix2fv()");
  949. return uniformMatrixHelper(args, 2);
  950. }
  951. v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix3fvCallback(const v8::Arguments& args)
  952. {
  953. INC_STATS("DOM.WebGLRenderingContext.uniformMatrix3fv()");
  954. return uniformMatrixHelper(args, 3);
  955. }
  956. v8::Handle<v8::Value> V8WebGLRenderingContext::uniformMatrix4fvCallback(const v8::Arguments& args)
  957. {
  958. INC_STATS("DOM.WebGLRenderingContext.uniformMatrix4fv()");
  959. return uniformMatrixHelper(args, 4);
  960. }
  961. v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib1fvCallback(const v8::Arguments& args)
  962. {
  963. INC_STATS("DOM.WebGLRenderingContext.vertexAttrib1fv()");
  964. return vertexAttribAndUniformHelperf(args, kVertexAttrib1v);
  965. }
  966. v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib2fvCallback(const v8::Arguments& args)
  967. {
  968. INC_STATS("DOM.WebGLRenderingContext.vertexAttrib2fv()");
  969. return vertexAttribAndUniformHelperf(args, kVertexAttrib2v);
  970. }
  971. v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib3fvCallback(const v8::Arguments& args)
  972. {
  973. INC_STATS("DOM.WebGLRenderingContext.vertexAttrib3fv()");
  974. return vertexAttribAndUniformHelperf(args, kVertexAttrib3v);
  975. }
  976. v8::Handle<v8::Value> V8WebGLRenderingContext::vertexAttrib4fvCallback(const v8::Arguments& args)
  977. {
  978. INC_STATS("DOM.WebGLRenderingContext.vertexAttrib4fv()");
  979. return vertexAttribAndUniformHelperf(args, kVertexAttrib4v);
  980. }
  981. } // namespace WebCore
  982. #endif // ENABLE(3D_CANVAS)