diff options
Diffstat (limited to 'gfx/angle/src/libGLESv2/entry_points_gles_2_0.cpp')
-rwxr-xr-x | gfx/angle/src/libGLESv2/entry_points_gles_2_0.cpp | 1338 |
1 files changed, 1209 insertions, 129 deletions
diff --git a/gfx/angle/src/libGLESv2/entry_points_gles_2_0.cpp b/gfx/angle/src/libGLESv2/entry_points_gles_2_0.cpp index ca6129800..c3e9ad875 100755 --- a/gfx/angle/src/libGLESv2/entry_points_gles_2_0.cpp +++ b/gfx/angle/src/libGLESv2/entry_points_gles_2_0.cpp @@ -28,7 +28,6 @@ #include "libANGLE/validationES2.h" #include "libANGLE/validationES3.h" #include "libANGLE/queryconversions.h" -#include "libANGLE/queryutils.h" #include "common/debug.h" #include "common/utilities.h" @@ -44,8 +43,9 @@ void GL_APIENTRY ActiveTexture(GLenum texture) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateActiveTexture(context, texture)) + if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1) { + context->handleError(Error(GL_INVALID_ENUM)); return; } @@ -60,12 +60,23 @@ void GL_APIENTRY AttachShader(GLuint program, GLuint shader) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateAttachShader(context, program, shader)) + Program *programObject = GetValidProgram(context, program); + if (!programObject) { return; } - context->attachShader(program, shader); + Shader *shaderObject = GetValidShader(context, shader); + if (!shaderObject) + { + return; + } + + if (!programObject->attachShader(shaderObject)) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } } } @@ -76,13 +87,26 @@ void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateBindAttribLocation(context, program, index, name)) + if (index >= MAX_VERTEX_ATTRIBS) { + context->handleError(Error(GL_INVALID_VALUE)); return; } - context->bindAttribLocation(program, index, name); + Program *programObject = GetValidProgram(context, program); + + if (!programObject) + { + return; + } + + if (strncmp(name, "gl_", 3) == 0) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + + programObject->bindAttributeLocation(index, name); } } @@ -93,12 +117,43 @@ void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateBindBuffer(context, target, buffer)) + if (!ValidBufferTarget(context, target)) { + context->handleError(Error(GL_INVALID_ENUM)); return; } - context->bindBuffer(target, buffer); + switch (target) + { + 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: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } } } @@ -109,12 +164,21 @@ void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateBindFramebuffer(context, target, framebuffer)) + if (!ValidFramebufferTarget(target)) { + context->handleError(Error(GL_INVALID_ENUM)); return; } - context->bindFramebuffer(target, 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); + } } } @@ -125,12 +189,13 @@ void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateBindRenderbuffer(context, target, renderbuffer)) + if (target != GL_RENDERBUFFER) { + context->handleError(Error(GL_INVALID_ENUM)); return; } - context->bindRenderbuffer(target, renderbuffer); + context->bindRenderbuffer(renderbuffer); } } @@ -141,7 +206,7 @@ void GL_APIENTRY BindTexture(GLenum target, GLuint texture) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateBindTexture(context, target, texture)) + if (!ValidateBindTexture(context, target, texture)) { return; } @@ -164,18 +229,7 @@ void GL_APIENTRY BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp void GL_APIENTRY BlendEquation(GLenum mode) { - EVENT("(GLenum mode = 0x%X)", mode); - - Context *context = GetValidGlobalContext(); - if (context) - { - if (!context->skipValidation() && !ValidateBlendEquation(context, mode)) - { - return; - } - - context->blendEquation(mode); - } + BlendEquationSeparate(mode, mode); } void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) @@ -185,9 +239,31 @@ void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateBlendEquationSeparate(context, modeRGB, modeAlpha)) + switch (modeRGB) { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; + + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + switch (modeAlpha) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; + + default: + context->handleError(Error(GL_INVALID_ENUM)); return; } @@ -197,18 +273,7 @@ void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor) { - EVENT("(GLenum sfactor = 0x%X, GLenum dfactor = 0x%X)", sfactor, dfactor); - - Context *context = GetValidGlobalContext(); - if (context) - { - if (!context->skipValidation() && !ValidateBlendFunc(context, sfactor, dfactor)) - { - return; - } - - context->blendFunc(sfactor, dfactor); - } + BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); } void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) @@ -219,10 +284,135 @@ void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateBlendFuncSeparate(context, srcRGB, dstRGB, srcAlpha, dstAlpha)) + switch (srcRGB) { - return; + 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: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + 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->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + 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: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + 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; + + case GL_SRC_ALPHA_SATURATE: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc) + { + 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); + + if (constantColorUsed && constantAlphaUsed) + { + ERR( + "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and " + "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this " + "implementation."); + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } } context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); @@ -237,12 +427,57 @@ void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateBufferData(context, target, size, data, usage)) + if (size < 0) + { + context->handleError(Error(GL_INVALID_VALUE)); + return; + } + + 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->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidBufferTarget(context, target)) { + context->handleError(Error(GL_INVALID_ENUM)); return; } - context->bufferData(target, size, data, usage); + Buffer *buffer = context->getGLState().getTargetBuffer(target); + + if (!buffer) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = buffer->bufferData(data, size, usage); + if (error.isError()) + { + context->handleError(error); + return; + } } } @@ -254,13 +489,58 @@ void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateBufferSubData(context, target, offset, size, data)) + if (size < 0 || offset < 0) + { + context->handleError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getGLState().getTargetBuffer(target); + + if (!buffer) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + + if (buffer->isMapped()) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + + // Check for possible overflow of size + offset + angle::CheckedNumeric<size_t> checkedSize(size); + checkedSize += offset; + if (!checkedSize.IsValid()) + { + context->handleError(Error(GL_OUT_OF_MEMORY)); + return; + } + + if (size + offset > buffer->getSize()) + { + context->handleError(Error(GL_INVALID_VALUE)); + return; + } + + if (data == NULL) { return; } - context->bufferSubData(target, offset, size, data); + Error error = buffer->bufferSubData(data, size, offset); + if (error.isError()) + { + context->handleError(error); + return; + } } } @@ -360,7 +640,7 @@ void GL_APIENTRY CompileShader(GLuint shader) { return; } - shaderObject->compile(context); + shaderObject->compile(context->getCompiler()); } } @@ -727,8 +1007,9 @@ void GL_APIENTRY Disable(GLenum cap) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateDisable(context, cap)) + if (!ValidCap(context, cap)) { + context->handleError(Error(GL_INVALID_ENUM)); return; } @@ -760,7 +1041,7 @@ void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count) Context *context = GetValidGlobalContext(); if (context) { - if (!ValidateDrawArrays(context, mode, first, count, 1)) + if (!ValidateDrawArrays(context, mode, first, count, 0)) { return; } @@ -783,7 +1064,7 @@ void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLv if (context) { IndexRange indexRange; - if (!ValidateDrawElements(context, mode, count, type, indices, 1, &indexRange)) + if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) { return; } @@ -804,11 +1085,26 @@ void GL_APIENTRY Enable(GLenum cap) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateEnable(context, cap)) + if (!ValidCap(context, cap)) { + context->handleError(Error(GL_INVALID_ENUM)); return; } + if (context->getLimitations().noSampleAlphaToCoverageSupport) + { + if (cap == GL_SAMPLE_ALPHA_TO_COVERAGE) + { + const char *errorMessage = "Current renderer doesn't support alpha-to-coverage"; + context->handleError(Error(GL_INVALID_OPERATION, errorMessage)); + + // We also output an error message to the debugger window if tracing is active, so that developers can see the error message. + ERR("%s", errorMessage); + + return; + } + } + context->enable(cap); } } @@ -1160,14 +1456,53 @@ void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateGetBufferParameteriv(context, target, pname, params)) + if (!ValidBufferTarget(context, target)) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidBufferParameter(context, pname)) { + context->handleError(Error(GL_INVALID_ENUM)); return; } Buffer *buffer = context->getGLState().getTargetBuffer(target); - QueryBufferParameteriv(buffer, pname, params); + + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast<GLint>(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = clampCast<GLint>(buffer->getSize()); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = buffer->getAccessFlags(); + break; + case GL_BUFFER_ACCESS_OES: + *params = buffer->getAccess(); + break; + case GL_BUFFER_MAPPED: + static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal."); + *params = static_cast<GLint>(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = clampCast<GLint>(buffer->getMapOffset()); + break; + case GL_BUFFER_MAP_LENGTH: + *params = clampCast<GLint>(buffer->getMapLength()); + break; + default: UNREACHABLE(); break; + } } } @@ -1218,16 +1553,259 @@ void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attac Context *context = GetValidGlobalContext(); if (context) { - GLsizei numParams = 0; - if (!context->skipValidation() && - !ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, - &numParams)) + if (!ValidFramebufferTarget(target)) { + context->handleError(Error(GL_INVALID_ENUM)); return; } + int clientVersion = context->getClientMajorVersion(); + + switch (pname) + { + 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) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + 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) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + // 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) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + break; + + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + default: + if (attachment < GL_COLOR_ATTACHMENT0_EXT || + (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + break; + } + const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target); - QueryFramebufferAttachmentParameteriv(framebuffer, attachment, pname, params); + ASSERT(framebuffer); + + if (framebuffer->id() == 0) + { + if (clientVersion < 3) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (attachment) + { + case GL_BACK: + case GL_DEPTH: + case GL_STENCIL: + break; + + default: + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + } + else + { + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + // Valid attachment query + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + case GL_DEPTH_STENCIL_ATTACHMENT: + if (!framebuffer->hasValidDepthStencil()) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + break; + + default: + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + } + } + + const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment); + if (attachmentObject) + { + ASSERT(attachmentObject->type() == GL_RENDERBUFFER || + attachmentObject->type() == GL_TEXTURE || + attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = attachmentObject->type(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (attachmentObject->type() != GL_RENDERBUFFER && attachmentObject->type() != GL_TEXTURE) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->id(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + if (attachmentObject->type() != GL_TEXTURE) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->mipLevel(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + if (attachmentObject->type() != GL_TEXTURE) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->cubeMapFace(); + break; + + 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_ATTACHMENT) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + *params = attachmentObject->getComponentType(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + *params = attachmentObject->getColorEncoding(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (attachmentObject->type() != GL_TEXTURE) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->layer(); + break; + + default: + UNREACHABLE(); + break; + } + } + else + { + // 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 = GL_NONE; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (clientVersion < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = 0; + break; + + default: + if (clientVersion < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + else + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + } + } } } @@ -1264,15 +1842,83 @@ void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params) Context *context = GetValidGlobalContext(); if (context) { - GLsizei numParams = 0; - if (!context->skipValidation() && - !ValidateGetProgramiv(context, program, pname, &numParams)) + Program *programObject = GetValidProgram(context, program); + + if (!programObject) { return; } - Program *programObject = context->getProgram(program); - QueryProgramiv(programObject, pname, params); + if (context->getClientMajorVersion() < 3) + { + switch (pname) + { + 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: + case GL_PROGRAM_BINARY_RETRIEVABLE_HINT: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + } + + 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->getBinaryLength(); + 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; + case GL_PROGRAM_BINARY_RETRIEVABLE_HINT: + *params = programObject->getBinaryRetrievableHint(); + break; + + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } } } @@ -1307,14 +1953,64 @@ void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateGetRenderbufferParameteriv(context, target, pname, params)) + if (target != GL_RENDERBUFFER) { + context->handleError(Error(GL_INVALID_ENUM)); return; } - Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer(); - QueryRenderbufferiv(renderbuffer, pname, params); + if (context->getGLState().getRenderbufferId() == 0) + { + context->handleError(Error(GL_INVALID_OPERATION)); + return; + } + + Renderbuffer *renderbuffer = + context->getRenderbuffer(context->getGLState().getRenderbufferId()); + + 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->getFormat().info->internalFormat; + 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) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = renderbuffer->getSamples(); + break; + + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } } } @@ -1325,13 +2021,37 @@ void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateGetShaderiv(context, shader, pname, params)) + Shader *shaderObject = GetValidShader(context, shader); + if (!shaderObject) { return; } - Shader *shaderObject = context->getShader(shader); - QueryShaderiv(shaderObject, pname, params); + 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->getTranslatedSourceWithDebugInfoLength(); + return; + + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } } } @@ -1471,7 +2191,7 @@ const GLubyte *GL_APIENTRY GetString(GLenum name) return reinterpret_cast<const GLubyte *>("Google Inc."); case GL_RENDERER: - return reinterpret_cast<const GLubyte *>(context->getRendererString()); + return reinterpret_cast<const GLubyte *>(context->getRendererString().c_str()); case GL_VERSION: if (context->getClientMajorVersion() == 2) @@ -1498,7 +2218,7 @@ const GLubyte *GL_APIENTRY GetString(GLenum name) } case GL_EXTENSIONS: - return reinterpret_cast<const GLubyte *>(context->getExtensionString()); + return reinterpret_cast<const GLubyte *>(context->getExtensionString().c_str()); default: context->handleError(Error(GL_INVALID_ENUM)); @@ -1516,14 +2236,153 @@ void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateGetTexParameterfv(context, target, pname, params)) + if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) { + context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target")); return; } Texture *texture = context->getTargetTexture(target); - QueryTexParameterfv(texture, pname, params); + + if (!texture) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + 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_WRAP_R: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getWrapR(); + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = (GLfloat)(texture->getImmutableFormat() ? GL_TRUE : GL_FALSE); + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getImmutableLevels(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = (GLfloat)texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getMaxAnisotropy(); + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSwizzleRed(); + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSwizzleGreen(); + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSwizzleBlue(); + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSwizzleAlpha(); + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getBaseLevel(); + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getMaxLevel(); + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().maxLod; + break; + case GL_TEXTURE_COMPARE_MODE: + if (context->getClientMajorVersion() < 3) + { + context->handleError( + Error(GL_INVALID_ENUM, + "GL_TEXTURE_COMPARE_MODE not available in ES versions < 3.0")); + return; + } + *params = static_cast<GLfloat>(texture->getCompareMode()); + break; + case GL_TEXTURE_COMPARE_FUNC: + if (context->getClientMajorVersion() < 3) + { + context->handleError( + Error(GL_INVALID_ENUM, + "GL_TEXTURE_COMPARE_FUNC not available in ES versions < 3.0")); + return; + } + *params = static_cast<GLfloat>(texture->getCompareFunc()); + break; + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } } } @@ -1534,14 +2393,153 @@ void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateGetTexParameteriv(context, target, pname, params)) + if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) { + context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target")); return; } Texture *texture = context->getTargetTexture(target); - QueryTexParameteriv(texture, pname, params); + + if (!texture) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + 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->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = texture->getImmutableFormat() ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = static_cast<GLint>(texture->getImmutableLevels()); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getMaxAnisotropy(); + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSwizzleRed(); + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSwizzleGreen(); + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSwizzleBlue(); + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSwizzleAlpha(); + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getBaseLevel(); + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getMaxLevel(); + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = iround<GLint>(texture->getMinLod()); + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientMajorVersion() < 3) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + *params = iround<GLint>(texture->getMaxLod()); + break; + case GL_TEXTURE_COMPARE_MODE: + if (context->getClientMajorVersion() < 3) + { + context->handleError( + Error(GL_INVALID_ENUM, + "GL_TEXTURE_COMPARE_MODE not available in ES versions < 3.0")); + return; + } + *params = texture->getCompareMode(); + break; + case GL_TEXTURE_COMPARE_FUNC: + if (context->getClientMajorVersion() < 3) + { + context->handleError( + Error(GL_INVALID_ENUM, + "GL_TEXTURE_COMPARE_FUNC not available in ES versions < 3.0")); + return; + } + *params = texture->getCompareFunc(); + break; + default: + context->handleError(Error(GL_INVALID_ENUM)); + return; + } } } @@ -1621,16 +2619,32 @@ void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateGetVertexAttribfv(context, index, pname, params)) + if (index >= MAX_VERTEX_ATTRIBS) { + context->handleError(Error(GL_INVALID_VALUE)); return; } - const VertexAttribCurrentValueData ¤tValues = - context->getGLState().getVertexAttribCurrentValue(index); - const VertexAttribute &attrib = - context->getGLState().getVertexArray()->getVertexAttribute(index); - QueryVertexAttribfv(attrib, currentValues, pname, params); + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = + context->getGLState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.FloatValues[i]; + } + } + else + { + const VertexAttribute &attribState = + context->getGLState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter<GLfloat>(attribState, pname); + } } } @@ -1641,16 +2655,33 @@ void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateGetVertexAttribiv(context, index, pname, params)) + if (index >= MAX_VERTEX_ATTRIBS) { + context->handleError(Error(GL_INVALID_VALUE)); return; } - const VertexAttribCurrentValueData ¤tValues = - context->getGLState().getVertexAttribCurrentValue(index); - const VertexAttribute &attrib = - context->getGLState().getVertexArray()->getVertexAttribute(index); - QueryVertexAttribiv(attrib, currentValues, pname, params); + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = + context->getGLState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + float currentValue = currentValueData.FloatValues[i]; + params[i] = iround<GLint>(currentValue); + } + } + else + { + const VertexAttribute &attribState = + context->getGLState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter<GLint>(attribState, pname); + } } } @@ -1661,15 +2692,19 @@ void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && - !ValidateGetVertexAttribPointerv(context, index, pname, pointer)) + if (index >= MAX_VERTEX_ATTRIBS) { + context->handleError(Error(GL_INVALID_VALUE)); return; } - const VertexAttribute &attrib = - context->getGLState().getVertexArray()->getVertexAttribute(index); - QueryVertexAttribPointerv(attrib, pname, pointer); + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) + { + context->handleError(Error(GL_INVALID_ENUM)); + return; + } + + *pointer = const_cast<GLvoid *>(context->getGLState().getVertexAttribPointer(index)); } } @@ -1732,8 +2767,9 @@ GLboolean GL_APIENTRY IsEnabled(GLenum cap) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateIsEnabled(context, cap)) + if (!ValidCap(context, cap)) { + context->handleError(Error(GL_INVALID_ENUM)); return GL_FALSE; } @@ -2288,34 +3324,56 @@ void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateTexParameterf(context, target, pname, param)) + if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) { + context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target")); return; } - Texture *texture = context->getTargetTexture(target); - SetTexParameterf(texture, pname, param); - } -} + if (!ValidateTexParamParameters(context, target, pname, static_cast<GLint>(param))) + { + return; + } -void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat *params) -{ - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLfloat* params = 0x%0.8p)", target, - pname, params); + Texture *texture = context->getTargetTexture(target); - Context *context = GetValidGlobalContext(); - if (context) - { - if (!context->skipValidation() && !ValidateTexParameterfv(context, target, pname, params)) + if (!texture) { + context->handleError(Error(GL_INVALID_ENUM)); return; } - Texture *texture = context->getTargetTexture(target); - SetTexParameterfv(texture, pname, params); + // clang-format off + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->setWrapS(uiround<GLenum>(param)); break; + case GL_TEXTURE_WRAP_T: texture->setWrapT(uiround<GLenum>(param)); break; + case GL_TEXTURE_WRAP_R: texture->setWrapR(uiround<GLenum>(param)); break; + case GL_TEXTURE_MIN_FILTER: texture->setMinFilter(uiround<GLenum>(param)); break; + case GL_TEXTURE_MAG_FILTER: texture->setMagFilter(uiround<GLenum>(param)); break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(uiround<GLenum>(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->setMaxAnisotropy(std::min(param, context->getExtensions().maxTextureAnisotropy)); break; + case GL_TEXTURE_COMPARE_MODE: texture->setCompareMode(uiround<GLenum>(param)); break; + case GL_TEXTURE_COMPARE_FUNC: texture->setCompareFunc(uiround<GLenum>(param)); break; + case GL_TEXTURE_SWIZZLE_R: texture->setSwizzleRed(uiround<GLenum>(param)); break; + case GL_TEXTURE_SWIZZLE_G: texture->setSwizzleGreen(uiround<GLenum>(param)); break; + case GL_TEXTURE_SWIZZLE_B: texture->setSwizzleBlue(uiround<GLenum>(param)); break; + case GL_TEXTURE_SWIZZLE_A: texture->setSwizzleAlpha(uiround<GLenum>(param)); break; + case GL_TEXTURE_BASE_LEVEL: texture->setBaseLevel(uiround<GLuint>(param)); break; + case GL_TEXTURE_MAX_LEVEL: texture->setMaxLevel(uiround<GLuint>(param)); break; + case GL_TEXTURE_MIN_LOD: texture->setMinLod(param); break; + case GL_TEXTURE_MAX_LOD: texture->setMaxLod(param); break; + default: UNREACHABLE(); break; + } + // clang-format on } } +void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) +{ + TexParameterf(target, pname, (GLfloat)*params); +} + void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); @@ -2323,34 +3381,56 @@ void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param) Context *context = GetValidGlobalContext(); if (context) { - if (!context->skipValidation() && !ValidateTexParameteri(context, target, pname, param)) + if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) { + context->handleError(Error(GL_INVALID_ENUM, "Invalid Texture target")); return; } - Texture *texture = context->getTargetTexture(target); - SetTexParameteri(texture, pname, param); - } -} + if (!ValidateTexParamParameters(context, target, pname, param)) + { + return; + } -void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint *params) -{ - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLint* params = 0x%0.8p)", target, - pname, params); + Texture *texture = context->getTargetTexture(target); - Context *context = GetValidGlobalContext(); - if (context) - { - if (!context->skipValidation() && !ValidateTexParameteriv(context, target, pname, params)) + if (!texture) { + context->handleError(Error(GL_INVALID_ENUM)); return; } - Texture *texture = context->getTargetTexture(target); - SetTexParameteriv(texture, pname, params); + // clang-format off + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->setWrapS(static_cast<GLenum>(param)); break; + case GL_TEXTURE_WRAP_T: texture->setWrapT(static_cast<GLenum>(param)); break; + case GL_TEXTURE_WRAP_R: texture->setWrapR(static_cast<GLenum>(param)); break; + case GL_TEXTURE_MIN_FILTER: texture->setMinFilter(static_cast<GLenum>(param)); break; + case GL_TEXTURE_MAG_FILTER: texture->setMagFilter(static_cast<GLenum>(param)); break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(static_cast<GLenum>(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->setMaxAnisotropy(std::min(static_cast<GLfloat>(param), context->getExtensions().maxTextureAnisotropy)); break; + case GL_TEXTURE_COMPARE_MODE: texture->setCompareMode(static_cast<GLenum>(param)); break; + case GL_TEXTURE_COMPARE_FUNC: texture->setCompareFunc(static_cast<GLenum>(param)); break; + case GL_TEXTURE_SWIZZLE_R: texture->setSwizzleRed(static_cast<GLenum>(param)); break; + case GL_TEXTURE_SWIZZLE_G: texture->setSwizzleGreen(static_cast<GLenum>(param)); break; + case GL_TEXTURE_SWIZZLE_B: texture->setSwizzleBlue(static_cast<GLenum>(param)); break; + case GL_TEXTURE_SWIZZLE_A: texture->setSwizzleAlpha(static_cast<GLenum>(param)); break; + case GL_TEXTURE_BASE_LEVEL: texture->setBaseLevel(static_cast<GLuint>(param)); break; + case GL_TEXTURE_MAX_LEVEL: texture->setMaxLevel(static_cast<GLuint>(param)); break; + case GL_TEXTURE_MIN_LOD: texture->setMinLod(static_cast<GLfloat>(param)); break; + case GL_TEXTURE_MAX_LOD: texture->setMaxLod(static_cast<GLfloat>(param)); break; + default: UNREACHABLE(); break; + } + // clang-format on } } +void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params) +{ + TexParameteri(target, pname, *params); +} + void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) { |