PageRenderTime 65ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/lib_angle/src/libGLESv2/entry_points_gles_3_0.cpp

https://bitbucket.org/xixs/lua
C++ | 3377 lines | 2818 code | 525 blank | 34 comment | 503 complexity | d2001ff41eb41ce33f10fab375a2b261 MD5 | raw file
Possible License(s): Zlib, BSD-3-Clause, CC0-1.0, GPL-3.0, GPL-2.0, CPL-1.0, MPL-2.0-no-copyleft-exception, LGPL-2.0, LGPL-2.1, LGPL-3.0, 0BSD, Cube
  1. //
  2. // Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style license that can be
  4. // found in the LICENSE file.
  5. //
  6. // entry_points_gles_3_0.cpp : Implements the GLES 3.0 entry points.
  7. #include "libGLESv2/entry_points_gles_3_0.h"
  8. #include "libGLESv2/entry_points_gles_2_0_ext.h"
  9. #include "libGLESv2/global_state.h"
  10. #include "libANGLE/formatutils.h"
  11. #include "libANGLE/Buffer.h"
  12. #include "libANGLE/Context.h"
  13. #include "libANGLE/Error.h"
  14. #include "libANGLE/Fence.h"
  15. #include "libANGLE/Framebuffer.h"
  16. #include "libANGLE/Query.h"
  17. #include "libANGLE/VertexArray.h"
  18. #include "libANGLE/validationES.h"
  19. #include "libANGLE/validationES3.h"
  20. #include "libANGLE/queryconversions.h"
  21. #include "common/debug.h"
  22. namespace gl
  23. {
  24. void GL_APIENTRY ReadBuffer(GLenum mode)
  25. {
  26. EVENT("(GLenum mode = 0x%X)", mode);
  27. Context *context = GetValidGlobalContext();
  28. if (context)
  29. {
  30. if (context->getClientVersion() < 3)
  31. {
  32. context->recordError(Error(GL_INVALID_OPERATION));
  33. return;
  34. }
  35. // glReadBuffer
  36. UNIMPLEMENTED();
  37. }
  38. }
  39. void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
  40. {
  41. EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, "
  42. "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices);
  43. Context *context = GetValidGlobalContext();
  44. if (context)
  45. {
  46. if (context->getClientVersion() < 3)
  47. {
  48. context->recordError(Error(GL_INVALID_OPERATION));
  49. return;
  50. }
  51. // glDrawRangeElements
  52. UNIMPLEMENTED();
  53. }
  54. }
  55. void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
  56. {
  57. EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
  58. "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
  59. "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
  60. target, level, internalformat, width, height, depth, border, format, type, pixels);
  61. Context *context = GetValidGlobalContext();
  62. if (context)
  63. {
  64. if (context->getClientVersion() < 3)
  65. {
  66. context->recordError(Error(GL_INVALID_OPERATION));
  67. return;
  68. }
  69. // validateES3TexImageFormat sets the error code if there is an error
  70. if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
  71. 0, 0, 0, width, height, depth, border, format, type, pixels))
  72. {
  73. return;
  74. }
  75. Extents size(width, height, depth);
  76. Texture *texture = context->getTargetTexture(target);
  77. Error error = texture->setImage(target, level, internalformat, size, format, type, context->getState().getUnpackState(),
  78. reinterpret_cast<const uint8_t *>(pixels));
  79. if (error.isError())
  80. {
  81. context->recordError(error);
  82. return;
  83. }
  84. }
  85. }
  86. void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
  87. {
  88. EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
  89. "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
  90. "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
  91. target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
  92. Context *context = GetValidGlobalContext();
  93. if (context)
  94. {
  95. if (context->getClientVersion() < 3)
  96. {
  97. context->recordError(Error(GL_INVALID_OPERATION));
  98. return;
  99. }
  100. // validateES3TexImageFormat sets the error code if there is an error
  101. if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
  102. xoffset, yoffset, zoffset, width, height, depth, 0,
  103. format, type, pixels))
  104. {
  105. return;
  106. }
  107. // Zero sized uploads are valid but no-ops
  108. if (width == 0 || height == 0 || depth == 0)
  109. {
  110. return;
  111. }
  112. Box area(xoffset, yoffset, zoffset, width, height, depth);
  113. Texture *texture = context->getTargetTexture(target);
  114. Error error = texture->setSubImage(target, level, area, format, type, context->getState().getUnpackState(),
  115. reinterpret_cast<const uint8_t *>(pixels));
  116. if (error.isError())
  117. {
  118. context->recordError(error);
  119. return;
  120. }
  121. }
  122. }
  123. void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
  124. {
  125. EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
  126. "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
  127. target, level, xoffset, yoffset, zoffset, x, y, width, height);
  128. Context *context = GetValidGlobalContext();
  129. if (context)
  130. {
  131. if (context->getClientVersion() < 3)
  132. {
  133. context->recordError(Error(GL_INVALID_OPERATION));
  134. return;
  135. }
  136. if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset,
  137. x, y, width, height, 0))
  138. {
  139. return;
  140. }
  141. Offset destOffset(xoffset, yoffset, zoffset);
  142. Rectangle sourceArea(x, y, width, height);
  143. const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
  144. Texture *texture = context->getTargetTexture(target);
  145. Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer);
  146. if (error.isError())
  147. {
  148. context->recordError(error);
  149. return;
  150. }
  151. }
  152. }
  153. void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
  154. {
  155. EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
  156. "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
  157. "const GLvoid* data = 0x%0.8p)",
  158. target, level, internalformat, width, height, depth, border, imageSize, data);
  159. Context *context = GetValidGlobalContext();
  160. if (context)
  161. {
  162. if (context->getClientVersion() < 3)
  163. {
  164. context->recordError(Error(GL_INVALID_OPERATION));
  165. return;
  166. }
  167. const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
  168. if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
  169. {
  170. context->recordError(Error(GL_INVALID_VALUE));
  171. return;
  172. }
  173. // validateES3TexImageFormat sets the error code if there is an error
  174. if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
  175. 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data))
  176. {
  177. return;
  178. }
  179. Extents size(width, height, depth);
  180. Texture *texture = context->getTargetTexture(target);
  181. Error error = texture->setCompressedImage(target, level, internalformat, size, context->getState().getUnpackState(),
  182. reinterpret_cast<const uint8_t *>(data));
  183. if (error.isError())
  184. {
  185. context->recordError(error);
  186. return;
  187. }
  188. }
  189. }
  190. void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
  191. {
  192. EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
  193. "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
  194. "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
  195. target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
  196. Context *context = GetValidGlobalContext();
  197. if (context)
  198. {
  199. if (context->getClientVersion() < 3)
  200. {
  201. context->recordError(Error(GL_INVALID_OPERATION));
  202. return;
  203. }
  204. const InternalFormat &formatInfo = GetInternalFormatInfo(format);
  205. if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
  206. {
  207. context->recordError(Error(GL_INVALID_VALUE));
  208. return;
  209. }
  210. if (!data)
  211. {
  212. context->recordError(Error(GL_INVALID_VALUE));
  213. return;
  214. }
  215. // validateES3TexImageFormat sets the error code if there is an error
  216. if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
  217. 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data))
  218. {
  219. return;
  220. }
  221. // Zero sized uploads are valid but no-ops
  222. if (width == 0 || height == 0)
  223. {
  224. return;
  225. }
  226. Box area(xoffset, yoffset, zoffset, width, height, depth);
  227. Texture *texture = context->getTargetTexture(target);
  228. Error error = texture->setCompressedSubImage(target, level, area, format, context->getState().getUnpackState(),
  229. reinterpret_cast<const uint8_t *>(data));
  230. if (error.isError())
  231. {
  232. context->recordError(error);
  233. return;
  234. }
  235. }
  236. }
  237. void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids)
  238. {
  239. EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
  240. Context *context = GetValidGlobalContext();
  241. if (context)
  242. {
  243. if (context->getClientVersion() < 3)
  244. {
  245. context->recordError(Error(GL_INVALID_OPERATION));
  246. return;
  247. }
  248. if (n < 0)
  249. {
  250. context->recordError(Error(GL_INVALID_VALUE));
  251. return;
  252. }
  253. for (GLsizei i = 0; i < n; i++)
  254. {
  255. ids[i] = context->createQuery();
  256. }
  257. }
  258. }
  259. void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids)
  260. {
  261. EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
  262. Context *context = GetValidGlobalContext();
  263. if (context)
  264. {
  265. if (context->getClientVersion() < 3)
  266. {
  267. context->recordError(Error(GL_INVALID_OPERATION));
  268. return;
  269. }
  270. if (n < 0)
  271. {
  272. context->recordError(Error(GL_INVALID_VALUE));
  273. return;
  274. }
  275. for (GLsizei i = 0; i < n; i++)
  276. {
  277. context->deleteQuery(ids[i]);
  278. }
  279. }
  280. }
  281. GLboolean GL_APIENTRY IsQuery(GLuint id)
  282. {
  283. EVENT("(GLuint id = %u)", id);
  284. Context *context = GetValidGlobalContext();
  285. if (context)
  286. {
  287. if (context->getClientVersion() < 3)
  288. {
  289. context->recordError(Error(GL_INVALID_OPERATION));
  290. return GL_FALSE;
  291. }
  292. return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
  293. }
  294. return GL_FALSE;
  295. }
  296. void GL_APIENTRY BeginQuery(GLenum target, GLuint id)
  297. {
  298. EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
  299. Context *context = GetValidGlobalContext();
  300. if (context)
  301. {
  302. if (context->getClientVersion() < 3)
  303. {
  304. context->recordError(Error(GL_INVALID_OPERATION));
  305. return;
  306. }
  307. if (!ValidateBeginQuery(context, target, id))
  308. {
  309. return;
  310. }
  311. Error error = context->beginQuery(target, id);
  312. if (error.isError())
  313. {
  314. context->recordError(error);
  315. return;
  316. }
  317. }
  318. }
  319. void GL_APIENTRY EndQuery(GLenum target)
  320. {
  321. EVENT("(GLenum target = 0x%X)", target);
  322. Context *context = GetValidGlobalContext();
  323. if (context)
  324. {
  325. if (context->getClientVersion() < 3)
  326. {
  327. context->recordError(Error(GL_INVALID_OPERATION));
  328. return;
  329. }
  330. if (!ValidateEndQuery(context, target))
  331. {
  332. return;
  333. }
  334. Error error = context->endQuery(target);
  335. if (error.isError())
  336. {
  337. context->recordError(error);
  338. return;
  339. }
  340. }
  341. }
  342. void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params)
  343. {
  344. EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
  345. Context *context = GetValidGlobalContext();
  346. if (context)
  347. {
  348. if (context->getClientVersion() < 3)
  349. {
  350. context->recordError(Error(GL_INVALID_OPERATION));
  351. return;
  352. }
  353. if (!ValidQueryType(context, target))
  354. {
  355. context->recordError(Error(GL_INVALID_ENUM));
  356. return;
  357. }
  358. switch (pname)
  359. {
  360. case GL_CURRENT_QUERY:
  361. params[0] = static_cast<GLint>(context->getState().getActiveQueryId(target));
  362. break;
  363. default:
  364. context->recordError(Error(GL_INVALID_ENUM));
  365. return;
  366. }
  367. }
  368. }
  369. void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
  370. {
  371. EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
  372. Context *context = GetValidGlobalContext();
  373. if (context)
  374. {
  375. if (context->getClientVersion() < 3)
  376. {
  377. context->recordError(Error(GL_INVALID_OPERATION));
  378. return;
  379. }
  380. Query *queryObject = context->getQuery(id, false, GL_NONE);
  381. if (!queryObject)
  382. {
  383. context->recordError(Error(GL_INVALID_OPERATION));
  384. return;
  385. }
  386. if (context->getState().getActiveQueryId(queryObject->getType()) == id)
  387. {
  388. context->recordError(Error(GL_INVALID_OPERATION));
  389. return;
  390. }
  391. switch(pname)
  392. {
  393. case GL_QUERY_RESULT_EXT:
  394. {
  395. Error error = queryObject->getResult(params);
  396. if (error.isError())
  397. {
  398. context->recordError(error);
  399. return;
  400. }
  401. }
  402. break;
  403. case GL_QUERY_RESULT_AVAILABLE_EXT:
  404. {
  405. Error error = queryObject->isResultAvailable(params);
  406. if (error.isError())
  407. {
  408. context->recordError(error);
  409. return;
  410. }
  411. }
  412. break;
  413. default:
  414. context->recordError(Error(GL_INVALID_ENUM));
  415. return;
  416. }
  417. }
  418. }
  419. GLboolean GL_APIENTRY UnmapBuffer(GLenum target)
  420. {
  421. EVENT("(GLenum target = 0x%X)", target);
  422. Context *context = GetValidGlobalContext();
  423. if (context)
  424. {
  425. if (context->getClientVersion() < 3)
  426. {
  427. context->recordError(Error(GL_INVALID_OPERATION));
  428. return GL_FALSE;
  429. }
  430. return UnmapBufferOES(target);
  431. }
  432. return GL_FALSE;
  433. }
  434. void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
  435. {
  436. EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
  437. Context *context = GetValidGlobalContext();
  438. if (context)
  439. {
  440. if (context->getClientVersion() < 3)
  441. {
  442. context->recordError(Error(GL_INVALID_OPERATION));
  443. return;
  444. }
  445. GetBufferPointervOES(target, pname, params);
  446. }
  447. }
  448. void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs)
  449. {
  450. Context *context = GetValidGlobalContext();
  451. if (context)
  452. {
  453. if (context->getClientVersion() < 3)
  454. {
  455. context->recordError(Error(GL_INVALID_OPERATION));
  456. return;
  457. }
  458. DrawBuffersEXT(n, bufs);
  459. }
  460. }
  461. void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
  462. {
  463. EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
  464. location, count, transpose, value);
  465. Context *context = GetValidGlobalContext();
  466. if (context)
  467. {
  468. if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose))
  469. {
  470. return;
  471. }
  472. Program *program = context->getState().getProgram();
  473. program->setUniformMatrix2x3fv(location, count, transpose, value);
  474. }
  475. }
  476. void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
  477. {
  478. EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
  479. location, count, transpose, value);
  480. Context *context = GetValidGlobalContext();
  481. if (context)
  482. {
  483. if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose))
  484. {
  485. return;
  486. }
  487. Program *program = context->getState().getProgram();
  488. program->setUniformMatrix3x2fv(location, count, transpose, value);
  489. }
  490. }
  491. void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
  492. {
  493. EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
  494. location, count, transpose, value);
  495. Context *context = GetValidGlobalContext();
  496. if (context)
  497. {
  498. if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose))
  499. {
  500. return;
  501. }
  502. Program *program = context->getState().getProgram();
  503. program->setUniformMatrix2x4fv(location, count, transpose, value);
  504. }
  505. }
  506. void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
  507. {
  508. EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
  509. location, count, transpose, value);
  510. Context *context = GetValidGlobalContext();
  511. if (context)
  512. {
  513. if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose))
  514. {
  515. return;
  516. }
  517. Program *program = context->getState().getProgram();
  518. program->setUniformMatrix4x2fv(location, count, transpose, value);
  519. }
  520. }
  521. void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
  522. {
  523. EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
  524. location, count, transpose, value);
  525. Context *context = GetValidGlobalContext();
  526. if (context)
  527. {
  528. if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose))
  529. {
  530. return;
  531. }
  532. Program *program = context->getState().getProgram();
  533. program->setUniformMatrix3x4fv(location, count, transpose, value);
  534. }
  535. }
  536. void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
  537. {
  538. EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
  539. location, count, transpose, value);
  540. Context *context = GetValidGlobalContext();
  541. if (context)
  542. {
  543. if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose))
  544. {
  545. return;
  546. }
  547. Program *program = context->getState().getProgram();
  548. program->setUniformMatrix4x3fv(location, count, transpose, value);
  549. }
  550. }
  551. void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
  552. {
  553. EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, "
  554. "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
  555. srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
  556. Context *context = GetValidGlobalContext();
  557. if (context)
  558. {
  559. if (context->getClientVersion() < 3)
  560. {
  561. context->recordError(Error(GL_INVALID_OPERATION));
  562. return;
  563. }
  564. if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
  565. dstX0, dstY0, dstX1, dstY1, mask, filter,
  566. false))
  567. {
  568. return;
  569. }
  570. Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
  571. ASSERT(readFramebuffer);
  572. Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
  573. ASSERT(drawFramebuffer);
  574. Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
  575. Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
  576. Error error = drawFramebuffer->blit(context->getState(), srcArea, dstArea, mask, filter, readFramebuffer);
  577. if (error.isError())
  578. {
  579. context->recordError(error);
  580. return;
  581. }
  582. }
  583. }
  584. void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
  585. {
  586. EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
  587. target, samples, internalformat, width, height);
  588. Context *context = GetValidGlobalContext();
  589. if (context)
  590. {
  591. if (context->getClientVersion() < 3)
  592. {
  593. context->recordError(Error(GL_INVALID_OPERATION));
  594. return;
  595. }
  596. if (!ValidateES3RenderbufferStorageParameters(context, target, samples, internalformat, width, height))
  597. {
  598. return;
  599. }
  600. Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
  601. renderbuffer->setStorage(width, height, internalformat, samples);
  602. }
  603. }
  604. void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
  605. {
  606. EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)",
  607. target, attachment, texture, level, layer);
  608. Context *context = GetValidGlobalContext();
  609. if (context)
  610. {
  611. if (!ValidateFramebufferTextureLayer(context, target, attachment, texture,
  612. level, layer))
  613. {
  614. return;
  615. }
  616. Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
  617. ASSERT(framebuffer);
  618. if (texture != 0)
  619. {
  620. Texture *textureObject = context->getTexture(texture);
  621. ImageIndex index = ImageIndex::MakeInvalid();
  622. if (textureObject->getTarget() == GL_TEXTURE_3D)
  623. {
  624. index = ImageIndex::Make3D(level, layer);
  625. }
  626. else
  627. {
  628. ASSERT(textureObject->getTarget() == GL_TEXTURE_2D_ARRAY);
  629. index = ImageIndex::Make2DArray(level, layer);
  630. }
  631. framebuffer->setTextureAttachment(attachment, textureObject, index);
  632. }
  633. else
  634. {
  635. framebuffer->setNULLAttachment(attachment);
  636. }
  637. }
  638. }
  639. GLvoid *GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
  640. {
  641. EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
  642. target, offset, length, access);
  643. Context *context = GetValidGlobalContext();
  644. if (context)
  645. {
  646. if (context->getClientVersion() < 3)
  647. {
  648. context->recordError(Error(GL_INVALID_OPERATION));
  649. return NULL;
  650. }
  651. return MapBufferRangeEXT(target, offset, length, access);
  652. }
  653. return NULL;
  654. }
  655. void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
  656. {
  657. EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
  658. Context *context = GetValidGlobalContext();
  659. if (context)
  660. {
  661. if (context->getClientVersion() < 3)
  662. {
  663. context->recordError(Error(GL_INVALID_OPERATION));
  664. return;
  665. }
  666. FlushMappedBufferRangeEXT(target, offset, length);
  667. }
  668. }
  669. void GL_APIENTRY BindVertexArray(GLuint array)
  670. {
  671. EVENT("(GLuint array = %u)", array);
  672. Context *context = GetValidGlobalContext();
  673. if (context)
  674. {
  675. if (context->getClientVersion() < 3)
  676. {
  677. context->recordError(Error(GL_INVALID_OPERATION));
  678. return;
  679. }
  680. VertexArray *vao = context->getVertexArray(array);
  681. if (!vao)
  682. {
  683. // The default VAO should always exist
  684. ASSERT(array != 0);
  685. context->recordError(Error(GL_INVALID_OPERATION));
  686. return;
  687. }
  688. context->bindVertexArray(array);
  689. }
  690. }
  691. void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays)
  692. {
  693. EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
  694. Context *context = GetValidGlobalContext();
  695. if (context)
  696. {
  697. if (context->getClientVersion() < 3)
  698. {
  699. context->recordError(Error(GL_INVALID_OPERATION));
  700. return;
  701. }
  702. if (n < 0)
  703. {
  704. context->recordError(Error(GL_INVALID_VALUE));
  705. return;
  706. }
  707. for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
  708. {
  709. if (arrays[arrayIndex] != 0)
  710. {
  711. context->deleteVertexArray(arrays[arrayIndex]);
  712. }
  713. }
  714. }
  715. }
  716. void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays)
  717. {
  718. EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
  719. Context *context = GetValidGlobalContext();
  720. if (context)
  721. {
  722. if (context->getClientVersion() < 3)
  723. {
  724. context->recordError(Error(GL_INVALID_OPERATION));
  725. return;
  726. }
  727. if (n < 0)
  728. {
  729. context->recordError(Error(GL_INVALID_VALUE));
  730. return;
  731. }
  732. for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
  733. {
  734. arrays[arrayIndex] = context->createVertexArray();
  735. }
  736. }
  737. }
  738. GLboolean GL_APIENTRY IsVertexArray(GLuint array)
  739. {
  740. EVENT("(GLuint array = %u)", array);
  741. Context *context = GetValidGlobalContext();
  742. if (context)
  743. {
  744. if (context->getClientVersion() < 3)
  745. {
  746. context->recordError(Error(GL_INVALID_OPERATION));
  747. return GL_FALSE;
  748. }
  749. if (array == 0)
  750. {
  751. return GL_FALSE;
  752. }
  753. VertexArray *vao = context->getVertexArray(array);
  754. return (vao != NULL ? GL_TRUE : GL_FALSE);
  755. }
  756. return GL_FALSE;
  757. }
  758. void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data)
  759. {
  760. EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
  761. target, index, data);
  762. Context *context = GetValidGlobalContext();
  763. if (context)
  764. {
  765. if (context->getClientVersion() < 3)
  766. {
  767. context->recordError(Error(GL_INVALID_OPERATION));
  768. return;
  769. }
  770. const Caps &caps = context->getCaps();
  771. switch (target)
  772. {
  773. case GL_TRANSFORM_FEEDBACK_BUFFER_START:
  774. case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
  775. case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
  776. if (index >= caps.maxTransformFeedbackSeparateAttributes)
  777. {
  778. context->recordError(Error(GL_INVALID_VALUE));
  779. return;
  780. }
  781. break;
  782. case GL_UNIFORM_BUFFER_START:
  783. case GL_UNIFORM_BUFFER_SIZE:
  784. case GL_UNIFORM_BUFFER_BINDING:
  785. if (index >= caps.maxCombinedUniformBlocks)
  786. {
  787. context->recordError(Error(GL_INVALID_VALUE));
  788. return;
  789. }
  790. break;
  791. default:
  792. context->recordError(Error(GL_INVALID_ENUM));
  793. return;
  794. }
  795. if (!(context->getIndexedIntegerv(target, index, data)))
  796. {
  797. GLenum nativeType;
  798. unsigned int numParams = 0;
  799. if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
  800. {
  801. context->recordError(Error(GL_INVALID_ENUM));
  802. return;
  803. }
  804. if (numParams == 0)
  805. {
  806. return; // it is known that pname is valid, but there are no parameters to return
  807. }
  808. if (nativeType == GL_INT_64_ANGLEX)
  809. {
  810. GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min());
  811. GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max());
  812. GLint64 *int64Params = new GLint64[numParams];
  813. context->getIndexedInteger64v(target, index, int64Params);
  814. for (unsigned int i = 0; i < numParams; ++i)
  815. {
  816. GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue);
  817. data[i] = static_cast<GLint>(clampedValue);
  818. }
  819. delete [] int64Params;
  820. }
  821. else
  822. {
  823. UNREACHABLE();
  824. }
  825. }
  826. }
  827. }
  828. void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode)
  829. {
  830. EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
  831. Context *context = GetValidGlobalContext();
  832. if (context)
  833. {
  834. if (context->getClientVersion() < 3)
  835. {
  836. context->recordError(Error(GL_INVALID_OPERATION));
  837. return;
  838. }
  839. switch (primitiveMode)
  840. {
  841. case GL_TRIANGLES:
  842. case GL_LINES:
  843. case GL_POINTS:
  844. break;
  845. default:
  846. context->recordError(Error(GL_INVALID_ENUM));
  847. return;
  848. }
  849. TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
  850. ASSERT(transformFeedback != NULL);
  851. if (transformFeedback->isStarted())
  852. {
  853. context->recordError(Error(GL_INVALID_OPERATION));
  854. return;
  855. }
  856. if (transformFeedback->isPaused())
  857. {
  858. transformFeedback->resume();
  859. }
  860. else
  861. {
  862. transformFeedback->start(primitiveMode);
  863. }
  864. }
  865. }
  866. void GL_APIENTRY EndTransformFeedback(void)
  867. {
  868. EVENT("(void)");
  869. Context *context = GetValidGlobalContext();
  870. if (context)
  871. {
  872. if (context->getClientVersion() < 3)
  873. {
  874. context->recordError(Error(GL_INVALID_OPERATION));
  875. return;
  876. }
  877. TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
  878. ASSERT(transformFeedback != NULL);
  879. if (!transformFeedback->isStarted())
  880. {
  881. context->recordError(Error(GL_INVALID_OPERATION));
  882. return;
  883. }
  884. transformFeedback->stop();
  885. }
  886. }
  887. void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
  888. {
  889. EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)",
  890. target, index, buffer, offset, size);
  891. Context *context = GetValidGlobalContext();
  892. if (context)
  893. {
  894. if (context->getClientVersion() < 3)
  895. {
  896. context->recordError(Error(GL_INVALID_OPERATION));
  897. return;
  898. }
  899. const Caps &caps = context->getCaps();
  900. switch (target)
  901. {
  902. case GL_TRANSFORM_FEEDBACK_BUFFER:
  903. if (index >= caps.maxTransformFeedbackSeparateAttributes)
  904. {
  905. context->recordError(Error(GL_INVALID_VALUE));
  906. return;
  907. }
  908. break;
  909. case GL_UNIFORM_BUFFER:
  910. if (index >= caps.maxUniformBufferBindings)
  911. {
  912. context->recordError(Error(GL_INVALID_VALUE));
  913. return;
  914. }
  915. break;
  916. default:
  917. context->recordError(Error(GL_INVALID_ENUM));
  918. return;
  919. }
  920. if (buffer != 0 && size <= 0)
  921. {
  922. context->recordError(Error(GL_INVALID_VALUE));
  923. return;
  924. }
  925. switch (target)
  926. {
  927. case GL_TRANSFORM_FEEDBACK_BUFFER:
  928. {
  929. // size and offset must be a multiple of 4
  930. if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
  931. {
  932. context->recordError(Error(GL_INVALID_VALUE));
  933. return;
  934. }
  935. // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2)
  936. TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
  937. if (curTransformFeedback && curTransformFeedback->isStarted())
  938. {
  939. context->recordError(Error(GL_INVALID_OPERATION));
  940. return;
  941. }
  942. context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
  943. context->bindGenericTransformFeedbackBuffer(buffer);
  944. break;
  945. }
  946. case GL_UNIFORM_BUFFER:
  947. // it is an error to bind an offset not a multiple of the alignment
  948. if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
  949. {
  950. context->recordError(Error(GL_INVALID_VALUE));
  951. return;
  952. }
  953. context->bindIndexedUniformBuffer(buffer, index, offset, size);
  954. context->bindGenericUniformBuffer(buffer);
  955. break;
  956. default:
  957. UNREACHABLE();
  958. }
  959. }
  960. }
  961. void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
  962. {
  963. EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)",
  964. target, index, buffer);
  965. Context *context = GetValidGlobalContext();
  966. if (context)
  967. {
  968. if (context->getClientVersion() < 3)
  969. {
  970. context->recordError(Error(GL_INVALID_OPERATION));
  971. return;
  972. }
  973. const Caps &caps = context->getCaps();
  974. switch (target)
  975. {
  976. case GL_TRANSFORM_FEEDBACK_BUFFER:
  977. if (index >= caps.maxTransformFeedbackSeparateAttributes)
  978. {
  979. context->recordError(Error(GL_INVALID_VALUE));
  980. return;
  981. }
  982. break;
  983. case GL_UNIFORM_BUFFER:
  984. if (index >= caps.maxUniformBufferBindings)
  985. {
  986. context->recordError(Error(GL_INVALID_VALUE));
  987. return;
  988. }
  989. break;
  990. default:
  991. context->recordError(Error(GL_INVALID_ENUM));
  992. return;
  993. }
  994. switch (target)
  995. {
  996. case GL_TRANSFORM_FEEDBACK_BUFFER:
  997. {
  998. // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2)
  999. TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
  1000. if (curTransformFeedback && curTransformFeedback->isStarted())
  1001. {
  1002. context->recordError(Error(GL_INVALID_OPERATION));
  1003. return;
  1004. }
  1005. context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
  1006. context->bindGenericTransformFeedbackBuffer(buffer);
  1007. break;
  1008. }
  1009. case GL_UNIFORM_BUFFER:
  1010. context->bindIndexedUniformBuffer(buffer, index, 0, 0);
  1011. context->bindGenericUniformBuffer(buffer);
  1012. break;
  1013. default:
  1014. UNREACHABLE();
  1015. }
  1016. }
  1017. }
  1018. void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
  1019. {
  1020. EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
  1021. program, count, varyings, bufferMode);
  1022. Context *context = GetValidGlobalContext();
  1023. if (context)
  1024. {
  1025. if (context->getClientVersion() < 3)
  1026. {
  1027. context->recordError(Error(GL_INVALID_OPERATION));
  1028. return;
  1029. }
  1030. if (count < 0)
  1031. {
  1032. context->recordError(Error(GL_INVALID_VALUE));
  1033. return;
  1034. }
  1035. const Caps &caps = context->getCaps();
  1036. switch (bufferMode)
  1037. {
  1038. case GL_INTERLEAVED_ATTRIBS:
  1039. break;
  1040. case GL_SEPARATE_ATTRIBS:
  1041. if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
  1042. {
  1043. context->recordError(Error(GL_INVALID_VALUE));
  1044. return;
  1045. }
  1046. break;
  1047. default:
  1048. context->recordError(Error(GL_INVALID_ENUM));
  1049. return;
  1050. }
  1051. if (!ValidProgram(context, program))
  1052. {
  1053. return;
  1054. }
  1055. Program *programObject = context->getProgram(program);
  1056. ASSERT(programObject);
  1057. programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
  1058. }
  1059. }
  1060. void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
  1061. {
  1062. EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
  1063. "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
  1064. program, index, bufSize, length, size, type, name);
  1065. Context *context = GetValidGlobalContext();
  1066. if (context)
  1067. {
  1068. if (context->getClientVersion() < 3)
  1069. {
  1070. context->recordError(Error(GL_INVALID_OPERATION));
  1071. return;
  1072. }
  1073. if (bufSize < 0)
  1074. {
  1075. context->recordError(Error(GL_INVALID_VALUE));
  1076. return;
  1077. }
  1078. if (!ValidProgram(context, program))
  1079. {
  1080. return;
  1081. }
  1082. Program *programObject = context->getProgram(program);
  1083. ASSERT(programObject);
  1084. if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
  1085. {
  1086. context->recordError(Error(GL_INVALID_VALUE));
  1087. return;
  1088. }
  1089. programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
  1090. }
  1091. }
  1092. void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
  1093. {
  1094. EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)",
  1095. index, size, type, stride, pointer);
  1096. Context *context = GetValidGlobalContext();
  1097. if (context)
  1098. {
  1099. if (context->getClientVersion() < 3)
  1100. {
  1101. context->recordError(Error(GL_INVALID_OPERATION));
  1102. return;
  1103. }
  1104. if (index >= MAX_VERTEX_ATTRIBS)
  1105. {
  1106. context->recordError(Error(GL_INVALID_VALUE));
  1107. return;
  1108. }
  1109. if (size < 1 || size > 4)
  1110. {
  1111. context->recordError(Error(GL_INVALID_VALUE));
  1112. return;
  1113. }
  1114. switch (type)
  1115. {
  1116. case GL_BYTE:
  1117. case GL_UNSIGNED_BYTE:
  1118. case GL_SHORT:
  1119. case GL_UNSIGNED_SHORT:
  1120. case GL_INT:
  1121. case GL_UNSIGNED_INT:
  1122. case GL_INT_2_10_10_10_REV:
  1123. case GL_UNSIGNED_INT_2_10_10_10_REV:
  1124. break;
  1125. default:
  1126. context->recordError(Error(GL_INVALID_ENUM));
  1127. return;
  1128. }
  1129. if (stride < 0)
  1130. {
  1131. context->recordError(Error(GL_INVALID_VALUE));
  1132. return;
  1133. }
  1134. if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
  1135. {
  1136. context->recordError(Error(GL_INVALID_OPERATION));
  1137. return;
  1138. }
  1139. // [OpenGL ES 3.0.2] Section 2.8 page 24:
  1140. // An INVALID_OPERATION error is generated when a non-zero vertex array object
  1141. // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
  1142. // and the pointer argument is not NULL.
  1143. if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL)
  1144. {
  1145. context->recordError(Error(GL_INVALID_OPERATION));
  1146. return;
  1147. }
  1148. context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true,
  1149. stride, pointer);
  1150. }
  1151. }
  1152. void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
  1153. {
  1154. EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
  1155. index, pname, params);
  1156. Context *context = GetValidGlobalContext();
  1157. if (context)
  1158. {
  1159. if (context->getClientVersion() < 3)
  1160. {
  1161. context->recordError(Error(GL_INVALID_OPERATION));
  1162. return;
  1163. }
  1164. if (index >= MAX_VERTEX_ATTRIBS)
  1165. {
  1166. context->recordError(Error(GL_INVALID_VALUE));
  1167. return;
  1168. }
  1169. const VertexAttribute &attribState = context->getState().getVertexAttribState(index);
  1170. if (!ValidateGetVertexAttribParameters(context, pname))
  1171. {
  1172. return;
  1173. }
  1174. if (pname == GL_CURRENT_VERTEX_ATTRIB)
  1175. {
  1176. const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
  1177. for (int i = 0; i < 4; ++i)
  1178. {
  1179. params[i] = currentValueData.IntValues[i];
  1180. }
  1181. }
  1182. else
  1183. {
  1184. *params = QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
  1185. }
  1186. }
  1187. }
  1188. void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
  1189. {
  1190. EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)",
  1191. index, pname, params);
  1192. Context *context = GetValidGlobalContext();
  1193. if (context)
  1194. {
  1195. if (context->getClientVersion() < 3)
  1196. {
  1197. context->recordError(Error(GL_INVALID_OPERATION));
  1198. return;
  1199. }
  1200. if (index >= MAX_VERTEX_ATTRIBS)
  1201. {
  1202. context->recordError(Error(GL_INVALID_VALUE));
  1203. return;
  1204. }
  1205. const VertexAttribute &attribState = context->getState().getVertexAttribState(index);
  1206. if (!ValidateGetVertexAttribParameters(context, pname))
  1207. {
  1208. return;
  1209. }
  1210. if (pname == GL_CURRENT_VERTEX_ATTRIB)
  1211. {
  1212. const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
  1213. for (int i = 0; i < 4; ++i)
  1214. {
  1215. params[i] = currentValueData.UnsignedIntValues[i];
  1216. }
  1217. }
  1218. else
  1219. {
  1220. *params = QuerySingleVertexAttributeParameter<GLuint>(attribState, pname);
  1221. }
  1222. }
  1223. }
  1224. void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
  1225. {
  1226. EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
  1227. index, x, y, z, w);
  1228. Context *context = GetValidGlobalContext();
  1229. if (context)
  1230. {
  1231. if (context->getClientVersion() < 3)
  1232. {
  1233. context->recordError(Error(GL_INVALID_OPERATION));
  1234. return;
  1235. }
  1236. if (index >= MAX_VERTEX_ATTRIBS)
  1237. {
  1238. context->recordError(Error(GL_INVALID_VALUE));
  1239. return;
  1240. }
  1241. GLint vals[4] = { x, y, z, w };
  1242. context->getState().setVertexAttribi(index, vals);
  1243. }
  1244. }
  1245. void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
  1246. {
  1247. EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)",
  1248. index, x, y, z, w);
  1249. Context *context = GetValidGlobalContext();
  1250. if (context)
  1251. {
  1252. if (context->getClientVersion() < 3)
  1253. {
  1254. context->recordError(Error(GL_INVALID_OPERATION));
  1255. return;
  1256. }
  1257. if (index >= MAX_VERTEX_ATTRIBS)
  1258. {
  1259. context->recordError(Error(GL_INVALID_VALUE));
  1260. return;
  1261. }
  1262. GLuint vals[4] = { x, y, z, w };
  1263. context->getState().setVertexAttribu(index, vals);
  1264. }
  1265. }
  1266. void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v)
  1267. {
  1268. EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
  1269. Context *context = GetValidGlobalContext();
  1270. if (context)
  1271. {
  1272. if (context->getClientVersion() < 3)
  1273. {
  1274. context->recordError(Error(GL_INVALID_OPERATION));
  1275. return;
  1276. }
  1277. if (index >= MAX_VERTEX_ATTRIBS)
  1278. {
  1279. context->recordError(Error(GL_INVALID_VALUE));
  1280. return;
  1281. }
  1282. context->getState().setVertexAttribi(index, v);
  1283. }
  1284. }
  1285. void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v)
  1286. {
  1287. EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
  1288. Context *context = GetValidGlobalContext();
  1289. if (context)
  1290. {
  1291. if (context->getClientVersion() < 3)
  1292. {
  1293. context->recordError(Error(GL_INVALID_OPERATION));
  1294. return;
  1295. }
  1296. if (index >= MAX_VERTEX_ATTRIBS)
  1297. {
  1298. context->recordError(Error(GL_INVALID_VALUE));
  1299. return;
  1300. }
  1301. context->getState().setVertexAttribu(index, v);
  1302. }
  1303. }
  1304. void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params)
  1305. {
  1306. EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)",
  1307. program, location, params);
  1308. Context *context = GetValidGlobalContext();
  1309. if (context)
  1310. {
  1311. if (!ValidateGetUniformuiv(context, program, location, params))
  1312. {
  1313. return;
  1314. }
  1315. Program *programObject = context->getProgram(program);
  1316. ASSERT(programObject);
  1317. programObject->getUniformuiv(location, params);
  1318. }
  1319. }
  1320. GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name)
  1321. {
  1322. EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)",
  1323. program, name);
  1324. Context *context = GetValidGlobalContext();
  1325. if (context)
  1326. {
  1327. if (context->getClientVersion() < 3)
  1328. {
  1329. context->recordError(Error(GL_INVALID_OPERATION));
  1330. return -1;
  1331. }
  1332. if (program == 0)
  1333. {
  1334. context->recordError(Error(GL_INVALID_VALUE));
  1335. return -1;
  1336. }
  1337. Program *programObject = context->getProgram(program);
  1338. if (!programObject || !programObject->isLinked())
  1339. {
  1340. context->recordError(Error(GL_INVALID_OPERATION));
  1341. return -1;
  1342. }
  1343. return programObject->getFragDataLocation(name);
  1344. }
  1345. return 0;
  1346. }
  1347. void GL_APIENTRY Uniform1ui(GLint location, GLuint v0)
  1348. {
  1349. Uniform1uiv(location, 1, &v0);
  1350. }
  1351. void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1)
  1352. {
  1353. const GLuint xy[] = { v0, v1 };
  1354. Uniform2uiv(location, 1, xy);
  1355. }
  1356. void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
  1357. {
  1358. const GLuint xyz[] = { v0, v1, v2 };
  1359. Uniform3uiv(location, 1, xyz);
  1360. }
  1361. void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
  1362. {
  1363. const GLuint xyzw[] = { v0, v1, v2, v3 };
  1364. Uniform4uiv(location, 1, xyzw);
  1365. }
  1366. void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value)
  1367. {
  1368. EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
  1369. location, count, value);
  1370. Context *context = GetValidGlobalContext();
  1371. if (context)
  1372. {
  1373. if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count))
  1374. {
  1375. return;
  1376. }
  1377. Program *program = context->getState().getProgram();
  1378. program->setUniform1uiv(location, count, value);
  1379. }
  1380. }
  1381. void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value)
  1382. {
  1383. EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
  1384. location, count, value);
  1385. Context *context = GetValidGlobalContext();
  1386. if (context)
  1387. {
  1388. if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count))
  1389. {
  1390. return;
  1391. }
  1392. Program *program = context->getState().getProgram();
  1393. program->setUniform2uiv(location, count, value);
  1394. }
  1395. }
  1396. void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value)
  1397. {
  1398. EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)",
  1399. location, count, value);
  1400. Context *context = GetValidGlobalContext();
  1401. if (context)
  1402. {
  1403. if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count))
  1404. {
  1405. return;
  1406. }
  1407. Program *program = context->getState().getProgram();
  1408. program->setUniform3uiv(location, count, value);
  1409. }
  1410. }
  1411. void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value)
  1412. {
  1413. EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
  1414. location, count, value);
  1415. Context *context = GetValidGlobalContext();
  1416. if (context)
  1417. {
  1418. if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count))
  1419. {
  1420. return;
  1421. }
  1422. Program *program = context->getState().getProgram();
  1423. program->setUniform4uiv(location, count, value);
  1424. }
  1425. }
  1426. void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
  1427. {
  1428. EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)",
  1429. buffer, drawbuffer, value);
  1430. Context *context = GetValidGlobalContext();
  1431. if (context)
  1432. {
  1433. if (!ValidateClearBuffer(context))
  1434. {
  1435. return;
  1436. }
  1437. switch (buffer)
  1438. {
  1439. case GL_COLOR:
  1440. if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
  1441. {
  1442. context->recordError(Error(GL_INVALID_VALUE));
  1443. return;
  1444. }
  1445. break;
  1446. case GL_STENCIL:
  1447. if (drawbuffer != 0)
  1448. {
  1449. context->recordError(Error(GL_INVALID_VALUE));
  1450. return;
  1451. }
  1452. break;
  1453. default:
  1454. context->recordError(Error(GL_INVALID_ENUM));
  1455. return;
  1456. }
  1457. Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
  1458. ASSERT(framebufferObject);
  1459. Error error = framebufferObject->clearBufferiv(context->getState(), buffer, drawbuffer, value);
  1460. if (error.isError())
  1461. {
  1462. context->recordError(error);
  1463. return;
  1464. }
  1465. }
  1466. }
  1467. void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
  1468. {
  1469. EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)",
  1470. buffer, drawbuffer, value);
  1471. Context *context = GetValidGlobalContext();
  1472. if (context)
  1473. {
  1474. if (!ValidateClearBuffer(context))
  1475. {
  1476. return;
  1477. }
  1478. switch (buffer)
  1479. {
  1480. case GL_COLOR:
  1481. if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
  1482. {
  1483. context->recordError(Error(GL_INVALID_VALUE));
  1484. return;
  1485. }
  1486. break;
  1487. default:
  1488. context->recordError(Error(GL_INVALID_ENUM));
  1489. return;
  1490. }
  1491. Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
  1492. ASSERT(framebufferObject);
  1493. Error error = framebufferObject->clearBufferuiv(context->getState(), buffer, drawbuffer, value);
  1494. if (error.isError())
  1495. {
  1496. context->recordError(error);
  1497. return;
  1498. }
  1499. }
  1500. }
  1501. void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
  1502. {
  1503. EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)",
  1504. buffer, drawbuffer, value);
  1505. Context *context = GetValidGlobalContext();
  1506. if (context)
  1507. {
  1508. if (!ValidateClearBuffer(context))
  1509. {
  1510. return;
  1511. }
  1512. switch (buffer)
  1513. {
  1514. case GL_COLOR:
  1515. if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
  1516. {
  1517. context->recordError(Error(GL_INVALID_VALUE));
  1518. return;
  1519. }
  1520. break;
  1521. case GL_DEPTH:
  1522. if (drawbuffer != 0)
  1523. {
  1524. context->recordError(Error(GL_INVALID_VALUE));
  1525. return;
  1526. }
  1527. break;
  1528. default:
  1529. context->recordError(Error(GL_INVALID_ENUM));
  1530. return;
  1531. }
  1532. Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
  1533. ASSERT(framebufferObject);
  1534. Error error = framebufferObject->clearBufferfv(context->getState(), buffer, drawbuffer, value);
  1535. if (error.isError())
  1536. {
  1537. context->recordError(error);
  1538. return;
  1539. }
  1540. }
  1541. }
  1542. void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
  1543. {
  1544. EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
  1545. buffer, drawbuffer, depth, stencil);
  1546. Context *context = GetValidGlobalContext();
  1547. if (context)
  1548. {
  1549. if (!ValidateClearBuffer(context))
  1550. {
  1551. return;
  1552. }
  1553. switch (buffer)
  1554. {
  1555. case GL_DEPTH_STENCIL:
  1556. if (drawbuffer != 0)
  1557. {
  1558. context->recordError(Error(GL_INVALID_VALUE));
  1559. return;
  1560. }
  1561. break;
  1562. default:
  1563. context->recordError(Error(GL_INVALID_ENUM));
  1564. return;
  1565. }
  1566. Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
  1567. ASSERT(framebufferObject);
  1568. Error error = framebufferObject->clearBufferfi(context->getState(), buffer, drawbuffer, depth, stencil);
  1569. if (error.isError())
  1570. {
  1571. context->recordError(error);
  1572. return;
  1573. }
  1574. }
  1575. }
  1576. const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index)
  1577. {
  1578. EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
  1579. Context *context = GetValidGlobalContext();
  1580. if (context)
  1581. {
  1582. if (context->getClientVersion() < 3)
  1583. {
  1584. context->recordError(Error(GL_INVALID_OPERATION));
  1585. return NULL;
  1586. }
  1587. if (name != GL_EXTENSIONS)
  1588. {
  1589. context->recordError(Error(GL_INVALID_ENUM));
  1590. return NULL;
  1591. }
  1592. if (index >= context->getExtensionStringCount())
  1593. {
  1594. context->recordError(Error(GL_INVALID_VALUE));
  1595. return NULL;
  1596. }
  1597. return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str());
  1598. }
  1599. return NULL;
  1600. }
  1601. void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
  1602. {
  1603. EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
  1604. readTarget, writeTarget, readOffset, writeOffset, size);
  1605. Context *context = GetValidGlobalContext();
  1606. if (context)
  1607. {
  1608. if (context->getClientVersion() < 3)
  1609. {
  1610. context->recordError(Error(GL_INVALID_OPERATION));
  1611. return;
  1612. }
  1613. if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
  1614. {
  1615. context->recordError(Error(GL_INVALID_ENUM));
  1616. return;
  1617. }
  1618. Buffer *readBuffer = context->getState().getTargetBuffer(readTarget);
  1619. Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
  1620. if (!readBuffer || !writeBuffer)
  1621. {
  1622. context->recordError(Error(GL_INVALID_OPERATION));
  1623. return;
  1624. }
  1625. // Verify that readBuffer and writeBuffer are not currently mapped
  1626. if (readBuffer->isMapped() || writeBuffer->isMapped())
  1627. {
  1628. context->recordError(Error(GL_INVALID_OPERATION));
  1629. return;
  1630. }
  1631. if (readOffset < 0 || writeOffset < 0 || size < 0 ||
  1632. static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() ||
  1633. static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize())
  1634. {
  1635. context->recordError(Error(GL_INVALID_VALUE));
  1636. return;
  1637. }
  1638. if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size)
  1639. {
  1640. context->recordError(Error(GL_INVALID_VALUE));
  1641. return;
  1642. }
  1643. // if size is zero, the copy is a successful no-op
  1644. if (size > 0)
  1645. {
  1646. Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size);
  1647. if (error.isError())
  1648. {
  1649. context->recordError(error);
  1650. return;
  1651. }
  1652. }
  1653. }
  1654. }
  1655. void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
  1656. {
  1657. EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
  1658. program, uniformCount, uniformNames, uniformIndices);
  1659. Context *context = GetValidGlobalContext();
  1660. if (context)
  1661. {
  1662. if (context->getClientVersion() < 3)
  1663. {
  1664. context->recordError(Error(GL_INVALID_OPERATION));
  1665. return;
  1666. }
  1667. if (uniformCount < 0)
  1668. {
  1669. context->recordError(Error(GL_INVALID_VALUE));
  1670. return;
  1671. }
  1672. Program *programObject = context->getProgram(program);
  1673. if (!programObject)
  1674. {
  1675. if (context->getShader(program))
  1676. {
  1677. context->recordError(Error(GL_INVALID_OPERATION));
  1678. return;
  1679. }
  1680. else
  1681. {
  1682. context->recordError(Error(GL_INVALID_VALUE));
  1683. return;
  1684. }
  1685. }
  1686. if (!programObject->isLinked())
  1687. {
  1688. for (int uniformId = 0; uniformId < uniformCount; uniformId++)
  1689. {
  1690. uniformIndices[uniformId] = GL_INVALID_INDEX;
  1691. }
  1692. }
  1693. else
  1694. {
  1695. for (int uniformId = 0; uniformId < uniformCount; uniformId++)
  1696. {
  1697. uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
  1698. }
  1699. }
  1700. }
  1701. }
  1702. void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
  1703. {
  1704. EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
  1705. program, uniformCount, uniformIndices, pname, params);
  1706. Context *context = GetValidGlobalContext();
  1707. if (context)
  1708. {
  1709. if (context->getClientVersion() < 3)
  1710. {
  1711. context->recordError(Error(GL_INVALID_OPERATION));
  1712. return;
  1713. }
  1714. if (uniformCount < 0)
  1715. {
  1716. context->recordError(Error(GL_INVALID_VALUE));
  1717. return;
  1718. }
  1719. Program *programObject = context->getProgram(program);
  1720. if (!programObject)
  1721. {
  1722. if (context->getShader(program))
  1723. {
  1724. context->recordError(Error(GL_INVALID_OPERATION));
  1725. return;
  1726. }
  1727. else
  1728. {
  1729. context->recordError(Error(GL_INVALID_VALUE));
  1730. return;
  1731. }
  1732. }
  1733. switch (pname)
  1734. {
  1735. case GL_UNIFORM_TYPE:
  1736. case GL_UNIFORM_SIZE:
  1737. case GL_UNIFORM_NAME_LENGTH:
  1738. case GL_UNIFORM_BLOCK_INDEX:
  1739. case GL_UNIFORM_OFFSET:
  1740. case GL_UNIFORM_ARRAY_STRIDE:
  1741. case GL_UNIFORM_MATRIX_STRIDE:
  1742. case GL_UNIFORM_IS_ROW_MAJOR:
  1743. break;
  1744. default:
  1745. context->recordError(Error(GL_INVALID_ENUM));
  1746. return;
  1747. }
  1748. if (uniformCount > 0)
  1749. {
  1750. context->recordError(Error(GL_INVALID_VALUE));
  1751. return;
  1752. }
  1753. for (int uniformId = 0; uniformId < uniformCount; uniformId++)
  1754. {
  1755. const GLuint index = uniformIndices[uniformId];
  1756. if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
  1757. {
  1758. context->recordError(Error(GL_INVALID_VALUE));
  1759. return;
  1760. }
  1761. }
  1762. for (int uniformId = 0; uniformId < uniformCount; uniformId++)
  1763. {
  1764. const GLuint index = uniformIndices[uniformId];
  1765. params[uniformId] = programObject->getActiveUniformi(index, pname);
  1766. }
  1767. }
  1768. }
  1769. GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
  1770. {
  1771. EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName);
  1772. Context *context = GetValidGlobalContext();
  1773. if (context)
  1774. {
  1775. if (context->getClientVersion() < 3)
  1776. {
  1777. context->recordError(Error(GL_INVALID_OPERATION));
  1778. return GL_INVALID_INDEX;
  1779. }
  1780. Program *programObject = context->getProgram(program);
  1781. if (!programObject)
  1782. {
  1783. if (context->getShader(program))
  1784. {
  1785. context->recordError(Error(GL_INVALID_OPERATION));
  1786. return GL_INVALID_INDEX;
  1787. }
  1788. else
  1789. {
  1790. context->recordError(Error(GL_INVALID_VALUE));
  1791. return GL_INVALID_INDEX;
  1792. }
  1793. }
  1794. return programObject->getUniformBlockIndex(uniformBlockName);
  1795. }
  1796. return 0;
  1797. }
  1798. void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
  1799. {
  1800. EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
  1801. program, uniformBlockIndex, pname, params);
  1802. Context *context = GetValidGlobalContext();
  1803. if (context)
  1804. {
  1805. if (context->getClientVersion() < 3)
  1806. {
  1807. context->recordError(Error(GL_INVALID_OPERATION));
  1808. return;
  1809. }
  1810. Program *programObject = context->getProgram(program);
  1811. if (!programObject)
  1812. {
  1813. if (context->getShader(program))
  1814. {
  1815. context->recordError(Error(GL_INVALID_OPERATION));
  1816. return;
  1817. }
  1818. else
  1819. {
  1820. context->recordError(Error(GL_INVALID_VALUE));
  1821. return;
  1822. }
  1823. }
  1824. if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
  1825. {
  1826. context->recordError(Error(GL_INVALID_VALUE));
  1827. return;
  1828. }
  1829. switch (pname)
  1830. {
  1831. case GL_UNIFORM_BLOCK_BINDING:
  1832. *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
  1833. break;
  1834. case GL_UNIFORM_BLOCK_DATA_SIZE:
  1835. case GL_UNIFORM_BLOCK_NAME_LENGTH:
  1836. case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
  1837. case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
  1838. case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
  1839. case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
  1840. programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
  1841. break;
  1842. default:
  1843. context->recordError(Error(GL_INVALID_ENUM));
  1844. return;
  1845. }
  1846. }
  1847. }
  1848. void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
  1849. {
  1850. EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
  1851. program, uniformBlockIndex, bufSize, length, uniformBlockName);
  1852. Context *context = GetValidGlobalContext();
  1853. if (context)
  1854. {
  1855. if (context->getClientVersion() < 3)
  1856. {
  1857. context->recordError(Error(GL_INVALID_OPERATION));
  1858. return;
  1859. }
  1860. Program *programObject = context->getProgram(program);
  1861. if (!programObject)
  1862. {
  1863. if (context->getShader(program))
  1864. {
  1865. context->recordError(Error(GL_INVALID_OPERATION));
  1866. return;
  1867. }
  1868. else
  1869. {
  1870. context->recordError(Error(GL_INVALID_VALUE));
  1871. return;
  1872. }
  1873. }
  1874. if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
  1875. {
  1876. context->recordError(Error(GL_INVALID_VALUE));
  1877. return;
  1878. }
  1879. programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
  1880. }
  1881. }
  1882. void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
  1883. {
  1884. EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
  1885. program, uniformBlockIndex, uniformBlockBinding);
  1886. Context *context = GetValidGlobalContext();
  1887. if (context)
  1888. {
  1889. if (context->getClientVersion() < 3)
  1890. {
  1891. context->recordError(Error(GL_INVALID_OPERATION));
  1892. return;
  1893. }
  1894. if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
  1895. {
  1896. context->recordError(Error(GL_INVALID_VALUE));
  1897. return;
  1898. }
  1899. Program *programObject = context->getProgram(program);
  1900. if (!programObject)
  1901. {
  1902. if (context->getShader(program))
  1903. {
  1904. context->recordError(Error(GL_INVALID_OPERATION));
  1905. return;
  1906. }
  1907. else
  1908. {
  1909. context->recordError(Error(GL_INVALID_VALUE));
  1910. return;
  1911. }
  1912. }
  1913. // if never linked, there won't be any uniform blocks
  1914. if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
  1915. {
  1916. context->recordError(Error(GL_INVALID_VALUE));
  1917. return;
  1918. }
  1919. programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
  1920. }
  1921. }
  1922. void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
  1923. {
  1924. EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
  1925. mode, first, count, instanceCount);
  1926. Context *context = GetValidGlobalContext();
  1927. if (context)
  1928. {
  1929. if (context->getClientVersion() < 3)
  1930. {
  1931. context->recordError(Error(GL_INVALID_OPERATION));
  1932. return;
  1933. }
  1934. if (!ValidateDrawArraysInstanced(context, mode, first, count, instanceCount))
  1935. {
  1936. return;
  1937. }
  1938. Error error = context->drawArrays(mode, first, count, instanceCount);
  1939. if (error.isError())
  1940. {
  1941. context->recordError(error);
  1942. return;
  1943. }
  1944. }
  1945. }
  1946. void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
  1947. {
  1948. EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)",
  1949. mode, count, type, indices, instanceCount);
  1950. Context *context = GetValidGlobalContext();
  1951. if (context)
  1952. {
  1953. if (context->getClientVersion() < 3)
  1954. {
  1955. context->recordError(Error(GL_INVALID_OPERATION));
  1956. return;
  1957. }
  1958. rx::RangeUI indexRange;
  1959. if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, instanceCount, &indexRange))
  1960. {
  1961. return;
  1962. }
  1963. Error error = context->drawElements(mode, count, type, indices, instanceCount, indexRange);
  1964. if (error.isError())
  1965. {
  1966. context->recordError(error);
  1967. return;
  1968. }
  1969. }
  1970. }
  1971. GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags)
  1972. {
  1973. EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
  1974. Context *context = GetValidGlobalContext();
  1975. if (context)
  1976. {
  1977. if (context->getClientVersion() < 3)
  1978. {
  1979. context->recordError(Error(GL_INVALID_OPERATION));
  1980. return 0;
  1981. }
  1982. if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
  1983. {
  1984. context->recordError(Error(GL_INVALID_ENUM));
  1985. return 0;
  1986. }
  1987. if (flags != 0)
  1988. {
  1989. context->recordError(Error(GL_INVALID_VALUE));
  1990. return 0;
  1991. }
  1992. GLsync fenceSync = context->createFenceSync();
  1993. FenceSync *fenceSyncObject = context->getFenceSync(fenceSync);
  1994. Error error = fenceSyncObject->set(condition);
  1995. if (error.isError())
  1996. {
  1997. context->deleteFenceSync(fenceSync);
  1998. context->recordError(error);
  1999. return NULL;
  2000. }
  2001. return fenceSync;
  2002. }
  2003. return NULL;
  2004. }
  2005. GLboolean GL_APIENTRY IsSync(GLsync sync)
  2006. {
  2007. EVENT("(GLsync sync = 0x%0.8p)", sync);
  2008. Context *context = GetValidGlobalContext();
  2009. if (context)
  2010. {
  2011. if (context->getClientVersion() < 3)
  2012. {
  2013. context->recordError(Error(GL_INVALID_OPERATION));
  2014. return GL_FALSE;
  2015. }
  2016. return (context->getFenceSync(sync) != NULL);
  2017. }
  2018. return GL_FALSE;
  2019. }
  2020. void GL_APIENTRY DeleteSync(GLsync sync)
  2021. {
  2022. EVENT("(GLsync sync = 0x%0.8p)", sync);
  2023. Context *context = GetValidGlobalContext();
  2024. if (context)
  2025. {
  2026. if (context->getClientVersion() < 3)
  2027. {
  2028. context->recordError(Error(GL_INVALID_OPERATION));
  2029. return;
  2030. }
  2031. if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
  2032. {
  2033. context->recordError(Error(GL_INVALID_VALUE));
  2034. return;
  2035. }
  2036. context->deleteFenceSync(sync);
  2037. }
  2038. }
  2039. GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
  2040. {
  2041. EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
  2042. sync, flags, timeout);
  2043. Context *context = GetValidGlobalContext();
  2044. if (context)
  2045. {
  2046. if (context->getClientVersion() < 3)
  2047. {
  2048. context->recordError(Error(GL_INVALID_OPERATION));
  2049. return GL_WAIT_FAILED;
  2050. }
  2051. if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
  2052. {
  2053. context->recordError(Error(GL_INVALID_VALUE));
  2054. return GL_WAIT_FAILED;
  2055. }
  2056. FenceSync *fenceSync = context->getFenceSync(sync);
  2057. if (!fenceSync)
  2058. {
  2059. context->recordError(Error(GL_INVALID_VALUE));
  2060. return GL_WAIT_FAILED;
  2061. }
  2062. GLenum result = GL_WAIT_FAILED;
  2063. Error error = fenceSync->clientWait(flags, timeout, &result);
  2064. if (error.isError())
  2065. {
  2066. context->recordError(error);
  2067. return GL_WAIT_FAILED;
  2068. }
  2069. return result;
  2070. }
  2071. return GL_FALSE;
  2072. }
  2073. void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
  2074. {
  2075. EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
  2076. sync, flags, timeout);
  2077. Context *context = GetValidGlobalContext();
  2078. if (context)
  2079. {
  2080. if (context->getClientVersion() < 3)
  2081. {
  2082. context->recordError(Error(GL_INVALID_OPERATION));
  2083. return;
  2084. }
  2085. if (flags != 0)
  2086. {
  2087. context->recordError(Error(GL_INVALID_VALUE));
  2088. return;
  2089. }
  2090. if (timeout != GL_TIMEOUT_IGNORED)
  2091. {
  2092. context->recordError(Error(GL_INVALID_VALUE));
  2093. return;
  2094. }
  2095. FenceSync *fenceSync = context->getFenceSync(sync);
  2096. if (!fenceSync)
  2097. {
  2098. context->recordError(Error(GL_INVALID_VALUE));
  2099. return;
  2100. }
  2101. Error error = fenceSync->serverWait(flags, timeout);
  2102. if (error.isError())
  2103. {
  2104. context->recordError(error);
  2105. }
  2106. }
  2107. }
  2108. void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params)
  2109. {
  2110. EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
  2111. pname, params);
  2112. Context *context = GetValidGlobalContext();
  2113. if (context)
  2114. {
  2115. if (context->getClientVersion() < 3)
  2116. {
  2117. context->recordError(Error(GL_INVALID_OPERATION));
  2118. return;
  2119. }
  2120. GLenum nativeType;
  2121. unsigned int numParams = 0;
  2122. if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
  2123. {
  2124. return;
  2125. }
  2126. if (nativeType == GL_INT_64_ANGLEX)
  2127. {
  2128. context->getInteger64v(pname, params);
  2129. }
  2130. else
  2131. {
  2132. CastStateValues(context, nativeType, pname, numParams, params);
  2133. }
  2134. }
  2135. }
  2136. void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
  2137. {
  2138. EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)",
  2139. sync, pname, bufSize, length, values);
  2140. Context *context = GetValidGlobalContext();
  2141. if (context)
  2142. {
  2143. if (context->getClientVersion() < 3)
  2144. {
  2145. context->recordError(Error(GL_INVALID_OPERATION));
  2146. return;
  2147. }
  2148. if (bufSize < 0)
  2149. {
  2150. context->recordError(Error(GL_INVALID_VALUE));
  2151. return;
  2152. }
  2153. FenceSync *fenceSync = context->getFenceSync(sync);
  2154. if (!fenceSync)
  2155. {
  2156. context->recordError(Error(GL_INVALID_VALUE));
  2157. return;
  2158. }
  2159. switch (pname)
  2160. {
  2161. case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break;
  2162. case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break;
  2163. case GL_SYNC_FLAGS: values[0] = 0; break;
  2164. case GL_SYNC_STATUS:
  2165. {
  2166. Error error = fenceSync->getStatus(values);
  2167. if (error.isError())
  2168. {
  2169. context->recordError(error);
  2170. return;
  2171. }
  2172. break;
  2173. }
  2174. default:
  2175. context->recordError(Error(GL_INVALID_ENUM));
  2176. return;
  2177. }
  2178. }
  2179. }
  2180. void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data)
  2181. {
  2182. EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)",
  2183. target, index, data);
  2184. Context *context = GetValidGlobalContext();
  2185. if (context)
  2186. {
  2187. if (context->getClientVersion() < 3)
  2188. {
  2189. context->recordError(Error(GL_INVALID_OPERATION));
  2190. return;
  2191. }
  2192. const Caps &caps = context->getCaps();
  2193. switch (target)
  2194. {
  2195. case GL_TRANSFORM_FEEDBACK_BUFFER_START:
  2196. case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
  2197. case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
  2198. if (index >= caps.maxTransformFeedbackSeparateAttributes)
  2199. {
  2200. context->recordError(Error(GL_INVALID_VALUE));
  2201. return;
  2202. }
  2203. break;
  2204. case GL_UNIFORM_BUFFER_START:
  2205. case GL_UNIFORM_BUFFER_SIZE:
  2206. case GL_UNIFORM_BUFFER_BINDING:
  2207. if (index >= caps.maxUniformBufferBindings)
  2208. {
  2209. context->recordError(Error(GL_INVALID_VALUE));
  2210. return;
  2211. }
  2212. break;
  2213. default:
  2214. context->recordError(Error(GL_INVALID_ENUM));
  2215. return;
  2216. }
  2217. if (!(context->getIndexedInteger64v(target, index, data)))
  2218. {
  2219. GLenum nativeType;
  2220. unsigned int numParams = 0;
  2221. if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
  2222. {
  2223. context->recordError(Error(GL_INVALID_ENUM));
  2224. return;
  2225. }
  2226. if (numParams == 0)
  2227. return; // it is known that pname is valid, but there are no parameters to return
  2228. if (nativeType == GL_INT)
  2229. {
  2230. GLint *intParams = new GLint[numParams];
  2231. context->getIndexedIntegerv(target, index, intParams);
  2232. for (unsigned int i = 0; i < numParams; ++i)
  2233. {
  2234. data[i] = static_cast<GLint64>(intParams[i]);
  2235. }
  2236. delete [] intParams;
  2237. }
  2238. else
  2239. {
  2240. UNREACHABLE();
  2241. }
  2242. }
  2243. }
  2244. }
  2245. void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
  2246. {
  2247. EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
  2248. target, pname, params);
  2249. Context *context = GetValidGlobalContext();
  2250. if (context)
  2251. {
  2252. if (context->getClientVersion() < 3)
  2253. {
  2254. context->recordError(Error(GL_INVALID_OPERATION));
  2255. return;
  2256. }
  2257. if (!ValidBufferTarget(context, target))
  2258. {
  2259. context->recordError(Error(GL_INVALID_ENUM));
  2260. return;
  2261. }
  2262. if (!ValidBufferParameter(context, pname))
  2263. {
  2264. context->recordError(Error(GL_INVALID_ENUM));
  2265. return;
  2266. }
  2267. Buffer *buffer = context->getState().getTargetBuffer(target);
  2268. if (!buffer)
  2269. {
  2270. // A null buffer means that "0" is bound to the requested buffer target
  2271. context->recordError(Error(GL_INVALID_OPERATION));
  2272. return;
  2273. }
  2274. switch (pname)
  2275. {
  2276. case GL_BUFFER_USAGE:
  2277. *params = static_cast<GLint64>(buffer->getUsage());
  2278. break;
  2279. case GL_BUFFER_SIZE:
  2280. *params = buffer->getSize();
  2281. break;
  2282. case GL_BUFFER_ACCESS_FLAGS:
  2283. *params = static_cast<GLint64>(buffer->getAccessFlags());
  2284. break;
  2285. case GL_BUFFER_MAPPED:
  2286. *params = static_cast<GLint64>(buffer->isMapped());
  2287. break;
  2288. case GL_BUFFER_MAP_OFFSET:
  2289. *params = buffer->getMapOffset();
  2290. break;
  2291. case GL_BUFFER_MAP_LENGTH:
  2292. *params = buffer->getMapLength();
  2293. break;
  2294. default: UNREACHABLE(); break;
  2295. }
  2296. }
  2297. }
  2298. void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers)
  2299. {
  2300. EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
  2301. Context *context = GetValidGlobalContext();
  2302. if (context)
  2303. {
  2304. if (context->getClientVersion() < 3)
  2305. {
  2306. context->recordError(Error(GL_INVALID_OPERATION));
  2307. return;
  2308. }
  2309. if (count < 0)
  2310. {
  2311. context->recordError(Error(GL_INVALID_VALUE));
  2312. return;
  2313. }
  2314. for (int i = 0; i < count; i++)
  2315. {
  2316. samplers[i] = context->createSampler();
  2317. }
  2318. }
  2319. }
  2320. void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers)
  2321. {
  2322. EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
  2323. Context *context = GetValidGlobalContext();
  2324. if (context)
  2325. {
  2326. if (context->getClientVersion() < 3)
  2327. {
  2328. context->recordError(Error(GL_INVALID_OPERATION));
  2329. return;
  2330. }
  2331. if (count < 0)
  2332. {
  2333. context->recordError(Error(GL_INVALID_VALUE));
  2334. return;
  2335. }
  2336. for (int i = 0; i < count; i++)
  2337. {
  2338. context->deleteSampler(samplers[i]);
  2339. }
  2340. }
  2341. }
  2342. GLboolean GL_APIENTRY IsSampler(GLuint sampler)
  2343. {
  2344. EVENT("(GLuint sampler = %u)", sampler);
  2345. Context *context = GetValidGlobalContext();
  2346. if (context)
  2347. {
  2348. if (context->getClientVersion() < 3)
  2349. {
  2350. context->recordError(Error(GL_INVALID_OPERATION));
  2351. return GL_FALSE;
  2352. }
  2353. return context->isSampler(sampler);
  2354. }
  2355. return GL_FALSE;
  2356. }
  2357. void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler)
  2358. {
  2359. EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
  2360. Context *context = GetValidGlobalContext();
  2361. if (context)
  2362. {
  2363. if (context->getClientVersion() < 3)
  2364. {
  2365. context->recordError(Error(GL_INVALID_OPERATION));
  2366. return;
  2367. }
  2368. if (sampler != 0 && !context->isSampler(sampler))
  2369. {
  2370. context->recordError(Error(GL_INVALID_OPERATION));
  2371. return;
  2372. }
  2373. if (unit >= context->getCaps().maxCombinedTextureImageUnits)
  2374. {
  2375. context->recordError(Error(GL_INVALID_VALUE));
  2376. return;
  2377. }
  2378. context->bindSampler(unit, sampler);
  2379. }
  2380. }
  2381. void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
  2382. {
  2383. EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
  2384. Context *context = GetValidGlobalContext();
  2385. if (context)
  2386. {
  2387. if (context->getClientVersion() < 3)
  2388. {
  2389. context->recordError(Error(GL_INVALID_OPERATION));
  2390. return;
  2391. }
  2392. if (!ValidateSamplerObjectParameter(context, pname))
  2393. {
  2394. return;
  2395. }
  2396. if (!ValidateTexParamParameters(context, pname, param))
  2397. {
  2398. return;
  2399. }
  2400. if (!context->isSampler(sampler))
  2401. {
  2402. context->recordError(Error(GL_INVALID_OPERATION));
  2403. return;
  2404. }
  2405. context->samplerParameteri(sampler, pname, param);
  2406. }
  2407. }
  2408. void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
  2409. {
  2410. SamplerParameteri(sampler, pname, *param);
  2411. }
  2412. void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
  2413. {
  2414. EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
  2415. Context *context = GetValidGlobalContext();
  2416. if (context)
  2417. {
  2418. if (context->getClientVersion() < 3)
  2419. {
  2420. context->recordError(Error(GL_INVALID_OPERATION));
  2421. return;
  2422. }
  2423. if (!ValidateSamplerObjectParameter(context, pname))
  2424. {
  2425. return;
  2426. }
  2427. if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
  2428. {
  2429. return;
  2430. }
  2431. if (!context->isSampler(sampler))
  2432. {
  2433. context->recordError(Error(GL_INVALID_OPERATION));
  2434. return;
  2435. }
  2436. context->samplerParameterf(sampler, pname, param);
  2437. }
  2438. }
  2439. void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
  2440. {
  2441. SamplerParameterf(sampler, pname, *param);
  2442. }
  2443. void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
  2444. {
  2445. EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params);
  2446. Context *context = GetValidGlobalContext();
  2447. if (context)
  2448. {
  2449. if (context->getClientVersion() < 3)
  2450. {
  2451. context->recordError(Error(GL_INVALID_OPERATION));
  2452. return;
  2453. }
  2454. if (!ValidateSamplerObjectParameter(context, pname))
  2455. {
  2456. return;
  2457. }
  2458. if (!context->isSampler(sampler))
  2459. {
  2460. context->recordError(Error(GL_INVALID_OPERATION));
  2461. return;
  2462. }
  2463. *params = context->getSamplerParameteri(sampler, pname);
  2464. }
  2465. }
  2466. void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
  2467. {
  2468. EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params);
  2469. Context *context = GetValidGlobalContext();
  2470. if (context)
  2471. {
  2472. if (context->getClientVersion() < 3)
  2473. {
  2474. context->recordError(Error(GL_INVALID_OPERATION));
  2475. return;
  2476. }
  2477. if (!ValidateSamplerObjectParameter(context, pname))
  2478. {
  2479. return;
  2480. }
  2481. if (!context->isSampler(sampler))
  2482. {
  2483. context->recordError(Error(GL_INVALID_OPERATION));
  2484. return;
  2485. }
  2486. *params = context->getSamplerParameterf(sampler, pname);
  2487. }
  2488. }
  2489. void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor)
  2490. {
  2491. EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
  2492. Context *context = GetValidGlobalContext();
  2493. if (context)
  2494. {
  2495. if (context->getClientVersion() < 3)
  2496. {
  2497. context->recordError(Error(GL_INVALID_OPERATION));
  2498. return;
  2499. }
  2500. if (index >= MAX_VERTEX_ATTRIBS)
  2501. {
  2502. context->recordError(Error(GL_INVALID_VALUE));
  2503. return;
  2504. }
  2505. context->setVertexAttribDivisor(index, divisor);
  2506. }
  2507. }
  2508. void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id)
  2509. {
  2510. EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
  2511. Context *context = GetValidGlobalContext();
  2512. if (context)
  2513. {
  2514. if (context->getClientVersion() < 3)
  2515. {
  2516. context->recordError(Error(GL_INVALID_OPERATION));
  2517. return;
  2518. }
  2519. switch (target)
  2520. {
  2521. case GL_TRANSFORM_FEEDBACK:
  2522. {
  2523. // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1)
  2524. TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
  2525. if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
  2526. {
  2527. context->recordError(Error(GL_INVALID_OPERATION));
  2528. return;
  2529. }
  2530. // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1)
  2531. if (context->getTransformFeedback(id) == NULL)
  2532. {
  2533. context->recordError(Error(GL_INVALID_OPERATION));
  2534. return;
  2535. }
  2536. context->bindTransformFeedback(id);
  2537. }
  2538. break;
  2539. default:
  2540. context->recordError(Error(GL_INVALID_ENUM));
  2541. return;
  2542. }
  2543. }
  2544. }
  2545. void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
  2546. {
  2547. EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
  2548. Context *context = GetValidGlobalContext();
  2549. if (context)
  2550. {
  2551. if (context->getClientVersion() < 3)
  2552. {
  2553. context->recordError(Error(GL_INVALID_OPERATION));
  2554. return;
  2555. }
  2556. for (int i = 0; i < n; i++)
  2557. {
  2558. context->deleteTransformFeedback(ids[i]);
  2559. }
  2560. }
  2561. }
  2562. void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids)
  2563. {
  2564. EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
  2565. Context *context = GetValidGlobalContext();
  2566. if (context)
  2567. {
  2568. if (context->getClientVersion() < 3)
  2569. {
  2570. context->recordError(Error(GL_INVALID_OPERATION));
  2571. return;
  2572. }
  2573. for (int i = 0; i < n; i++)
  2574. {
  2575. ids[i] = context->createTransformFeedback();
  2576. }
  2577. }
  2578. }
  2579. GLboolean GL_APIENTRY IsTransformFeedback(GLuint id)
  2580. {
  2581. EVENT("(GLuint id = %u)", id);
  2582. Context *context = GetValidGlobalContext();
  2583. if (context)
  2584. {
  2585. if (context->getClientVersion() < 3)
  2586. {
  2587. context->recordError(Error(GL_INVALID_OPERATION));
  2588. return GL_FALSE;
  2589. }
  2590. return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE);
  2591. }
  2592. return GL_FALSE;
  2593. }
  2594. void GL_APIENTRY PauseTransformFeedback(void)
  2595. {
  2596. EVENT("(void)");
  2597. Context *context = GetValidGlobalContext();
  2598. if (context)
  2599. {
  2600. if (context->getClientVersion() < 3)
  2601. {
  2602. context->recordError(Error(GL_INVALID_OPERATION));
  2603. return;
  2604. }
  2605. TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
  2606. ASSERT(transformFeedback != NULL);
  2607. // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86)
  2608. if (!transformFeedback->isStarted() || transformFeedback->isPaused())
  2609. {
  2610. context->recordError(Error(GL_INVALID_OPERATION));
  2611. return;
  2612. }
  2613. transformFeedback->pause();
  2614. }
  2615. }
  2616. void GL_APIENTRY ResumeTransformFeedback(void)
  2617. {
  2618. EVENT("(void)");
  2619. Context *context = GetValidGlobalContext();
  2620. if (context)
  2621. {
  2622. if (context->getClientVersion() < 3)
  2623. {
  2624. context->recordError(Error(GL_INVALID_OPERATION));
  2625. return;
  2626. }
  2627. TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
  2628. ASSERT(transformFeedback != NULL);
  2629. // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86)
  2630. if (!transformFeedback->isStarted() || !transformFeedback->isPaused())
  2631. {
  2632. context->recordError(Error(GL_INVALID_OPERATION));
  2633. return;
  2634. }
  2635. transformFeedback->resume();
  2636. }
  2637. }
  2638. void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
  2639. {
  2640. EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)",
  2641. program, bufSize, length, binaryFormat, binary);
  2642. Context *context = GetValidGlobalContext();
  2643. if (context)
  2644. {
  2645. if (context->getClientVersion() < 3)
  2646. {
  2647. context->recordError(Error(GL_INVALID_OPERATION));
  2648. return;
  2649. }
  2650. // glGetProgramBinary
  2651. UNIMPLEMENTED();
  2652. }
  2653. }
  2654. void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
  2655. {
  2656. EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
  2657. program, binaryFormat, binary, length);
  2658. Context *context = GetValidGlobalContext();
  2659. if (context)
  2660. {
  2661. if (context->getClientVersion() < 3)
  2662. {
  2663. context->recordError(Error(GL_INVALID_OPERATION));
  2664. return;
  2665. }
  2666. // glProgramBinary
  2667. UNIMPLEMENTED();
  2668. }
  2669. }
  2670. void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value)
  2671. {
  2672. EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)",
  2673. program, pname, value);
  2674. Context *context = GetValidGlobalContext();
  2675. if (context)
  2676. {
  2677. if (context->getClientVersion() < 3)
  2678. {
  2679. context->recordError(Error(GL_INVALID_OPERATION));
  2680. return;
  2681. }
  2682. // glProgramParameteri
  2683. UNIMPLEMENTED();
  2684. }
  2685. }
  2686. void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
  2687. {
  2688. EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
  2689. target, numAttachments, attachments);
  2690. Context *context = GetValidGlobalContext();
  2691. if (context)
  2692. {
  2693. if (context->getClientVersion() < 3)
  2694. {
  2695. context->recordError(Error(GL_INVALID_OPERATION));
  2696. return;
  2697. }
  2698. if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
  2699. {
  2700. return;
  2701. }
  2702. Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
  2703. ASSERT(framebuffer);
  2704. if (framebuffer->checkStatus(context->getData()) == GL_FRAMEBUFFER_COMPLETE)
  2705. {
  2706. Error error = framebuffer->invalidate(numAttachments, attachments);
  2707. if (error.isError())
  2708. {
  2709. context->recordError(error);
  2710. return;
  2711. }
  2712. }
  2713. }
  2714. }
  2715. void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
  2716. {
  2717. EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, "
  2718. "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
  2719. target, numAttachments, attachments, x, y, width, height);
  2720. Context *context = GetValidGlobalContext();
  2721. if (context)
  2722. {
  2723. if (context->getClientVersion() < 3)
  2724. {
  2725. context->recordError(Error(GL_INVALID_OPERATION));
  2726. return;
  2727. }
  2728. if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
  2729. {
  2730. return;
  2731. }
  2732. Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
  2733. ASSERT(framebuffer);
  2734. if (framebuffer->checkStatus(context->getData()) == GL_FRAMEBUFFER_COMPLETE)
  2735. {
  2736. Rectangle area(x, y, width, height);
  2737. Error error = framebuffer->invalidateSub(numAttachments, attachments, area);
  2738. if (error.isError())
  2739. {
  2740. context->recordError(error);
  2741. return;
  2742. }
  2743. }
  2744. }
  2745. }
  2746. void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
  2747. {
  2748. EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
  2749. target, levels, internalformat, width, height);
  2750. Context *context = GetValidGlobalContext();
  2751. if (context)
  2752. {
  2753. if (context->getClientVersion() < 3)
  2754. {
  2755. context->recordError(Error(GL_INVALID_OPERATION));
  2756. return;
  2757. }
  2758. if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
  2759. {
  2760. return;
  2761. }
  2762. Extents size(width, height, 1);
  2763. Texture *texture = context->getTargetTexture(target);
  2764. Error error = texture->setStorage(target, levels, internalformat, size);
  2765. if (error.isError())
  2766. {
  2767. context->recordError(error);
  2768. return;
  2769. }
  2770. }
  2771. }
  2772. void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
  2773. {
  2774. EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
  2775. "GLsizei height = %d, GLsizei depth = %d)",
  2776. target, levels, internalformat, width, height, depth);
  2777. Context *context = GetValidGlobalContext();
  2778. if (context)
  2779. {
  2780. if (context->getClientVersion() < 3)
  2781. {
  2782. context->recordError(Error(GL_INVALID_OPERATION));
  2783. return;
  2784. }
  2785. if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth))
  2786. {
  2787. return;
  2788. }
  2789. Extents size(width, height, depth);
  2790. Texture *texture = context->getTargetTexture(target);
  2791. Error error = texture->setStorage(target, levels, internalformat, size);
  2792. if (error.isError())
  2793. {
  2794. context->recordError(error);
  2795. return;
  2796. }
  2797. }
  2798. }
  2799. void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
  2800. {
  2801. EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, "
  2802. "GLint* params = 0x%0.8p)",
  2803. target, internalformat, pname, bufSize, params);
  2804. Context *context = GetValidGlobalContext();
  2805. if (context)
  2806. {
  2807. if (context->getClientVersion() < 3)
  2808. {
  2809. context->recordError(Error(GL_INVALID_OPERATION));
  2810. return;
  2811. }
  2812. const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
  2813. if (!formatCaps.renderable)
  2814. {
  2815. context->recordError(Error(GL_INVALID_ENUM));
  2816. return;
  2817. }
  2818. if (target != GL_RENDERBUFFER)
  2819. {
  2820. context->recordError(Error(GL_INVALID_ENUM));
  2821. return;
  2822. }
  2823. if (bufSize < 0)
  2824. {
  2825. context->recordError(Error(GL_INVALID_VALUE));
  2826. return;
  2827. }
  2828. switch (pname)
  2829. {
  2830. case GL_NUM_SAMPLE_COUNTS:
  2831. if (bufSize != 0)
  2832. {
  2833. *params = formatCaps.sampleCounts.size();
  2834. }
  2835. break;
  2836. case GL_SAMPLES:
  2837. {
  2838. size_t returnCount = std::min<size_t>(bufSize, formatCaps.sampleCounts.size());
  2839. auto sampleReverseIt = formatCaps.sampleCounts.rbegin();
  2840. for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex)
  2841. {
  2842. params[sampleIndex] = *sampleReverseIt++;;
  2843. }
  2844. }
  2845. break;
  2846. default:
  2847. context->recordError(Error(GL_INVALID_ENUM));
  2848. return;
  2849. }
  2850. }
  2851. }
  2852. }