OSDN Git Service

Accept GL_TEXTURE_MAX_ANISOTROPY_EXT for samplers.
[android-x86/external-swiftshader.git] / src / OpenGL / libGLESv2 / Context.cpp
index 8590b54..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,16 +749,32 @@ 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);
+               }
+       }
+       else
+       {
+               return error(GL_INVALID_OPERATION);
        }
 }
 
@@ -845,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()
@@ -1174,39 +1173,11 @@ void Context::bindTransformFeedbackBuffer(GLuint buffer)
        }
 }
 
-void Context::bindTexture2D(GLuint texture)
+void Context::bindTexture(TextureType type, GLuint texture)
 {
-       mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
+       mResourceManager->checkTextureAllocation(texture, type);
 
-       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)
-{
-       mResourceManager->checkTextureAllocation(texture, TEXTURE_EXTERNAL);
-
-       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)
@@ -1579,32 +1550,46 @@ Buffer *Context::getGenericUniformBuffer() const
        return mState.genericUniformBuffer;
 }
 
-GLsizei Context::getRequiredBufferSize(GLsizei width, GLsizei height, GLsizei depth, GLint internalformat, GLenum type) const
+GLsizei Context::getRequiredBufferSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type) const
 {
-       GLenum format = GetSizedInternalFormat(internalformat, type);
-       GLsizei inputWidth = (mState.unpackInfo.rowLength == 0) ? width : mState.unpackInfo.rowLength;
-       GLsizei inputPitch = egl::ComputePitch(inputWidth, format, type, mState.unpackInfo.alignment);
-       GLsizei inputHeight = (mState.unpackInfo.imageHeight == 0) ? height : mState.unpackInfo.imageHeight;
+       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 **data, GLenum type, GLsizei imageSize) const
+GLenum Context::getPixels(const GLvoid **pixels, GLenum type, GLsizei imageSize) const
 {
        if(mState.pixelUnpackBuffer)
        {
-               if(mState.pixelUnpackBuffer->name)
+               ASSERT(mState.pixelUnpackBuffer->name != 0);
+
+               if(mState.pixelUnpackBuffer->isMapped())
                {
-                       if(mState.pixelUnpackBuffer->isMapped() ||
-                          (mState.pixelUnpackBuffer->size() < static_cast<size_t>(imageSize)) ||
-                          (static_cast<GLsizei>((ptrdiff_t)(*data)) % GetTypeSize(type)))
-                       {
-                               return GL_INVALID_OPERATION;
-                       }
+                       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;
                }
 
-               *data = static_cast<const unsigned char*>(mState.pixelUnpackBuffer->data()) + (ptrdiff_t)(*data);
+               *pixels = static_cast<const unsigned char*>(mState.pixelUnpackBuffer->data()) + offset;
        }
-       return GL_NONE;
+
+       return GL_NO_ERROR;
 }
 
 bool Context::getBuffer(GLenum target, es2::Buffer **buffer) const
@@ -1681,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));
@@ -1696,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));
@@ -1713,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);
                }
@@ -1730,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;
        }
 }
 
@@ -1752,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;
        }
 }
 
@@ -1774,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;
        }
 }
 
@@ -1796,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;
        }
 }
 
@@ -1932,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;
@@ -1965,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)
                                {
@@ -2003,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:
@@ -2047,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)
                        {
@@ -2068,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)
                        {
@@ -2083,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)
                        {
@@ -2113,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)
                {
@@ -2149,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
                {
@@ -2189,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;
@@ -2284,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();
@@ -2303,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();
@@ -2321,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;
@@ -2491,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:
@@ -2535,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:
@@ -2617,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;
@@ -2721,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);
        }
@@ -3089,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)
@@ -3103,6 +3141,7 @@ void Context::applyTextures(sw::SamplerType samplerType)
                                        maxLOD = samplerObject->getMaxLod();
                                        compFunc = samplerObject->getCompareFunc();
                                        compMode = samplerObject->getCompareMode();
+                                       maxAnisotropy = samplerObject->getMaxAnisotropy();
                                }
                                else
                                {
@@ -3115,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();
@@ -3172,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)
        {
@@ -3183,98 +3222,96 @@ void Context::applyTexture(sw::SamplerType type, int index, Texture *baseTexture
 
        if(baseTexture && textureUsed)
        {
-               int topLevel = baseTexture->getTopLevel();
+               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 > topLevel)
+                               for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
                                {
-                                       surfaceLevel = topLevel;
-                               }
+                                       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)
-               {
-                       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 > topLevel)
+                               for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
                                {
-                                       surfaceLevel = topLevel;
-                               }
+                                       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)
+                               for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
                                {
-                                       surfaceLevel = 0;
-                               }
-                               else if(surfaceLevel > topLevel)
-                               {
-                                       surfaceLevel = topLevel;
-                               }
+                                       int surfaceLevel = mipmapLevel + baseLevel;
 
-                               egl::Image *surface = texture->getImage(surfaceLevel);
-                               device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D_ARRAY);
-                       }
-               }
-               else if(baseTexture->getTarget() == GL_TEXTURE_CUBE_MAP)
-               {
-                       TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(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_2D_ARRAY);
+                               }
+                       }
+                       break;
+               case GL_TEXTURE_CUBE_MAP:
                        {
-                               cubeTexture->updateBorders(mipmapLevel);
+                               TextureCubeMap *cubeTexture = static_cast<TextureCubeMap*>(baseTexture);
 
-                               for(int face = 0; face < 6; face++)
+                               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 > topLevel)
-                                       {
-                                               surfaceLevel = topLevel;
-                                       }
+                                               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
        {
@@ -3287,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);
        }
@@ -3302,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)
@@ -3321,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:
@@ -3338,7 +3375,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
        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::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, false, false);
@@ -3356,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);
        }
@@ -3401,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)
@@ -3439,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)
@@ -3463,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)
@@ -3484,6 +3533,16 @@ void Context::clearStencilBuffer(const GLint value)
 
 void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
 {
+       if(!applyRenderTarget())
+       {
+               return;
+       }
+
+       if(mState.currentProgram == 0)
+       {
+               return;   // Nothing to process.
+       }
+
        sw::DrawType primitiveType;
        int primitiveCount;
        int verticesPerPrimitive;
@@ -3493,11 +3552,6 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
                return error(GL_INVALID_ENUM);
        }
 
-       if(!applyRenderTarget())
-       {
-               return;
-       }
-
        applyState(mode);
 
        for(int i = 0; i < instanceCount; ++i)
@@ -3510,11 +3564,6 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan
                        return error(err);
                }
 
-               if(!mState.currentProgram)
-               {
-                       return;
-               }
-
                applyShaders();
                applyTextures();
 
@@ -3542,6 +3591,16 @@ 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(!applyRenderTarget())
+       {
+               return;
+       }
+
+       if(mState.currentProgram == 0)
+       {
+               return;   // Nothing to process.
+       }
+
        if(!indices && !getCurrentVertexArray()->getElementArrayBuffer())
        {
                return error(GL_INVALID_OPERATION);
@@ -3574,11 +3633,6 @@ void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
                return error(GL_INVALID_ENUM);
        }
 
-       if(!applyRenderTarget())
-       {
-               return;
-       }
-
        TranslatedIndexData indexInfo(primitiveCount);
        GLenum err = applyIndexBuffer(indices, start, end, count, mode, type, &indexInfo);
        if(err != GL_NO_ERROR)
@@ -3599,11 +3653,6 @@ void Context::drawElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
                        return error(err);
                }
 
-               if(!mState.currentProgram)
-               {
-                       return;
-               }
-
                applyShaders();
                applyTextures();
 
@@ -3948,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);
        }
@@ -3962,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)
        {
@@ -4008,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 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;
+               sw::Rect scissorRect(mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight);
+               Device::ClipDstRect(sourceScissoredRect, destScissoredRect, scissorRect, flipX, flipY);
        }
 
-       if(sourceTrimmedRect.x1 > readBufferWidth)
-       {
-               int xDiff = sourceTrimmedRect.x1 - readBufferWidth;
-               sourceTrimmedRect.x1 = readBufferWidth;
-               destTrimmedRect.x1 -= xDiff;
-       }
+       sw::SliceRectF sourceTrimmedRect = sourceScissoredRect;
+       sw::SliceRect destTrimmedRect = destScissoredRect;
 
-       if(sourceTrimmedRect.y0 < 0)
-       {
-               int yDiff = 0 - sourceTrimmedRect.y0;
-               sourceTrimmedRect.y0 = 0;
-               destTrimmedRect.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(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;
 
@@ -4123,8 +4098,8 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
        {
                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);
@@ -4175,10 +4150,14 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
                        return error(GL_INVALID_OPERATION);
                }
 
-               if((readRenderbuffer->getSamples() > 0) &&
-                  (readRenderbuffer->getFormat() != drawRenderbuffer->getFormat()))
+               if((readRenderbuffer->getSamples() > 0) && (readFormat != drawFormat))
                {
-                       return error(GL_INVALID_OPERATION);
+                       // 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;
@@ -4257,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();
@@ -4288,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();
@@ -4305,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();
@@ -4321,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)
        {
@@ -4463,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",
@@ -4476,9 +4458,7 @@ 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",
@@ -4486,13 +4466,14 @@ const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const
                "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",