OSDN Git Service

Accept GL_TEXTURE_MAX_ANISOTROPY_EXT for samplers.
[android-x86/external-swiftshader.git] / src / OpenGL / libGLESv2 / Context.cpp
index 9eefb3f..7bd9fea 100644 (file)
@@ -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<const unsigned char*>(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<size_t>((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<size_t>(imageSize))
+               {
+                       return GL_INVALID_OPERATION;
+               }
+
+               *pixels = static_cast<const unsigned char*>(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<Texture2D*>(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<Texture3D*>(getSamplerTexture(mState.activeSampler, TEXTURE_3D));
@@ -1652,6 +1694,11 @@ TextureCubeMap *Context::getTextureCubeMap() const
        return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
 }
 
+Texture2DRect *Context::getTexture2DRect() const
+{
+       return static_cast<Texture2DRect*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D_RECT));
+}
+
 TextureExternal *Context::getTextureExternal() const
 {
        return static_cast<TextureExternal*>(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<GLenum>(param));   break;
-       case GL_TEXTURE_MAG_FILTER:   samplerObject->setMagFilter(static_cast<GLenum>(param));   break;
-       case GL_TEXTURE_WRAP_S:       samplerObject->setWrapS(static_cast<GLenum>(param));       break;
-       case GL_TEXTURE_WRAP_T:       samplerObject->setWrapT(static_cast<GLenum>(param));       break;
-       case GL_TEXTURE_WRAP_R:       samplerObject->setWrapR(static_cast<GLenum>(param));       break;
-       case GL_TEXTURE_MIN_LOD:      samplerObject->setMinLod(static_cast<GLfloat>(param));     break;
-       case GL_TEXTURE_MAX_LOD:      samplerObject->setMaxLod(static_cast<GLfloat>(param));     break;
-       case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast<GLenum>(param)); break;
-       case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast<GLenum>(param)); break;
-       default:                      UNREACHABLE(pname); break;
+       case GL_TEXTURE_MIN_FILTER:         samplerObject->setMinFilter(static_cast<GLenum>(param));      break;
+       case GL_TEXTURE_MAG_FILTER:         samplerObject->setMagFilter(static_cast<GLenum>(param));      break;
+       case GL_TEXTURE_WRAP_S:             samplerObject->setWrapS(static_cast<GLenum>(param));          break;
+       case GL_TEXTURE_WRAP_T:             samplerObject->setWrapT(static_cast<GLenum>(param));          break;
+       case GL_TEXTURE_WRAP_R:             samplerObject->setWrapR(static_cast<GLenum>(param));          break;
+       case GL_TEXTURE_MIN_LOD:            samplerObject->setMinLod(static_cast<GLfloat>(param));        break;
+       case GL_TEXTURE_MAX_LOD:            samplerObject->setMaxLod(static_cast<GLfloat>(param));        break;
+       case GL_TEXTURE_COMPARE_MODE:       samplerObject->setCompareMode(static_cast<GLenum>(param));    break;
+       case GL_TEXTURE_COMPARE_FUNC:       samplerObject->setCompareFunc(static_cast<GLenum>(param));    break;
+       case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(static_cast<GLfloat>(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<GLenum>(roundf(param)));   break;
-       case GL_TEXTURE_MAG_FILTER:   samplerObject->setMagFilter(static_cast<GLenum>(roundf(param)));   break;
-       case GL_TEXTURE_WRAP_S:       samplerObject->setWrapS(static_cast<GLenum>(roundf(param)));       break;
-       case GL_TEXTURE_WRAP_T:       samplerObject->setWrapT(static_cast<GLenum>(roundf(param)));       break;
-       case GL_TEXTURE_WRAP_R:       samplerObject->setWrapR(static_cast<GLenum>(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<GLenum>(roundf(param))); break;
-       case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast<GLenum>(roundf(param))); break;
-       default:                      UNREACHABLE(pname); break;
+       case GL_TEXTURE_MIN_FILTER:         samplerObject->setMinFilter(static_cast<GLenum>(roundf(param)));   break;
+       case GL_TEXTURE_MAG_FILTER:         samplerObject->setMagFilter(static_cast<GLenum>(roundf(param)));   break;
+       case GL_TEXTURE_WRAP_S:             samplerObject->setWrapS(static_cast<GLenum>(roundf(param)));       break;
+       case GL_TEXTURE_WRAP_T:             samplerObject->setWrapT(static_cast<GLenum>(roundf(param)));       break;
+       case GL_TEXTURE_WRAP_R:             samplerObject->setWrapR(static_cast<GLenum>(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<GLenum>(roundf(param))); break;
+       case GL_TEXTURE_COMPARE_FUNC:       samplerObject->setCompareFunc(static_cast<GLenum>(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<GLint>(samplerObject->getMinFilter());
-       case GL_TEXTURE_MAG_FILTER:   return static_cast<GLint>(samplerObject->getMagFilter());
-       case GL_TEXTURE_WRAP_S:       return static_cast<GLint>(samplerObject->getWrapS());
-       case GL_TEXTURE_WRAP_T:       return static_cast<GLint>(samplerObject->getWrapT());
-       case GL_TEXTURE_WRAP_R:       return static_cast<GLint>(samplerObject->getWrapR());
-       case GL_TEXTURE_MIN_LOD:      return static_cast<GLint>(roundf(samplerObject->getMinLod()));
-       case GL_TEXTURE_MAX_LOD:      return static_cast<GLint>(roundf(samplerObject->getMaxLod()));
-       case GL_TEXTURE_COMPARE_MODE: return static_cast<GLint>(samplerObject->getCompareMode());
-       case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLint>(samplerObject->getCompareFunc());
-       default:                      UNREACHABLE(pname); return 0;
+       case GL_TEXTURE_MIN_FILTER:         return static_cast<GLint>(samplerObject->getMinFilter());
+       case GL_TEXTURE_MAG_FILTER:         return static_cast<GLint>(samplerObject->getMagFilter());
+       case GL_TEXTURE_WRAP_S:             return static_cast<GLint>(samplerObject->getWrapS());
+       case GL_TEXTURE_WRAP_T:             return static_cast<GLint>(samplerObject->getWrapT());
+       case GL_TEXTURE_WRAP_R:             return static_cast<GLint>(samplerObject->getWrapR());
+       case GL_TEXTURE_MIN_LOD:            return static_cast<GLint>(roundf(samplerObject->getMinLod()));
+       case GL_TEXTURE_MAX_LOD:            return static_cast<GLint>(roundf(samplerObject->getMaxLod()));
+       case GL_TEXTURE_COMPARE_MODE:       return static_cast<GLint>(samplerObject->getCompareMode());
+       case GL_TEXTURE_COMPARE_FUNC:       return static_cast<GLint>(samplerObject->getCompareFunc());
+       case GL_TEXTURE_MAX_ANISOTROPY_EXT: return static_cast<GLint>(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<GLfloat>(samplerObject->getMinFilter());
-       case GL_TEXTURE_MAG_FILTER:   return static_cast<GLfloat>(samplerObject->getMagFilter());
-       case GL_TEXTURE_WRAP_S:       return static_cast<GLfloat>(samplerObject->getWrapS());
-       case GL_TEXTURE_WRAP_T:       return static_cast<GLfloat>(samplerObject->getWrapT());
-       case GL_TEXTURE_WRAP_R:       return static_cast<GLfloat>(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<GLfloat>(samplerObject->getCompareMode());
-       case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLfloat>(samplerObject->getCompareFunc());
-       default:                      UNREACHABLE(pname); return 0;
+       case GL_TEXTURE_MIN_FILTER:         return static_cast<GLfloat>(samplerObject->getMinFilter());
+       case GL_TEXTURE_MAG_FILTER:         return static_cast<GLfloat>(samplerObject->getMagFilter());
+       case GL_TEXTURE_WRAP_S:             return static_cast<GLfloat>(samplerObject->getWrapS());
+       case GL_TEXTURE_WRAP_T:             return static_cast<GLfloat>(samplerObject->getWrapT());
+       case GL_TEXTURE_WRAP_R:             return static_cast<GLfloat>(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<GLfloat>(samplerObject->getCompareMode());
+       case GL_TEXTURE_COMPARE_FUNC:       return static_cast<GLfloat>(samplerObject->getCompareFunc());
+       case GL_TEXTURE_MAX_ANISOTROPY_EXT: return samplerObject->getMaxAnisotropy();
+       default:                            UNREACHABLE(pname); return 0;
        }
 }
 
@@ -1888,12 +1940,12 @@ template<typename T> 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<typename T> 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<typename T> 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<typename T> 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<typename T> 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<typename T> 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<typename T> 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<typename T> 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<typename T> 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;
@@ -2240,13 +2317,13 @@ template<typename T> 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();
@@ -2259,7 +2336,10 @@ template<typename T> 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();
@@ -2277,19 +2357,19 @@ template<typename T> bool Context::getIntegerv(GLenum pname, T *params) const
                        *params = static_cast<T>(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;
@@ -2379,6 +2459,20 @@ template bool Context::getUniformBufferiv<GLint64>(GLuint index, GLenum pname, G
 
 template<typename T> 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)
@@ -2433,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:
@@ -2477,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:
@@ -2559,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;
@@ -2663,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);
        }
@@ -2673,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;
@@ -3028,7 +3127,7 @@ void Context::applyTextures(sw::SamplerType samplerType)
                        if(texture->isSamplerComplete())
                        {
                                GLenum wrapS, wrapT, wrapR, minFilter, magFilter, compFunc, compMode;
-                               GLfloat minLOD, maxLOD;
+                               GLfloat minLOD, maxLOD, maxAnisotropy;
 
                                Sampler *samplerObject = mState.sampler[textureUnit];
                                if(samplerObject)
@@ -3042,6 +3141,7 @@ void Context::applyTextures(sw::SamplerType samplerType)
                                        maxLOD = samplerObject->getMaxLod();
                                        compFunc = samplerObject->getCompareFunc();
                                        compMode = samplerObject->getCompareMode();
+                                       maxAnisotropy = samplerObject->getMaxAnisotropy();
                                }
                                else
                                {
@@ -3054,9 +3154,9 @@ void Context::applyTextures(sw::SamplerType samplerType)
                                        maxLOD = texture->getMaxLOD();
                                        compFunc = texture->getCompareFunc();
                                        compMode = texture->getCompareMode();
+                                       maxAnisotropy = texture->getMaxAnisotropy();
                                }
 
-                               GLfloat maxAnisotropy = texture->getMaxAnisotropy();
                                GLint baseLevel = texture->getBaseLevel();
                                GLint maxLevel = texture->getMaxLevel();
                                GLenum swizzleR = texture->getSwizzleR();
@@ -3111,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)
        {
@@ -3122,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<Texture2D*>(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<Texture2D*>(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<Texture3D*>(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<Texture3D*>(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<Texture2DArray*>(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<Texture2DArray*>(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<TextureCubeMap*>(baseTexture);
 
                                for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
                                {
-                                       int surfaceLevel = mipmapLevel;
+                                       cubeTexture->updateBorders(mipmapLevel);
 
-                                       if(surfaceLevel < 0)
+                                       for(int face = 0; face < 6; face++)
                                        {
-                                               surfaceLevel = 0;
-                                       }
-                                       else if(surfaceLevel >= levelCount)
-                                       {
-                                               surfaceLevel = levelCount - 1;
-                                       }
+                                               int surfaceLevel = mipmapLevel + baseLevel;
 
-                                       egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);
-                                       device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
+                                               if(surfaceLevel > maxLevel)
+                                               {
+                                                       surfaceLevel = maxLevel;
+                                               }
+
+                                               egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);
+                                               device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
+                                       }
                                }
                        }
+                       break;
+               default:
+                       UNIMPLEMENTED();
+                       break;
                }
-               else UNIMPLEMENTED();
        }
        else
        {
@@ -3224,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);
        }
@@ -3239,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)
@@ -3258,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:
@@ -3271,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();
@@ -3293,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);
        }
@@ -3338,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)
@@ -3376,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)
@@ -3400,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)
@@ -3421,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;
@@ -3431,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);
@@ -3463,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()))
                {
@@ -3477,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())
@@ -3510,16 +3629,8 @@ void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
        int verticesPerPrimitive;
 
        if(!es2sw::ConvertPrimitiveType(internalMode, count, type, primitiveType, primitiveCount, verticesPerPrimitive))
-               return error(GL_INVALID_ENUM);
-
-       if(primitiveCount <= 0)
-       {
-               return;
-       }
-
-       if(!applyRenderTarget())
        {
-               return;
+               return error(GL_INVALID_ENUM);
        }
 
        TranslatedIndexData indexInfo(primitiveCount);
@@ -3550,6 +3661,11 @@ 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(internalMode) || (transformFeedback->isActive() && !transformFeedback->isPaused()))
                {
@@ -3564,7 +3680,8 @@ void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
 
 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()
@@ -3880,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);
        }
@@ -3894,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)
        {
@@ -3940,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<float>(sourceRect.x0), static_cast<float>(sourceRect.y0),
+                                     static_cast<float>(sourceRect.x1), static_cast<float>(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 scissorRect(mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight);
+               Device::ClipDstRect(sourceScissoredRect, destScissoredRect, scissorRect, flipX, flipY);
        }
 
-       sw::Rect sourceTrimmedRect = sourceScissoredRect;
-       sw::Rect destTrimmedRect = destScissoredRect;
+       sw::SliceRectF sourceTrimmedRect = sourceScissoredRect;
+       sw::SliceRect 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;
-       }
+       // 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(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;
-       }
-
-       if(destTrimmedRect.x1 > drawBufferWidth)
-       {
-               int xDiff = destTrimmedRect.x1 - drawBufferWidth;
-               destTrimmedRect.x1 = drawBufferWidth;
-               sourceTrimmedRect.x1 -= xDiff;
-       }
-
-       if(destTrimmedRect.y0 < 0)
-       {
-               int yDiff = 0 - destTrimmedRect.y0;
-               destTrimmedRect.y0 = 0;
-               sourceTrimmedRect.y0 += yDiff;
-       }
-
-       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;
 
@@ -4053,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);
@@ -4067,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;
        }
 
@@ -4090,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);
+                               }
                        }
                }
 
@@ -4108,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);
+                               }
                        }
                }
 
@@ -4133,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();
@@ -4164,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();
@@ -4181,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();
@@ -4197,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)
        {
@@ -4252,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;
                }
@@ -4339,12 +4443,14 @@ 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",
@@ -4352,19 +4458,22 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const
                "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",