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);
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;
mTexture3DZero = nullptr;
mTexture2DArrayZero = nullptr;
mTextureCubeMapZero = nullptr;
+ mTexture2DRectZero = nullptr;
mTextureExternalZero = nullptr;
delete mVertexDataManager;
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
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
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()
}
}
-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;
{
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;
{
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;
+ }
}
}
return mTransformFeedbackNameSpace.find(transformFeedback);
}
+bool Context::isTransformFeedback(GLuint array) const
+{
+ return mTransformFeedbackNameSpace.isReserved(array);
+}
+
Sampler *Context::getSampler(GLuint sampler) const
{
return mResourceManager->getSampler(sampler);
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
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));
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));
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);
}
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->setComparisonMode(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(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;
}
}
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->setComparisonMode(static_cast<GLenum>(roundf(param))); break;
- case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(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;
}
}
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->getComparisonMode());
- case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLint>(samplerObject->getComparisonFunc());
- 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;
}
}
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->getComparisonMode());
- case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLfloat>(samplerObject->getComparisonFunc());
- 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;
}
}
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;
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)
{
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:
case GL_ALPHA_BITS:
{
Framebuffer *framebuffer = getDrawFramebuffer();
- Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
+ Renderbuffer *colorbuffer = framebuffer ? framebuffer->getColorbuffer(0) : nullptr;
if(colorbuffer)
{
case GL_DEPTH_BITS:
{
Framebuffer *framebuffer = getDrawFramebuffer();
- Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
+ Renderbuffer *depthbuffer = framebuffer ? framebuffer->getDepthbuffer() : nullptr;
if(depthbuffer)
{
case GL_STENCIL_BITS:
{
Framebuffer *framebuffer = getDrawFramebuffer();
- Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
+ Renderbuffer *stencilbuffer = framebuffer ? framebuffer->getStencilbuffer() : nullptr;
if(stencilbuffer)
{
*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)
{
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
{
*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;
*params = MAX_FRAGMENT_UNIFORM_COMPONENTS;
return true;
case GL_MAX_PROGRAM_TEXEL_OFFSET:
- UNIMPLEMENTED();
+ // Note: SwiftShader has no actual texel offset limit, so this limit can be modified if required.
+ // In any case, any behavior outside the specified range is valid since the spec mentions:
+ // (see OpenGL ES 3.0.5, 3.8.10.1 Scale Factor and Level of Detail, p.153)
+ // "If any of the offset values are outside the range of the implementation-defined values
+ // MIN_PROGRAM_TEXEL_OFFSET and MAX_PROGRAM_TEXEL_OFFSET, results of the texture lookup are
+ // undefined."
*params = MAX_PROGRAM_TEXEL_OFFSET;
return true;
case GL_MAX_SERVER_WAIT_TIMEOUT:
*params = 0;
return true;
case GL_MAX_TEXTURE_LOD_BIAS:
- UNIMPLEMENTED();
- *params = 2;
+ *params = MAX_TEXTURE_LOD_BIAS;
return true;
case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
*params = sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS;
*params = MAX_VERTEX_UNIFORM_COMPONENTS;
return true;
case GL_MIN_PROGRAM_TEXEL_OFFSET:
- UNIMPLEMENTED();
+ // Note: SwiftShader has no actual texel offset limit, so this limit can be modified if required.
+ // In any case, any behavior outside the specified range is valid since the spec mentions:
+ // (see OpenGL ES 3.0.5, 3.8.10.1 Scale Factor and Level of Detail, p.153)
+ // "If any of the offset values are outside the range of the implementation-defined values
+ // MIN_PROGRAM_TEXEL_OFFSET and MAX_PROGRAM_TEXEL_OFFSET, results of the texture lookup are
+ // undefined."
*params = MIN_PROGRAM_TEXEL_OFFSET;
return true;
case GL_MINOR_VERSION:
*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();
// 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();
*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;
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)
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:
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:
*numParams = 1;
}
break;
- case GL_MAX_SAMPLES_ANGLE:
+ case GL_MAX_SAMPLES:
{
*type = GL_INT;
*numParams = 1;
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);
}
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;
if(depthbuffer)
{
device->setSlopeDepthBias(mState.polygonOffsetFactor);
- float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
+ float depthBias = ldexp(mState.polygonOffsetUnits, -23); // We use 32-bit floating-point for all depth formats, with 23 mantissa bits.
device->setDepthBias(depthBias);
}
}
// Applies the indices and element array bindings
GLenum Context::applyIndexBuffer(const void *indices, GLuint start, GLuint end, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
{
- GLenum err = mIndexDataManager->prepareIndexData(type, start, end, count, getCurrentVertexArray()->getElementArrayBuffer(), indices, indexInfo);
+ GLenum err = mIndexDataManager->prepareIndexData(mode, type, start, end, count, getCurrentVertexArray()->getElementArrayBuffer(), indices, indexInfo, isPrimitiveRestartFixedIndexEnabled());
if(err == GL_NO_ERROR)
{
if(texture->isSamplerComplete())
{
- GLenum wrapS, wrapT, wrapR, minFilter, magFilter;
- GLfloat minLOD, maxLOD;
+ GLenum wrapS, wrapT, wrapR, minFilter, magFilter, compFunc, compMode;
+ GLfloat minLOD, maxLOD, maxAnisotropy;
Sampler *samplerObject = mState.sampler[textureUnit];
if(samplerObject)
magFilter = samplerObject->getMagFilter();
minLOD = samplerObject->getMinLod();
maxLOD = samplerObject->getMaxLod();
+ compFunc = samplerObject->getCompareFunc();
+ compMode = samplerObject->getCompareMode();
+ maxAnisotropy = samplerObject->getMaxAnisotropy();
}
else
{
magFilter = texture->getMagFilter();
minLOD = texture->getMinLOD();
maxLOD = texture->getMaxLOD();
+ compFunc = texture->getCompareFunc();
+ compMode = texture->getCompareMode();
+ maxAnisotropy = texture->getMaxAnisotropy();
}
- GLfloat maxAnisotropy = texture->getMaxAnisotropy();
GLint baseLevel = texture->getBaseLevel();
GLint maxLevel = texture->getMaxLevel();
device->setAddressingModeU(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapS));
device->setAddressingModeV(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapT));
device->setAddressingModeW(samplerType, samplerIndex, es2sw::ConvertTextureWrap(wrapR));
+ device->setCompareFunc(samplerType, samplerIndex, es2sw::ConvertCompareFunc(compFunc, compMode));
device->setSwizzleR(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleR));
device->setSwizzleG(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleG));
device->setSwizzleB(samplerType, samplerIndex, es2sw::ConvertSwizzleType(swizzleB));
device->setMaxLod(samplerType, samplerIndex, maxLOD);
device->setBaseLevel(samplerType, samplerIndex, baseLevel);
device->setMaxLevel(samplerType, samplerIndex, maxLevel);
-
device->setTextureFilter(samplerType, samplerIndex, es2sw::ConvertTextureFilter(minFilter, magFilter, maxAnisotropy));
device->setMipmapFilter(samplerType, samplerIndex, es2sw::ConvertMipMapFilter(minFilter));
device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy);
}
else UNREACHABLE(type);
- sw::Resource *resource = 0;
+ sw::Resource *resource = nullptr;
if(baseTexture && textureUsed)
{
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)
- {
- surfaceLevel = 0;
- }
- else if(surfaceLevel >= levelCount)
+ for(int face = 0; face < 6; face++)
{
- surfaceLevel = levelCount - 1;
- }
+ int surfaceLevel = mipmapLevel + baseLevel;
+
+ if(surfaceLevel > maxLevel)
+ {
+ surfaceLevel = maxLevel;
+ }
- egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);
- device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
+ egl::Image *surface = cubeTexture->getImage(face, surfaceLevel);
+ device->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
+ }
}
}
+ break;
+ default:
+ UNIMPLEMENTED();
+ break;
}
- else UNIMPLEMENTED();
}
else
{
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);
}
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)
egl::Image *renderTarget = nullptr;
switch(format)
{
- case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT: // GL_NV_read_depth
renderTarget = framebuffer->getDepthBuffer();
break;
default:
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();
Framebuffer *framebuffer = getDrawFramebuffer();
- if(!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
{
return error(GL_INVALID_FRAMEBUFFER_OPERATION);
}
if(rgbaMask && !mState.rasterizerDiscardEnabled)
{
Framebuffer *framebuffer = getDrawFramebuffer();
+ if(!framebuffer)
+ {
+ return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+ }
egl::Image *colorbuffer = framebuffer->getRenderTarget(drawbuffer);
if(colorbuffer)
if(mState.depthMask && !mState.rasterizerDiscardEnabled)
{
Framebuffer *framebuffer = getDrawFramebuffer();
+ if(!framebuffer)
+ {
+ return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+ }
egl::Image *depthbuffer = framebuffer->getDepthBuffer();
if(depthbuffer)
if(mState.stencilWritemask && !mState.rasterizerDiscardEnabled)
{
Framebuffer *framebuffer = getDrawFramebuffer();
+ if(!framebuffer)
+ {
+ return error(GL_INVALID_FRAMEBUFFER_OPERATION);
+ }
egl::Image *stencilbuffer = framebuffer->getStencilBuffer();
if(stencilbuffer)
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;
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);
return error(GL_INVALID_OPERATION);
}
+ if(primitiveCount <= 0)
+ {
+ return;
+ }
+
TransformFeedback* transformFeedback = getTransformFeedback();
if(!cullSkipsDraw(mode) || (transformFeedback->isActive() && !transformFeedback->isPaused()))
{
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())
return error(GL_INVALID_OPERATION);
}
+ GLenum internalMode = mode;
+ if(isPrimitiveRestartFixedIndexEnabled())
+ {
+ switch(mode)
+ {
+ case GL_TRIANGLE_FAN:
+ case GL_TRIANGLE_STRIP:
+ internalMode = GL_TRIANGLES;
+ break;
+ case GL_LINE_LOOP:
+ case GL_LINE_STRIP:
+ internalMode = GL_LINES;
+ break;
+ default:
+ break;
+ }
+ }
+
sw::DrawType primitiveType;
int primitiveCount;
int verticesPerPrimitive;
- if(!es2sw::ConvertPrimitiveType(mode, count, type, primitiveType, primitiveCount, verticesPerPrimitive))
- return error(GL_INVALID_ENUM);
-
- if(primitiveCount <= 0)
+ if(!es2sw::ConvertPrimitiveType(internalMode, count, type, primitiveType, primitiveCount, verticesPerPrimitive))
{
- return;
+ return error(GL_INVALID_ENUM);
}
- if(!applyRenderTarget())
+ TranslatedIndexData indexInfo(primitiveCount);
+ GLenum err = applyIndexBuffer(indices, start, end, count, mode, type, &indexInfo);
+ if(err != GL_NO_ERROR)
{
- return;
+ return error(err);
}
- applyState(mode);
+ applyState(internalMode);
for(int i = 0; i < instanceCount; ++i)
{
device->setInstanceID(i);
- TranslatedIndexData indexInfo;
- GLenum err = applyIndexBuffer(indices, start, end, count, mode, type, &indexInfo);
- if(err != GL_NO_ERROR)
- {
- return error(err);
- }
-
GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
err = applyVertexBuffer(-(int)indexInfo.minIndex, indexInfo.minIndex, vertexCount, i);
if(err != GL_NO_ERROR)
return error(GL_INVALID_OPERATION);
}
+ if(primitiveCount <= 0)
+ {
+ return;
+ }
+
TransformFeedback* transformFeedback = getTransformFeedback();
- if(!cullSkipsDraw(mode) || (transformFeedback->isActive() && !transformFeedback->isPaused()))
+ if(!cullSkipsDraw(internalMode) || (transformFeedback->isActive() && !transformFeedback->isPaused()))
{
- device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, primitiveCount);
+ device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, indexInfo.primitiveCount);
}
if(transformFeedback)
{
- transformFeedback->addVertexOffset(primitiveCount * verticesPerPrimitive);
+ transformFeedback->addVertexOffset(indexInfo.primitiveCount * verticesPerPrimitive);
}
}
}
void Context::blit(sw::Surface *source, const sw::SliceRect &sRect, sw::Surface *dest, const sw::SliceRect &dRect)
{
- device->blit(source, sRect, dest, dRect, false);
+ sw::SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, sRect.slice);
+ device->blit(source, sRectF, dest, dRect, false);
}
void Context::finish()
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);
}
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)
{
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;
- }
-
- if(sourceTrimmedRect.x1 > readBufferWidth)
- {
- int xDiff = sourceTrimmedRect.x1 - readBufferWidth;
- sourceTrimmedRect.x1 = readBufferWidth;
- destTrimmedRect.x1 -= xDiff;
- }
-
- if(sourceTrimmedRect.y0 < 0)
- {
- int yDiff = 0 - sourceTrimmedRect.y0;
- sourceTrimmedRect.y0 = 0;
- destTrimmedRect.y0 += yDiff;
- }
-
- if(sourceTrimmedRect.y1 > readBufferHeight)
- {
- int yDiff = sourceTrimmedRect.y1 - readBufferHeight;
- sourceTrimmedRect.y1 = readBufferHeight;
- destTrimmedRect.y1 -= yDiff;
- }
-
- if(destTrimmedRect.x0 < 0)
- {
- int xDiff = 0 - destTrimmedRect.x0;
- destTrimmedRect.x0 = 0;
- sourceTrimmedRect.x0 += xDiff;
+ sw::Rect scissorRect(mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight);
+ Device::ClipDstRect(sourceScissoredRect, destScissoredRect, scissorRect, flipX, flipY);
}
- if(destTrimmedRect.x1 > drawBufferWidth)
- {
- int xDiff = destTrimmedRect.x1 - drawBufferWidth;
- destTrimmedRect.x1 = drawBufferWidth;
- sourceTrimmedRect.x1 -= xDiff;
- }
+ sw::SliceRectF sourceTrimmedRect = sourceScissoredRect;
+ sw::SliceRect destTrimmedRect = destScissoredRect;
- if(destTrimmedRect.y0 < 0)
- {
- int yDiff = 0 - destTrimmedRect.y0;
- destTrimmedRect.y0 = 0;
- sourceTrimmedRect.y0 += yDiff;
- }
+ // The source & destination rectangles also may need to be trimmed if
+ // they fall out of the bounds of the actual draw and read surfaces.
+ sw::Rect sourceTrimRect(0, 0, readBufferWidth, readBufferHeight);
+ Device::ClipSrcRect(sourceTrimmedRect, destTrimmedRect, sourceTrimRect, flipX, flipY);
- if(destTrimmedRect.y1 > drawBufferHeight)
- {
- int yDiff = destTrimmedRect.y1 - drawBufferHeight;
- destTrimmedRect.y1 = drawBufferHeight;
- sourceTrimmedRect.y1 -= yDiff;
- }
+ sw::Rect destTrimRect(0, 0, drawBufferWidth, drawBufferHeight);
+ Device::ClipDstRect(sourceTrimmedRect, destTrimmedRect, destTrimRect, flipX, flipY);
bool partialBufferCopy = false;
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);
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;
}
blitDepth = true;
readDSBuffer = readFramebuffer->getDepthbuffer();
drawDSBuffer = drawFramebuffer->getDepthbuffer();
+
+ if(readDSBuffer->getFormat() != drawDSBuffer->getFormat())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
}
}
blitStencil = true;
readDSBuffer = readFramebuffer->getStencilbuffer();
drawDSBuffer = drawFramebuffer->getStencilbuffer();
+
+ if(readDSBuffer->getFormat() != drawDSBuffer->getFormat())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
}
}
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();
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();
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();
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)
{
return EGL_BAD_PARAMETER;
}
- if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getLevelCount() == 1))
+ if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getTopLevel() == 0))
{
return EGL_BAD_PARAMETER;
}
"GL_OES_packed_depth_stencil",
"GL_OES_rgb8_rgba8",
"GL_OES_standard_derivatives",
+ "GL_OES_surfaceless_context",
"GL_OES_texture_float",
"GL_OES_texture_float_linear",
"GL_OES_texture_half_float",
"GL_OES_texture_half_float_linear",
"GL_OES_texture_npot",
"GL_OES_texture_3D",
+ "GL_OES_vertex_array_object",
+ "GL_OES_vertex_half_float",
"GL_EXT_blend_minmax",
"GL_EXT_color_buffer_half_float",
"GL_EXT_draw_buffers",
"GL_EXT_instanced_arrays",
"GL_EXT_occlusion_query_boolean",
"GL_EXT_read_format_bgra",
-#if (S3TC_SUPPORT)
"GL_EXT_texture_compression_dxt1",
-#endif
"GL_EXT_texture_filter_anisotropic",
"GL_EXT_texture_format_BGRA8888",
"GL_EXT_texture_rg",
+#if (ASTC_SUPPORT)
+ "GL_KHR_texture_compression_astc_hdr",
+ "GL_KHR_texture_compression_astc_ldr",
+#endif
+ "GL_ARB_texture_rectangle",
"GL_ANGLE_framebuffer_blit",
"GL_ANGLE_framebuffer_multisample",
"GL_ANGLE_instanced_arrays",
-#if (S3TC_SUPPORT)
"GL_ANGLE_texture_compression_dxt3",
"GL_ANGLE_texture_compression_dxt5",
-#endif
+ "GL_APPLE_texture_format_BGRA8888",
+ "GL_CHROMIUM_color_buffer_float_rgba", // A subset of EXT_color_buffer_float on top of OpenGL ES 2.0
"GL_CHROMIUM_texture_filtering_hint",
"GL_NV_fence",
"GL_NV_framebuffer_blit",
{
extensionsCat += std::string(extension) + " ";
}
+
+ if(clientVersion >= 3)
+ {
+ for(const char *extension : es3extensions)
+ {
+ extensionsCat += std::string(extension) + " ";
+ }
+ }
}
return (const GLubyte*)extensionsCat.c_str();