X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2FOpenGL%2FlibGLESv2%2FContext.cpp;h=7bd9feabe4832db43e2d594ddcfc753573c5a79a;hb=cbb80f5f0078a9941f3ec43e83e52c3d15a43bea;hp=ed1c36662a296bcf6ba06f005f091678b820e501;hpb=506cc5e06043ba0819cc8f7c9190826faf47b1d6;p=android-x86%2Fexternal-swiftshader.git diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp index ed1c36662..7bd9feabe 100644 --- a/src/OpenGL/libGLESv2/Context.cpp +++ b/src/OpenGL/libGLESv2/Context.cpp @@ -142,14 +142,19 @@ Context::Context(egl::Display *display, const Context *shareContext, EGLint clie mTexture3DZero = new Texture3D(0); mTexture2DArrayZero = new Texture2DArray(0); mTextureCubeMapZero = new TextureCubeMap(0); + mTexture2DRectZero = new Texture2DRect(0); mTextureExternalZero = new TextureExternal(0); mState.activeSampler = 0; + + for(int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + bindTexture((TextureType)type, 0); + } + bindVertexArray(0); bindArrayBuffer(0); bindElementArrayBuffer(0); - bindTextureCubeMap(0); - bindTexture2D(0); bindReadFramebuffer(0); bindDrawFramebuffer(0); bindRenderbuffer(0); @@ -158,19 +163,6 @@ Context::Context(egl::Display *display, const Context *shareContext, EGLint clie mState.currentProgram = 0; - mState.packAlignment = 4; - mState.unpackInfo.alignment = 4; - mState.packRowLength = 0; - mState.packImageHeight = 0; - mState.packSkipPixels = 0; - mState.packSkipRows = 0; - mState.packSkipImages = 0; - mState.unpackInfo.rowLength = 0; - mState.unpackInfo.imageHeight = 0; - mState.unpackInfo.skipPixels = 0; - mState.unpackInfo.skipRows = 0; - mState.unpackInfo.skipImages = 0; - mVertexDataManager = nullptr; mIndexDataManager = nullptr; @@ -262,6 +254,7 @@ Context::~Context() mTexture3DZero = nullptr; mTexture2DArrayZero = nullptr; mTextureCubeMapZero = nullptr; + mTexture2DRectZero = nullptr; mTextureExternalZero = nullptr; delete mVertexDataManager; @@ -756,31 +749,33 @@ GLuint Context::getRenderbufferName() const void Context::setFramebufferReadBuffer(GLuint buf) { - getReadFramebuffer()->setReadBuffer(buf); + Framebuffer *framebuffer = getReadFramebuffer(); + + if(framebuffer) + { + framebuffer->setReadBuffer(buf); + } + else + { + return error(GL_INVALID_OPERATION); + } } void Context::setFramebufferDrawBuffers(GLsizei n, const GLenum *bufs) { Framebuffer *drawFramebuffer = getDrawFramebuffer(); - for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++) + if(drawFramebuffer) { - drawFramebuffer->setDrawBuffer(i, (i < n) ? bufs[i] : GL_NONE); + for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++) + { + drawFramebuffer->setDrawBuffer(i, (i < n) ? bufs[i] : GL_NONE); + } } -} - -GLuint Context::getReadFramebufferColorIndex() const -{ - GLenum buf = getReadFramebuffer()->getReadBuffer(); - switch(buf) + else { - case GL_BACK: - return 0; - case GL_NONE: - return GL_INVALID_INDEX; - default: - return buf - GL_COLOR_ATTACHMENT0; -} + return error(GL_INVALID_OPERATION); + } } GLuint Context::getArrayBufferName() const @@ -836,10 +831,10 @@ const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) con return getCurrentVertexArray()->getVertexAttribute(attribNum); } -void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, - GLsizei stride, const void *pointer) +void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, bool pureInteger, GLsizei stride, const void *pointer) { - getCurrentVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, stride, pointer); + getCurrentVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); } const void *Context::getVertexAttribPointer(unsigned int attribNum) const @@ -859,67 +854,57 @@ const VertexAttributeArray &Context::getCurrentVertexAttributes() void Context::setPackAlignment(GLint alignment) { - mState.packAlignment = alignment; + mState.packParameters.alignment = alignment; } void Context::setUnpackAlignment(GLint alignment) { - mState.unpackInfo.alignment = alignment; + mState.unpackParameters.alignment = alignment; } -const egl::Image::UnpackInfo& Context::getUnpackInfo() const +const gl::PixelStorageModes &Context::getUnpackParameters() const { - return mState.unpackInfo; + return mState.unpackParameters; } void Context::setPackRowLength(GLint rowLength) { - mState.packRowLength = rowLength; -} - -void Context::setPackImageHeight(GLint imageHeight) -{ - mState.packImageHeight = imageHeight; + mState.packParameters.rowLength = rowLength; } void Context::setPackSkipPixels(GLint skipPixels) { - mState.packSkipPixels = skipPixels; + mState.packParameters.skipPixels = skipPixels; } void Context::setPackSkipRows(GLint skipRows) { - mState.packSkipRows = skipRows; -} - -void Context::setPackSkipImages(GLint skipImages) -{ - mState.packSkipImages = skipImages; + mState.packParameters.skipRows = skipRows; } void Context::setUnpackRowLength(GLint rowLength) { - mState.unpackInfo.rowLength = rowLength; + mState.unpackParameters.rowLength = rowLength; } void Context::setUnpackImageHeight(GLint imageHeight) { - mState.unpackInfo.imageHeight = imageHeight; + mState.unpackParameters.imageHeight = imageHeight; } void Context::setUnpackSkipPixels(GLint skipPixels) { - mState.unpackInfo.skipPixels = skipPixels; + mState.unpackParameters.skipPixels = skipPixels; } void Context::setUnpackSkipRows(GLint skipRows) { - mState.unpackInfo.skipRows = skipRows; + mState.unpackParameters.skipRows = skipRows; } void Context::setUnpackSkipImages(GLint skipImages) { - mState.unpackInfo.skipImages = skipImages; + mState.unpackParameters.skipImages = skipImages; } GLuint Context::createBuffer() @@ -1188,46 +1173,25 @@ void Context::bindTransformFeedbackBuffer(GLuint buffer) } } -void Context::bindTexture2D(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); - - mState.samplerTexture[TEXTURE_2D][mState.activeSampler] = getTexture(texture); -} - -void Context::bindTextureCubeMap(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE); - - mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler] = getTexture(texture); -} - -void Context::bindTextureExternal(GLuint texture) +void Context::bindTexture(TextureType type, GLuint texture) { - mResourceManager->checkTextureAllocation(texture, TEXTURE_EXTERNAL); + mResourceManager->checkTextureAllocation(texture, type); - mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler] = getTexture(texture); -} - -void Context::bindTexture3D(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_3D); - - mState.samplerTexture[TEXTURE_3D][mState.activeSampler] = getTexture(texture); -} - -void Context::bindTexture2DArray(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_2D_ARRAY); - - mState.samplerTexture[TEXTURE_2D_ARRAY][mState.activeSampler] = getTexture(texture); + mState.samplerTexture[type][mState.activeSampler] = getTexture(texture); } void Context::bindReadFramebuffer(GLuint framebuffer) { if(!getFramebuffer(framebuffer)) { - mFramebufferNameSpace.insert(framebuffer, new Framebuffer()); + if(framebuffer == 0) + { + mFramebufferNameSpace.insert(framebuffer, new DefaultFramebuffer()); + } + else + { + mFramebufferNameSpace.insert(framebuffer, new Framebuffer()); + } } mState.readFramebuffer = framebuffer; @@ -1237,7 +1201,14 @@ void Context::bindDrawFramebuffer(GLuint framebuffer) { if(!getFramebuffer(framebuffer)) { - mFramebufferNameSpace.insert(framebuffer, new Framebuffer()); + if(framebuffer == 0) + { + mFramebufferNameSpace.insert(framebuffer, new DefaultFramebuffer()); + } + else + { + mFramebufferNameSpace.insert(framebuffer, new Framebuffer()); + } } mState.drawFramebuffer = framebuffer; @@ -1357,7 +1328,25 @@ void Context::beginQuery(GLenum target, GLuint query) { if(mState.activeQuery[i]) { - return error(GL_INVALID_OPERATION); + switch(mState.activeQuery[i]->getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + if((target == GL_ANY_SAMPLES_PASSED_EXT) || + (target == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT)) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + if(target == GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) + { + return error(GL_INVALID_OPERATION); + } + break; + default: + break; + } } } @@ -1511,6 +1500,11 @@ TransformFeedback *Context::getTransformFeedback(GLuint transformFeedback) const return mTransformFeedbackNameSpace.find(transformFeedback); } +bool Context::isTransformFeedback(GLuint array) const +{ + return mTransformFeedbackNameSpace.isReserved(array); +} + Sampler *Context::getSampler(GLuint sampler) const { return mResourceManager->getSampler(sampler); @@ -1556,11 +1550,46 @@ Buffer *Context::getGenericUniformBuffer() const return mState.genericUniformBuffer; } -const GLvoid* Context::getPixels(const GLvoid* data) const +GLsizei Context::getRequiredBufferSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type) const { - es2::Buffer* unpackBuffer = getPixelUnpackBuffer(); - const unsigned char* unpackBufferData = unpackBuffer ? static_cast(unpackBuffer->data()) : nullptr; - return unpackBufferData ? unpackBufferData + (ptrdiff_t)(data) : data; + GLsizei inputWidth = (mState.unpackParameters.rowLength == 0) ? width : mState.unpackParameters.rowLength; + GLsizei inputPitch = gl::ComputePitch(inputWidth, format, type, mState.unpackParameters.alignment); + GLsizei inputHeight = (mState.unpackParameters.imageHeight == 0) ? height : mState.unpackParameters.imageHeight; + return inputPitch * inputHeight * depth; +} + +GLenum Context::getPixels(const GLvoid **pixels, GLenum type, GLsizei imageSize) const +{ + if(mState.pixelUnpackBuffer) + { + ASSERT(mState.pixelUnpackBuffer->name != 0); + + if(mState.pixelUnpackBuffer->isMapped()) + { + return GL_INVALID_OPERATION; + } + + size_t offset = static_cast((ptrdiff_t)(*pixels)); + + if(offset % GetTypeSize(type) != 0) + { + return GL_INVALID_OPERATION; + } + + if(offset > mState.pixelUnpackBuffer->size()) + { + return GL_INVALID_OPERATION; + } + + if(mState.pixelUnpackBuffer->size() - offset < static_cast(imageSize)) + { + return GL_INVALID_OPERATION; + } + + *pixels = static_cast(mState.pixelUnpackBuffer->data()) + offset; + } + + return GL_NO_ERROR; } bool Context::getBuffer(GLenum target, es2::Buffer **buffer) const @@ -1637,6 +1666,19 @@ Texture2D *Context::getTexture2D() const return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_2D)); } +Texture2D *Context::getTexture2D(GLenum target) const +{ + switch(target) + { + case GL_TEXTURE_2D: return getTexture2D(); + case GL_TEXTURE_RECTANGLE_ARB: return getTexture2DRect(); + case GL_TEXTURE_EXTERNAL_OES: return getTextureExternal(); + default: UNREACHABLE(target); + } + + return nullptr; +} + Texture3D *Context::getTexture3D() const { return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_3D)); @@ -1652,6 +1694,11 @@ TextureCubeMap *Context::getTextureCubeMap() const return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE)); } +Texture2DRect *Context::getTexture2DRect() const +{ + return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_2D_RECT)); +} + TextureExternal *Context::getTextureExternal() const { return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_EXTERNAL)); @@ -1669,6 +1716,7 @@ Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) cons case TEXTURE_3D: return mTexture3DZero; case TEXTURE_2D_ARRAY: return mTexture2DArrayZero; case TEXTURE_CUBE: return mTextureCubeMapZero; + case TEXTURE_2D_RECT: return mTexture2DRectZero; case TEXTURE_EXTERNAL: return mTextureExternalZero; default: UNREACHABLE(type); } @@ -1686,16 +1734,17 @@ void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) switch(pname) { - case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(param)); break; - case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(param)); break; - case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(param)); break; - case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(param)); break; - case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(param)); break; - case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast(param)); break; - case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast(param)); break; - case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(static_cast(param)); break; - case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(static_cast(param)); break; - default: UNREACHABLE(pname); break; + case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(param)); break; + case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(param)); break; + case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(param)); break; + case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(param)); break; + case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(param)); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast(param)); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast(param)); break; + case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast(param)); break; + case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(static_cast(param)); break; + default: UNREACHABLE(pname); break; } } @@ -1708,16 +1757,17 @@ void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) switch(pname) { - case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(roundf(param))); break; - case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(roundf(param))); break; - case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(roundf(param))); break; - case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(roundf(param))); break; - case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(roundf(param))); break; - case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; - case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; - case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(static_cast(roundf(param))); break; - case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(static_cast(roundf(param))); break; - default: UNREACHABLE(pname); break; + case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(roundf(param))); break; + case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(roundf(param))); break; + case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(roundf(param))); break; + case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(roundf(param))); break; + case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(roundf(param))); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; + case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast(roundf(param))); break; + case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast(roundf(param))); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(param); break; + default: UNREACHABLE(pname); break; } } @@ -1730,16 +1780,17 @@ GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname) switch(pname) { - case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); - case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); - case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); - case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); - case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); - case GL_TEXTURE_MIN_LOD: return static_cast(roundf(samplerObject->getMinLod())); - case GL_TEXTURE_MAX_LOD: return static_cast(roundf(samplerObject->getMaxLod())); - case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); - case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); - default: UNREACHABLE(pname); return 0; + case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); + case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); + case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); + case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); + case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); + case GL_TEXTURE_MIN_LOD: return static_cast(roundf(samplerObject->getMinLod())); + case GL_TEXTURE_MAX_LOD: return static_cast(roundf(samplerObject->getMaxLod())); + case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getCompareMode()); + case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getCompareFunc()); + case GL_TEXTURE_MAX_ANISOTROPY_EXT: return static_cast(samplerObject->getMaxAnisotropy()); + default: UNREACHABLE(pname); return 0; } } @@ -1752,16 +1803,17 @@ GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) switch(pname) { - case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); - case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); - case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); - case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); - case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); - case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod(); - case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod(); - case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); - case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); - default: UNREACHABLE(pname); return 0; + case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); + case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); + case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); + case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); + case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); + case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod(); + case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod(); + case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getCompareMode()); + case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getCompareFunc()); + case GL_TEXTURE_MAX_ANISOTROPY_EXT: return samplerObject->getMaxAnisotropy(); + default: UNREACHABLE(pname); return 0; } } @@ -1888,12 +1940,12 @@ template bool Context::getIntegerv(GLenum pname, T *params) const case GL_ARRAY_BUFFER_BINDING: *params = getArrayBufferName(); return true; case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getElementArrayBufferName(); return true; // case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; return true; - case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; return true; + case GL_DRAW_FRAMEBUFFER_BINDING: *params = mState.drawFramebuffer; return true; + case GL_READ_FRAMEBUFFER_BINDING: *params = mState.readFramebuffer; return true; case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.name(); return true; case GL_CURRENT_PROGRAM: *params = mState.currentProgram; return true; - case GL_PACK_ALIGNMENT: *params = mState.packAlignment; return true; - case GL_UNPACK_ALIGNMENT: *params = mState.unpackInfo.alignment; return true; + case GL_PACK_ALIGNMENT: *params = mState.packParameters.alignment; return true; + case GL_UNPACK_ALIGNMENT: *params = mState.unpackParameters.alignment; return true; case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; return true; case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; return true; case GL_TEXTURE_FILTERING_HINT_CHROMIUM: *params = mState.textureFilteringHint; return true; @@ -1921,17 +1973,18 @@ template bool Context::getIntegerv(GLenum pname, T *params) const case GL_STENCIL_BACK_WRITEMASK: *params = sw::clampToSignedInt(mState.stencilBackWritemask); return true; case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; return true; case GL_SUBPIXEL_BITS: *params = 4; return true; + case GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB: case GL_MAX_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; return true; case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE; return true; case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = NUM_COMPRESSED_TEXTURE_FORMATS; return true; - case GL_MAX_SAMPLES_ANGLE: *params = IMPLEMENTATION_MAX_SAMPLES; return true; + case GL_MAX_SAMPLES: *params = IMPLEMENTATION_MAX_SAMPLES; return true; case GL_SAMPLE_BUFFERS: case GL_SAMPLES: { Framebuffer *framebuffer = getDrawFramebuffer(); int width, height, samples; - if(framebuffer->completeness(width, height, samples) == GL_FRAMEBUFFER_COMPLETE) + if(framebuffer && (framebuffer->completeness(width, height, samples) == GL_FRAMEBUFFER_COMPLETE)) { switch(pname) { @@ -1959,13 +2012,27 @@ template bool Context::getIntegerv(GLenum pname, T *params) const case GL_IMPLEMENTATION_COLOR_READ_TYPE: { Framebuffer *framebuffer = getReadFramebuffer(); - *params = framebuffer->getImplementationColorReadType(); + if(framebuffer) + { + *params = framebuffer->getImplementationColorReadType(); + } + else + { + return error(GL_INVALID_OPERATION, true); + } } return true; case GL_IMPLEMENTATION_COLOR_READ_FORMAT: { Framebuffer *framebuffer = getReadFramebuffer(); - *params = framebuffer->getImplementationColorReadFormat(); + if(framebuffer) + { + *params = framebuffer->getImplementationColorReadFormat(); + } + else + { + return error(GL_INVALID_OPERATION, true); + } } return true; case GL_MAX_VIEWPORT_DIMS: @@ -2003,7 +2070,7 @@ template bool Context::getIntegerv(GLenum pname, T *params) const case GL_ALPHA_BITS: { Framebuffer *framebuffer = getDrawFramebuffer(); - Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + Renderbuffer *colorbuffer = framebuffer ? framebuffer->getColorbuffer(0) : nullptr; if(colorbuffer) { @@ -2024,7 +2091,7 @@ template bool Context::getIntegerv(GLenum pname, T *params) const case GL_DEPTH_BITS: { Framebuffer *framebuffer = getDrawFramebuffer(); - Renderbuffer *depthbuffer = framebuffer->getDepthbuffer(); + Renderbuffer *depthbuffer = framebuffer ? framebuffer->getDepthbuffer() : nullptr; if(depthbuffer) { @@ -2039,7 +2106,7 @@ template bool Context::getIntegerv(GLenum pname, T *params) const case GL_STENCIL_BITS: { Framebuffer *framebuffer = getDrawFramebuffer(); - Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer(); + Renderbuffer *stencilbuffer = framebuffer ? framebuffer->getStencilbuffer() : nullptr; if(stencilbuffer) { @@ -2069,6 +2136,15 @@ template bool Context::getIntegerv(GLenum pname, T *params) const *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].name(); return true; + case GL_TEXTURE_BINDING_RECTANGLE_ARB: + if(mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1) + { + error(GL_INVALID_OPERATION); + return false; + } + + *params = mState.samplerTexture[TEXTURE_2D_RECT][mState.activeSampler].name(); + return true; case GL_TEXTURE_BINDING_EXTERNAL_OES: if(mState.activeSampler > MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1) { @@ -2105,7 +2181,8 @@ template bool Context::getIntegerv(GLenum pname, T *params) const case GL_DRAW_BUFFER15: if((pname - GL_DRAW_BUFFER0) < MAX_DRAW_BUFFERS) { - *params = getDrawFramebuffer()->getDrawBuffer(pname - GL_DRAW_BUFFER0); + Framebuffer* framebuffer = getDrawFramebuffer(); + *params = framebuffer ? framebuffer->getDrawBuffer(pname - GL_DRAW_BUFFER0) : GL_NONE; } else { @@ -2145,7 +2222,7 @@ template bool Context::getIntegerv(GLenum pname, T *params) const *params = clientVersion; return true; case GL_MAX_3D_TEXTURE_SIZE: - *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; + *params = IMPLEMENTATION_MAX_3D_TEXTURE_SIZE; return true; case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; @@ -2178,15 +2255,19 @@ template bool Context::getIntegerv(GLenum pname, T *params) const *params = MAX_FRAGMENT_UNIFORM_COMPONENTS; return true; case GL_MAX_PROGRAM_TEXEL_OFFSET: - UNIMPLEMENTED(); + // Note: SwiftShader has no actual texel offset limit, so this limit can be modified if required. + // In any case, any behavior outside the specified range is valid since the spec mentions: + // (see OpenGL ES 3.0.5, 3.8.10.1 Scale Factor and Level of Detail, p.153) + // "If any of the offset values are outside the range of the implementation-defined values + // MIN_PROGRAM_TEXEL_OFFSET and MAX_PROGRAM_TEXEL_OFFSET, results of the texture lookup are + // undefined." *params = MAX_PROGRAM_TEXEL_OFFSET; return true; case GL_MAX_SERVER_WAIT_TIMEOUT: *params = 0; return true; case GL_MAX_TEXTURE_LOD_BIAS: - UNIMPLEMENTED(); - *params = 2; + *params = MAX_TEXTURE_LOD_BIAS; return true; case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; @@ -2216,7 +2297,12 @@ template bool Context::getIntegerv(GLenum pname, T *params) const *params = MAX_VERTEX_UNIFORM_COMPONENTS; return true; case GL_MIN_PROGRAM_TEXEL_OFFSET: - UNIMPLEMENTED(); + // Note: SwiftShader has no actual texel offset limit, so this limit can be modified if required. + // In any case, any behavior outside the specified range is valid since the spec mentions: + // (see OpenGL ES 3.0.5, 3.8.10.1 Scale Factor and Level of Detail, p.153) + // "If any of the offset values are outside the range of the implementation-defined values + // MIN_PROGRAM_TEXEL_OFFSET and MAX_PROGRAM_TEXEL_OFFSET, results of the texture lookup are + // undefined." *params = MIN_PROGRAM_TEXEL_OFFSET; return true; case GL_MINOR_VERSION: @@ -2231,13 +2317,13 @@ template bool Context::getIntegerv(GLenum pname, T *params) const *params = NUM_PROGRAM_BINARY_FORMATS; return true; case GL_PACK_ROW_LENGTH: - *params = mState.packRowLength; + *params = mState.packParameters.rowLength; return true; case GL_PACK_SKIP_PIXELS: - *params = mState.packSkipPixels; + *params = mState.packParameters.skipPixels; return true; case GL_PACK_SKIP_ROWS: - *params = mState.packSkipRows; + *params = mState.packParameters.skipRows; return true; case GL_PIXEL_PACK_BUFFER_BINDING: *params = mState.pixelPackBuffer.name(); @@ -2250,7 +2336,10 @@ template bool Context::getIntegerv(GLenum pname, T *params) const // should be a 0 sized array, so don't write to params return true; case GL_READ_BUFFER: - *params = getReadFramebuffer()->getReadBuffer(); + { + Framebuffer* framebuffer = getReadFramebuffer(); + *params = framebuffer ? framebuffer->getReadBuffer() : GL_NONE; + } return true; case GL_SAMPLER_BINDING: *params = mState.sampler[mState.activeSampler].name(); @@ -2268,19 +2357,19 @@ template bool Context::getIntegerv(GLenum pname, T *params) const *params = static_cast(mState.genericUniformBuffer->offset()); return true; case GL_UNPACK_IMAGE_HEIGHT: - *params = mState.unpackInfo.imageHeight; + *params = mState.unpackParameters.imageHeight; return true; case GL_UNPACK_ROW_LENGTH: - *params = mState.unpackInfo.rowLength; + *params = mState.unpackParameters.rowLength; return true; case GL_UNPACK_SKIP_IMAGES: - *params = mState.unpackInfo.skipImages; + *params = mState.unpackParameters.skipImages; return true; case GL_UNPACK_SKIP_PIXELS: - *params = mState.unpackInfo.skipPixels; + *params = mState.unpackParameters.skipPixels; return true; case GL_UNPACK_SKIP_ROWS: - *params = mState.unpackInfo.skipRows; + *params = mState.unpackParameters.skipRows; return true; case GL_VERTEX_ARRAY_BINDING: *params = getCurrentVertexArray()->name; @@ -2370,6 +2459,20 @@ template bool Context::getUniformBufferiv(GLuint index, GLenum pname, G template bool Context::getUniformBufferiv(GLuint index, GLenum pname, T *param) const { + switch(pname) + { + case GL_UNIFORM_BUFFER_BINDING: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_START: + if(index >= MAX_UNIFORM_BUFFER_BINDINGS) + { + return error(GL_INVALID_VALUE, true); + } + break; + default: + break; + } + const BufferBinding& uniformBuffer = mState.uniformBuffers[index]; switch(pname) @@ -2424,8 +2527,8 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_NUM_SHADER_BINARY_FORMATS: case GL_NUM_COMPRESSED_TEXTURE_FORMATS: case GL_ARRAY_BUFFER_BINDING: - case GL_FRAMEBUFFER_BINDING: // Same as GL_DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_READ_FRAMEBUFFER_BINDING_ANGLE: + case GL_FRAMEBUFFER_BINDING: // Same as GL_DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_READ_FRAMEBUFFER_BINDING: // Same as GL_READ_FRAMEBUFFER_BINDING_ANGLE case GL_RENDERBUFFER_BINDING: case GL_CURRENT_PROGRAM: case GL_PACK_ALIGNMENT: @@ -2468,12 +2571,14 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_SUBPIXEL_BITS: case GL_MAX_TEXTURE_SIZE: case GL_MAX_CUBE_MAP_TEXTURE_SIZE: + case GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB: case GL_SAMPLE_BUFFERS: case GL_SAMPLES: case GL_IMPLEMENTATION_COLOR_READ_TYPE: case GL_IMPLEMENTATION_COLOR_READ_FORMAT: case GL_TEXTURE_BINDING_2D: case GL_TEXTURE_BINDING_CUBE_MAP: + case GL_TEXTURE_BINDING_RECTANGLE_ARB: case GL_TEXTURE_BINDING_EXTERNAL_OES: case GL_TEXTURE_BINDING_3D_OES: case GL_COPY_READ_BUFFER_BINDING: @@ -2550,7 +2655,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu *numParams = 1; } break; - case GL_MAX_SAMPLES_ANGLE: + case GL_MAX_SAMPLES: { *type = GL_INT; *numParams = 1; @@ -2654,7 +2759,7 @@ bool Context::applyRenderTarget() Framebuffer *framebuffer = getDrawFramebuffer(); int width, height, samples; - if(!framebuffer || framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE) + if(!framebuffer || (framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE)) { return error(GL_INVALID_FRAMEBUFFER_OPERATION, false); } @@ -2664,21 +2769,24 @@ bool Context::applyRenderTarget() if(framebuffer->getDrawBuffer(i) != GL_NONE) { egl::Image *renderTarget = framebuffer->getRenderTarget(i); - device->setRenderTarget(i, renderTarget); + GLint layer = framebuffer->getColorbufferLayer(i); + device->setRenderTarget(i, renderTarget, layer); if(renderTarget) renderTarget->release(); } else { - device->setRenderTarget(i, nullptr); + device->setRenderTarget(i, nullptr, 0); } } egl::Image *depthBuffer = framebuffer->getDepthBuffer(); - device->setDepthBuffer(depthBuffer); + GLint dLayer = framebuffer->getDepthbufferLayer(); + device->setDepthBuffer(depthBuffer, dLayer); if(depthBuffer) depthBuffer->release(); egl::Image *stencilBuffer = framebuffer->getStencilBuffer(); - device->setStencilBuffer(stencilBuffer); + GLint sLayer = framebuffer->getStencilbufferLayer(); + device->setStencilBuffer(stencilBuffer, sLayer); if(stencilBuffer) stencilBuffer->release(); Viewport viewport; @@ -2848,7 +2956,7 @@ void Context::applyState(GLenum drawMode) if(depthbuffer) { device->setSlopeDepthBias(mState.polygonOffsetFactor); - float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize())); + float depthBias = ldexp(mState.polygonOffsetUnits, -23); // We use 32-bit floating-point for all depth formats, with 23 mantissa bits. device->setDepthBias(depthBias); } } @@ -2963,7 +3071,7 @@ GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count, GLsize // Applies the indices and element array bindings GLenum Context::applyIndexBuffer(const void *indices, GLuint start, GLuint end, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) { - GLenum err = mIndexDataManager->prepareIndexData(type, start, end, count, getCurrentVertexArray()->getElementArrayBuffer(), indices, indexInfo); + GLenum err = mIndexDataManager->prepareIndexData(mode, type, start, end, count, getCurrentVertexArray()->getElementArrayBuffer(), indices, indexInfo, isPrimitiveRestartFixedIndexEnabled()); if(err == GL_NO_ERROR) { @@ -3018,8 +3126,8 @@ void Context::applyTextures(sw::SamplerType samplerType) if(texture->isSamplerComplete()) { - GLenum wrapS, wrapT, wrapR, minFilter, magFilter; - GLfloat minLOD, maxLOD; + GLenum wrapS, wrapT, wrapR, minFilter, magFilter, compFunc, compMode; + GLfloat minLOD, maxLOD, maxAnisotropy; Sampler *samplerObject = mState.sampler[textureUnit]; if(samplerObject) @@ -3031,6 +3139,9 @@ void Context::applyTextures(sw::SamplerType samplerType) magFilter = samplerObject->getMagFilter(); minLOD = samplerObject->getMinLod(); maxLOD = samplerObject->getMaxLod(); + compFunc = samplerObject->getCompareFunc(); + compMode = samplerObject->getCompareMode(); + maxAnisotropy = samplerObject->getMaxAnisotropy(); } else { @@ -3041,8 +3152,10 @@ void Context::applyTextures(sw::SamplerType samplerType) magFilter = texture->getMagFilter(); minLOD = texture->getMinLOD(); maxLOD = texture->getMaxLOD(); + compFunc = texture->getCompareFunc(); + compMode = texture->getCompareMode(); + maxAnisotropy = texture->getMaxAnisotropy(); } - GLfloat maxAnisotropy = texture->getMaxAnisotropy(); GLint baseLevel = texture->getBaseLevel(); GLint maxLevel = texture->getMaxLevel(); @@ -3054,6 +3167,7 @@ void Context::applyTextures(sw::SamplerType samplerType) device->setAddressingModeU(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapS)); device->setAddressingModeV(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapT)); device->setAddressingModeW(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapR)); + device->setCompareFunc(samplerType, samplerIndex, es2sw::ConvertCompareFunc(compFunc, compMode)); device->setSwizzleR(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleR)); device->setSwizzleG(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleG)); device->setSwizzleB(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleB)); @@ -3062,7 +3176,6 @@ void Context::applyTextures(sw::SamplerType samplerType) device->setMaxLod(samplerType, samplerIndex, maxLOD); device->setBaseLevel(samplerType, samplerIndex, baseLevel); device->setMaxLevel(samplerType, samplerIndex, maxLevel); - device->setTextureFilter(samplerType, samplerIndex, es2sw::ConvertTextureFilter(minFilter, magFilter, maxAnisotropy)); device->setMipmapFilter(samplerType, samplerIndex, es2sw::ConvertMipMapFilter(minFilter)); device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy); @@ -3098,7 +3211,7 @@ void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture } else UNREACHABLE(type); - sw::Resource *resource = 0; + sw::Resource *resource = nullptr; if(baseTexture && textureUsed) { @@ -3109,96 +3222,96 @@ void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture if(baseTexture && textureUsed) { - int levelCount = baseTexture->getLevelCount(); + int baseLevel = baseTexture->getBaseLevel(); + int maxLevel = std::min(baseTexture->getTopLevel(), baseTexture->getMaxLevel()); + GLenum target = baseTexture->getTarget(); - if(baseTexture->getTarget() == GL_TEXTURE_2D || baseTexture->getTarget() == GL_TEXTURE_EXTERNAL_OES) + switch(target) { - Texture2D *texture = static_cast(baseTexture); - - for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) + case GL_TEXTURE_2D: + case GL_TEXTURE_EXTERNAL_OES: + case GL_TEXTURE_RECTANGLE_ARB: { - int surfaceLevel = mipmapLevel; + Texture2D *texture = static_cast(baseTexture); - if(surfaceLevel < 0) - { - surfaceLevel = 0; - } - else if(surfaceLevel >= levelCount) + for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) { - surfaceLevel = levelCount - 1; - } + int surfaceLevel = mipmapLevel + baseLevel; - egl::Image *surface = texture->getImage(surfaceLevel); - device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D); - } - } - else if(baseTexture->getTarget() == GL_TEXTURE_3D_OES) - { - Texture3D *texture = static_cast(baseTexture); + if(surfaceLevel > maxLevel) + { + surfaceLevel = maxLevel; + } - for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) + egl::Image *surface = texture->getImage(surfaceLevel); + device->setTextureLevel(sampler, 0, mipmapLevel, surface, + (target == GL_TEXTURE_RECTANGLE_ARB) ? sw::TEXTURE_RECTANGLE : sw::TEXTURE_2D); + } + } + break; + case GL_TEXTURE_3D: { - int surfaceLevel = mipmapLevel; + Texture3D *texture = static_cast(baseTexture); - if(surfaceLevel < 0) - { - surfaceLevel = 0; - } - else if(surfaceLevel >= levelCount) + for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) { - surfaceLevel = levelCount - 1; - } + int surfaceLevel = mipmapLevel + baseLevel; - egl::Image *surface = texture->getImage(surfaceLevel); - device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_3D); - } - } - else if(baseTexture->getTarget() == GL_TEXTURE_2D_ARRAY) - { - Texture2DArray *texture = static_cast(baseTexture); + if(surfaceLevel > maxLevel) + { + surfaceLevel = maxLevel; + } - for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) + egl::Image *surface = texture->getImage(surfaceLevel); + device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_3D); + } + } + break; + case GL_TEXTURE_2D_ARRAY: { - int surfaceLevel = mipmapLevel; + Texture2DArray *texture = static_cast(baseTexture); - if(surfaceLevel < 0) - { - surfaceLevel = 0; - } - else if(surfaceLevel >= levelCount) + for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) { - surfaceLevel = levelCount - 1; - } + int surfaceLevel = mipmapLevel + baseLevel; + + if(surfaceLevel > maxLevel) + { + surfaceLevel = maxLevel; + } - egl::Image *surface = texture->getImage(surfaceLevel); - device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D_ARRAY); + egl::Image *surface = texture->getImage(surfaceLevel); + device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D_ARRAY); + } } - } - else if(baseTexture->getTarget() == GL_TEXTURE_CUBE_MAP) - { - for(int face = 0; face < 6; face++) + break; + case GL_TEXTURE_CUBE_MAP: { TextureCubeMap *cubeTexture = static_cast(baseTexture); for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) { - int surfaceLevel = mipmapLevel; + cubeTexture->updateBorders(mipmapLevel); - if(surfaceLevel < 0) - { - surfaceLevel = 0; - } - else if(surfaceLevel >= levelCount) + for(int face = 0; face < 6; face++) { - surfaceLevel = levelCount - 1; - } + int surfaceLevel = mipmapLevel + baseLevel; + + if(surfaceLevel > maxLevel) + { + surfaceLevel = maxLevel; + } - egl::Image *surface = cubeTexture->getImage(face, surfaceLevel); - device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE); + egl::Image *surface = cubeTexture->getImage(face, surfaceLevel); + device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE); + } } } + break; + default: + UNIMPLEMENTED(); + break; } - else UNIMPLEMENTED(); } else { @@ -3211,7 +3324,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum Framebuffer *framebuffer = getReadFramebuffer(); int framebufferWidth, framebufferHeight, framebufferSamples; - if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE) + if(!framebuffer || (framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE)) { return error(GL_INVALID_FRAMEBUFFER_OPERATION); } @@ -3226,11 +3339,11 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum return error(GL_INVALID_OPERATION); } - GLsizei outputWidth = (mState.packRowLength > 0) ? mState.packRowLength : width; - GLsizei outputPitch = egl::ComputePitch(outputWidth, format, type, mState.packAlignment); - GLsizei outputHeight = (mState.packImageHeight == 0) ? height : mState.packImageHeight; + GLsizei outputWidth = (mState.packParameters.rowLength > 0) ? mState.packParameters.rowLength : width; + GLsizei outputPitch = gl::ComputePitch(outputWidth, format, type, mState.packParameters.alignment); + GLsizei outputHeight = (mState.packParameters.imageHeight == 0) ? height : mState.packParameters.imageHeight; pixels = getPixelPackBuffer() ? (unsigned char*)getPixelPackBuffer()->data() + (ptrdiff_t)pixels : (unsigned char*)pixels; - pixels = ((char*)pixels) + egl::ComputePackingOffset(format, type, outputWidth, outputHeight, mState.packAlignment, mState.packSkipImages, mState.packSkipRows, mState.packSkipPixels); + pixels = ((char*)pixels) + gl::ComputePackingOffset(format, type, outputWidth, outputHeight, mState.packParameters); // Sized query sanity check if(bufSize) @@ -3245,7 +3358,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum egl::Image *renderTarget = nullptr; switch(format) { - case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT: // GL_NV_read_depth renderTarget = framebuffer->getDepthBuffer(); break; default: @@ -3258,14 +3371,14 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum return error(GL_INVALID_OPERATION); } - sw::Rect rect = {x, y, x + width, y + height}; - sw::Rect dstRect = { 0, 0, width, height }; - rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight()); + sw::RectF rect((float)x, (float)y, (float)(x + width), (float)(y + height)); + sw::Rect dstRect(0, 0, width, height); + rect.clip(0.0f, 0.0f, (float)renderTarget->getWidth(), (float)renderTarget->getHeight()); - sw::Surface *externalSurface = sw::Surface::create(width, height, 1, egl::ConvertFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight); - sw::SliceRect sliceRect(rect); + sw::Surface *externalSurface = sw::Surface::create(width, height, 1, gl::ConvertReadFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight); + sw::SliceRectF sliceRect(rect); sw::SliceRect dstSliceRect(dstRect); - device->blit(renderTarget, sliceRect, externalSurface, dstSliceRect, false); + device->blit(renderTarget, sliceRect, externalSurface, dstSliceRect, false, false, false); delete externalSurface; renderTarget->release(); @@ -3280,7 +3393,7 @@ void Context::clear(GLbitfield mask) Framebuffer *framebuffer = getDrawFramebuffer(); - if(!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)) { return error(GL_INVALID_FRAMEBUFFER_OPERATION); } @@ -3325,6 +3438,10 @@ void Context::clearColorBuffer(GLint drawbuffer, void *value, sw::Format format) if(rgbaMask && !mState.rasterizerDiscardEnabled) { Framebuffer *framebuffer = getDrawFramebuffer(); + if(!framebuffer) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION); + } egl::Image *colorbuffer = framebuffer->getRenderTarget(drawbuffer); if(colorbuffer) @@ -3363,6 +3480,10 @@ void Context::clearDepthBuffer(const GLfloat value) if(mState.depthMask && !mState.rasterizerDiscardEnabled) { Framebuffer *framebuffer = getDrawFramebuffer(); + if(!framebuffer) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION); + } egl::Image *depthbuffer = framebuffer->getDepthBuffer(); if(depthbuffer) @@ -3387,6 +3508,10 @@ void Context::clearStencilBuffer(const GLint value) if(mState.stencilWritemask && !mState.rasterizerDiscardEnabled) { Framebuffer *framebuffer = getDrawFramebuffer(); + if(!framebuffer) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION); + } egl::Image *stencilbuffer = framebuffer->getStencilBuffer(); if(stencilbuffer) @@ -3408,9 +3533,14 @@ void Context::clearStencilBuffer(const GLint value) void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) { - if(!mState.currentProgram) + if(!applyRenderTarget()) { - return error(GL_INVALID_OPERATION); + return; + } + + if(mState.currentProgram == 0) + { + return; // Nothing to process. } sw::DrawType primitiveType; @@ -3418,16 +3548,8 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan int verticesPerPrimitive; if(!es2sw::ConvertPrimitiveType(mode, count, GL_NONE, primitiveType, primitiveCount, verticesPerPrimitive)) - return error(GL_INVALID_ENUM); - - if(primitiveCount <= 0) { - return; - } - - if(!applyRenderTarget()) - { - return; + return error(GL_INVALID_ENUM); } applyState(mode); @@ -3450,6 +3572,11 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan return error(GL_INVALID_OPERATION); } + if(primitiveCount <= 0) + { + return; + } + TransformFeedback* transformFeedback = getTransformFeedback(); if(!cullSkipsDraw(mode) || (transformFeedback->isActive() && !transformFeedback->isPaused())) { @@ -3464,9 +3591,14 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount) { - if(!mState.currentProgram) + if(!applyRenderTarget()) { - return error(GL_INVALID_OPERATION); + return; + } + + if(mState.currentProgram == 0) + { + return; // Nothing to process. } if(!indices && !getCurrentVertexArray()->getElementArrayBuffer()) @@ -3474,36 +3606,46 @@ void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count, return error(GL_INVALID_OPERATION); } + GLenum internalMode = mode; + if(isPrimitiveRestartFixedIndexEnabled()) + { + switch(mode) + { + case GL_TRIANGLE_FAN: + case GL_TRIANGLE_STRIP: + internalMode = GL_TRIANGLES; + break; + case GL_LINE_LOOP: + case GL_LINE_STRIP: + internalMode = GL_LINES; + break; + default: + break; + } + } + sw::DrawType primitiveType; int primitiveCount; int verticesPerPrimitive; - if(!es2sw::ConvertPrimitiveType(mode, count, type, primitiveType, primitiveCount, verticesPerPrimitive)) - return error(GL_INVALID_ENUM); - - if(primitiveCount <= 0) + if(!es2sw::ConvertPrimitiveType(internalMode, count, type, primitiveType, primitiveCount, verticesPerPrimitive)) { - return; + return error(GL_INVALID_ENUM); } - if(!applyRenderTarget()) + TranslatedIndexData indexInfo(primitiveCount); + GLenum err = applyIndexBuffer(indices, start, end, count, mode, type, &indexInfo); + if(err != GL_NO_ERROR) { - return; + return error(err); } - applyState(mode); + applyState(internalMode); for(int i = 0; i < instanceCount; ++i) { device->setInstanceID(i); - TranslatedIndexData indexInfo; - GLenum err = applyIndexBuffer(indices, start, end, count, mode, type, &indexInfo); - if(err != GL_NO_ERROR) - { - return error(err); - } - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; err = applyVertexBuffer(-(int)indexInfo.minIndex, indexInfo.minIndex, vertexCount, i); if(err != GL_NO_ERROR) @@ -3519,21 +3661,27 @@ void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count, return error(GL_INVALID_OPERATION); } + if(primitiveCount <= 0) + { + return; + } + TransformFeedback* transformFeedback = getTransformFeedback(); - if(!cullSkipsDraw(mode) || (transformFeedback->isActive() && !transformFeedback->isPaused())) + if(!cullSkipsDraw(internalMode) || (transformFeedback->isActive() && !transformFeedback->isPaused())) { - device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, primitiveCount); + device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, indexInfo.primitiveCount); } if(transformFeedback) { - transformFeedback->addVertexOffset(primitiveCount * verticesPerPrimitive); + transformFeedback->addVertexOffset(indexInfo.primitiveCount * verticesPerPrimitive); } } } void Context::blit(sw::Surface *source, const sw::SliceRect &sRect, sw::Surface *dest, const sw::SliceRect &dRect) { - device->blit(source, sRect, dest, dRect, false); + sw::SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, sRect.slice); + device->blit(source, sRectF, dest, dRect, false); } void Context::finish() @@ -3849,8 +3997,8 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 int readBufferWidth, readBufferHeight, readBufferSamples; int drawBufferWidth, drawBufferHeight, drawBufferSamples; - if(!readFramebuffer || readFramebuffer->completeness(readBufferWidth, readBufferHeight, readBufferSamples) != GL_FRAMEBUFFER_COMPLETE || - !drawFramebuffer || drawFramebuffer->completeness(drawBufferWidth, drawBufferHeight, drawBufferSamples) != GL_FRAMEBUFFER_COMPLETE) + if(!readFramebuffer || (readFramebuffer->completeness(readBufferWidth, readBufferHeight, readBufferSamples) != GL_FRAMEBUFFER_COMPLETE) || + !drawFramebuffer || (drawFramebuffer->completeness(drawBufferWidth, drawBufferHeight, drawBufferSamples) != GL_FRAMEBUFFER_COMPLETE)) { return error(GL_INVALID_FRAMEBUFFER_OPERATION); } @@ -3863,7 +4011,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 sw::SliceRect sourceRect; sw::SliceRect destRect; bool flipX = (srcX0 < srcX1) ^ (dstX0 < dstX1); - bool flipy = (srcY0 < srcY1) ^ (dstY0 < dstY1); + bool flipY = (srcY0 < srcY1) ^ (dstY0 < dstY1); if(srcX0 < srcX1) { @@ -3909,100 +4057,26 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 destRect.y1 = dstY0; } - sw::Rect sourceScissoredRect = sourceRect; + sw::RectF sourceScissoredRect(static_cast(sourceRect.x0), static_cast(sourceRect.y0), + static_cast(sourceRect.x1), static_cast(sourceRect.y1)); sw::Rect destScissoredRect = destRect; if(mState.scissorTestEnabled) // Only write to parts of the destination framebuffer which pass the scissor test { - if(destRect.x0 < mState.scissorX) - { - int xDiff = mState.scissorX - destRect.x0; - destScissoredRect.x0 = mState.scissorX; - sourceScissoredRect.x0 += xDiff; - } - - if(destRect.x1 > mState.scissorX + mState.scissorWidth) - { - int xDiff = destRect.x1 - (mState.scissorX + mState.scissorWidth); - destScissoredRect.x1 = mState.scissorX + mState.scissorWidth; - sourceScissoredRect.x1 -= xDiff; - } - - if(destRect.y0 < mState.scissorY) - { - int yDiff = mState.scissorY - destRect.y0; - destScissoredRect.y0 = mState.scissorY; - sourceScissoredRect.y0 += yDiff; - } - - if(destRect.y1 > mState.scissorY + mState.scissorHeight) - { - int yDiff = destRect.y1 - (mState.scissorY + mState.scissorHeight); - destScissoredRect.y1 = mState.scissorY + mState.scissorHeight; - sourceScissoredRect.y1 -= yDiff; - } - } - - sw::Rect sourceTrimmedRect = sourceScissoredRect; - sw::Rect destTrimmedRect = destScissoredRect; - - // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of - // the actual draw and read surfaces. - if(sourceTrimmedRect.x0 < 0) - { - int xDiff = 0 - sourceTrimmedRect.x0; - sourceTrimmedRect.x0 = 0; - destTrimmedRect.x0 += xDiff; - } - - if(sourceTrimmedRect.x1 > readBufferWidth) - { - int xDiff = sourceTrimmedRect.x1 - readBufferWidth; - sourceTrimmedRect.x1 = readBufferWidth; - destTrimmedRect.x1 -= xDiff; - } - - if(sourceTrimmedRect.y0 < 0) - { - int yDiff = 0 - sourceTrimmedRect.y0; - sourceTrimmedRect.y0 = 0; - destTrimmedRect.y0 += yDiff; - } - - if(sourceTrimmedRect.y1 > readBufferHeight) - { - int yDiff = sourceTrimmedRect.y1 - readBufferHeight; - sourceTrimmedRect.y1 = readBufferHeight; - destTrimmedRect.y1 -= yDiff; - } - - if(destTrimmedRect.x0 < 0) - { - int xDiff = 0 - destTrimmedRect.x0; - destTrimmedRect.x0 = 0; - sourceTrimmedRect.x0 += xDiff; + sw::Rect scissorRect(mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight); + Device::ClipDstRect(sourceScissoredRect, destScissoredRect, scissorRect, flipX, flipY); } - if(destTrimmedRect.x1 > drawBufferWidth) - { - int xDiff = destTrimmedRect.x1 - drawBufferWidth; - destTrimmedRect.x1 = drawBufferWidth; - sourceTrimmedRect.x1 -= xDiff; - } + sw::SliceRectF sourceTrimmedRect = sourceScissoredRect; + sw::SliceRect destTrimmedRect = destScissoredRect; - if(destTrimmedRect.y0 < 0) - { - int yDiff = 0 - destTrimmedRect.y0; - destTrimmedRect.y0 = 0; - sourceTrimmedRect.y0 += yDiff; - } + // The source & destination rectangles also may need to be trimmed if + // they fall out of the bounds of the actual draw and read surfaces. + sw::Rect sourceTrimRect(0, 0, readBufferWidth, readBufferHeight); + Device::ClipSrcRect(sourceTrimmedRect, destTrimmedRect, sourceTrimRect, flipX, flipY); - if(destTrimmedRect.y1 > drawBufferHeight) - { - int yDiff = destTrimmedRect.y1 - drawBufferHeight; - destTrimmedRect.y1 = drawBufferHeight; - sourceTrimmedRect.y1 -= yDiff; - } + sw::Rect destTrimRect(0, 0, drawBufferWidth, drawBufferHeight); + Device::ClipDstRect(sourceTrimmedRect, destTrimmedRect, destTrimRect, flipX, flipY); bool partialBufferCopy = false; @@ -4022,10 +4096,10 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if(mask & GL_COLOR_BUFFER_BIT) { - GLenum readColorbufferType = readFramebuffer->getColorbufferType(getReadFramebufferColorIndex()); + GLenum readColorbufferType = readFramebuffer->getReadBufferType(); GLenum drawColorbufferType = drawFramebuffer->getColorbufferType(0); - const bool validReadType = readColorbufferType == GL_TEXTURE_2D || Framebuffer::IsRenderbuffer(readColorbufferType); - const bool validDrawType = drawColorbufferType == GL_TEXTURE_2D || Framebuffer::IsRenderbuffer(drawColorbufferType); + const bool validReadType = readColorbufferType == GL_TEXTURE_2D || readColorbufferType == GL_TEXTURE_RECTANGLE_ARB || Framebuffer::IsRenderbuffer(readColorbufferType); + const bool validDrawType = drawColorbufferType == GL_TEXTURE_2D || drawColorbufferType == GL_TEXTURE_RECTANGLE_ARB || Framebuffer::IsRenderbuffer(drawColorbufferType); if(!validReadType || !validDrawType) { return error(GL_INVALID_OPERATION); @@ -4036,6 +4110,56 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 return error(GL_INVALID_OPERATION); } + // The GL ES 3.0.2 spec (pg 193) states that: + // 1) If the read buffer is fixed point format, the draw buffer must be as well + // 2) If the read buffer is an unsigned integer format, the draw buffer must be + // as well + // 3) If the read buffer is a signed integer format, the draw buffer must be as + // well + es2::Renderbuffer *readRenderbuffer = readFramebuffer->getReadColorbuffer(); + es2::Renderbuffer *drawRenderbuffer = drawFramebuffer->getColorbuffer(0); + GLint readFormat = readRenderbuffer->getFormat(); + GLint drawFormat = drawRenderbuffer->getFormat(); + GLenum readComponentType = GetComponentType(readFormat, GL_COLOR_ATTACHMENT0); + GLenum drawComponentType = GetComponentType(drawFormat, GL_COLOR_ATTACHMENT0); + bool readFixedPoint = ((readComponentType == GL_UNSIGNED_NORMALIZED) || + (readComponentType == GL_SIGNED_NORMALIZED)); + bool drawFixedPoint = ((drawComponentType == GL_UNSIGNED_NORMALIZED) || + (drawComponentType == GL_SIGNED_NORMALIZED)); + bool readFixedOrFloat = (readFixedPoint || (readComponentType == GL_FLOAT)); + bool drawFixedOrFloat = (drawFixedPoint || (drawComponentType == GL_FLOAT)); + + if(readFixedOrFloat != drawFixedOrFloat) + { + return error(GL_INVALID_OPERATION); + } + + if((readComponentType == GL_UNSIGNED_INT) && (drawComponentType != GL_UNSIGNED_INT)) + { + return error(GL_INVALID_OPERATION); + } + + if((readComponentType == GL_INT) && (drawComponentType != GL_INT)) + { + return error(GL_INVALID_OPERATION); + } + + // Cannot filter integer data + if(((readComponentType == GL_UNSIGNED_INT) || (readComponentType == GL_INT)) && filter) + { + return error(GL_INVALID_OPERATION); + } + + if((readRenderbuffer->getSamples() > 0) && (readFormat != drawFormat)) + { + // RGBA8 and BGRA8 should be interchangeable here + if(!(((readFormat == GL_RGBA8) && (drawFormat == GL_BGRA8_EXT)) || + ((readFormat == GL_BGRA8_EXT) && (drawFormat == GL_RGBA8)))) + { + return error(GL_INVALID_OPERATION); + } + } + blitRenderTarget = true; } @@ -4059,6 +4183,11 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 blitDepth = true; readDSBuffer = readFramebuffer->getDepthbuffer(); drawDSBuffer = drawFramebuffer->getDepthbuffer(); + + if(readDSBuffer->getFormat() != drawDSBuffer->getFormat()) + { + return error(GL_INVALID_OPERATION); + } } } @@ -4077,6 +4206,11 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 blitStencil = true; readDSBuffer = readFramebuffer->getStencilbuffer(); drawDSBuffer = drawFramebuffer->getStencilbuffer(); + + if(readDSBuffer->getFormat() != drawDSBuffer->getFormat()) + { + return error(GL_INVALID_OPERATION); + } } } @@ -4102,21 +4236,21 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if(blitRenderTarget || blitDepth || blitStencil) { + if(flipX) + { + swap(destTrimmedRect.x0, destTrimmedRect.x1); + } + if(flipY) + { + swap(destTrimmedRect.y0, destTrimmedRect.y1); + } + if(blitRenderTarget) { egl::Image *readRenderTarget = readFramebuffer->getReadRenderTarget(); egl::Image *drawRenderTarget = drawFramebuffer->getRenderTarget(0); - if(flipX) - { - swap(destRect.x0, destRect.x1); - } - if(flipy) - { - swap(destRect.y0, destRect.y1); - } - - bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, (filter ? Device::USE_FILTER : 0) | Device::COLOR_BUFFER); + bool success = device->stretchRect(readRenderTarget, &sourceTrimmedRect, drawRenderTarget, &destTrimmedRect, (filter ? Device::USE_FILTER : 0) | Device::COLOR_BUFFER); readRenderTarget->release(); drawRenderTarget->release(); @@ -4133,7 +4267,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 egl::Image *readRenderTarget = readFramebuffer->getDepthBuffer(); egl::Image *drawRenderTarget = drawFramebuffer->getDepthBuffer(); - bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, (filter ? Device::USE_FILTER : 0) | Device::DEPTH_BUFFER); + bool success = device->stretchRect(readRenderTarget, &sourceTrimmedRect, drawRenderTarget, &destTrimmedRect, (filter ? Device::USE_FILTER : 0) | Device::DEPTH_BUFFER); readRenderTarget->release(); drawRenderTarget->release(); @@ -4150,7 +4284,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 egl::Image *readRenderTarget = readFramebuffer->getStencilBuffer(); egl::Image *drawRenderTarget = drawFramebuffer->getStencilBuffer(); - bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, (filter ? Device::USE_FILTER : 0) | Device::STENCIL_BUFFER); + bool success = device->stretchRect(readRenderTarget, &sourceTrimmedRect, drawRenderTarget, &destTrimmedRect, (filter ? Device::USE_FILTER : 0) | Device::STENCIL_BUFFER); readRenderTarget->release(); drawRenderTarget->release(); @@ -4166,7 +4300,8 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 void Context::bindTexImage(gl::Surface *surface) { - es2::Texture2D *textureObject = getTexture2D(); + bool isRect = (surface->getTextureTarget() == EGL_TEXTURE_RECTANGLE_ANGLE); + es2::Texture2D *textureObject = isRect ? getTexture2DRect() : getTexture2D(); if(textureObject) { @@ -4221,7 +4356,7 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture return EGL_BAD_PARAMETER; } - if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getLevelCount() == 1)) + if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getTopLevel() == 0)) { return EGL_BAD_PARAMETER; } @@ -4308,31 +4443,37 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const "GL_OES_packed_depth_stencil", "GL_OES_rgb8_rgba8", "GL_OES_standard_derivatives", + "GL_OES_surfaceless_context", "GL_OES_texture_float", "GL_OES_texture_float_linear", "GL_OES_texture_half_float", "GL_OES_texture_half_float_linear", "GL_OES_texture_npot", "GL_OES_texture_3D", + "GL_OES_vertex_array_object", + "GL_OES_vertex_half_float", "GL_EXT_blend_minmax", "GL_EXT_color_buffer_half_float", "GL_EXT_draw_buffers", "GL_EXT_instanced_arrays", "GL_EXT_occlusion_query_boolean", "GL_EXT_read_format_bgra", -#if (S3TC_SUPPORT) "GL_EXT_texture_compression_dxt1", -#endif "GL_EXT_texture_filter_anisotropic", "GL_EXT_texture_format_BGRA8888", "GL_EXT_texture_rg", +#if (ASTC_SUPPORT) + "GL_KHR_texture_compression_astc_hdr", + "GL_KHR_texture_compression_astc_ldr", +#endif + "GL_ARB_texture_rectangle", "GL_ANGLE_framebuffer_blit", "GL_ANGLE_framebuffer_multisample", "GL_ANGLE_instanced_arrays", -#if (S3TC_SUPPORT) "GL_ANGLE_texture_compression_dxt3", "GL_ANGLE_texture_compression_dxt5", -#endif + "GL_APPLE_texture_format_BGRA8888", + "GL_CHROMIUM_color_buffer_float_rgba", // A subset of EXT_color_buffer_float on top of OpenGL ES 2.0 "GL_CHROMIUM_texture_filtering_hint", "GL_NV_fence", "GL_NV_framebuffer_blit", @@ -4370,6 +4511,14 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const { extensionsCat += std::string(extension) + " "; } + + if(clientVersion >= 3) + { + for(const char *extension : es3extensions) + { + extensionsCat += std::string(extension) + " "; + } + } } return (const GLubyte*)extensionsCat.c_str();