diff options
author | Andrew Knight <andrew.knight@digia.com> | 2014-08-05 12:59:44 +0300 |
---|---|---|
committer | Andrew Knight <andrew.knight@digia.com> | 2014-08-05 16:43:22 +0200 |
commit | a6a12d8c0fc918972c15268f749ecc7c90b95d6c (patch) | |
tree | cb6d986d30ef97e932ab51768854d5d9b46729d3 /src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | |
parent | 14f9c09542bd6cc19430473da9ce4c68f239ec7d (diff) |
ANGLE: upgrade to 2.1~07d49ef5350a
This version of ANGLE provides partial ES3 support, numerous
bug fixes, and several potentially useful vendor extensions.
All patches have been rebased. The following changes are noted:
0000-General-fixes-for-ANGLE-2.1.patch
contains compile fixes for the new ANGLE
0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch
has incorporated patch 0015.
0007-Make-DX9-DX11-mutually-exclusive.patch
has been removed as it was fixed upstream.
0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
has been moved up to fill the patch number gap.
0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch
now contains patch 0014 and 0017.
0013-ANGLE-Allow-for-universal-program-binaries.patch
has been removed as it is no longer relevant.
0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch
has been merged with patch 0010.
0015-ANGLE-Don-t-export-DLLMain-functions-for-static-buil.patch
has been merged with patch 0004.
0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch
has been removed and will be replaced by a follow-up patch using a
different technique.
0017-ANGLE-D3D11-Don-t-use-mipmaps-in-level-9-textures.patch
has been merged with patch 0010.
0018-ANGLE-WinRT-Create-swap-chain-using-physical-resolut.patch
has been removed and will be replaced by a follow-up patch extending
the EGL_ANGLE_window_fixed_size extension.
0019-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
is now patch 0007.
[ChangeLog][Third-party libraries] ANGLE has been upgraded to
version 2.1, bringing partial support for OpenGL ES3 over
Direct3D 11, numerous bug fixes, and several new vendor extensions.
Change-Id: I6d95ce1480462d67228d83c1e5c74a1706b5b21c
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 10370 |
1 files changed, 5815 insertions, 4555 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 814dfbf965..5e2ec4a4ee 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,7 +10,8 @@ #include "common/version.h" #include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" +#include "common/utilities.h" +#include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" @@ -20,345 +21,94 @@ #include "libGLESv2/Texture.h" #include "libGLESv2/Query.h" #include "libGLESv2/Context.h" +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/FramebufferAttachment.h" -bool validImageSize(GLint level, GLsizei width, GLsizei height) -{ - if (level < 0 || width < 0 || height < 0) - { - return false; - } - - if (gl::getContext() && gl::getContext()->supportsNonPower2Texture()) - { - return true; - } - - if (level == 0) - { - return true; - } - - if (gl::isPow2(width) && gl::isPow2(height)) - { - return true; - } - - return false; -} +#include "libGLESv2/validationES.h" +#include "libGLESv2/validationES2.h" +#include "libGLESv2/validationES3.h" +#include "libGLESv2/queryconversions.h" -// Verify that format/type are one of the combinations from table 3.4. -bool checkTextureFormatType(GLenum format, GLenum type) -{ - // validate <format> by itself (used as secondary key below) - switch (format) - { - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - break; - default: - return gl::error(GL_INVALID_ENUM, false); - } - - // invalid <type> -> sets INVALID_ENUM - // invalid <format>+<type> combination -> sets INVALID_OPERATION - switch (type) - { - case GL_UNSIGNED_BYTE: - switch (format) - { - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); - } - - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - switch (format) - { - case GL_RGBA: - case GL_RGB: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); - } - - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - switch (format) - { - case GL_RGBA: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); - } - - case GL_UNSIGNED_SHORT_5_6_5: - switch (format) - { - case GL_RGB: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); - } - - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - switch (format) - { - case GL_DEPTH_COMPONENT: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); - } - - case GL_UNSIGNED_INT_24_8_OES: - switch (format) - { - case GL_DEPTH_STENCIL_OES: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); - } - - default: - return gl::error(GL_INVALID_ENUM, false); - } -} - -bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, - GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type, - gl::Texture2D *texture) +extern "C" { - if (!texture) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (compressed != texture->isCompressed(level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (format != GL_NONE) - { - GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); - if (internalformat != texture->getInternalFormat(level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - } - if (compressed) - { - if ((width % 4 != 0 && width != texture->getWidth(0)) || - (height % 4 != 0 && height != texture->getHeight(0))) - { - return gl::error(GL_INVALID_OPERATION, false); - } - } +// OpenGL ES 2.0 functions - if (xoffset + width > texture->getWidth(level) || - yoffset + height > texture->getHeight(level)) - { - return gl::error(GL_INVALID_VALUE, false); - } - - return true; -} - -bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, - GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type, - gl::TextureCubeMap *texture) +void __stdcall glActiveTexture(GLenum texture) { - if (!texture) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (compressed != texture->isCompressed(target, level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } + EVENT("(GLenum texture = 0x%X)", texture); - if (format != GL_NONE) - { - GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); - if (internalformat != texture->getInternalFormat(target, level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } - } + gl::Context *context = gl::getNonLostContext(); - if (compressed) + if (context) { - if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || - (height % 4 != 0 && height != texture->getHeight(target, 0))) + if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) { - return gl::error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_ENUM); } - } - if (xoffset + width > texture->getWidth(target, level) || - yoffset + height > texture->getHeight(target, level)) - { - return gl::error(GL_INVALID_VALUE, false); + context->getState().setActiveSampler(texture - GL_TEXTURE0); } - - return true; } -// check for combinations of format and type that are valid for ReadPixels -bool validReadFormatType(GLenum format, GLenum type) -{ - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - break; - default: - return false; - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - break; - default: - return false; - } - break; - default: - return false; - } - return true; -} - -extern "C" +void __stdcall glAttachShader(GLuint program, GLuint shader) { + EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); -void __stdcall glActiveTexture(GLenum texture) -{ - EVENT("(GLenum texture = 0x%X)", texture); + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!programObject) { - if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) + if (context->getShader(program)) { - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - context->setActiveSampler(texture - GL_TEXTURE0); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} - -void __stdcall glAttachShader(GLuint program, GLuint shader) -{ - EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - try - { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!shaderObject) { - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) + if (context->getProgram(shader)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); } - - if (!shaderObject) + else { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); } + } - if (!programObject->attachShader(shaderObject)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programObject->attachShader(shaderObject)) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glBeginQueryEXT(GLenum target, GLuint id) { EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); - try - { - switch (target) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); - if (id == 0) + if (context) + { + if (!ValidateBeginQuery(context, target, id)) { - return gl::error(GL_INVALID_OPERATION); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->beginQuery(target, id); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->beginQuery(target, id); } } @@ -366,42 +116,35 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* { EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); - try + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); } - - if (strncmp(name, "gl_", 3) == 0) + else { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } + } - programObject->bindAttributeLocation(index, name); + if (strncmp(name, "gl_", 3) == 0) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->bindAttributeLocation(index, name); } } @@ -409,84 +152,86 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer) { EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } - if (context) + switch (target) { - switch (target) - { - case GL_ARRAY_BUFFER: - context->bindArrayBuffer(buffer); - return; - case GL_ELEMENT_ARRAY_BUFFER: - context->bindElementArrayBuffer(buffer); - return; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_ARRAY_BUFFER: + context->bindArrayBuffer(buffer); + return; + case GL_ELEMENT_ARRAY_BUFFER: + context->bindElementArrayBuffer(buffer); + return; + case GL_COPY_READ_BUFFER: + context->bindCopyReadBuffer(buffer); + return; + case GL_COPY_WRITE_BUFFER: + context->bindCopyWriteBuffer(buffer); + return; + case GL_PIXEL_PACK_BUFFER: + context->bindPixelPackBuffer(buffer); + return; + case GL_PIXEL_UNPACK_BUFFER: + context->bindPixelUnpackBuffer(buffer); + return; + case GL_UNIFORM_BUFFER: + context->bindGenericUniformBuffer(buffer); + return; + case GL_TRANSFORM_FEEDBACK_BUFFER: + context->bindGenericTransformFeedbackBuffer(buffer); + return; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) { EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - try + if (!gl::ValidFramebufferTarget(target)) { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + return gl::error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) { - return gl::error(GL_INVALID_ENUM); + context->bindReadFramebuffer(framebuffer); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) { - if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindReadFramebuffer(framebuffer); - } - - if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindDrawFramebuffer(framebuffer); - } + context->bindDrawFramebuffer(framebuffer); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) { EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); - try + if (target != GL_RENDERBUFFER) { - if (target != GL_RENDERBUFFER) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->bindRenderbuffer(renderbuffer); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->bindRenderbuffer(renderbuffer); } } @@ -494,36 +239,43 @@ void __stdcall glBindTexture(GLenum target, GLuint texture) { EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *textureObject = context->getTexture(texture); - if (context) + if (textureObject && textureObject->getTarget() != target && texture != 0) { - gl::Texture *textureObject = context->getTexture(texture); + return gl::error(GL_INVALID_OPERATION); + } - if (textureObject && textureObject->getTarget() != target && texture != 0) + switch (target) + { + case GL_TEXTURE_2D: + context->bindTexture2D(texture); + return; + case GL_TEXTURE_CUBE_MAP: + context->bindTextureCubeMap(texture); + return; + case GL_TEXTURE_3D: + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_ENUM); } - - switch (target) + context->bindTexture3D(texture); + return; + case GL_TEXTURE_2D_ARRAY: + if (context->getClientVersion() < 3) { - case GL_TEXTURE_2D: - context->bindTexture2D(texture); - return; - case GL_TEXTURE_CUBE_MAP: - context->bindTextureCubeMap(texture); - return; - default: return gl::error(GL_INVALID_ENUM); } + context->bindTexture2DArray(texture); + return; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) @@ -531,18 +283,11 @@ void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); - try - { - gl::Context* context = gl::getNonLostContext(); + gl::Context* context = gl::getNonLostContext(); - if (context) - { - context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha)); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha)); } } @@ -555,38 +300,37 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); - try + gl::Context *context = gl::getNonLostContext(); + + switch (modeRGB) { - switch (modeRGB) - { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; - switch (modeAlpha) - { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + default: + return gl::error(GL_INVALID_ENUM); + } - gl::Context *context = gl::getNonLostContext(); + switch (modeAlpha) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; - if (context) - { - context->setBlendEquation(modeRGB, modeAlpha); - } + default: + return gl::error(GL_INVALID_ENUM); } - catch(std::bad_alloc&) + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setBlendEquation(modeRGB, modeAlpha); } } @@ -600,116 +344,125 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", srcRGB, dstRGB, srcAlpha, dstAlpha); - try - { - switch (srcRGB) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); + + switch (srcRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + default: + return gl::error(GL_INVALID_ENUM); + } - switch (dstRGB) + switch (dstRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + + case GL_SRC_ALPHA_SATURATE: + if (!context || context->getClientVersion() < 3) { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - default: return gl::error(GL_INVALID_ENUM); } + break; - switch (srcAlpha) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + default: + return gl::error(GL_INVALID_ENUM); + } + + switch (srcAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + switch (dstAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; - switch (dstAlpha) + case GL_SRC_ALPHA_SATURATE: + if (!context || context->getClientVersion() < 3) { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - default: return gl::error(GL_INVALID_ENUM); } + break; - bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || - dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); - - bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || - dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); + default: + return gl::error(GL_INVALID_ENUM); + } - if (constantColorUsed && constantAlphaUsed) - { - ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); - return gl::error(GL_INVALID_OPERATION); - } + bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || + dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); - gl::Context *context = gl::getNonLostContext(); + bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || + dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); - if (context) - { - context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); - } + if (constantColorUsed && constantAlphaUsed) + { + ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); + return gl::error(GL_INVALID_OPERATION); } - catch(std::bad_alloc&) + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); } } @@ -718,52 +471,51 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", target, size, data, usage); - try + if (size < 0) { - if (size < 0) + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + switch (usage) + { + case GL_STREAM_DRAW: + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + break; + + case GL_STREAM_READ: + case GL_STREAM_COPY: + case GL_STATIC_READ: + case GL_STATIC_COPY: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + if (context && context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM); } + break; - switch (usage) + default: + return gl::error(GL_INVALID_ENUM); + } + + if (context) + { + if (!gl::ValidBufferTarget(context, target)) { - case GL_STREAM_DRAW: - case GL_STATIC_DRAW: - case GL_DYNAMIC_DRAW: - break; - default: return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - if (context) + if (!buffer) { - gl::Buffer *buffer; - - switch (target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - if (!buffer) - { - return gl::error(GL_INVALID_OPERATION); - } - - buffer->bufferData(data, size, usage); + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + buffer->bufferData(data, size, usage); } } @@ -772,52 +524,49 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", target, offset, size, data); - try + if (size < 0 || offset < 0) { - if (size < 0 || offset < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - if (data == NULL) + if (data == NULL) + { + return; + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!gl::ValidBufferTarget(context, target)) { - return; + return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - if (context) + if (!buffer) { - gl::Buffer *buffer; - - switch (target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_OPERATION); + } - if (!buffer) - { - return gl::error(GL_INVALID_OPERATION); - } + if (buffer->isMapped()) + { + return gl::error(GL_INVALID_OPERATION); + } - if ((size_t)size + offset > buffer->size()) - { - return gl::error(GL_INVALID_VALUE); - } + // Check for possible overflow of size + offset + if (!rx::IsUnsignedAdditionSafe<size_t>(size, offset)) + { + return gl::error(GL_OUT_OF_MEMORY); + } - buffer->bufferSubData(data, size, offset); + if (size + offset > buffer->getSize()) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + buffer->bufferSubData(data, size, offset); } } @@ -825,33 +574,18 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - try + if (!gl::ValidFramebufferTarget(target)) { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) - { - return gl::error(GL_INVALID_ENUM, 0); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_ENUM, 0); + } - if (context) - { - gl::Framebuffer *framebuffer = NULL; - if (target == GL_READ_FRAMEBUFFER_ANGLE) - { - framebuffer = context->getReadFramebuffer(); - } - else - { - framebuffer = context->getDrawFramebuffer(); - } + gl::Context *context = gl::getNonLostContext(); - return framebuffer->completeness(); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY, 0); + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + return framebuffer->completeness(); } return 0; @@ -859,20 +593,25 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) void __stdcall glClear(GLbitfield mask) { - EVENT("(GLbitfield mask = %X)", mask); + EVENT("(GLbitfield mask = 0x%X)", mask); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); - if (context) + if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) { - context->clear(mask); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) + { + return gl::error(GL_INVALID_VALUE); + } + + context->clear(mask); } } @@ -881,18 +620,11 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setClearColor(red, green, blue, alpha); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearColor(red, green, blue, alpha); } } @@ -900,18 +632,11 @@ void __stdcall glClearDepthf(GLclampf depth) { EVENT("(GLclampf depth = %f)", depth); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setClearDepth(depth); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearDepth(depth); } } @@ -919,38 +644,24 @@ void __stdcall glClearStencil(GLint s) { EVENT("(GLint s = %d)", s); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setClearStencil(s); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearStencil(s); } } void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { - EVENT("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)", + EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)", red, green, blue, alpha); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); } } @@ -958,191 +669,82 @@ void __stdcall glCompileShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) + if (context->getProgram(shader)) { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - shaderObject->compile(); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->compile(); } } -void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, +void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", target, level, internalformat, width, height, border, imageSize, data); - try - { - if (!validImageSize(level, width, height) || border != 0 || imageSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (internalformat) - { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); - if (border != 0) + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, width, height, border, GL_NONE, GL_NONE, data)) { - return gl::error(GL_INVALID_OPERATION); + return; } - if (width != 1 && width != 2 && width % 4 != 0) + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data)) { - return gl::error(GL_INVALID_OPERATION); + return; } - if (height != 1 && height != 2 && height % 4 != 0) + if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, width, height)) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (target) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (target) - { - case GL_TEXTURE_2D: - if (width > (context->getMaximumTextureDimension() >> level) || - height > (context->getMaximumTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) - { - return gl::error(GL_INVALID_VALUE); - } - - if (width > (context->getMaximumCubeTextureDimension() >> level) || - height > (context->getMaximumCubeTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - switch (internalformat) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - default: UNREACHABLE(); - } - - if (imageSize != gl::ComputeCompressedSize(width, height, internalformat)) - { - return gl::error(GL_INVALID_VALUE); - } - - if (target == GL_TEXTURE_2D) + case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } - texture->setCompressedImage(level, internalformat, width, height, imageSize, data); } - else + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (target) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); - break; - default: UNREACHABLE(); - } + texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); } - } + break; - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + default: + return gl::error(GL_INVALID_ENUM); + } } } @@ -1154,103 +756,54 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", target, level, xoffset, yoffset, width, height, format, imageSize, data); - try - { - if (!gl::IsInternalTextureTarget(target)) - { - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); - if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0) + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data)) { - return gl::error(GL_INVALID_VALUE); + return; } - switch (format) + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - break; - default: - return gl::error(GL_INVALID_ENUM); + return; } - if (width == 0 || height == 0 || data == NULL) + if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, width, height)) { - return; + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (target) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (format) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - default: UNREACHABLE(); - } - - if (imageSize != gl::ComputeCompressedSize(width, height, format)) - { - return gl::error(GL_INVALID_VALUE); - } - - if (xoffset % 4 != 0 || yoffset % 4 != 0) - { - return gl::error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction - // does not exist unless DXT textures are supported. - } - - if (target == GL_TEXTURE_2D) + case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - if (validateSubImageParams2D(true, width, height, xoffset, yoffset, level, format, GL_NONE, texture)) - { - texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); - } + texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); } - else if (gl::IsCubemapTextureTarget(target)) + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - if (validateSubImageParamsCube(true, width, height, xoffset, yoffset, target, level, format, GL_NONE, texture)) - { - texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); - } - } - else - { - UNREACHABLE(); + texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); } + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) @@ -1259,194 +812,51 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", target, level, internalformat, x, y, width, height, border); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (!validImageSize(level, width, height)) + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, x, y, width, height, border)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (border != 0) + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, 0, x, y, width, height, border)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (context) + switch (target) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (target) - { - case GL_TEXTURE_2D: - if (width > (context->getMaximumTextureDimension() >> level) || - height > (context->getMaximumTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) - { - return gl::error(GL_INVALID_VALUE); - } - - if (width > (context->getMaximumCubeTextureDimension() >> level) || - height > (context->getMaximumCubeTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); - - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); - } - - if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); - GLenum colorbufferFormat = source->getInternalFormat(); - - // [OpenGL ES 2.0.24] table 3.9 - switch (internalformat) - { - case GL_ALPHA: - if (colorbufferFormat != GL_ALPHA8_EXT && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE: - case GL_RGB: - if (colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE_ALPHA: - case GL_RGBA: - if (colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH_STENCIL_OES: - case GL_DEPTH24_STENCIL8_OES: - if (context->supportsDepthTextures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - default: - return gl::error(GL_INVALID_ENUM); - } - - if (target == GL_TEXTURE_2D) + case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } - texture->copyImage(level, internalformat, x, y, width, height, framebuffer); } - else if (gl::IsCubemapTextureTarget(target)) + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } - texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); } - else UNREACHABLE(); + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) @@ -1455,148 +865,61 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", target, level, xoffset, yoffset, x, y, width, height); - try - { - if (!gl::IsInternalTextureTarget(target)) - { - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); - if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, x, y, width, height, 0)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) - { - return gl::error(GL_INVALID_VALUE); - } - - if (width == 0 || height == 0) + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, 0, x, y, width, height, 0)) { return; } - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (context) + switch (target) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); - - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); - } - - if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) + case GL_TEXTURE_2D: { - return gl::error(GL_INVALID_OPERATION); - } - - gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); - GLenum colorbufferFormat = source->getInternalFormat(); - gl::Texture *texture = NULL; - GLenum textureFormat = GL_RGBA; - - if (target == GL_TEXTURE_2D) - { - gl::Texture2D *tex2d = context->getTexture2D(); - - if (!validateSubImageParams2D(false, width, height, xoffset, yoffset, level, GL_NONE, GL_NONE, tex2d)) - { - return; // error already registered by validateSubImageParams - } - textureFormat = gl::ExtractFormat(tex2d->getInternalFormat(level)); - texture = tex2d; - } - else if (gl::IsCubemapTextureTarget(target)) - { - gl::TextureCubeMap *texcube = context->getTextureCubeMap(); - - if (!validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, GL_NONE, GL_NONE, texcube)) - { - return; // error already registered by validateSubImageParams - } - textureFormat = gl::ExtractFormat(texcube->getInternalFormat(target, level)); - texture = texcube; + gl::Texture2D *texture = context->getTexture2D(); + texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); } - else UNREACHABLE(); + break; - // [OpenGL ES 2.0.24] table 3.9 - switch (textureFormat) + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { - case GL_ALPHA: - if (colorbufferFormat != GL_ALPHA8_EXT && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE: - case GL_RGB: - if (colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE_ALPHA: - case GL_RGBA: - if (colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return gl::error(GL_INVALID_OPERATION); - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - return gl::error(GL_INVALID_OPERATION); - default: - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); } + break; - texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer); + default: + return gl::error(GL_INVALID_ENUM); } } - - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLuint __stdcall glCreateProgram(void) { EVENT("()"); - try - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - return context->createProgram(); - } - } - catch(std::bad_alloc&) + gl::Context *context = gl::getNonLostContext(); + if (context) { - return gl::error(GL_OUT_OF_MEMORY, 0); + return context->createProgram(); } return 0; @@ -1606,26 +929,19 @@ GLuint __stdcall glCreateShader(GLenum type) { EVENT("(GLenum type = 0x%X)", type); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + switch (type) { - switch (type) - { - case GL_FRAGMENT_SHADER: - case GL_VERTEX_SHADER: - return context->createShader(type); - default: - return gl::error(GL_INVALID_ENUM, 0); - } + case GL_FRAGMENT_SHADER: + case GL_VERTEX_SHADER: + return context->createShader(type); + default: + return gl::error(GL_INVALID_ENUM, 0); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } return 0; } @@ -1634,29 +950,22 @@ void __stdcall glCullFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - try + switch (mode) { - switch (mode) + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setCullMode(mode); - } + if (context) + { + context->getState().setCullMode(mode); } - break; - default: - return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + break; + default: + return gl::error(GL_INVALID_ENUM); } } @@ -1664,119 +973,91 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) { EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteBuffer(buffers[i]); - } + context->deleteBuffer(buffers[i]); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) { EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteFence(fences[i]); - } + context->deleteFenceNV(fences[i]); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) + if (framebuffers[i] != 0) { - if (framebuffers[i] != 0) - { - context->deleteFramebuffer(framebuffers[i]); - } + context->deleteFramebuffer(framebuffers[i]); } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - try + if (program == 0) { - if (program == 0) - { - return; - } + return; + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!context->getProgram(program)) { - if (!context->getProgram(program)) + if(context->getShader(program)) { - if(context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - context->deleteProgram(program); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->deleteProgram(program); } } @@ -1784,89 +1065,68 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) { EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteQuery(ids[i]); - } + context->deleteQuery(ids[i]); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteRenderbuffer(renderbuffers[i]); - } + context->deleteRenderbuffer(renderbuffers[i]); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - try + if (shader == 0) { - if (shader == 0) - { - return; - } + return; + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!context->getShader(shader)) { - if (!context->getShader(shader)) + if(context->getProgram(shader)) { - if(context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - context->deleteShader(shader); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->deleteShader(shader); } } @@ -1874,82 +1134,61 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) { EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) + if (textures[i] != 0) { - if (textures[i] != 0) - { - context->deleteTexture(textures[i]); - } + context->deleteTexture(textures[i]); } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDepthFunc(GLenum func) { EVENT("(GLenum func = 0x%X)", func); - try + switch (func) { - switch (func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GREATER: - case GL_GEQUAL: - case GL_NOTEQUAL: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_NOTEQUAL: + break; + default: + return gl::error(GL_INVALID_ENUM); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setDepthFunc(func); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setDepthFunc(func); } } void __stdcall glDepthMask(GLboolean flag) { - EVENT("(GLboolean flag = %d)", flag); + EVENT("(GLboolean flag = %u)", flag); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setDepthMask(flag != GL_FALSE); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setDepthMask(flag != GL_FALSE); } } @@ -1957,18 +1196,11 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar) { EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setDepthRange(zNear, zFar); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setDepthRange(zNear, zFar); } } @@ -1976,52 +1208,45 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) { EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); - if (context) - { + gl::Program *programObject = context->getProgram(program); + gl::Shader *shaderObject = context->getShader(shader); - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) + if (!programObject) + { + gl::Shader *shaderByProgramHandle; + shaderByProgramHandle = context->getShader(program); + if (!shaderByProgramHandle) { - gl::Shader *shaderByProgramHandle; - shaderByProgramHandle = context->getShader(program); - if (!shaderByProgramHandle) - { - return gl::error(GL_INVALID_VALUE); - } - else - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_VALUE); } - - if (!shaderObject) + else { - gl::Program *programByShaderHandle = context->getProgram(shader); - if (!programByShaderHandle) - { - return gl::error(GL_INVALID_VALUE); - } - else - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); } + } - if (!programObject->detachShader(shaderObject)) + if (!shaderObject) + { + gl::Program *programByShaderHandle = context->getProgram(shader); + if (!programByShaderHandle) + { + return gl::error(GL_INVALID_VALUE); + } + else { return gl::error(GL_INVALID_OPERATION); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!programObject->detachShader(shaderObject)) + { + return gl::error(GL_INVALID_OPERATION); + } } } @@ -2029,31 +1254,16 @@ void __stdcall glDisable(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!ValidCap(context, cap)) { - switch (cap) - { - case GL_CULL_FACE: context->setCullFace(false); break; - case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(false); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break; - case GL_SAMPLE_COVERAGE: context->setSampleCoverage(false); break; - case GL_SCISSOR_TEST: context->setScissorTest(false); break; - case GL_STENCIL_TEST: context->setStencilTest(false); break; - case GL_DEPTH_TEST: context->setDepthTest(false); break; - case GL_BLEND: context->setBlend(false); break; - case GL_DITHER: context->setDither(false); break; - default: - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setEnableFeature(cap, false); } } @@ -2061,23 +1271,16 @@ void __stdcall glDisableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); - try + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setEnableVertexAttribArray(index, false); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setEnableVertexAttribArray(index, false); } } @@ -2085,23 +1288,16 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) { EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0 || first < 0) + if (!ValidateDrawArrays(context, mode, first, count)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->drawArrays(mode, first, count, 0); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawArrays(mode, first, count, 0); } } @@ -2109,26 +1305,16 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun { EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0 || first < 0 || primcount < 0) + if (!ValidateDrawArraysInstanced(context, mode, first, count, primcount)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (primcount > 0) - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->drawArrays(mode, first, count, primcount); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawArrays(mode, first, count, primcount); } } @@ -2137,38 +1323,16 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", mode, count, type, indices); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0) + if (!ValidateDrawElements(context, mode, count, type, indices)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (!context->supports32bitIndices()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - context->drawElements(mode, count, type, indices, 0); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawElements(mode, count, type, indices, 0); } } @@ -2177,41 +1341,16 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)", mode, count, type, indices, primcount); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0 || primcount < 0) + if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (primcount > 0) - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (!context->supports32bitIndices()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - context->drawElements(mode, count, type, indices, primcount); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawElements(mode, count, type, indices, primcount); } } @@ -2219,31 +1358,16 @@ void __stdcall glEnable(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!ValidCap(context, cap)) { - switch (cap) - { - case GL_CULL_FACE: context->setCullFace(true); break; - case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(true); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break; - case GL_SAMPLE_COVERAGE: context->setSampleCoverage(true); break; - case GL_SCISSOR_TEST: context->setScissorTest(true); break; - case GL_STENCIL_TEST: context->setStencilTest(true); break; - case GL_DEPTH_TEST: context->setDepthTest(true); break; - case GL_BLEND: context->setBlend(true); break; - case GL_DITHER: context->setDither(true); break; - default: - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setEnableFeature(cap, true); } } @@ -2251,23 +1375,16 @@ void __stdcall glEnableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); - try + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setEnableVertexAttribArray(index, true); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setEnableVertexAttribArray(index, true); } } @@ -2275,27 +1392,16 @@ void __stdcall glEndQueryEXT(GLenum target) { EVENT("GLenum target = 0x%X)", target); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - switch (target) + if (!ValidateEndQuery(context, target)) { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - break; - default: - return gl::error(GL_INVALID_ENUM); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->endQuery(target); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->endQuery(target); } } @@ -2303,25 +1409,23 @@ void __stdcall glFinishFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::Fence* fenceObject = context->getFence(fence); - - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); + } - fenceObject->finishFence(); + if (fenceObject->isFence() != GL_TRUE) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + fenceObject->finishFence(); } } @@ -2329,18 +1433,11 @@ void __stdcall glFinish(void) { EVENT("()"); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->sync(true); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->sync(true); } } @@ -2348,18 +1445,11 @@ void __stdcall glFlush(void) { EVENT("()"); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->sync(false); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->sync(false); } } @@ -2368,67 +1458,47 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); - try + if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) { - if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) - || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer)) { - gl::Framebuffer *framebuffer = NULL; - GLuint framebufferHandle = 0; - if (target == GL_READ_FRAMEBUFFER_ANGLE) - { - framebuffer = context->getReadFramebuffer(); - framebufferHandle = context->getReadFramebufferHandle(); - } - else - { - framebuffer = context->getDrawFramebuffer(); - framebufferHandle = context->getDrawFramebufferHandle(); - } - - if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) - { - return gl::error(GL_INVALID_OPERATION); - } + return; + } - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE); - } - - framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer); - } - else + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer, 0, 0); + } + else + { + switch (attachment) { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer); - break; - case GL_STENCIL_ATTACHMENT: - framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_DEPTH_ATTACHMENT: + framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + case GL_STENCIL_ATTACHMENT: + framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + case GL_DEPTH_STENCIL_ATTACHMENT: + framebuffer->setDepthStencilBuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + default: + UNREACHABLE(); + break; } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) @@ -2436,167 +1506,57 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); - try + gl::Context *context = gl::getNonLostContext(); + if (context) { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level)) { - return gl::error(GL_INVALID_ENUM); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (texture == 0) { - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE); - } - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - } - - if (texture == 0) - { - textarget = GL_NONE; - } - else - { - gl::Texture *tex = context->getTexture(texture); - - if (tex == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (textarget) - { - case GL_TEXTURE_2D: - { - if (tex->getTarget() != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION); - } - gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex); - if (tex2d->isCompressed(0)) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - } - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) - { - return gl::error(GL_INVALID_OPERATION); - } - gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex); - if (texcube->isCompressed(textarget, level)) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - } - - default: - return gl::error(GL_INVALID_ENUM); - } - - if (level != 0) - { - return gl::error(GL_INVALID_VALUE); - } - } - - gl::Framebuffer *framebuffer = NULL; - GLuint framebufferHandle = 0; - if (target == GL_READ_FRAMEBUFFER_ANGLE) - { - framebuffer = context->getReadFramebuffer(); - framebufferHandle = context->getReadFramebufferHandle(); - } - else - { - framebuffer = context->getDrawFramebuffer(); - framebufferHandle = context->getDrawFramebufferHandle(); - } - - if (framebufferHandle == 0 || !framebuffer) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + textarget = GL_NONE; + } - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE); - } + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - framebuffer->setColorbuffer(colorAttachment, textarget, texture); - } - else + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, 0); + } + else + { + switch (attachment) { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; - } + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, 0); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, 0); break; + case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, 0); break; } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glFrontFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - try + switch (mode) { - switch (mode) + case GL_CW: + case GL_CCW: { - case GL_CW: - case GL_CCW: - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setFrontFace(mode); - } + if (context) + { + context->getState().setFrontFace(mode); } - break; - default: - return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + break; + default: + return gl::error(GL_INVALID_ENUM); } } @@ -2604,79 +1564,87 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) { EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - buffers[i] = context->createBuffer(); - } + buffers[i] = context->createBuffer(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenerateMipmap(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (!ValidTextureTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } + + gl::Texture *texture = context->getTargetTexture(target); - if (context) + if (texture == NULL) { - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *tex2d = context->getTexture2D(); + return gl::error(GL_INVALID_OPERATION); + } - if (tex2d->isCompressed(0)) - { - return gl::error(GL_INVALID_OPERATION); - } - if (tex2d->isDepth(0)) - { - return gl::error(GL_INVALID_OPERATION); - } + GLenum internalFormat = texture->getBaseLevelInternalFormat(); + const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); - tex2d->generateMipmaps(); - break; - } + // GenerateMipmap should not generate an INVALID_OPERATION for textures created with + // unsized formats or that are color renderable and filterable. Since we do not track if + // the texture was created with sized or unsized format (only sized formats are stored), + // it is not possible to make sure the the LUMA formats can generate mipmaps (they should + // be able to) because they aren't color renderable. Simply do a special case for LUMA + // textures since they're the only texture format that can be created with unsized formats + // that is not color renderable. New unsized formats are unlikely to be added, since ES2 + // was the last version to use add them. + bool isLUMA = internalFormat == GL_LUMINANCE8_EXT || + internalFormat == GL_LUMINANCE8_ALPHA8_EXT || + internalFormat == GL_ALPHA8_EXT; - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *texcube = context->getTextureCubeMap(); + if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0 || !formatCaps.filterable || + (!formatCaps.renderable && !isLUMA) || gl::IsFormatCompressed(internalFormat)) + { + return gl::error(GL_INVALID_OPERATION); + } - if (texcube->isCompressed(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) - { - return gl::error(GL_INVALID_OPERATION); - } + // GL_EXT_sRGB does not support mipmap generation on sRGB textures + if (context->getClientVersion() == 2 && gl::GetColorEncoding(internalFormat) == GL_SRGB) + { + return gl::error(GL_INVALID_OPERATION); + } - texcube->generateMipmaps(); - break; - } + // Non-power of 2 ES2 check + if (!context->getExtensions().textureNPOT && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight()))) + { + ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP)); + return gl::error(GL_INVALID_OPERATION); + } - default: - return gl::error(GL_INVALID_ENUM); + // Cube completeness check + if (target == GL_TEXTURE_CUBE_MAP) + { + gl::TextureCubeMap *textureCube = static_cast<gl::TextureCubeMap *>(texture); + if (!textureCube->isCubeComplete()) + { + return gl::error(GL_INVALID_OPERATION); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + texture->generateMipmaps(); } } @@ -2684,135 +1652,100 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) { EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - fences[i] = context->createFence(); - } + fences[i] = context->createFenceNV(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) { EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - framebuffers[i] = context->createFramebuffer(); - } + framebuffers[i] = context->createFramebuffer(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { if (n < 0) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (GLsizei i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - ids[i] = context->createQuery(); - } + ids[i] = context->createQuery(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - renderbuffers[i] = context->createRenderbuffer(); - } + renderbuffers[i] = context->createRenderbuffer(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenTextures(GLsizei n, GLuint* textures) { - EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); + EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - textures[i] = context->createTexture(); - } + textures[i] = context->createTexture(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) @@ -2821,42 +1754,35 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", program, index, bufsize, length, size, type, name); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); } - - if (index >= (GLuint)programObject->getActiveAttributeCount()) + else { return gl::error(GL_INVALID_VALUE); } + } - programObject->getActiveAttribute(index, bufsize, length, size, type, name); + if (index >= (GLuint)programObject->getActiveAttributeCount()) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->getActiveAttribute(index, bufsize, length, size, type, name); } } @@ -2866,42 +1792,35 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", program, index, bufsize, length, size, type, name); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); } - - if (index >= (GLuint)programObject->getActiveUniformCount()) + else { return gl::error(GL_INVALID_VALUE); } + } - programObject->getActiveUniform(index, bufsize, length, size, type, name); + if (index >= (GLuint)programObject->getActiveUniformCount()) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->getActiveUniform(index, bufsize, length, size, type, name); } } @@ -2910,37 +1829,30 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", program, maxcount, count, shaders); - try + if (maxcount < 0) { - if (maxcount < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - return programObject->getAttachedShaders(maxcount, count, shaders); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + return programObject->getAttachedShaders(maxcount, count, shaders); } } @@ -2948,39 +1860,32 @@ int __stdcall glGetAttribLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { + if (context) + { - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - else - { - return gl::error(GL_INVALID_VALUE, -1); - } + return gl::error(GL_INVALID_OPERATION, -1); } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) + else { - return gl::error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_VALUE, -1); } + } - return programBinary->getAttributeLocation(name); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + return gl::error(GL_INVALID_OPERATION, -1); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, -1); + + return programBinary->getAttributeLocation(name); } return -1; @@ -2990,62 +1895,25 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) { EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - if (!(context->getBooleanv(pname, params))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); - - if (numParams == 0) - return; // it is known that the pname is valid, but there are no parameters to return - - if (nativeType == GL_FLOAT) - { - GLfloat *floatParams = NULL; - floatParams = new GLfloat[numParams]; - - context->getFloatv(pname, floatParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (floatParams[i] == 0.0f) - params[i] = GL_FALSE; - else - params[i] = GL_TRUE; - } - - delete [] floatParams; - } - else if (nativeType == GL_INT) - { - GLint *intParams = NULL; - intParams = new GLint[numParams]; - - context->getIntegerv(pname, intParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (intParams[i] == 0) - params[i] = GL_FALSE; - else - params[i] = GL_TRUE; - } + return; + } - delete [] intParams; - } - } + if (nativeType == GL_BOOL) + { + context->getBooleanv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3053,47 +1921,51 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } - if (context) + if (!gl::ValidBufferParameter(context, pname)) { - gl::Buffer *buffer; + return gl::error(GL_INVALID_ENUM); + } - switch (target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: return gl::error(GL_INVALID_ENUM); - } + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - if (!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - return gl::error(GL_INVALID_OPERATION); - } + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + return gl::error(GL_INVALID_OPERATION); + } - switch (pname) - { - case GL_BUFFER_USAGE: - *params = buffer->usage(); - break; - case GL_BUFFER_SIZE: - *params = buffer->size(); - break; - default: return gl::error(GL_INVALID_ENUM); - } + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast<GLint>(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = gl::clampCast<GLint>(buffer->getSize()); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = buffer->getAccessFlags(); + break; + case GL_BUFFER_MAPPED: + *params = static_cast<GLint>(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = gl::clampCast<GLint>(buffer->getMapOffset()); + break; + case GL_BUFFER_MAP_LENGTH: + *params = gl::clampCast<GLint>(buffer->getMapLength()); + break; + default: UNREACHABLE(); break; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLenum __stdcall glGetError(void) @@ -3114,26 +1986,33 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) { EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); - try + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::Fence *fenceObject = context->getFence(fence); + return gl::error(GL_INVALID_OPERATION); + } - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } + if (fenceObject->isFence() != GL_TRUE) + { + return gl::error(GL_INVALID_OPERATION); + } - fenceObject->getFenceiv(pname, params); + switch (pname) + { + case GL_FENCE_STATUS_NV: + case GL_FENCE_CONDITION_NV: + break; + + default: return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + params[0] = fenceObject->getFencei(pname); } } @@ -3141,59 +2020,25 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params) { EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - if (!(context->getFloatv(pname, params))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); - - if (numParams == 0) - return; // it is known that the pname is valid, but that there are no parameters to return. - - if (nativeType == GL_BOOL) - { - GLboolean *boolParams = NULL; - boolParams = new GLboolean[numParams]; - - context->getBooleanv(pname, boolParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (boolParams[i] == GL_FALSE) - params[i] = 0.0f; - else - params[i] = 1.0f; - } - - delete [] boolParams; - } - else if (nativeType == GL_INT) - { - GLint *intParams = NULL; - intParams = new GLint[numParams]; - - context->getIntegerv(pname, intParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - params[i] = (GLfloat)intParams[i]; - } + return; + } - delete [] intParams; - } - } + if (nativeType == GL_FLOAT) + { + context->getFloatv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3202,219 +2047,313 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, attachment, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (!gl::ValidFramebufferTarget(target)) + { + return gl::error(GL_INVALID_ENUM); + } - if (context) + int clientVersion = context->getClientVersion(); + + switch (pname) { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + break; + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + if (clientVersion < 3 && !context->getExtensions().sRGB) { return gl::error(GL_INVALID_ENUM); } - - gl::Framebuffer *framebuffer = NULL; - if (target == GL_READ_FRAMEBUFFER_ANGLE) + break; + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (clientVersion < 3) { - if(context->getReadFramebufferHandle() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - framebuffer = context->getReadFramebuffer(); + return gl::error(GL_INVALID_ENUM); } - else - { - if (context->getDrawFramebufferHandle() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + break; + default: + return gl::error(GL_INVALID_ENUM); + } - framebuffer = context->getDrawFramebuffer(); + // Determine if the attachment is a valid enum + switch (attachment) + { + case GL_BACK: + case GL_FRONT: + case GL_DEPTH: + case GL_STENCIL: + case GL_DEPTH_STENCIL_ATTACHMENT: + if (clientVersion < 3) + { + return gl::error(GL_INVALID_ENUM); } + break; - GLenum attachmentType; - GLuint attachmentHandle; + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + default: + if (attachment < GL_COLOR_ATTACHMENT0_EXT || + (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + return gl::error(GL_INVALID_ENUM); + } + break; + } - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_ENUM); - } + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle); - attachmentType = framebuffer->getColorbufferType(colorAttachment); - attachmentHandle = framebuffer->getColorbufferHandle(colorAttachment); + if (framebufferHandle == 0) + { + if (clientVersion < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (attachment) + { + case GL_BACK: + case GL_DEPTH: + case GL_STENCIL: + break; + default: + return gl::error(GL_INVALID_OPERATION); + } + } + else + { + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + // Valid attachment query } else { switch (attachment) { case GL_DEPTH_ATTACHMENT: - attachmentType = framebuffer->getDepthbufferType(); - attachmentHandle = framebuffer->getDepthbufferHandle(); - break; case GL_STENCIL_ATTACHMENT: - attachmentType = framebuffer->getStencilbufferType(); - attachmentHandle = framebuffer->getStencilbufferHandle(); break; - default: return gl::error(GL_INVALID_ENUM); + case GL_DEPTH_STENCIL_ATTACHMENT: + if (framebuffer->hasValidDepthStencil()) + { + return gl::error(GL_INVALID_OPERATION); + } + break; + default: + return gl::error(GL_INVALID_OPERATION); } } + } - GLenum attachmentObjectType; // Type category - if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER) - { - attachmentObjectType = attachmentType; - } - else if (gl::IsInternalTextureTarget(attachmentType)) - { - attachmentObjectType = GL_TEXTURE; - } - else - { - UNREACHABLE(); - return; - } + GLenum attachmentType = GL_NONE; + GLuint attachmentHandle = 0; + GLuint attachmentLevel = 0; + GLuint attachmentLayer = 0; + + const gl::FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment); + + if (attachmentObject) + { + attachmentType = attachmentObject->type(); + attachmentHandle = attachmentObject->id(); + attachmentLevel = attachmentObject->mipLevel(); + attachmentLayer = attachmentObject->layer(); + } + + GLenum attachmentObjectType; // Type category + if (framebufferHandle == 0) + { + attachmentObjectType = GL_FRAMEBUFFER_DEFAULT; + } + else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER) + { + attachmentObjectType = attachmentType; + } + else if (gl::ValidTexture2DDestinationTarget(context, attachmentType)) + { + attachmentObjectType = GL_TEXTURE; + } + else + { + UNREACHABLE(); + return; + } + + if (attachmentObjectType == GL_NONE) + { + // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE + // is NONE, then querying any other pname will generate INVALID_ENUM. + + // ES 3.0.2 spec pg 235 states that if the attachment type is none, + // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an + // INVALID_OPERATION for all other pnames switch (pname) { case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: *params = attachmentObjectType; break; + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE) + if (clientVersion < 3) { - *params = attachmentHandle; + return gl::error(GL_INVALID_ENUM); + } + *params = 0; + break; + + default: + if (clientVersion < 3) + { + return gl::error(GL_INVALID_ENUM); } else { + gl::error(GL_INVALID_OPERATION); + } + } + } + else + { + ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE || + attachmentObjectType == GL_FRAMEBUFFER_DEFAULT); + ASSERT(attachmentObject != NULL); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = attachmentObjectType; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE) + { return gl::error(GL_INVALID_ENUM); } + *params = attachmentHandle; break; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - if (attachmentObjectType == GL_TEXTURE) + if (attachmentObjectType != GL_TEXTURE) { - *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0 + return gl::error(GL_INVALID_ENUM); } - else + *params = attachmentLevel; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + if (attachmentObjectType != GL_TEXTURE) { return gl::error(GL_INVALID_ENUM); } + *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0; break; - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - if (attachmentObjectType == GL_TEXTURE) + + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + *params = attachmentObject->getRedSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + *params = attachmentObject->getGreenSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + *params = attachmentObject->getBlueSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + *params = attachmentObject->getAlphaSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + *params = attachmentObject->getDepthSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + *params = attachmentObject->getStencilSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + if (attachment == GL_DEPTH_STENCIL) { - if (gl::IsCubemapTextureTarget(attachmentType)) - { - *params = attachmentType; - } - else - { - *params = 0; - } + gl::error(GL_INVALID_OPERATION); } - else + *params = attachmentObject->getComponentType(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + *params = attachmentObject->getColorEncoding(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (attachmentObjectType != GL_TEXTURE) { return gl::error(GL_INVALID_ENUM); } + *params = attachmentLayer; break; + default: - return gl::error(GL_INVALID_ENUM); + UNREACHABLE(); + break; } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLenum __stdcall glGetGraphicsResetStatusEXT(void) { EVENT("()"); - try - { - gl::Context *context = gl::getContext(); - - if (context) - { - return context->getResetStatus(); - } + gl::Context *context = gl::getContext(); - return GL_NO_ERROR; - } - catch(std::bad_alloc&) + if (context) { - return GL_OUT_OF_MEMORY; + return context->getResetStatus(); } + + return GL_NO_ERROR; } void __stdcall glGetIntegerv(GLenum pname, GLint* params) { EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + GLenum nativeType; + unsigned int numParams = 0; - if (context) + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - if (!(context->getIntegerv(pname, params))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); - - if (numParams == 0) - return; // it is known that pname is valid, but there are no parameters to return - - if (nativeType == GL_BOOL) - { - GLboolean *boolParams = NULL; - boolParams = new GLboolean[numParams]; - - context->getBooleanv(pname, boolParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (boolParams[i] == GL_FALSE) - params[i] = 0; - else - params[i] = 1; - } - - delete [] boolParams; - } - else if (nativeType == GL_FLOAT) - { - GLfloat *floatParams = NULL; - floatParams = new GLfloat[numParams]; - - context->getFloatv(pname, floatParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR) - { - params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f); - } - else - params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5)); - } + return; + } - delete [] floatParams; - } - } + if (nativeType == GL_INT) + { + context->getIntegerv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3422,59 +2361,80 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) { EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } + if (context->getClientVersion() < 3) + { switch (pname) { - case GL_DELETE_STATUS: - *params = programObject->isFlaggedForDeletion(); - return; - case GL_LINK_STATUS: - *params = programObject->isLinked(); - return; - case GL_VALIDATE_STATUS: - *params = programObject->isValidated(); - return; - case GL_INFO_LOG_LENGTH: - *params = programObject->getInfoLogLength(); - return; - case GL_ATTACHED_SHADERS: - *params = programObject->getAttachedShadersCount(); - return; - case GL_ACTIVE_ATTRIBUTES: - *params = programObject->getActiveAttributeCount(); - return; - case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = programObject->getActiveAttributeMaxLength(); - return; - case GL_ACTIVE_UNIFORMS: - *params = programObject->getActiveUniformCount(); - return; - case GL_ACTIVE_UNIFORM_MAX_LENGTH: - *params = programObject->getActiveUniformMaxLength(); - return; - case GL_PROGRAM_BINARY_LENGTH_OES: - *params = programObject->getProgramBinaryLength(); - return; - default: + case GL_ACTIVE_UNIFORM_BLOCKS: + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + case GL_TRANSFORM_FEEDBACK_VARYINGS: + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: return gl::error(GL_INVALID_ENUM); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + switch (pname) + { + case GL_DELETE_STATUS: + *params = programObject->isFlaggedForDeletion(); + return; + case GL_LINK_STATUS: + *params = programObject->isLinked(); + return; + case GL_VALIDATE_STATUS: + *params = programObject->isValidated(); + return; + case GL_INFO_LOG_LENGTH: + *params = programObject->getInfoLogLength(); + return; + case GL_ATTACHED_SHADERS: + *params = programObject->getAttachedShadersCount(); + return; + case GL_ACTIVE_ATTRIBUTES: + *params = programObject->getActiveAttributeCount(); + return; + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = programObject->getActiveAttributeMaxLength(); + return; + case GL_ACTIVE_UNIFORMS: + *params = programObject->getActiveUniformCount(); + return; + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + *params = programObject->getActiveUniformMaxLength(); + return; + case GL_PROGRAM_BINARY_LENGTH_OES: + *params = programObject->getProgramBinaryLength(); + return; + case GL_ACTIVE_UNIFORM_BLOCKS: + *params = programObject->getActiveUniformBlockCount(); + return; + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + *params = programObject->getActiveUniformBlockMaxLength(); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + *params = programObject->getTransformFeedbackBufferMode(); + break; + case GL_TRANSFORM_FEEDBACK_VARYINGS: + *params = programObject->getTransformFeedbackVaryingCount(); + break; + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: + *params = programObject->getTransformFeedbackVaryingMaxLength(); + break; + default: + return gl::error(GL_INVALID_ENUM); + } } } @@ -3483,30 +2443,23 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", program, bufsize, length, infolog); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_VALUE); + } - if (context) - { - gl::Program *programObject = context->getProgram(program); + gl::Context *context = gl::getNonLostContext(); - if (!programObject) - { - return gl::error(GL_INVALID_VALUE); - } + if (context) + { + gl::Program *programObject = context->getProgram(program); - programObject->getInfoLog(bufsize, length, infolog); + if (!programObject) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->getInfoLog(bufsize, length, infolog); } } @@ -3514,26 +2467,24 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) { EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { + if (!ValidQueryType(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } + switch (pname) { case GL_CURRENT_QUERY_EXT: + params[0] = context->getState().getActiveQueryId(target); break; + default: return gl::error(GL_INVALID_ENUM); } - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - params[0] = context->getActiveQuery(target); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3541,48 +2492,33 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) { EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - switch (pname) + gl::Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch(pname) { case GL_QUERY_RESULT_EXT: + params[0] = queryObject->getResult(); + break; case GL_QUERY_RESULT_AVAILABLE_EXT: + params[0] = queryObject->isResultAvailable(); break; default: return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - - if (!queryObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (context->getActiveQuery(queryObject->getType()) == id) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch(pname) - { - case GL_QUERY_RESULT_EXT: - params[0] = queryObject->getResult(); - break; - case GL_QUERY_RESULT_AVAILABLE_EXT: - params[0] = queryObject->isResultAvailable(); - break; - default: - ASSERT(false); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3590,102 +2526,85 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (target != GL_RENDERBUFFER) { - if (target != GL_RENDERBUFFER) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); + } - if (context->getRenderbufferHandle() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context->getState().getRenderbufferId() == 0) + { + return gl::error(GL_INVALID_OPERATION); + } - gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle()); + gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId()); - switch (pname) + switch (pname) + { + case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; + case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; + case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; + case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; + case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; + case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; + case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; + case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; + case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; + case GL_RENDERBUFFER_SAMPLES_ANGLE: + if (!context->getExtensions().framebufferMultisample) { - case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; - case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; - case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; - case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; - case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; - case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; - case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; - case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; - case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; - case GL_RENDERBUFFER_SAMPLES_ANGLE: - if (context->getMaxSupportedSamples() != 0) - { - *params = renderbuffer->getSamples(); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: return gl::error(GL_INVALID_ENUM); } + *params = renderbuffer->getSamples(); + break; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) { EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - switch (pname) - { - case GL_SHADER_TYPE: - *params = shaderObject->getType(); - return; - case GL_DELETE_STATUS: - *params = shaderObject->isFlaggedForDeletion(); - return; - case GL_COMPILE_STATUS: - *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; - return; - case GL_INFO_LOG_LENGTH: - *params = shaderObject->getInfoLogLength(); - return; - case GL_SHADER_SOURCE_LENGTH: - *params = shaderObject->getSourceLength(); - return; - case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: - *params = shaderObject->getTranslatedSourceLength(); - return; - default: - return gl::error(GL_INVALID_ENUM); - } + switch (pname) + { + case GL_SHADER_TYPE: + *params = shaderObject->getType(); + return; + case GL_DELETE_STATUS: + *params = shaderObject->isFlaggedForDeletion(); + return; + case GL_COMPILE_STATUS: + *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; + return; + case GL_INFO_LOG_LENGTH: + *params = shaderObject->getInfoLogLength(); + return; + case GL_SHADER_SOURCE_LENGTH: + *params = shaderObject->getSourceLength(); + return; + case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: + *params = shaderObject->getTranslatedSourceLength(); + return; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) @@ -3693,30 +2612,23 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", shader, bufsize, length, infolog); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - return gl::error(GL_INVALID_VALUE); - } + if (context) + { + gl::Shader *shaderObject = context->getShader(shader); - shaderObject->getInfoLog(bufsize, length, infolog); + if (!shaderObject) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getInfoLog(bufsize, length, infolog); } } @@ -3725,43 +2637,36 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", shadertype, precisiontype, range, precision); - try + switch (shadertype) { - switch (shadertype) - { - case GL_VERTEX_SHADER: - case GL_FRAGMENT_SHADER: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - switch (precisiontype) - { - case GL_LOW_FLOAT: - case GL_MEDIUM_FLOAT: - case GL_HIGH_FLOAT: - // Assume IEEE 754 precision - range[0] = 127; - range[1] = 127; - *precision = 23; - break; - case GL_LOW_INT: - case GL_MEDIUM_INT: - case GL_HIGH_INT: - // Some (most) hardware only supports single-precision floating-point numbers, - // which can accurately represent integers up to +/-16777216 - range[0] = 24; - range[1] = 24; - *precision = 0; - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + break; + default: + return gl::error(GL_INVALID_ENUM); } - catch(std::bad_alloc&) + + switch (precisiontype) { - return gl::error(GL_OUT_OF_MEMORY); + case GL_LOW_FLOAT: + case GL_MEDIUM_FLOAT: + case GL_HIGH_FLOAT: + // Assume IEEE 754 precision + range[0] = 127; + range[1] = 127; + *precision = 23; + break; + case GL_LOW_INT: + case GL_MEDIUM_INT: + case GL_HIGH_INT: + // Some (most) hardware only supports single-precision floating-point numbers, + // which can accurately represent integers up to +/-16777216 + range[0] = 24; + range[1] = 24; + *precision = 0; + break; + default: + return gl::error(GL_INVALID_ENUM); } } @@ -3770,30 +2675,23 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", shader, bufsize, length, source); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_VALUE); + } - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); + gl::Context *context = gl::getNonLostContext(); - if (!shaderObject) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context) + { + gl::Shader *shaderObject = context->getShader(shader); - shaderObject->getSource(bufsize, length, source); + if (!shaderObject) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getSource(bufsize, length, source); } } @@ -3802,30 +2700,23 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", shader, bufsize, length, source); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_VALUE); + } - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); + gl::Context *context = gl::getNonLostContext(); - if (!shaderObject) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context) + { + gl::Shader *shaderObject = context->getShader(shader); - shaderObject->getTranslatedSource(bufsize, length, source); + if (!shaderObject) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getTranslatedSource(bufsize, length, source); } } @@ -3833,29 +2724,36 @@ const GLubyte* __stdcall glGetString(GLenum name) { EVENT("(GLenum name = 0x%X)", name); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - switch (name) + switch (name) + { + case GL_VENDOR: + return (GLubyte*)"Google Inc."; + case GL_RENDERER: + return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE"); + case GL_VERSION: + if (context->getClientVersion() == 2) { - case GL_VENDOR: - return (GLubyte*)"Google Inc."; - case GL_RENDERER: - return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE"); - case GL_VERSION: return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; - case GL_SHADING_LANGUAGE_VERSION: + } + else + { + return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; + } + case GL_SHADING_LANGUAGE_VERSION: + if (context->getClientVersion() == 2) + { return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; - case GL_EXTENSIONS: - return (GLubyte*)((context != NULL) ? context->getExtensionString() : ""); - default: - return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, (GLubyte*)NULL); + else + { + return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; + } + case GL_EXTENSIONS: + return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : ""); + default: + return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL); } } @@ -3863,124 +2761,238 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *texture = context->getTargetTexture(target); - if (context) + if (!texture) { - gl::Texture *texture; + return gl::error(GL_INVALID_ENUM); + } - switch (target) + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = (GLfloat)texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLfloat)texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = (GLfloat)texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = (GLfloat)texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: return gl::error(GL_INVALID_ENUM); } - - switch (pname) + *params = (GLfloat)texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->immutableLevelCount(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = (GLfloat)texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) { - case GL_TEXTURE_MAG_FILTER: - *params = (GLfloat)texture->getMagFilter(); - break; - case GL_TEXTURE_MIN_FILTER: - *params = (GLfloat)texture->getMinFilter(); - break; - case GL_TEXTURE_WRAP_S: - *params = (GLfloat)texture->getWrapS(); - break; - case GL_TEXTURE_WRAP_T: - *params = (GLfloat)texture->getWrapT(); - break; - case GL_TEXTURE_IMMUTABLE_FORMAT_EXT: - *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = (GLfloat)texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getMaxAnisotropy(); - break; - default: return gl::error(GL_INVALID_ENUM); } + *params = texture->getSamplerState().maxLod; + break; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *texture = context->getTargetTexture(target); - if (context) + if (!texture) { - gl::Texture *texture; + return gl::error(GL_INVALID_ENUM); + } - switch (target) + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: return gl::error(GL_INVALID_ENUM); } - - switch (pname) + *params = texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->immutableLevelCount(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) { - case GL_TEXTURE_MAG_FILTER: - *params = texture->getMagFilter(); - break; - case GL_TEXTURE_MIN_FILTER: - *params = texture->getMinFilter(); - break; - case GL_TEXTURE_WRAP_S: - *params = texture->getWrapS(); - break; - case GL_TEXTURE_WRAP_T: - *params = texture->getWrapT(); - break; - case GL_TEXTURE_IMMUTABLE_FORMAT_EXT: - *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLint)texture->getMaxAnisotropy(); - break; - default: return gl::error(GL_INVALID_ENUM); } + *params = (GLint)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLint)texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLint)texture->getSamplerState().maxLod; + break; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) @@ -3988,214 +3000,179 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", program, location, bufSize, params); - try + if (bufSize < 0) { - if (bufSize < 0) + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (program == 0) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject || !programObject->isLinked()) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); + } - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->getUniformfv(location, &bufSize, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary->getUniformfv(location, &bufSize, params)) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params) { EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (program == 0) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programObject || !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION); + } - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->getUniformfv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary->getUniformfv(location, NULL, params)) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) { - EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", + EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", program, location, bufSize, params); - try + if (bufSize < 0) { - if (bufSize < 0) + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (program == 0) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject || !programObject->isLinked()) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); + } - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->getUniformiv(location, &bufSize, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary->getUniformiv(location, &bufSize, params)) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params) { EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (program == 0) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programObject || !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION); + } - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->getUniformiv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary->getUniformiv(location, NULL, params)) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } int __stdcall glGetUniformLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); - try + gl::Context *context = gl::getNonLostContext(); + + if (strstr(name, "gl_") == name) { - gl::Context *context = gl::getNonLostContext(); + return -1; + } - if (strstr(name, "gl_") == name) - { - return -1; - } + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - else - { - return gl::error(GL_INVALID_VALUE, -1); - } + return gl::error(GL_INVALID_OPERATION, -1); } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) + else { - return gl::error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_VALUE, -1); } + } - return programBinary->getUniformLocation(name); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + return gl::error(GL_INVALID_OPERATION, -1); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, -1); + + return programBinary->getUniformLocation(name); } return -1; @@ -4205,55 +3182,33 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); + if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + { + return; + } - switch (pname) + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); - break; - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - *params = (GLfloat)attribState.mSize; - break; - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - *params = (GLfloat)attribState.mStride; - break; - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - *params = (GLfloat)attribState.mType; - break; - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE); - break; - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - *params = (GLfloat)attribState.mBoundBuffer.id(); - break; - case GL_CURRENT_VERTEX_ATTRIB: - for (int i = 0; i < 4; ++i) - { - params[i] = attribState.mCurrentValue[i]; - } - break; - case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: - *params = (GLfloat)attribState.mDivisor; - break; - default: return gl::error(GL_INVALID_ENUM); + params[i] = currentValueData.FloatValues[i]; } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + *params = gl::QuerySingleVertexAttributeParameter<GLfloat>(attribState, pname); + } } } @@ -4261,56 +3216,35 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - switch (pname) + if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); - break; - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - *params = attribState.mSize; - break; - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - *params = attribState.mStride; - break; - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - *params = attribState.mType; - break; - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE); - break; - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - *params = attribState.mBoundBuffer.id(); - break; - case GL_CURRENT_VERTEX_ATTRIB: - for (int i = 0; i < 4; ++i) - { - float currentValue = attribState.mCurrentValue[i]; - params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f)); - } - break; - case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: - *params = (GLint)attribState.mDivisor; - break; - default: return gl::error(GL_INVALID_ENUM); + float currentValue = currentValueData.FloatValues[i]; + params[i] = gl::iround<GLint>(currentValue); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + *params = gl::QuerySingleVertexAttributeParameter<GLint>(attribState, pname); + } } } @@ -4318,28 +3252,21 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_VALUE); + } - *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index)); + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) + { + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + *pointer = const_cast<GLvoid*>(context->getState().getVertexAttribPointer(index)); } } @@ -4347,34 +3274,27 @@ void __stdcall glHint(GLenum target, GLenum mode) { EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); - try + switch (mode) { - switch (mode) - { - case GL_FASTEST: - case GL_NICEST: - case GL_DONT_CARE: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - gl::Context *context = gl::getNonLostContext(); - switch (target) - { - case GL_GENERATE_MIPMAP_HINT: - if (context) context->setGenerateMipmapHint(mode); - break; - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: - if (context) context->setFragmentShaderDerivativeHint(mode); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: + break; + default: + return gl::error(GL_INVALID_ENUM); } - catch(std::bad_alloc&) + + gl::Context *context = gl::getNonLostContext(); + switch (target) { - return gl::error(GL_OUT_OF_MEMORY); + case GL_GENERATE_MIPMAP_HINT: + if (context) context->getState().setGenerateMipmapHint(mode); + break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: + if (context) context->getState().setFragmentShaderDerivativeHint(mode); + break; + default: + return gl::error(GL_INVALID_ENUM); } } @@ -4382,24 +3302,17 @@ GLboolean __stdcall glIsBuffer(GLuint buffer) { EVENT("(GLuint buffer = %d)", buffer); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && buffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Buffer *bufferObject = context->getBuffer(buffer); - if (context && buffer) + if (bufferObject) { - gl::Buffer *bufferObject = context->getBuffer(buffer); - - if (bufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4408,31 +3321,16 @@ GLboolean __stdcall glIsEnabled(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!ValidCap(context, cap)) { - switch (cap) - { - case GL_CULL_FACE: return context->isCullFaceEnabled(); - case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled(); - case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled(); - case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled(); - case GL_SCISSOR_TEST: return context->isScissorTestEnabled(); - case GL_STENCIL_TEST: return context->isStencilTestEnabled(); - case GL_DEPTH_TEST: return context->isDepthTestEnabled(); - case GL_BLEND: return context->isBlendEnabled(); - case GL_DITHER: return context->isDitherEnabled(); - default: - return gl::error(GL_INVALID_ENUM, false); - } + return gl::error(GL_INVALID_ENUM, false); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, false); + + return context->getState().getEnableFeature(cap); } return false; @@ -4442,25 +3340,18 @@ GLboolean __stdcall glIsFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::Fence *fenceObject = context->getFence(fence); - - if (fenceObject == NULL) - { - return GL_FALSE; - } - - return fenceObject->isFence(); + return GL_FALSE; } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + return fenceObject->isFence(); } return GL_FALSE; @@ -4470,24 +3361,17 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) { EVENT("(GLuint framebuffer = %d)", framebuffer); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && framebuffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - if (context && framebuffer) + if (framebufferObject) { - gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - - if (framebufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4496,24 +3380,17 @@ GLboolean __stdcall glIsProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && program) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context && program) + if (programObject) { - gl::Program *programObject = context->getProgram(program); - - if (programObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4522,28 +3399,11 @@ GLboolean __stdcall glIsQueryEXT(GLuint id) { EVENT("(GLuint id = %d)", id); - try - { - if (id == 0) - { - return GL_FALSE; - } - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); + gl::Context *context = gl::getNonLostContext(); - if (queryObject) - { - return GL_TRUE; - } - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; } return GL_FALSE; @@ -4553,24 +3413,17 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer) { EVENT("(GLuint renderbuffer = %d)", renderbuffer); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && renderbuffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - if (context && renderbuffer) + if (renderbufferObject) { - gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - - if (renderbufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4579,24 +3432,17 @@ GLboolean __stdcall glIsShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && shader) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context && shader) + if (shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (shaderObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4605,24 +3451,17 @@ GLboolean __stdcall glIsTexture(GLuint texture) { EVENT("(GLuint texture = %d)", texture); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && texture) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *textureObject = context->getTexture(texture); - if (context && texture) + if (textureObject) { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4631,23 +3470,16 @@ void __stdcall glLineWidth(GLfloat width) { EVENT("(GLfloat width = %f)", width); - try + if (width <= 0.0f) { - if (width <= 0.0f) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setLineWidth(width); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setLineWidth(width); } } @@ -4655,32 +3487,25 @@ void __stdcall glLinkProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - context->linkProgram(program); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->linkProgram(program); } } @@ -4688,63 +3513,64 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) { EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + switch (pname) { - switch (pname) + case GL_UNPACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) { - case GL_UNPACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - context->setUnpackAlignment(param); - break; + context->getState().setUnpackAlignment(param); + break; - case GL_PACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - return gl::error(GL_INVALID_VALUE); - } + case GL_PACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) + { + return gl::error(GL_INVALID_VALUE); + } - context->setPackAlignment(param); - break; + context->getState().setPackAlignment(param); + break; - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: - context->setPackReverseRowOrder(param != 0); - break; + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: + context->getState().setPackReverseRowOrder(param != 0); + break; - default: + case GL_UNPACK_IMAGE_HEIGHT: + case GL_UNPACK_SKIP_IMAGES: + case GL_UNPACK_ROW_LENGTH: + case GL_UNPACK_SKIP_ROWS: + case GL_UNPACK_SKIP_PIXELS: + case GL_PACK_ROW_LENGTH: + case GL_PACK_SKIP_ROWS: + case GL_PACK_SKIP_PIXELS: + if (context->getClientVersion() < 3) + { return gl::error(GL_INVALID_ENUM); } + UNIMPLEMENTED(); + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glPolygonOffset(GLfloat factor, GLfloat units) { EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setPolygonOffsetParams(factor, units); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setPolygonOffsetParams(factor, units); } } @@ -4756,36 +3582,22 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)", x, y, width, height, format, type, bufSize, data); - try + if (width < 0 || height < 0 || bufSize < 0) { - if (width < 0 || height < 0 || bufSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, + format, type, &bufSize, data)) { - GLenum currentFormat, currentType; - - // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound, - // and attempting to read back if that's the case is an error. The error will be registered - // by getCurrentReadFormat. - if (!context->getCurrentReadFormatType(¤tFormat, ¤tType)) - return; - - if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type)) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->readPixels(x, y, width, height, format, type, &bufSize, data); + return; } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->readPixels(x, y, width, height, format, type, &bufSize, data); } } @@ -4796,2077 +3608,4336 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)", x, y, width, height, format, type, pixels); - try + if (width < 0 || height < 0) { - if (width < 0 || height < 0) + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, + format, type, NULL, pixels)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); + context->readPixels(x, y, width, height, format, type, NULL, pixels); + } +} + +void __stdcall glReleaseShaderCompiler(void) +{ + EVENT("()"); - if (context) + gl::Shader::releaseCompiler(); +} + +void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, samples, internalformat, width, height); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, + width, height, true)) + { + return; + } + + context->setRenderbufferStorage(width, height, internalformat, samples); + } +} + +void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height); +} + +void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) +{ + EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert); + + gl::Context* context = gl::getNonLostContext(); + + if (context) + { + context->getState().setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); + } +} + +void __stdcall glSetFenceNV(GLuint fence, GLenum condition) +{ + EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); + + if (condition != GL_ALL_COMPLETED_NV) + { + return gl::error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + gl::FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) { - GLenum currentFormat, currentType; - - // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound, - // and attempting to read back if that's the case is an error. The error will be registered - // by getCurrentReadFormat. - if (!context->getCurrentReadFormatType(¤tFormat, ¤tType)) - return; + return gl::error(GL_INVALID_OPERATION); + } + + fenceObject->setFence(condition); + } +} + +void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + if (width < 0 || height < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context* context = gl::getNonLostContext(); + + if (context) + { + context->getState().setScissorParams(x, y, width, height); + } +} + +void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) +{ + EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, " + "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", + n, shaders, binaryformat, binary, length); - if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type)) + // No binary shader formats are supported. + return gl::error(GL_INVALID_ENUM); +} + +void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) +{ + EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", + shader, count, string, length); + + if (count < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + gl::Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + if (context->getProgram(shader)) { return gl::error(GL_INVALID_OPERATION); } + else + { + return gl::error(GL_INVALID_VALUE); + } + } + + shaderObject->setSource(count, string, length); + } +} + +void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); +} + +void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); - context->readPixels(x, y, width, height, format, type, NULL, pixels); + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + switch (func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilParams(func, ref, mask); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackParams(func, ref, mask); } } - catch(std::bad_alloc&) +} + +void __stdcall glStencilMask(GLuint mask) +{ + glStencilMaskSeparate(GL_FRONT_AND_BACK, mask); +} + +void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) +{ + EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); + + switch (face) { - return gl::error(GL_OUT_OF_MEMORY); + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilWritemask(mask); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackWritemask(mask); + } } } -void __stdcall glReleaseShaderCompiler(void) +void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) { - EVENT("()"); + glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass); +} + +void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", + face, fail, zfail, zpass); - try + switch (face) { - gl::Shader::releaseCompiler(); + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + return gl::error(GL_INVALID_ENUM); } - catch(std::bad_alloc&) + + switch (fail) { - return gl::error(GL_OUT_OF_MEMORY); + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + switch (zfail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + switch (zpass) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilOperations(fail, zfail, zpass); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackOperations(fail, zfail, zpass); + } } } -void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +GLboolean __stdcall glTestFenceNV(GLuint fence) { - EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, samples, internalformat, width, height); + EVENT("(GLuint fence = %d)", fence); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - switch (target) + gl::FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) { - case GL_RENDERBUFFER: - break; - default: - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION, GL_TRUE); } - if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat)) + if (fenceObject->isFence() != GL_TRUE) { - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION, GL_TRUE); } - if (width < 0 || height < 0 || samples < 0) + return fenceObject->testFence(); + } + + return GL_TRUE; +} + +void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " + "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, border, format, type, pixels); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, width, height, border, format, type, pixels)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, 1, border, format, type, pixels)) + { + return; + } - if (context) + switch (target) { - if (width > context->getMaximumRenderbufferDimension() || - height > context->getMaximumRenderbufferDimension() || - samples > context->getMaxSupportedSamples()) + case GL_TEXTURE_2D: { - return gl::error(GL_INVALID_VALUE); + gl::Texture2D *texture = context->getTexture2D(); + texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } - - GLuint handle = context->getRenderbufferHandle(); - if (handle == 0) + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: { - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } - - switch (internalformat) + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: { - case GL_DEPTH_COMPONENT16: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_RGB8_OES: - case GL_RGBA8_OES: - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: - case GL_BGRA8_EXT: - context->setRenderbufferStorage(width, height, internalformat, samples); - break; - default: - return gl::error(GL_INVALID_ENUM); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + default: UNREACHABLE(); } } - catch(std::bad_alloc&) +} + +void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param))) + { + return; + } + + gl::Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + return gl::error(GL_INVALID_ENUM); + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(gl::uiround<GLenum>(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = gl::uiround<GLenum>(param); break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = gl::iround<GLint>(param); break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = gl::iround<GLint>(param); break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break; + default: UNREACHABLE(); break; + } } } -void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) { - glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height); + glTexParameterf(target, pname, (GLfloat)*params); } -void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) +void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) { - EVENT("(GLclampf value = %f, GLboolean invert = %d)", value, invert); + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - gl::Context* context = gl::getNonLostContext(); + if (!ValidateTexParamParameters(context, pname, param)) + { + return; + } - if (context) + gl::Texture *texture = context->getTargetTexture(target); + + if (!texture) { - context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); + return gl::error(GL_INVALID_ENUM); + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break; + default: UNREACHABLE(); break; } } - catch(std::bad_alloc&) +} + +void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params) +{ + glTexParameteri(target, pname, *params); +} + +void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, levels, internalformat, width, height); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!context->getExtensions().textureStorage) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (context->getClientVersion() < 3 && + !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture2d = context->getTexture2D(); + texture2d->storage(levels, internalformat, width, height); + } + break; + + case GL_TEXTURE_CUBE_MAP: + { + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + textureCube->storage(levels, internalformat, width); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } } } -void __stdcall glSetFenceNV(GLuint fence, GLenum condition) +void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " + "const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, width, height, format, type, pixels); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (condition != GL_ALL_COMPLETED_NV) + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, width, height, 0, format, type, pixels)) { - return gl::error(GL_INVALID_ENUM); + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels)) + { + return; } - gl::Context *context = gl::getNonLostContext(); + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } - if (context) + switch (target) { - gl::Fence *fenceObject = context->getFence(fence); + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + } + break; - if (fenceObject == NULL) + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); } + break; - fenceObject->setFence(condition); + default: + UNREACHABLE(); } } - catch(std::bad_alloc&) +} + +void __stdcall glUniform1f(GLint location, GLfloat x) +{ + glUniform1fv(location, 1, &x); +} + +void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!ValidateUniform(context, GL_FLOAT, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1fv(location, count, v); } } -void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) +void __stdcall glUniform1i(GLint location, GLint x) { - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + glUniform1iv(location, 1, &x); +} - try +void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (width < 0 || height < 0) + if (!ValidateUniform(context, GL_INT, location, count)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context* context = gl::getNonLostContext(); + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1iv(location, count, v); + } +} - if (context) +void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y) +{ + GLfloat xy[2] = {x, y}; + + glUniform2fv(location, 1, xy); +} + +void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count)) { - context->setScissorParams(x, y, width, height); + return; } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2fv(location, count, v); } - catch(std::bad_alloc&) +} + +void __stdcall glUniform2i(GLint location, GLint x, GLint y) +{ + GLint xy[2] = {x, y}; + + glUniform2iv(location, 1, xy); +} + +void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!ValidateUniform(context, GL_INT_VEC2, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2iv(location, count, v); } } -void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) +void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) { - EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, " - "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", - n, shaders, binaryformat, binary, length); + GLfloat xyz[3] = {x, y, z}; + + glUniform3fv(location, 1, xyz); +} + +void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - // No binary shader formats are supported. - return gl::error(GL_INVALID_ENUM); + if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3fv(location, count, v); } - catch(std::bad_alloc&) +} + +void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z) +{ + GLint xyz[3] = {x, y, z}; + + glUniform3iv(location, 1, xyz); +} + +void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!ValidateUniform(context, GL_INT_VEC3, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3iv(location, count, v); } } -void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) +void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", - shader, count, string, length); + GLfloat xyzw[4] = {x, y, z, w}; + + glUniform4fv(location, 1, xyzw); +} - try +void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0) + if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4fv(location, count, v); + } +} - if (context) +void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ + GLint xyzw[4] = {x, y, z, w}; + + glUniform4iv(location, 1, xyzw); +} + +void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniform(context, GL_INT_VEC4, location, count)) { - gl::Shader *shaderObject = context->getShader(shader); + return; + } - if (!shaderObject) - { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4iv(location, count, v); + } +} - shaderObject->setSource(count, string, length); +void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) + { + return; } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2fv(location, count, transpose, value); } - catch(std::bad_alloc&) +} + +void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3fv(location, count, transpose, value); } } -void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask) +void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4fv(location, count, transpose, value); + } } -void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +void __stdcall glUseProgram(GLuint program) { - EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); + EVENT("(GLuint program = %d)", program); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - switch (face) + gl::Program *programObject = context->getProgram(program); + + if (!programObject && program != 0) { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - default: - return gl::error(GL_INVALID_ENUM); + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } } - switch (func) + if (program != 0 && !programObject->isLinked()) { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GEQUAL: - case GL_GREATER: - case GL_NOTEQUAL: - break; - default: - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + context->useProgram(program); + } +} + +void __stdcall glValidateProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + gl::Program *programObject = context->getProgram(program); + + if (!programObject) { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + if (context->getShader(program)) { - context->setStencilParams(func, ref, mask); + return gl::error(GL_INVALID_OPERATION); } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) + else { - context->setStencilBackParams(func, ref, mask); + return gl::error(GL_INVALID_VALUE); } } + + programObject->validate(); + } +} + +void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) +{ + EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); } - catch(std::bad_alloc&) + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + GLfloat vals[4] = { x, 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); } } -void __stdcall glStencilMask(GLuint mask) +void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) { - glStencilMaskSeparate(GL_FRONT_AND_BACK, mask); + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + GLfloat vals[4] = { values[0], 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } } -void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) +void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) { - EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); - try + if (index >= gl::MAX_VERTEX_ATTRIBS) { - switch (face) + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + GLfloat vals[4] = { x, y, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + GLfloat vals[4] = { values[0], values[1], 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + GLfloat vals[4] = { x, y, z, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + GLfloat vals[4] = { values[0], values[1], values[2], 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + GLfloat vals[4] = { x, y, z, w }; + context->getState().setVertexAttribf(index, vals); + } +} + +void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + context->getState().setVertexAttribf(index, values); + } +} + +void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) +{ + EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + context->setVertexAttribDivisor(index, divisor); + } +} + +void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +{ + EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " + "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", + index, size, type, normalized, stride, ptr); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + if (size < 1 || size > 4) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + switch (type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_FIXED: + case GL_FLOAT: + break; + case GL_HALF_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (context && context->getClientVersion() < 3) { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - default: return gl::error(GL_INVALID_ENUM); } + else + { + break; + } + default: + return gl::error(GL_INVALID_ENUM); + } - gl::Context *context = gl::getNonLostContext(); + if (stride < 0) + { + return gl::error(GL_INVALID_VALUE); + } - if (context) - { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->setStencilWritemask(mask); - } + if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) + { + return gl::error(GL_INVALID_OPERATION); + } - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->setStencilBackWritemask(mask); - } + if (context) + { + // [OpenGL ES 3.0.2] Section 2.8 page 24: + // An INVALID_OPERATION error is generated when a non-zero vertex array object + // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, + // and the pointer argument is not NULL. + if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL) + { + return gl::error(GL_INVALID_OPERATION); } + + context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, + normalized == GL_TRUE, false, stride, ptr); } - catch(std::bad_alloc&) +} + +void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + if (width < 0 || height < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setViewportParams(x, y, width, height); } } -void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) +// OpenGL ES 3.0 functions + +void __stdcall glReadBuffer(GLenum mode) { - glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass); + EVENT("(GLenum mode = 0x%X)", mode); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glReadBuffer + UNIMPLEMENTED(); + } } -void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) { - EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", - face, fail, zfail, zpass); + EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, " + "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - switch (face) + if (context->getClientVersion() < 3) { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: + return gl::error(GL_INVALID_OPERATION); + } + + // glDrawRangeElements + UNIMPLEMENTED(); + } +} + +void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, " + "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, format, type, pixels); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, depth, border, format, type, pixels)) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + } break; + default: return gl::error(GL_INVALID_ENUM); } + } +} + +void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); - switch (fail) + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, zoffset, width, height, depth, 0, + format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0 || depth == 0) { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + } break; + default: return gl::error(GL_INVALID_ENUM); } + } +} + +void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, level, xoffset, yoffset, zoffset, x, y, width, height); - switch (zfail) + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: + return gl::error(GL_INVALID_OPERATION); + } + + if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset, + x, y, width, height, 0)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + gl::Texture *texture = NULL; + switch (target) + { + case GL_TEXTURE_3D: + texture = context->getTexture3D(); break; + + case GL_TEXTURE_2D_ARRAY: + texture = context->getTexture2DArray(); + break; + default: return gl::error(GL_INVALID_ENUM); } - switch (zpass) + texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); + } +} + +void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, " + "const GLvoid* data = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, imageSize, data); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: + return gl::error(GL_INVALID_OPERATION); + } + + if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, width, height)) + { + return gl::error(GL_INVALID_VALUE); + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data)) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); + } break; + default: return gl::error(GL_INVALID_ENUM); } + } +} + +void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " + "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, width, height)) + { + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + if (!data) + { + return gl::error(GL_INVALID_VALUE); + } - if (context) + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data)) { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: { - context->setStencilOperations(fail, zfail, zpass); + gl::Texture3D *texture = context->getTexture3D(); + texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, data); } + break; - if (face == GL_BACK || face == GL_FRONT_AND_BACK) + case GL_TEXTURE_2D_ARRAY: { - context->setStencilBackOperations(fail, zfail, zpass); + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, data); } + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) +} + +void __stdcall glGenQueries(GLsizei n, GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (n < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + for (GLsizei i = 0; i < n; i++) + { + ids[i] = context->createQuery(); + } } } -GLboolean __stdcall glTestFenceNV(GLuint fence) +void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids) { - EVENT("(GLuint fence = %d)", fence); + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } - if (context) + if (n < 0) { - gl::Fence *fenceObject = context->getFence(fence); + return gl::error(GL_INVALID_VALUE); + } - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } + for (GLsizei i = 0; i < n; i++) + { + context->deleteQuery(ids[i]); + } + } +} - return fenceObject->testFence(); +GLboolean __stdcall glIsQuery(GLuint id) +{ + EVENT("(GLuint id = %u)", id); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_FALSE); } + + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; } - catch(std::bad_alloc&) + + return GL_FALSE; +} + +void __stdcall glBeginQuery(GLenum target, GLuint id) +{ + EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!ValidateBeginQuery(context, target, id)) + { + return; + } + context->beginQuery(target, id); } - - return GL_TRUE; } -void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid* pixels) +void __stdcall glEndQuery(GLenum target) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " - "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", - target, level, internalformat, width, height, border, format, type, pixels); + EVENT("(GLenum target = 0x%X)", target); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (!validImageSize(level, width, height)) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (internalformat != GLint(format)) + if (!ValidateEndQuery(context, target)) + { + return; + } + + context->endQuery(target); + } +} + +void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) { return gl::error(GL_INVALID_OPERATION); } - // validate <type> by itself (used as secondary key below) - switch (type) + if (!ValidQueryType(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } + + switch (pname) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_24_8_OES: - case GL_HALF_FLOAT_OES: - case GL_FLOAT: + case GL_CURRENT_QUERY: + params[0] = static_cast<GLint>(context->getState().getActiveQueryId(target)); break; + default: return gl::error(GL_INVALID_ENUM); } + } +} - // validate <format> + <type> combinations - // - invalid <format> -> sets INVALID_ENUM - // - invalid <format>+<type> combination -> sets INVALID_OPERATION - switch (format) +void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) +{ + EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - break; - default: - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - break; - case GL_DEPTH_COMPONENT: - switch (type) - { - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - break; - default: - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); + } + + gl::Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch(pname) + { + case GL_QUERY_RESULT: + params[0] = queryObject->getResult(); break; - case GL_DEPTH_STENCIL_OES: - switch (type) - { - case GL_UNSIGNED_INT_24_8_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION); - } + case GL_QUERY_RESULT_AVAILABLE: + params[0] = queryObject->isResultAvailable(); break; default: return gl::error(GL_INVALID_ENUM); } + } +} + +GLboolean __stdcall glUnmapBuffer(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + gl::Context *context = gl::getNonLostContext(); - if (border != 0) + if (context) + { + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION, GL_FALSE); } - gl::Context *context = gl::getNonLostContext(); + return glUnmapBufferOES(target); + } + + return GL_FALSE; +} + +void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); + + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (context->getClientVersion() < 3) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } - switch (target) - { - case GL_TEXTURE_2D: - if (width > (context->getMaximumTextureDimension() >> level) || - height > (context->getMaximumTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) - { - return gl::error(GL_INVALID_VALUE); - } + glGetBufferPointervOES(target, pname, params); + } +} - if (width > (context->getMaximumCubeTextureDimension() >> level) || - height > (context->getMaximumCubeTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } +void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs) +{ + gl::Context *context = gl::getNonLostContext(); - switch (format) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - if (!context->supportsDepthTextures()) - { - return gl::error(GL_INVALID_VALUE); - } - if (target != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION); - } - // OES_depth_texture supports loading depth data and multiple levels, - // but ANGLE_depth_texture does not - if (pixels != NULL || level != 0) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - default: - break; - } + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } - if (type == GL_FLOAT) - { - if (!context->supportsFloat32Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - } - else if (type == GL_HALF_FLOAT_OES) - { - if (!context->supportsFloat16Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - } + glDrawBuffersEXT(n, bufs); + } +} - if (target == GL_TEXTURE_2D) - { - gl::Texture2D *texture = context->getTexture2D(); +void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::Context *context = gl::getNonLostContext(); - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) + { + return; + } - texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels); - } - else - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2x3fv(location, count, transpose, value); + } +} - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } +void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::Context *context = gl::getNonLostContext(); - switch (target) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - texture->setImagePosX(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - texture->setImageNegX(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - texture->setImagePosY(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - texture->setImageNegY(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - texture->setImagePosZ(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - texture->setImageNegZ(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - default: UNREACHABLE(); - } - } + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) + { + return; } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3x2fv(location, count, transpose, value); } - catch(std::bad_alloc&) +} + +void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2x4fv(location, count, transpose, value); } } -void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) +void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) { - gl::Texture *texture; + return; + } - switch (target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4x2fv(location, count, transpose, value); + } +} - switch (pname) - { - case GL_TEXTURE_WRAP_S: - if (!texture->setWrapS((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_WRAP_T: - if (!texture->setWrapT((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MIN_FILTER: - if (!texture->setMinFilter((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAG_FILTER: - if (!texture->setMagFilter((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_USAGE_ANGLE: - if (!texture->setUsage((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy())) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } +void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) + { + return; } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3x4fv(location, count, transpose, value); } - catch(std::bad_alloc&) +} + +void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4x3fv(location, count, transpose, value); } } -void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) +void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - glTexParameterf(target, pname, (GLfloat)*params); + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, " + "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + gl::Context *context = gl::getNonLostContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + false)) + { + return; + } + + context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + mask, filter); + } } -void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) +void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); + EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, samples, internalformat, width, height); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } - if (context) + if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, + width, height, false)) { - gl::Texture *texture; + return; + } - switch (target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + context->setRenderbufferStorage(width, height, internalformat, samples); + } +} - switch (pname) +void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)", + target, attachment, texture, level, layer); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateFramebufferTextureLayer(context, target, attachment, texture, + level, layer)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + gl::Texture *textureObject = context->getTexture(texture); + GLenum textarget = textureObject ? textureObject->getTarget() : GL_NONE; + + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, layer); + } + else + { + switch (attachment) { - case GL_TEXTURE_WRAP_S: - if (!texture->setWrapS((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_WRAP_T: - if (!texture->setWrapT((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MIN_FILTER: - if (!texture->setMinFilter((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAG_FILTER: - if (!texture->setMagFilter((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_USAGE_ANGLE: - if (!texture->setUsage((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy())) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, layer); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, layer); break; + case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, layer); break; } } } - catch(std::bad_alloc&) +} + +GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", + target, offset, length, access); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL)); + } + + return glMapBufferRangeEXT(target, offset, length, access); } + + return NULL; } -void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params) +void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) { - glTexParameteri(target, pname, *params); + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + glFlushMappedBufferRangeEXT(target, offset, length); + } } -void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +void __stdcall glBindVertexArray(GLuint array) { - EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, levels, internalformat, width, height); + EVENT("(GLuint array = %u)", array); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION); } - if (width < 1 || height < 1 || levels < 1) + gl::VertexArray *vao = context->getVertexArray(array); + + if (!vao) { - return gl::error(GL_INVALID_VALUE); + // The default VAO should always exist + ASSERT(array != 0); + return gl::error(GL_INVALID_OPERATION); } - if (target == GL_TEXTURE_CUBE_MAP && width != height) + context->bindVertexArray(array); + } +} + +void __stdcall glDeleteVertexArrays(GLsizei n, const GLuint* arrays) +{ + EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (n < 0) { return gl::error(GL_INVALID_VALUE); } - if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + if (arrays[arrayIndex] != 0) + { + context->deleteVertexArray(arrays[arrayIndex]); + } + } + } +} + +void __stdcall glGenVertexArrays(GLsizei n, GLuint* arrays) +{ + EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) { return gl::error(GL_INVALID_OPERATION); } - GLenum format = gl::ExtractFormat(internalformat); - GLenum type = gl::ExtractType(internalformat); + if (n < 0) + { + return gl::error(GL_INVALID_VALUE); + } - if (format == GL_NONE || type == GL_NONE) + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) { - return gl::error(GL_INVALID_ENUM); + arrays[arrayIndex] = context->createVertexArray(); } + } +} + +GLboolean __stdcall glIsVertexArray(GLuint array) +{ + EVENT("(GLuint array = %u)", array); - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (context->getClientVersion() < 3) { - switch (target) - { - case GL_TEXTURE_2D: - if (width > context->getMaximumTextureDimension() || - height > context->getMaximumTextureDimension()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP: - if (width > context->getMaximumCubeTextureDimension() || - height > context->getMaximumCubeTextureDimension()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_OPERATION, GL_FALSE); + } - if (levels != 1 && !context->supportsNonPower2Texture()) - { - if (!gl::isPow2(width) || !gl::isPow2(height)) - { - return gl::error(GL_INVALID_OPERATION); - } - } + if (array == 0) + { + return GL_FALSE; + } - switch (internalformat) - { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - if (!context->supportsFloat32Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - if (!context->supportsFloat16Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - if (!context->supportsDepthTextures()) - { - return gl::error(GL_INVALID_ENUM); - } - if (target != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION); - } - // ANGLE_depth_texture only supports 1-level textures - if (levels != 1) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - default: - break; - } + gl::VertexArray *vao = context->getVertexArray(array); - if (target == GL_TEXTURE_2D) - { - gl::Texture2D *texture = context->getTexture2D(); + return (vao != NULL ? GL_TRUE : GL_FALSE); + } - if (!texture || texture->id() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + return GL_FALSE; +} - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } +void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", + target, index, data); - texture->storage(levels, internalformat, width, height); - } - else if (target == GL_TEXTURE_CUBE_MAP) + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index >= context->getMaxTransformFeedbackBufferBindings()) + return gl::error(GL_INVALID_VALUE); + break; + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_BINDING: + if (index >= context->getMaximumCombinedUniformBufferBindings()) + return gl::error(GL_INVALID_VALUE); + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + if (!(context->getIndexedIntegerv(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + return gl::error(GL_INVALID_ENUM); + + if (numParams == 0) + return; // it is known that pname is valid, but there are no parameters to return + + if (nativeType == GL_INT_64_ANGLEX) { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); + GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min()); + GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max()); + GLint64 *int64Params = new GLint64[numParams]; - if (!texture || texture->id() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + context->getIndexedInteger64v(target, index, int64Params); - if (texture->isImmutable()) + for (unsigned int i = 0; i < numParams; ++i) { - return gl::error(GL_INVALID_OPERATION); + GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue); + data[i] = static_cast<GLint>(clampedValue); } - texture->storage(levels, internalformat, width); + delete [] int64Params; + } + else + { + UNREACHABLE(); } - else UNREACHABLE(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid* pixels) +void __stdcall glBeginTransformFeedback(GLenum primitiveMode) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " - "const GLvoid* pixels = 0x%0.8p)", - target, level, xoffset, yoffset, width, height, format, type, pixels); + EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (!gl::IsInternalTextureTarget(target)) + if (context->getClientVersion() < 3) { + return gl::error(GL_INVALID_OPERATION); + } + + switch (primitiveMode) + { + case GL_TRIANGLES: + case GL_LINES: + case GL_POINTS: + break; + default: return gl::error(GL_INVALID_ENUM); } - if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (transformFeedback->isStarted()) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) + if (transformFeedback->isPaused()) { - return gl::error(GL_INVALID_VALUE); + transformFeedback->resume(); + } + else + { + transformFeedback->start(primitiveMode); + } + } +} + +void __stdcall glEndTransformFeedback(void) +{ + EVENT("(void)"); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); } - if (!checkTextureFormatType(format, type)) + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (!transformFeedback->isStarted()) { - return; // error is set by helper function + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + transformFeedback->stop(); + } +} + +void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)", + target, index, buffer, offset, size); - if (context) + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) { - if (level > context->getMaximumTextureLevel()) + return gl::error(GL_INVALID_OPERATION); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= context->getMaxTransformFeedbackBufferBindings()) { return gl::error(GL_INVALID_VALUE); } + break; - if (format == GL_FLOAT) + case GL_UNIFORM_BUFFER: + if (index >= context->getMaximumCombinedUniformBufferBindings()) { - if (!context->supportsFloat32Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - } - else if (format == GL_HALF_FLOAT_OES) - { - if (!context->supportsFloat16Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - } - else if (gl::IsDepthTexture(format)) - { - if (!context->supportsDepthTextures()) - { - return gl::error(GL_INVALID_ENUM); - } - if (target != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION); - } - // OES_depth_texture supports loading depth data, but ANGLE_depth_texture does not - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } + break; - if (width == 0 || height == 0 || pixels == NULL) + default: + return gl::error(GL_INVALID_ENUM); + } + + if (buffer != 0 && size <= 0) + { + return gl::error(GL_INVALID_VALUE); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + + // size and offset must be a multiple of 4 + if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) { - return; + return gl::error(GL_INVALID_VALUE); } - if (target == GL_TEXTURE_2D) + context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + + case GL_UNIFORM_BUFFER: + + // it is an error to bind an offset not a multiple of the alignment + if (buffer != 0 && (offset % context->getUniformBufferOffsetAlignment()) != 0) { - gl::Texture2D *texture = context->getTexture2D(); - if (validateSubImageParams2D(false, width, height, xoffset, yoffset, level, format, type, texture)) - { - texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); - } + return gl::error(GL_INVALID_VALUE); } - else if (gl::IsCubemapTextureTarget(target)) + + context->bindIndexedUniformBuffer(buffer, index, offset, size); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); + } + } +} + +void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", + target, index, buffer); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= context->getMaxTransformFeedbackBufferBindings()) { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - if (validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, format, type, texture)) - { - texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); - } + return gl::error(GL_INVALID_VALUE); } - else + break; + + case GL_UNIFORM_BUFFER: + if (index >= context->getMaximumCombinedUniformBufferBindings()) { - UNREACHABLE(); + return gl::error(GL_INVALID_VALUE); } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + + case GL_UNIFORM_BUFFER: + context->bindIndexedUniformBuffer(buffer, index, 0, 0); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } -void __stdcall glUniform1f(GLint location, GLfloat x) +void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) { - glUniform1fv(location, 1, &x); -} + EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)", + program, count, varyings, bufferMode); -void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) -{ - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (count < 0) { - return; + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (bufferMode) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) + case GL_INTERLEAVED_ATTRIBS: + break; + case GL_SEPARATE_ATTRIBS: + if (static_cast<GLuint>(count) > context->getMaxTransformFeedbackBufferBindings()) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } + break; + default: + return gl::error(GL_INVALID_ENUM); + } - if (!programBinary->setUniform1fv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!gl::ValidProgram(context, program)) + { + return; } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); } } -void __stdcall glUniform1i(GLint location, GLint x) +void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) { - glUniform1iv(location, 1, &x); -} + EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, " + "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", + program, index, bufSize, length, size, type, name); -void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) -{ - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (bufSize < 0) { return gl::error(GL_INVALID_VALUE); } - if (location == -1) + if (!gl::ValidProgram(context, program)) { return; } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); - if (context) + if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount())) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_VALUE); + } - if (!programBinary->setUniform1iv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); + } +} + +void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)", + index, size, type, stride, pointer); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) + + if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_OUT_OF_MEMORY); + return gl::error(GL_INVALID_VALUE); } -} -void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y) -{ - GLfloat xy[2] = {x, y}; + if (size < 1 || size > 4) + { + return gl::error(GL_INVALID_VALUE); + } + + switch (type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_2_10_10_10_REV: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + if (stride < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (context) + { + // [OpenGL ES 3.0.2] Section 2.8 page 24: + // An INVALID_OPERATION error is generated when a non-zero vertex array object + // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, + // and the pointer argument is not NULL. + if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL) + { + return gl::error(GL_INVALID_OPERATION); + } - glUniform2fv(location, 1, (GLfloat*)&xy); + context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true, + stride, pointer); + } } -void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) +void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + index, pname, params); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) { return gl::error(GL_INVALID_VALUE); } - - if (location == -1) + + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); + + if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (pname == GL_CURRENT_VERTEX_ATTRIB) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - return gl::error(GL_INVALID_OPERATION); + params[i] = currentValueData.IntValues[i]; } + } + else + { + *params = gl::QuerySingleVertexAttributeParameter<GLint>(attribState, pname); + } + } +} + +void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) +{ + EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", + index, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); + + if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + { + return; + } - if (!programBinary->setUniform2fv(location, count, v)) + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - return gl::error(GL_INVALID_OPERATION); + params[i] = currentValueData.UnsignedIntValues[i]; } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + *params = gl::QuerySingleVertexAttributeParameter<GLuint>(attribState, pname); + } } } -void __stdcall glUniform2i(GLint location, GLint x, GLint y) +void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) { - GLint xy[4] = {x, y}; + EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", + index, x, y, z, w); + + gl::Context *context = gl::getNonLostContext(); - glUniform2iv(location, 1, (GLint*)&xy); + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + GLint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribi(index, vals); + } } -void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) +void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", + index, x, y, z, w); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (index >= gl::MAX_VERTEX_ATTRIBS) { - return; + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + GLuint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribu(index, vals); + } +} - if (context) +void __stdcall glVertexAttribI4iv(GLuint index, const GLint* v) +{ + EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->setUniform2iv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); } + + context->getState().setVertexAttribi(index, v); } - catch(std::bad_alloc&) +} + +void __stdcall glVertexAttribI4uiv(GLuint index, const GLuint* v) +{ + EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + context->getState().setVertexAttribu(index, v); } } -void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params) { - GLfloat xyz[3] = {x, y, z}; + EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", + program, location, params); + + gl::Context *context = gl::getNonLostContext(); - glUniform3fv(location, 1, (GLfloat*)&xyz); + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (program == 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION); + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!programBinary->getUniformuiv(location, NULL, params)) + { + return gl::error(GL_INVALID_OPERATION); + } + } } -void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) +GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", + program, name); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION, -1); } - if (location == -1) + if (program == 0) { - return; + return gl::error(GL_INVALID_VALUE, -1); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject || !programObject->isLinked()) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION, -1); + } - if (!programBinary->setUniform3fv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION, -1); } + + return programBinary->getFragDataLocation(name); } - catch(std::bad_alloc&) + + return 0; +} + +void __stdcall glUniform1ui(GLint location, GLuint v0) +{ + glUniform1uiv(location, 1, &v0); +} + +void __stdcall glUniform2ui(GLint location, GLuint v0, GLuint v1) +{ + const GLuint xy[] = { v0, v1 }; + glUniform2uiv(location, 1, xy); +} + +void __stdcall glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) +{ + const GLuint xyz[] = { v0, v1, v2 }; + glUniform3uiv(location, 1, xyz); +} + +void __stdcall glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + const GLuint xyzw[] = { v0, v1, v2, v3 }; + glUniform4uiv(location, 1, xyzw); +} + +void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1uiv(location, count, value); } } -void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z) +void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value) { - GLint xyz[3] = {x, y, z}; + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + gl::Context *context = gl::getNonLostContext(); - glUniform3iv(location, 1, (GLint*)&xyz); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2uiv(location, count, value); + } } -void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) +void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", + location, count, value); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0) + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (location == -1) + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3uiv(location, count, value); + } +} + +void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) { return; } - gl::Context *context = gl::getNonLostContext(); + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4uiv(location, count, value); + } +} - if (context) +void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", + buffer, drawbuffer, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateClearBuffer(context)) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } - - if (!programBinary->setUniform3iv(location, count, v)) + break; + case GL_STENCIL: + if (drawbuffer != 0) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } + break; + default: + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->clearBufferiv(buffer, drawbuffer, value); } } -void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) { - GLfloat xyzw[4] = {x, y, z, w}; + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", + buffer, drawbuffer, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + return gl::error(GL_INVALID_VALUE); + } + break; + default: + return gl::error(GL_INVALID_ENUM); + } - glUniform4fv(location, 1, (GLfloat*)&xyzw); + context->clearBufferuiv(buffer, drawbuffer, value); + } } -void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) +void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", + buffer, drawbuffer, value); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0) + if (!ValidateClearBuffer(context)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (location == -1) + switch (buffer) { - return; + case GL_COLOR: + if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + return gl::error(GL_INVALID_VALUE); + } + break; + case GL_DEPTH: + if (drawbuffer != 0) + { + return gl::error(GL_INVALID_VALUE); + } + break; + default: + return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); + context->clearBufferfv(buffer, drawbuffer, value); + } +} + +void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)", + buffer, drawbuffer, depth, stencil); + + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!ValidateClearBuffer(context)) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + return; + } - if (!programBinary->setUniform4fv(location, count, v)) + switch (buffer) + { + case GL_DEPTH_STENCIL: + if (drawbuffer != 0) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } + break; + default: + return gl::error(GL_INVALID_ENUM); } + + context->clearBufferfi(buffer, drawbuffer, depth, stencil); } - catch(std::bad_alloc&) +} + +const GLubyte* __stdcall glGetStringi(GLenum name, GLuint index) +{ + EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLubyte*>(NULL)); + } + + if (name != GL_EXTENSIONS) + { + return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLubyte*>(NULL)); + } + + if (index >= context->getExtensionStringCount()) + { + return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLubyte*>(NULL)); + } + + return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str()); } + + return NULL; } -void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { - GLint xyzw[4] = {x, y, z, w}; + EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", + readTarget, writeTarget, readOffset, writeOffset, size); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget)) + { + return gl::error(GL_INVALID_ENUM); + } + + gl::Buffer *readBuffer = context->getState().getTargetBuffer(readTarget); + gl::Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget); + + if (!readBuffer || !writeBuffer) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (readBuffer->isMapped() || writeBuffer->isMapped()) + { + return gl::error(GL_INVALID_OPERATION); + } - glUniform4iv(location, 1, (GLint*)&xyzw); + if (readOffset < 0 || writeOffset < 0 || size < 0 || + static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() || + static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize()) + { + return gl::error(GL_INVALID_VALUE); + } + + if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size) + { + return gl::error(GL_INVALID_VALUE); + } + + // TODO: Verify that readBuffer and writeBuffer are not currently mapped (GL_INVALID_OPERATION) + + // if size is zero, the copy is a successful no-op + if (size > 0) + { + writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); + } + } } -void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) +void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)", + program, uniformCount, uniformNames, uniformIndices); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (uniformCount < 0) { - return; + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) + if (context->getShader(program)) { return gl::error(GL_INVALID_OPERATION); } + else + { + return gl::error(GL_INVALID_VALUE); + } + } - if (!programBinary->setUniform4iv(location, count, v)) + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) { - return gl::error(GL_INVALID_OPERATION); + uniformIndices[uniformId] = GL_INVALID_INDEX; + } + } + else + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } -void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); + EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + program, uniformCount, uniformIndices, pname, params); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0 || transpose != GL_FALSE) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (uniformCount < 0) { - return; + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) + if (context->getShader(program)) { return gl::error(GL_INVALID_OPERATION); } + else + { + return gl::error(GL_INVALID_VALUE); + } + } - if (!programBinary->setUniformMatrix2fv(location, count, value)) + switch (pname) + { + case GL_UNIFORM_TYPE: + case GL_UNIFORM_SIZE: + case GL_UNIFORM_NAME_LENGTH: + case GL_UNIFORM_BLOCK_INDEX: + case GL_UNIFORM_OFFSET: + case GL_UNIFORM_ARRAY_STRIDE: + case GL_UNIFORM_MATRIX_STRIDE: + case GL_UNIFORM_IS_ROW_MAJOR: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + if (!programBinary && uniformCount > 0) + { + return gl::error(GL_INVALID_VALUE); + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + + if (index >= (GLuint)programBinary->getActiveUniformCount()) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + params[uniformId] = programBinary->getActiveUniformi(index, pname); + } } - catch(std::bad_alloc&) +} + +GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) +{ + EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX); + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX); + } + else + { + return gl::error(GL_INVALID_VALUE, GL_INVALID_INDEX); + } + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return GL_INVALID_INDEX; + } + + return programBinary->getUniformBlockIndex(uniformBlockName); } + + return 0; } -void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + program, uniformBlockIndex, pname, params); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0 || transpose != GL_FALSE) + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) { return gl::error(GL_INVALID_VALUE); } - if (location == -1) + switch (pname) { - return; + case GL_UNIFORM_BLOCK_BINDING: + *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex)); + break; + + case GL_UNIFORM_BLOCK_DATA_SIZE: + case GL_UNIFORM_BLOCK_NAME_LENGTH: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params); + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)", + program, uniformBlockIndex, bufSize, length, uniformBlockName); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) + if (context->getShader(program)) { return gl::error(GL_INVALID_OPERATION); } - - if (!programBinary->setUniformMatrix3fv(location, count, value)) + else { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) + { + return gl::error(GL_INVALID_VALUE); + } + + programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); } } -void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)", + program, uniformBlockIndex, uniformBlockBinding); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0 || transpose != GL_FALSE) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (uniformBlockBinding >= context->getMaximumCombinedUniformBufferBindings()) { - return; + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) + if (context->getShader(program)) { return gl::error(GL_INVALID_OPERATION); } - - if (!programBinary->setUniformMatrix4fv(location, count, value)) + else { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + // if never linked, there won't be any uniform blocks + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) + { + return gl::error(GL_INVALID_VALUE); + } + + programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); } - catch(std::bad_alloc&) +} + +void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", + mode, first, count, instanceCount); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glDrawArraysInstanced + UNIMPLEMENTED(); } } -void __stdcall glUseProgram(GLuint program) +void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) { - EVENT("(GLuint program = %d)", program); + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)", + mode, count, type, indices, instanceCount); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glDrawElementsInstanced + UNIMPLEMENTED(); + } +} + +GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags) +{ + EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags); + + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (context->getClientVersion() < 3) { - gl::Program *programObject = context->getProgram(program); + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLsync>(0)); + } - if (!programObject && program != 0) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } + if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) + { + return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLsync>(0)); + } - if (program != 0 && !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (flags != 0) + { + return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLsync>(0)); + } - context->useProgram(program); + return context->createFenceSync(condition); + } + + return NULL; +} + +GLboolean __stdcall glIsSync(GLsync sync) +{ + EVENT("(GLsync sync = 0x%0.8p)", sync); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_FALSE); } + + return (context->getFenceSync(sync) != NULL); } - catch(std::bad_alloc&) + + return GL_FALSE; +} + +void __stdcall glDeleteSync(GLsync sync) +{ + EVENT("(GLsync sync = 0x%0.8p)", sync); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync)) + { + return gl::error(GL_INVALID_VALUE); + } + + context->deleteFenceSync(sync); } } -void __stdcall glValidateProgram(GLuint program) +GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { - EVENT("(GLuint program = %d)", program); + EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", + sync, flags, timeout); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_WAIT_FAILED); + } - if (context) + if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) { - gl::Program *programObject = context->getProgram(program); + return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED); + } - if (!programObject) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } + gl::FenceSync *fenceSync = context->getFenceSync(sync); - programObject->validate(); + if (!fenceSync) + { + return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED); } + + return fenceSync->clientWait(flags, timeout); } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } + + return GL_FALSE; } -void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) +void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { - EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); + EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", + sync, flags, timeout); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (flags != 0) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + if (timeout != GL_TIMEOUT_IGNORED) + { + return gl::error(GL_INVALID_VALUE); + } - if (context) + gl::FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) { - GLfloat vals[4] = { x, 0, 0, 1 }; - context->setVertexAttrib(index, vals); + return gl::error(GL_INVALID_VALUE); } + + fenceSync->serverWait(); } - catch(std::bad_alloc&) +} + +void __stdcall glGetInteger64v(GLenum pname, GLint64* params) +{ + EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", + pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_INT_64_ANGLEX) + { + context->getInteger64v(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } } } -void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) +void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)", + sync, pname, bufSize, length, values); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (bufSize < 0) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + gl::FenceSync *fenceSync = context->getFenceSync(sync); - if (context) + if (!fenceSync) { - GLfloat vals[4] = { values[0], 0, 0, 1 }; - context->setVertexAttrib(index, vals); + return gl::error(GL_INVALID_VALUE); + } + + switch (pname) + { + case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break; + case GL_SYNC_STATUS: values[0] = static_cast<GLint>(fenceSync->getStatus()); break; + case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break; + case GL_SYNC_FLAGS: values[0] = 0; break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) +} + +void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", + target, index, data); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index >= context->getMaxTransformFeedbackBufferBindings()) + return gl::error(GL_INVALID_VALUE); + break; + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_BINDING: + if (index >= context->getMaximumCombinedUniformBufferBindings()) + return gl::error(GL_INVALID_VALUE); + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + if (!(context->getIndexedInteger64v(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + return gl::error(GL_INVALID_ENUM); + + if (numParams == 0) + return; // it is known that pname is valid, but there are no parameters to return + + if (nativeType == GL_INT) + { + GLint *intParams = new GLint[numParams]; + + context->getIndexedIntegerv(target, index, intParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + data[i] = static_cast<GLint64>(intParams[i]); + } + + delete [] intParams; + } + else + { + UNREACHABLE(); + } + } } } -void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) +void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", + target, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } - if (context) + if (!gl::ValidBufferParameter(context, pname)) { - GLfloat vals[4] = { x, y, 0, 1 }; - context->setVertexAttrib(index, vals); + return gl::error(GL_INVALID_ENUM); + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + return gl::error(GL_INVALID_OPERATION); + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast<GLint64>(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = buffer->getSize(); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = static_cast<GLint64>(buffer->getAccessFlags()); + break; + case GL_BUFFER_MAPPED: + *params = static_cast<GLint64>(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = buffer->getMapOffset(); + break; + case GL_BUFFER_MAP_LENGTH: + *params = buffer->getMapLength(); + break; + default: UNREACHABLE(); break; } } - catch(std::bad_alloc&) +} + +void __stdcall glGenSamplers(GLsizei count, GLuint* samplers) +{ + EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (count < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + for (int i = 0; i < count; i++) + { + samplers[i] = context->createSampler(); + } } } -void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) +void __stdcall glDeleteSamplers(GLsizei count, const GLuint* samplers) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + if (count < 0) + { + return gl::error(GL_INVALID_VALUE); + } - if (context) + for (int i = 0; i < count; i++) { - GLfloat vals[4] = { values[0], values[1], 0, 1 }; - context->setVertexAttrib(index, vals); + context->deleteSampler(samplers[i]); } } - catch(std::bad_alloc&) +} + +GLboolean __stdcall glIsSampler(GLuint sampler) +{ + EVENT("(GLuint sampler = %u)", sampler); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_FALSE); + } + + return context->isSampler(sampler); } + + return GL_FALSE; } -void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) +void __stdcall glBindSampler(GLuint unit, GLuint sampler) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); + EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + if (sampler != 0 && !context->isSampler(sampler)) + { + return gl::error(GL_INVALID_OPERATION); + } - if (context) + if (unit >= context->getMaximumCombinedTextureImageUnits()) { - GLfloat vals[4] = { x, y, z, 1 }; - context->setVertexAttrib(index, vals); + return gl::error(GL_INVALID_VALUE); } + + context->bindSampler(unit, sampler); } - catch(std::bad_alloc&) +} + +void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!gl::ValidateSamplerObjectParameter(pname)) + { + return; + } + + if (!gl::ValidateTexParamParameters(context, pname, param)) + { + return; + } + + if (!context->isSampler(sampler)) + { + return gl::error(GL_INVALID_OPERATION); + } + + context->samplerParameteri(sampler, pname, param); } } -void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) +void __stdcall glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + glSamplerParameteri(sampler, pname, *param); +} + +void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + if (!gl::ValidateSamplerObjectParameter(pname)) + { + return; + } - if (context) + if (!gl::ValidateTexParamParameters(context, pname, static_cast<GLint>(param))) { - GLfloat vals[4] = { values[0], values[1], values[2], 1 }; - context->setVertexAttrib(index, vals); + return; } + + if (!context->isSampler(sampler)) + { + return gl::error(GL_INVALID_OPERATION); + } + + context->samplerParameterf(sampler, pname, param); } - catch(std::bad_alloc&) +} + +void __stdcall glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) +{ + glSamplerParameterf(sampler, pname, *param); +} + +void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!gl::ValidateSamplerObjectParameter(pname)) + { + return; + } + + if (!context->isSampler(sampler)) + { + return gl::error(GL_INVALID_OPERATION); + } + + *params = context->getSamplerParameteri(sampler, pname); } } -void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); + EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + if (!gl::ValidateSamplerObjectParameter(pname)) + { + return; + } - if (context) + if (!context->isSampler(sampler)) { - GLfloat vals[4] = { x, y, z, w }; - context->setVertexAttrib(index, vals); + return gl::error(GL_INVALID_OPERATION); } + + *params = context->getSamplerParameterf(sampler, pname); } - catch(std::bad_alloc&) +} + +void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor) +{ + EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor); + + if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_OUT_OF_MEMORY); + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + context->setVertexAttribDivisor(index, divisor); } } -void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) +void __stdcall glBindTransformFeedback(GLenum target, GLuint id) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (target) { - context->setVertexAttrib(index, values); + case GL_TRANSFORM_FEEDBACK: + { + // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1) + gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + return gl::error(GL_INVALID_OPERATION); + } + + // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1) + if (context->getTransformFeedback(id) == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + context->bindTransformFeedback(id); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) +} + +void __stdcall glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) +{ + EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + for (int i = 0; i < n; i++) + { + context->deleteTransformFeedback(ids[i]); + } } } -void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) +void __stdcall glGenTransformFeedbacks(GLsizei n, GLuint* ids) { - EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (int i = 0; i < n; i++) { - context->setVertexAttribDivisor(index, divisor); + ids[i] = context->createTransformFeedback(); } } - catch(std::bad_alloc&) +} + +GLboolean __stdcall glIsTransformFeedback(GLuint id) +{ + EVENT("(GLuint id = %u)", id); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_FALSE); + } + + return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); } + + return GL_FALSE; } -void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +void __stdcall glPauseTransformFeedback(void) { - EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " - "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", - index, size, type, normalized, stride, ptr); + EVENT("(void)"); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (size < 1 || size > 4) + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) + if (!transformFeedback->isStarted() || transformFeedback->isPaused()) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - switch (type) + transformFeedback->pause(); + } +} + +void __stdcall glResumeTransformFeedback(void) +{ + EVENT("(void)"); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_FIXED: - case GL_FLOAT: - break; - default: - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION); } - if (stride < 0) + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) + if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + transformFeedback->resume(); + } +} + +void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) +{ + EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)", + program, bufSize, length, binaryFormat, binary); + + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (context->getClientVersion() < 3) { - context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr); + return gl::error(GL_INVALID_OPERATION); } + + // glGetProgramBinary + UNIMPLEMENTED(); } - catch(std::bad_alloc&) +} + +void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) +{ + EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", + program, binaryFormat, binary, length); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glProgramBinary + UNIMPLEMENTED(); } } -void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) +void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value) { - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", + program, pname, value); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (width < 0 || height < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + // glProgramParameteri + UNIMPLEMENTED(); + } +} + +void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) +{ + EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)", + target, numAttachments, attachments); + + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (context->getClientVersion() < 3) { - context->setViewportParams(x, y, width, height); + return gl::error(GL_INVALID_OPERATION); } + + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) + { + return; + } + + GLuint maxDimension = context->getCaps().maxRenderbufferSize; + context->invalidateFrameBuffer(target, numAttachments, attachments, 0, 0, maxDimension, maxDimension); } - catch(std::bad_alloc&) +} + +void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, " + "GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, numAttachments, attachments, x, y, width, height); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) + { + return; + } + + context->invalidateFrameBuffer(target, numAttachments, attachments, x, y, width, height); } } -void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) +void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " - "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " - "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", - srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, levels, internalformat, width, height); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - switch (filter) + if (context->getClientVersion() < 3) { - case GL_NEAREST: + return gl::error(GL_INVALID_OPERATION); + } + + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture2d = context->getTexture2D(); + texture2d->storage(levels, internalformat, width, height); + } break; + + case GL_TEXTURE_CUBE_MAP: + { + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + textureCube->storage(levels, internalformat, width); + } + break; + default: return gl::error(GL_INVALID_ENUM); } + } +} - if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) - { - return gl::error(GL_INVALID_VALUE); - } +void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d)", + target, levels, internalformat, width, height, depth); + + gl::Context *context = gl::getNonLostContext(); - if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0) + if (context) + { + if (context->getClientVersion() < 3) { - ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation"); return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) + { + return; + } - if (context) + switch (target) { - if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle()) + case GL_TEXTURE_3D: { - ERR("Blits with the same source and destination framebuffer are not supported by this implementation."); - return gl::error(GL_INVALID_OPERATION); + gl::Texture3D *texture3d = context->getTexture3D(); + texture3d->storage(levels, internalformat, width, height, depth); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture2darray = context->getTexture2DArray(); + texture2darray->storage(levels, internalformat, width, height, depth); } + break; - context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask); + default: + UNREACHABLE(); } } - catch(std::bad_alloc&) +} + +void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, " + "GLint* params = 0x%0.8p)", + target, internalformat, pname, bufSize, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) + { + return gl::error(GL_INVALID_ENUM); + } + + if (target != GL_RENDERBUFFER) + { + return gl::error(GL_INVALID_ENUM); + } + + if (bufSize < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + switch (pname) + { + case GL_NUM_SAMPLE_COUNTS: + if (bufSize != 0) + *params = context->getNumSampleCounts(internalformat); + break; + case GL_SAMPLES: + context->getSampleCounts(internalformat, bufSize, params); + break; + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +// Extension functions + +void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " + "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " + "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + true)) + { + return; + } + + context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + mask, filter); } } @@ -6878,53 +7949,39 @@ void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", target, level, internalformat, width, height, depth, border, format, type, pixels); - try - { - UNIMPLEMENTED(); // FIXME - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } + UNIMPLEMENTED(); // FIXME } -void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, +void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) { EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", program, bufSize, length, binaryFormat, binary); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject || !programObject->isLinked()) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary->save(binary, bufSize, length)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } - *binaryFormat = GL_PROGRAM_BINARY_ANGLE; + if (!programBinary->save(binary, bufSize, length)) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + *binaryFormat = GL_PROGRAM_BINARY_ANGLE; } } @@ -6934,30 +7991,23 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", program, binaryFormat, binary, length); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) { - if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); + } - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->setProgramBinary(program, binary, length); + if (!programObject) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->setProgramBinary(program, binary, length); } } @@ -6965,57 +8015,271 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) { EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers) + { + return gl::error(GL_INVALID_VALUE); + } - if (context) + if (context->getState().getDrawFramebuffer()->id() == 0) { - if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets()) + if (n != 1) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (context->getDrawFramebufferHandle() == 0) + if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) { - if (n != 1) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); } - else + } + else + { + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) { - for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; + if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) { - const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; - if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); } } + } - gl::Framebuffer *framebuffer = context->getDrawFramebuffer(); + gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); - for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) - { - framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); - } + for (unsigned int colorAttachment = 0; colorAttachment < static_cast<unsigned int>(n); colorAttachment++) + { + framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); + } - for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++) - { - framebuffer->setDrawBufferState(colorAttachment, GL_NONE); - } + for (unsigned int colorAttachment = n; colorAttachment < context->getCaps().maxDrawBuffers; colorAttachment++) + { + framebuffer->setDrawBufferState(colorAttachment, GL_NONE); } } - catch (std::bad_alloc&) +} + +void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } + + if (pname != GL_BUFFER_MAP_POINTER) + { + return gl::error(GL_INVALID_ENUM); + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer || !buffer->isMapped()) + { + *params = NULL; + } + else + { + *params = buffer->getMapPointer(); + } + } +} + +void * __stdcall glMapBufferOES(GLenum target, GLenum access) +{ + EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLvoid*>(NULL)); + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL)); + } + + if (access != GL_WRITE_ONLY_OES) + { + return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLvoid*>(NULL)); + } + + if (buffer->isMapped()) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL)); + } + + return buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT); + } + + return NULL; +} + +GLboolean __stdcall glUnmapBufferOES(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM, GL_FALSE); + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL || !buffer->isMapped()) + { + return gl::error(GL_INVALID_OPERATION, GL_FALSE); + } + + // TODO: detect if we had corruption. if so, throw an error and return false. + + buffer->unmap(); + + return GL_TRUE; + } + + return GL_FALSE; +} + +void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", + target, offset, length, access); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLvoid*>(NULL)); + } + + if (offset < 0 || length < 0) + { + return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLvoid*>(NULL)); + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL)); + } + + // Check for buffer overflow + size_t offsetSize = static_cast<size_t>(offset); + size_t lengthSize = static_cast<size_t>(length); + + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast<size_t>(buffer->getSize())) + { + return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLvoid*>(NULL)); + } + + // Check for invalid bits in the mask + GLbitfield allAccessBits = GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if (access & ~(allAccessBits)) + { + return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLvoid*>(NULL)); + } + + if (length == 0 || buffer->isMapped()) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL)); + } + + // Check for invalid bit combinations + if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL)); + } + + GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL)); + } + + if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL)); + } + + return buffer->mapRange(offset, length, access); + } + + return NULL; +} + +void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (offset < 0 || length < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } + + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) + { + return gl::error(GL_INVALID_OPERATION); + } + + // Check for buffer overflow + size_t offsetSize = static_cast<size_t>(offset); + size_t lengthSize = static_cast<size_t>(length); + + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength())) + { + return gl::error(GL_INVALID_VALUE); + } + + // We do not currently support a non-trivial implementation of FlushMappedBufferRange } } @@ -7057,7 +8321,12 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char * {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE}, {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE}, {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES}, - {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES}, }; + {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES}, + {"glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)glGetBufferPointervOES}, + {"glMapBufferOES", (__eglMustCastToProperFunctionPointerType)glMapBufferOES}, + {"glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)glUnmapBufferOES}, + {"glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glMapBufferRangeEXT}, + {"glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glFlushMappedBufferRangeEXT}, }; for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++) { @@ -7077,28 +8346,19 @@ bool __stdcall glBindTexImage(egl::Surface *surface) EVENT("(egl::Surface* surface = 0x%0.8p)", surface); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture2D *textureObject = context->getTexture2D(); + ASSERT(textureObject != NULL); - if (context) + if (textureObject->isImmutable()) { - gl::Texture2D *textureObject = context->getTexture2D(); - - if (textureObject->isImmutable()) - { - return false; - } - - if (textureObject) - { - textureObject->bindTexImage(surface); - } + return false; } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, false); + + textureObject->bindTexImage(surface); } return true; |