Apply the Apache 2.0 license. Change-Id: I4a7aeefedcd2d891093520d5a10ebefadcddb5be Reviewed-on: https://swiftshader-review.googlesource.com/5320 Reviewed-by: Nicolas Capens <capn@google.com> Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLES_CM/Buffer.cpp b/src/OpenGL/libGLES_CM/Buffer.cpp index 7377d03..2947284 100644 --- a/src/OpenGL/libGLES_CM/Buffer.cpp +++ b/src/OpenGL/libGLES_CM/Buffer.cpp
@@ -1,13 +1,16 @@ -// SwiftShader Software Renderer +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright(c) 2005-2013 TransGaming Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Buffer.cpp: Implements the Buffer class, representing storage of vertex and/or // index data. Implements GL buffer objects and related functionality.
diff --git a/src/OpenGL/libGLES_CM/Buffer.h b/src/OpenGL/libGLES_CM/Buffer.h index 0310d1c..0ad1069 100644 --- a/src/OpenGL/libGLES_CM/Buffer.h +++ b/src/OpenGL/libGLES_CM/Buffer.h
@@ -1,53 +1,56 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// Buffer.h: Defines the Buffer class, representing storage of vertex and/or -// index data. Implements GL buffer objects and related functionality. -// [OpenGL ES 2.0.24] section 2.9 page 21. - -#ifndef LIBGLES_CM_BUFFER_H_ -#define LIBGLES_CM_BUFFER_H_ - -#include "common/Object.hpp" -#include "Common/Resource.hpp" - -#include <GLES/gl.h> - -#include <cstddef> -#include <vector> - -namespace es1 -{ -class Buffer : public gl::NamedObject -{ - public: - explicit Buffer(GLuint name); - - virtual ~Buffer(); - - void bufferData(const void *data, GLsizeiptr size, GLenum usage); - void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); - - const void *data() { return mContents ? mContents->data() : 0; } - size_t size() const { return mSize; } - GLenum usage() const { return mUsage; } - - sw::Resource *getResource(); - - private: - sw::Resource *mContents; - size_t mSize; - GLenum mUsage; -}; - -} - -#endif // LIBGLES_CM_BUFFER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Buffer.h: Defines the Buffer class, representing storage of vertex and/or +// index data. Implements GL buffer objects and related functionality. +// [OpenGL ES 2.0.24] section 2.9 page 21. + +#ifndef LIBGLES_CM_BUFFER_H_ +#define LIBGLES_CM_BUFFER_H_ + +#include "common/Object.hpp" +#include "Common/Resource.hpp" + +#include <GLES/gl.h> + +#include <cstddef> +#include <vector> + +namespace es1 +{ +class Buffer : public gl::NamedObject +{ +public: + explicit Buffer(GLuint name); + + virtual ~Buffer(); + + void bufferData(const void *data, GLsizeiptr size, GLenum usage); + void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); + + const void *data() { return mContents ? mContents->data() : 0; } + size_t size() const { return mSize; } + GLenum usage() const { return mUsage; } + + sw::Resource *getResource(); + +private: + sw::Resource *mContents; + size_t mSize; + GLenum mUsage; +}; + +} + +#endif // LIBGLES_CM_BUFFER_H_
diff --git a/src/OpenGL/libGLES_CM/Context.cpp b/src/OpenGL/libGLES_CM/Context.cpp index 0b1ce44..b659bd9 100644 --- a/src/OpenGL/libGLES_CM/Context.cpp +++ b/src/OpenGL/libGLES_CM/Context.cpp
@@ -1,3456 +1,3458 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// Context.cpp: Implements the es1::Context class, managing all GL state and performing -// rendering operations. It is the GLES2 specific implementation of EGLContext. - -#include "Context.h" - -#include "main.h" -#include "mathutil.h" -#include "utilities.h" -#include "ResourceManager.h" -#include "Buffer.h" -#include "Framebuffer.h" -#include "Renderbuffer.h" -#include "Texture.h" -#include "VertexDataManager.h" -#include "IndexDataManager.h" -#include "libEGL/Display.h" -#include "libEGL/Surface.h" -#include "Common/Half.hpp" - -#include <EGL/eglext.h> - -using std::abs; - -namespace es1 -{ -Context::Context(const egl::Config *config, const Context *shareContext) - : modelViewStack(MAX_MODELVIEW_STACK_DEPTH), - projectionStack(MAX_PROJECTION_STACK_DEPTH), - textureStack0(MAX_TEXTURE_STACK_DEPTH), - textureStack1(MAX_TEXTURE_STACK_DEPTH) -{ - sw::Context *context = new sw::Context(); - device = new es1::Device(context); - - mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new IndexDataManager(); - - setClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - mState.depthClearValue = 1.0f; - mState.stencilClearValue = 0; - - mState.cullFaceEnabled = false; - mState.cullMode = GL_BACK; - mState.frontFace = GL_CCW; - mState.depthTestEnabled = false; - mState.depthFunc = GL_LESS; - mState.blendEnabled = false; - mState.sourceBlendRGB = GL_ONE; - mState.sourceBlendAlpha = GL_ONE; - mState.destBlendRGB = GL_ZERO; - mState.destBlendAlpha = GL_ZERO; - mState.blendEquationRGB = GL_FUNC_ADD_OES; - mState.blendEquationAlpha = GL_FUNC_ADD_OES; - mState.stencilTestEnabled = false; - mState.stencilFunc = GL_ALWAYS; - mState.stencilRef = 0; - mState.stencilMask = -1; - mState.stencilWritemask = -1; - mState.stencilFail = GL_KEEP; - mState.stencilPassDepthFail = GL_KEEP; - mState.stencilPassDepthPass = GL_KEEP; - mState.polygonOffsetFillEnabled = false; - mState.polygonOffsetFactor = 0.0f; - mState.polygonOffsetUnits = 0.0f; - mState.sampleAlphaToCoverageEnabled = false; - mState.sampleCoverageEnabled = false; - mState.sampleCoverageValue = 1.0f; - mState.sampleCoverageInvert = false; - mState.scissorTestEnabled = false; - mState.ditherEnabled = true; - mState.shadeModel = GL_SMOOTH; - mState.generateMipmapHint = GL_DONT_CARE; - mState.perspectiveCorrectionHint = GL_DONT_CARE; - mState.fogHint = GL_DONT_CARE; - - mState.lineWidth = 1.0f; - - mState.viewportX = 0; - mState.viewportY = 0; - mState.viewportWidth = 0; - mState.viewportHeight = 0; - mState.zNear = 0.0f; - mState.zFar = 1.0f; - - mState.scissorX = 0; - mState.scissorY = 0; - mState.scissorWidth = 0; - mState.scissorHeight = 0; - - mState.colorMaskRed = true; - mState.colorMaskGreen = true; - mState.colorMaskBlue = true; - mState.colorMaskAlpha = true; - mState.depthMask = true; - - for(int i = 0; i < MAX_TEXTURE_UNITS; i++) - { - mState.textureUnit[i].color = {0, 0, 0, 0}; - mState.textureUnit[i].environmentMode = GL_MODULATE; - mState.textureUnit[i].combineRGB = GL_MODULATE; - mState.textureUnit[i].combineAlpha = GL_MODULATE; - mState.textureUnit[i].src0RGB = GL_TEXTURE; - mState.textureUnit[i].src1RGB = GL_PREVIOUS; - mState.textureUnit[i].src2RGB = GL_CONSTANT; - mState.textureUnit[i].src0Alpha = GL_TEXTURE; - mState.textureUnit[i].src1Alpha = GL_PREVIOUS; - mState.textureUnit[i].src2Alpha = GL_CONSTANT; - mState.textureUnit[i].operand0RGB = GL_SRC_COLOR; - mState.textureUnit[i].operand1RGB = GL_SRC_COLOR; - mState.textureUnit[i].operand2RGB = GL_SRC_ALPHA; - mState.textureUnit[i].operand0Alpha = GL_SRC_ALPHA; - mState.textureUnit[i].operand1Alpha = GL_SRC_ALPHA; - mState.textureUnit[i].operand2Alpha = GL_SRC_ALPHA; - } - - if(shareContext) - { - mResourceManager = shareContext->mResourceManager; - mResourceManager->addRef(); - } - else - { - mResourceManager = new ResourceManager(); - } - - // [OpenGL ES 2.0.24] section 3.7 page 83: - // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional - // and cube map texture state vectors respectively associated with them. - // In order that access to these initial textures not be lost, they are treated as texture - // objects all of whose names are 0. - - mTexture2DZero = new Texture2D(0); - mTextureExternalZero = new TextureExternal(0); - - mState.activeSampler = 0; - bindArrayBuffer(0); - bindElementArrayBuffer(0); - bindTexture2D(0); - bindFramebuffer(0); - bindRenderbuffer(0); - - mState.packAlignment = 4; - mState.unpackAlignment = 4; - - mInvalidEnum = false; - mInvalidValue = false; - mInvalidOperation = false; - mOutOfMemory = false; - mInvalidFramebufferOperation = false; - mMatrixStackOverflow = false; - mMatrixStackUnderflow = false; - - lightingEnabled = false; - - for(int i = 0; i < MAX_LIGHTS; i++) - { - light[i].enabled = false; - light[i].ambient = {0.0f, 0.0f, 0.0f, 1.0f}; - light[i].diffuse = {0.0f, 0.0f, 0.0f, 1.0f}; - light[i].specular = {0.0f, 0.0f, 0.0f, 1.0f}; - light[i].position = {0.0f, 0.0f, 1.0f, 0.0f}; - light[i].direction = {0.0f, 0.0f, -1.0f}; - light[i].attenuation = {1.0f, 0.0f, 0.0f}; - light[i].spotExponent = 0.0f; - light[i].spotCutoffAngle = 180.0f; - } - - light[0].diffuse = {1.0f, 1.0f, 1.0f, 1.0f}; - light[0].specular = {1.0f, 1.0f, 1.0f, 1.0f}; - - globalAmbient = {0.2f, 0.2f, 0.2f, 1.0f}; - materialAmbient = {0.2f, 0.2f, 0.2f, 1.0f}; - materialDiffuse = {0.8f, 0.8f, 0.8f, 1.0f}; - materialSpecular = {0.0f, 0.0f, 0.0f, 1.0f}; - materialEmission = {0.0f, 0.0f, 0.0f, 1.0f}; - materialShininess = 0.0f; - lightModelTwoSide = false; - - matrixMode = GL_MODELVIEW; - - for(int i = 0; i < MAX_TEXTURE_UNITS; i++) - { - texture2Denabled[i] = false; - textureExternalEnabled[i] = false; - } - - clientTexture = GL_TEXTURE0; - - setVertexAttrib(sw::Color0, 1.0f, 1.0f, 1.0f, 1.0f); - - for(int i = 0; i < MAX_TEXTURE_UNITS; i++) - { - setVertexAttrib(sw::TexCoord0 + i, 0.0f, 0.0f, 0.0f, 1.0f); - } - - setVertexAttrib(sw::Normal, 0.0f, 0.0f, 1.0f, 1.0f); - setVertexAttrib(sw::PointSize, 1.0f, 1.0f, 1.0f, 1.0f); - - clipFlags = 0; - - alphaTestEnabled = false; - alphaTestFunc = GL_ALWAYS; - alphaTestRef = 0; - - fogEnabled = false; - fogMode = GL_EXP; - fogDensity = 1.0f; - fogStart = 0.0f; - fogEnd = 1.0f; - fogColor = {0, 0, 0, 0}; - - lineSmoothEnabled = false; - colorMaterialEnabled = false; - normalizeEnabled = false; - rescaleNormalEnabled = false; - multisampleEnabled = true; - sampleAlphaToOneEnabled = false; - - colorLogicOpEnabled = false; - logicalOperation = GL_COPY; - - pointSpriteEnabled = false; - pointSmoothEnabled = false; - pointSizeMin = 0.0f; - pointSizeMax = 1.0f; - pointDistanceAttenuation = {1.0f, 0.0f, 0.0f}; - pointFadeThresholdSize = 1.0f; - - mHasBeenCurrent = false; - - markAllStateDirty(); -} - -Context::~Context() -{ - while(!mFramebufferNameSpace.empty()) - { - deleteFramebuffer(mFramebufferNameSpace.firstName()); - } - - for(int type = 0; type < TEXTURE_TYPE_COUNT; type++) - { - for(int sampler = 0; sampler < MAX_TEXTURE_UNITS; sampler++) - { - mState.samplerTexture[type][sampler] = nullptr; - } - } - - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mState.vertexAttribute[i].mBoundBuffer = nullptr; - } - - mState.arrayBuffer = nullptr; - mState.elementArrayBuffer = nullptr; - mState.renderbuffer = nullptr; - - mTexture2DZero = nullptr; - mTextureExternalZero = nullptr; - - delete mVertexDataManager; - delete mIndexDataManager; - - mResourceManager->release(); - delete device; -} - -void Context::makeCurrent(egl::Surface *surface) -{ - if(!mHasBeenCurrent) - { - mState.viewportX = 0; - mState.viewportY = 0; - mState.viewportWidth = surface->getWidth(); - mState.viewportHeight = surface->getHeight(); - - mState.scissorX = 0; - mState.scissorY = 0; - mState.scissorWidth = surface->getWidth(); - mState.scissorHeight = surface->getHeight(); - - mHasBeenCurrent = true; - } - - // Wrap the existing resources into GL objects and assign them to the '0' names - egl::Image *defaultRenderTarget = surface->getRenderTarget(); - egl::Image *depthStencil = surface->getDepthStencil(); - - Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget); - DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil); - Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); - - setFramebufferZero(framebufferZero); - - if(defaultRenderTarget) - { - defaultRenderTarget->release(); - } - - if(depthStencil) - { - depthStencil->release(); - } - - markAllStateDirty(); -} - -int Context::getClientVersion() const -{ - return 1; -} - -// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw. -void Context::markAllStateDirty() -{ - mDepthStateDirty = true; - mMaskStateDirty = true; - mBlendStateDirty = true; - mStencilStateDirty = true; - mPolygonOffsetStateDirty = true; - mSampleStateDirty = true; - mDitherStateDirty = true; - mFrontFaceDirty = true; -} - -void Context::setClearColor(float red, float green, float blue, float alpha) -{ - mState.colorClearValue.red = red; - mState.colorClearValue.green = green; - mState.colorClearValue.blue = blue; - mState.colorClearValue.alpha = alpha; -} - -void Context::setClearDepth(float depth) -{ - mState.depthClearValue = depth; -} - -void Context::setClearStencil(int stencil) -{ - mState.stencilClearValue = stencil; -} - -void Context::setCullFaceEnabled(bool enabled) -{ - mState.cullFaceEnabled = enabled; -} - -bool Context::isCullFaceEnabled() const -{ - return mState.cullFaceEnabled; -} - -void Context::setCullMode(GLenum mode) -{ - mState.cullMode = mode; -} - -void Context::setFrontFace(GLenum front) -{ - if(mState.frontFace != front) - { - mState.frontFace = front; - mFrontFaceDirty = true; - } -} - -void Context::setDepthTestEnabled(bool enabled) -{ - if(mState.depthTestEnabled != enabled) - { - mState.depthTestEnabled = enabled; - mDepthStateDirty = true; - } -} - -bool Context::isDepthTestEnabled() const -{ - return mState.depthTestEnabled; -} - -void Context::setDepthFunc(GLenum depthFunc) -{ - if(mState.depthFunc != depthFunc) - { - mState.depthFunc = depthFunc; - mDepthStateDirty = true; - } -} - -void Context::setDepthRange(float zNear, float zFar) -{ - mState.zNear = zNear; - mState.zFar = zFar; -} - -void Context::setAlphaTestEnabled(bool enabled) -{ - alphaTestEnabled = enabled; -} - -bool Context::isAlphaTestEnabled() const -{ - return alphaTestEnabled; -} - -void Context::setAlphaFunc(GLenum alphaFunc, GLclampf reference) -{ - alphaTestFunc = alphaFunc; - alphaTestRef = reference; -} - -void Context::setBlendEnabled(bool enabled) -{ - if(mState.blendEnabled != enabled) - { - mState.blendEnabled = enabled; - mBlendStateDirty = true; - } -} - -bool Context::isBlendEnabled() const -{ - return mState.blendEnabled; -} - -void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) -{ - if(mState.sourceBlendRGB != sourceRGB || - mState.sourceBlendAlpha != sourceAlpha || - mState.destBlendRGB != destRGB || - mState.destBlendAlpha != destAlpha) - { - mState.sourceBlendRGB = sourceRGB; - mState.destBlendRGB = destRGB; - mState.sourceBlendAlpha = sourceAlpha; - mState.destBlendAlpha = destAlpha; - mBlendStateDirty = true; - } -} - -void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) -{ - if(mState.blendEquationRGB != rgbEquation || - mState.blendEquationAlpha != alphaEquation) - { - mState.blendEquationRGB = rgbEquation; - mState.blendEquationAlpha = alphaEquation; - mBlendStateDirty = true; - } -} - -void Context::setStencilTestEnabled(bool enabled) -{ - if(mState.stencilTestEnabled != enabled) - { - mState.stencilTestEnabled = enabled; - mStencilStateDirty = true; - } -} - -bool Context::isStencilTestEnabled() const -{ - return mState.stencilTestEnabled; -} - -void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) -{ - if(mState.stencilFunc != stencilFunc || - mState.stencilRef != stencilRef || - mState.stencilMask != stencilMask) - { - mState.stencilFunc = stencilFunc; - mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; - mState.stencilMask = stencilMask; - mStencilStateDirty = true; - } -} - -void Context::setStencilWritemask(GLuint stencilWritemask) -{ - if(mState.stencilWritemask != stencilWritemask) - { - mState.stencilWritemask = stencilWritemask; - mStencilStateDirty = true; - } -} - -void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) -{ - if(mState.stencilFail != stencilFail || - mState.stencilPassDepthFail != stencilPassDepthFail || - mState.stencilPassDepthPass != stencilPassDepthPass) - { - mState.stencilFail = stencilFail; - mState.stencilPassDepthFail = stencilPassDepthFail; - mState.stencilPassDepthPass = stencilPassDepthPass; - mStencilStateDirty = true; - } -} - -void Context::setPolygonOffsetFillEnabled(bool enabled) -{ - if(mState.polygonOffsetFillEnabled != enabled) - { - mState.polygonOffsetFillEnabled = enabled; - mPolygonOffsetStateDirty = true; - } -} - -bool Context::isPolygonOffsetFillEnabled() const -{ - return mState.polygonOffsetFillEnabled; -} - -void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) -{ - if(mState.polygonOffsetFactor != factor || - mState.polygonOffsetUnits != units) - { - mState.polygonOffsetFactor = factor; - mState.polygonOffsetUnits = units; - mPolygonOffsetStateDirty = true; - } -} - -void Context::setSampleAlphaToCoverageEnabled(bool enabled) -{ - if(mState.sampleAlphaToCoverageEnabled != enabled) - { - mState.sampleAlphaToCoverageEnabled = enabled; - mSampleStateDirty = true; - } -} - -bool Context::isSampleAlphaToCoverageEnabled() const -{ - return mState.sampleAlphaToCoverageEnabled; -} - -void Context::setSampleCoverageEnabled(bool enabled) -{ - if(mState.sampleCoverageEnabled != enabled) - { - mState.sampleCoverageEnabled = enabled; - mSampleStateDirty = true; - } -} - -bool Context::isSampleCoverageEnabled() const -{ - return mState.sampleCoverageEnabled; -} - -void Context::setSampleCoverageParams(GLclampf value, bool invert) -{ - if(mState.sampleCoverageValue != value || - mState.sampleCoverageInvert != invert) - { - mState.sampleCoverageValue = value; - mState.sampleCoverageInvert = invert; - mSampleStateDirty = true; - } -} - -void Context::setScissorTestEnabled(bool enabled) -{ - mState.scissorTestEnabled = enabled; -} - -bool Context::isScissorTestEnabled() const -{ - return mState.scissorTestEnabled; -} - -void Context::setShadeModel(GLenum mode) -{ - mState.shadeModel = mode; -} - -void Context::setDitherEnabled(bool enabled) -{ - if(mState.ditherEnabled != enabled) - { - mState.ditherEnabled = enabled; - mDitherStateDirty = true; - } -} - -bool Context::isDitherEnabled() const -{ - return mState.ditherEnabled; -} - -void Context::setLightingEnabled(bool enable) -{ - lightingEnabled = enable; -} - -bool Context::isLightingEnabled() const -{ - return lightingEnabled; -} - -void Context::setLightEnabled(int index, bool enable) -{ - light[index].enabled = enable; -} - -bool Context::isLightEnabled(int index) const -{ - return light[index].enabled; -} - -void Context::setLightAmbient(int index, float r, float g, float b, float a) -{ - light[index].ambient = {r, g, b, a}; -} - -void Context::setLightDiffuse(int index, float r, float g, float b, float a) -{ - light[index].diffuse = {r, g, b, a}; -} - -void Context::setLightSpecular(int index, float r, float g, float b, float a) -{ - light[index].specular = {r, g, b, a}; -} - -void Context::setLightPosition(int index, float x, float y, float z, float w) -{ - sw::float4 v = {x, y, z, w}; - - // Transform from object coordinates to eye coordinates - v = modelViewStack.current() * v; - - light[index].position = {v.x, v.y, v.z, v.w}; -} - -void Context::setLightDirection(int index, float x, float y, float z) -{ - // FIXME: Transform by inverse of 3x3 model-view matrix - light[index].direction = {x, y, z}; -} - -void Context::setLightAttenuationConstant(int index, float constant) -{ - light[index].attenuation.constant = constant; -} - -void Context::setLightAttenuationLinear(int index, float linear) -{ - light[index].attenuation.linear = linear; -} - -void Context::setLightAttenuationQuadratic(int index, float quadratic) -{ - light[index].attenuation.quadratic = quadratic; -} - -void Context::setSpotLightExponent(int index, float exponent) -{ - light[index].spotExponent = exponent; -} - -void Context::setSpotLightCutoff(int index, float cutoff) -{ - light[index].spotCutoffAngle = cutoff; -} - -void Context::setGlobalAmbient(float red, float green, float blue, float alpha) -{ - globalAmbient.red = red; - globalAmbient.green = green; - globalAmbient.blue = blue; - globalAmbient.alpha = alpha; -} - -void Context::setMaterialAmbient(float red, float green, float blue, float alpha) -{ - materialAmbient.red = red; - materialAmbient.green = green; - materialAmbient.blue = blue; - materialAmbient.alpha = alpha; -} - -void Context::setMaterialDiffuse(float red, float green, float blue, float alpha) -{ - materialDiffuse.red = red; - materialDiffuse.green = green; - materialDiffuse.blue = blue; - materialDiffuse.alpha = alpha; -} - -void Context::setMaterialSpecular(float red, float green, float blue, float alpha) -{ - materialSpecular.red = red; - materialSpecular.green = green; - materialSpecular.blue = blue; - materialSpecular.alpha = alpha; -} - -void Context::setMaterialEmission(float red, float green, float blue, float alpha) -{ - materialEmission.red = red; - materialEmission.green = green; - materialEmission.blue = blue; - materialEmission.alpha = alpha; -} - -void Context::setMaterialShininess(float shininess) -{ - materialShininess = shininess; -} - -void Context::setLightModelTwoSide(bool enable) -{ - lightModelTwoSide = enable; -} - -void Context::setFogEnabled(bool enable) -{ - fogEnabled = enable; -} - -bool Context::isFogEnabled() const -{ - return fogEnabled; -} - -void Context::setFogMode(GLenum mode) -{ - fogMode = mode; -} - -void Context::setFogDensity(float fogDensity) -{ - this->fogDensity = fogDensity; -} - -void Context::setFogStart(float fogStart) -{ - this->fogStart = fogStart; -} - -void Context::setFogEnd(float fogEnd) -{ - this->fogEnd = fogEnd; -} - -void Context::setFogColor(float r, float g, float b, float a) -{ - this->fogColor = {r, g, b, a}; -} - -void Context::setTexture2Denabled(bool enable) -{ - texture2Denabled[mState.activeSampler] = enable; -} - -bool Context::isTexture2Denabled() const -{ - return texture2Denabled[mState.activeSampler]; -} - -void Context::setTextureExternalEnabled(bool enable) -{ - textureExternalEnabled[mState.activeSampler] = enable; -} - -bool Context::isTextureExternalEnabled() const -{ - return textureExternalEnabled[mState.activeSampler]; -} - -void Context::setLineWidth(GLfloat width) -{ - mState.lineWidth = width; - device->setLineWidth(clamp(width, ALIASED_LINE_WIDTH_RANGE_MIN, ALIASED_LINE_WIDTH_RANGE_MAX)); -} - -void Context::setGenerateMipmapHint(GLenum hint) -{ - mState.generateMipmapHint = hint; -} - -void Context::setPerspectiveCorrectionHint(GLenum hint) -{ - mState.perspectiveCorrectionHint = hint; -} - -void Context::setFogHint(GLenum hint) -{ - mState.fogHint = hint; -} - -void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) -{ - mState.viewportX = x; - mState.viewportY = y; - mState.viewportWidth = width; - mState.viewportHeight = height; -} - -void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) -{ - mState.scissorX = x; - mState.scissorY = y; - mState.scissorWidth = width; - mState.scissorHeight = height; -} - -void Context::setColorMask(bool red, bool green, bool blue, bool alpha) -{ - if(mState.colorMaskRed != red || mState.colorMaskGreen != green || - mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha) - { - mState.colorMaskRed = red; - mState.colorMaskGreen = green; - mState.colorMaskBlue = blue; - mState.colorMaskAlpha = alpha; - mMaskStateDirty = true; - } -} - -void Context::setDepthMask(bool mask) -{ - if(mState.depthMask != mask) - { - mState.depthMask = mask; - mMaskStateDirty = true; - } -} - -void Context::setActiveSampler(unsigned int active) -{ - mState.activeSampler = active; -} - -GLuint Context::getFramebufferName() const -{ - return mState.framebuffer; -} - -GLuint Context::getRenderbufferName() const -{ - return mState.renderbuffer.name(); -} - -GLuint Context::getArrayBufferName() const -{ - return mState.arrayBuffer.name(); -} - -void Context::setVertexAttribArrayEnabled(unsigned int attribNum, bool enabled) -{ - mState.vertexAttribute[attribNum].mArrayEnabled = enabled; -} - -const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) -{ - return mState.vertexAttribute[attribNum]; -} - -void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, - GLsizei stride, const void *pointer) -{ - mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer; - mState.vertexAttribute[attribNum].mSize = size; - mState.vertexAttribute[attribNum].mType = type; - mState.vertexAttribute[attribNum].mNormalized = normalized; - mState.vertexAttribute[attribNum].mStride = stride; - mState.vertexAttribute[attribNum].mPointer = pointer; -} - -const void *Context::getVertexAttribPointer(unsigned int attribNum) const -{ - return mState.vertexAttribute[attribNum].mPointer; -} - -const VertexAttributeArray &Context::getVertexAttributes() -{ - return mState.vertexAttribute; -} - -void Context::setPackAlignment(GLint alignment) -{ - mState.packAlignment = alignment; -} - -GLint Context::getPackAlignment() const -{ - return mState.packAlignment; -} - -void Context::setUnpackAlignment(GLint alignment) -{ - mState.unpackAlignment = alignment; -} - -GLint Context::getUnpackAlignment() const -{ - return mState.unpackAlignment; -} - -GLuint Context::createBuffer() -{ - return mResourceManager->createBuffer(); -} - -GLuint Context::createTexture() -{ - return mResourceManager->createTexture(); -} - -GLuint Context::createRenderbuffer() -{ - return mResourceManager->createRenderbuffer(); -} - -// Returns an unused framebuffer name -GLuint Context::createFramebuffer() -{ - return mFramebufferNameSpace.allocate(); -} - -void Context::deleteBuffer(GLuint buffer) -{ - detachBuffer(buffer); - - mResourceManager->deleteBuffer(buffer); -} - -void Context::deleteTexture(GLuint texture) -{ - detachTexture(texture); - - mResourceManager->deleteTexture(texture); -} - -void Context::deleteRenderbuffer(GLuint renderbuffer) -{ - detachRenderbuffer(renderbuffer); - - mResourceManager->deleteRenderbuffer(renderbuffer); -} - -void Context::deleteFramebuffer(GLuint framebuffer) -{ - detachFramebuffer(framebuffer); - - Framebuffer *framebufferObject = mFramebufferNameSpace.remove(framebuffer); - - if(framebufferObject) - { - delete framebufferObject; - } -} - -Buffer *Context::getBuffer(GLuint handle) -{ - return mResourceManager->getBuffer(handle); -} - -Texture *Context::getTexture(GLuint handle) -{ - return mResourceManager->getTexture(handle); -} - -Renderbuffer *Context::getRenderbuffer(GLuint handle) -{ - return mResourceManager->getRenderbuffer(handle); -} - -Framebuffer *Context::getFramebuffer() -{ - return getFramebuffer(mState.framebuffer); -} - -void Context::bindArrayBuffer(unsigned int buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.arrayBuffer = getBuffer(buffer); -} - -void Context::bindElementArrayBuffer(unsigned int buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.elementArrayBuffer = getBuffer(buffer); -} - -void Context::bindTexture2D(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); - - mState.samplerTexture[TEXTURE_2D][mState.activeSampler] = getTexture(texture); -} - -void Context::bindTextureExternal(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_EXTERNAL); - - mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler] = getTexture(texture); -} - -void Context::bindFramebuffer(GLuint framebuffer) -{ - if(!getFramebuffer(framebuffer)) - { - mFramebufferNameSpace.insert(framebuffer, new Framebuffer()); - } - - mState.framebuffer = framebuffer; -} - -void Context::bindRenderbuffer(GLuint renderbuffer) -{ - mResourceManager->checkRenderbufferAllocation(renderbuffer); - - mState.renderbuffer = getRenderbuffer(renderbuffer); -} - -void Context::setFramebufferZero(Framebuffer *buffer) -{ - delete mFramebufferNameSpace.remove(0); - mFramebufferNameSpace.insert(0, buffer); -} - -void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer) -{ - Renderbuffer *renderbufferObject = mState.renderbuffer; - renderbufferObject->setStorage(renderbuffer); -} - -Framebuffer *Context::getFramebuffer(unsigned int handle) -{ - return mFramebufferNameSpace.find(handle); -} - -Buffer *Context::getArrayBuffer() -{ - return mState.arrayBuffer; -} - -Buffer *Context::getElementArrayBuffer() -{ - return mState.elementArrayBuffer; -} - -Texture2D *Context::getTexture2D() -{ - return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D)); -} - -TextureExternal *Context::getTextureExternal() -{ - return static_cast<TextureExternal*>(getSamplerTexture(mState.activeSampler, TEXTURE_EXTERNAL)); -} - -Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) -{ - GLuint texid = mState.samplerTexture[type][sampler].name(); - - if(texid == 0) // Special case: 0 refers to different initial textures based on the target - { - switch(type) - { - case TEXTURE_2D: return mTexture2DZero; - case TEXTURE_EXTERNAL: return mTextureExternalZero; - default: UNREACHABLE(type); - } - } - - return mState.samplerTexture[type][sampler]; -} - -bool Context::getBooleanv(GLenum pname, GLboolean *params) -{ - switch(pname) - { - case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; - case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break; - case GL_COLOR_WRITEMASK: - params[0] = mState.colorMaskRed; - params[1] = mState.colorMaskGreen; - params[2] = mState.colorMaskBlue; - params[3] = mState.colorMaskAlpha; - break; - case GL_CULL_FACE: *params = mState.cullFaceEnabled; break; - case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFillEnabled; break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverageEnabled; break; - case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverageEnabled; break; - case GL_SCISSOR_TEST: *params = mState.scissorTestEnabled; break; - case GL_STENCIL_TEST: *params = mState.stencilTestEnabled; break; - case GL_DEPTH_TEST: *params = mState.depthTestEnabled; break; - case GL_BLEND: *params = mState.blendEnabled; break; - case GL_DITHER: *params = mState.ditherEnabled; break; - case GL_LIGHT_MODEL_TWO_SIDE: *params = lightModelTwoSide; break; - default: - return false; - } - - return true; -} - -bool Context::getFloatv(GLenum pname, GLfloat *params) -{ - // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation - // because it is stored as a float, despite the fact that the GL ES 2.0 spec names - // GetIntegerv as its native query function. As it would require conversion in any - // case, this should make no difference to the calling application. - switch(pname) - { - case GL_LINE_WIDTH: *params = mState.lineWidth; break; - case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; - case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; - case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break; - case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break; - case GL_ALIASED_LINE_WIDTH_RANGE: - params[0] = ALIASED_LINE_WIDTH_RANGE_MIN; - params[1] = ALIASED_LINE_WIDTH_RANGE_MAX; - break; - case GL_ALIASED_POINT_SIZE_RANGE: - params[0] = ALIASED_POINT_SIZE_RANGE_MIN; - params[1] = ALIASED_POINT_SIZE_RANGE_MAX; - break; - case GL_SMOOTH_LINE_WIDTH_RANGE: - params[0] = SMOOTH_LINE_WIDTH_RANGE_MIN; - params[1] = SMOOTH_LINE_WIDTH_RANGE_MAX; - break; - case GL_SMOOTH_POINT_SIZE_RANGE: - params[0] = SMOOTH_POINT_SIZE_RANGE_MIN; - params[1] = SMOOTH_POINT_SIZE_RANGE_MAX; - break; - case GL_DEPTH_RANGE: - params[0] = mState.zNear; - params[1] = mState.zFar; - break; - case GL_COLOR_CLEAR_VALUE: - params[0] = mState.colorClearValue.red; - params[1] = mState.colorClearValue.green; - params[2] = mState.colorClearValue.blue; - params[3] = mState.colorClearValue.alpha; - break; - case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - *params = MAX_TEXTURE_MAX_ANISOTROPY; - break; - case GL_MODELVIEW_MATRIX: - for(int i = 0; i < 16; i++) - { - params[i] = modelViewStack.current()[i % 4][i / 4]; - } - break; - case GL_PROJECTION_MATRIX: - for(int i = 0; i < 16; i++) - { - params[i] = projectionStack.current()[i % 4][i / 4]; - } - break; - default: - return false; - } - - return true; -} - -bool Context::getIntegerv(GLenum pname, GLint *params) -{ - // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation - // because it is stored as a float, despite the fact that the GL ES 2.0 spec names - // GetIntegerv as its native query function. As it would require conversion in any - // case, this should make no difference to the calling application. You may find it in - // Context::getFloatv. - switch(pname) - { - case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.name(); break; - case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.name(); break; - case GL_FRAMEBUFFER_BINDING_OES: *params = mState.framebuffer; break; - case GL_RENDERBUFFER_BINDING_OES: *params = mState.renderbuffer.name(); break; - case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break; - case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break; - case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break; - case GL_PERSPECTIVE_CORRECTION_HINT: *params = mState.perspectiveCorrectionHint; break; - case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break; - case GL_STENCIL_FUNC: *params = mState.stencilFunc; break; - case GL_STENCIL_REF: *params = mState.stencilRef; break; - case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break; - case GL_STENCIL_FAIL: *params = mState.stencilFail; break; - case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break; - case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break; - case GL_DEPTH_FUNC: *params = mState.depthFunc; break; - case GL_BLEND_SRC_RGB_OES: *params = mState.sourceBlendRGB; break; - case GL_BLEND_SRC_ALPHA_OES: *params = mState.sourceBlendAlpha; break; - case GL_BLEND_DST_RGB_OES: *params = mState.destBlendRGB; break; - case GL_BLEND_DST_ALPHA_OES: *params = mState.destBlendAlpha; break; - case GL_BLEND_EQUATION_RGB_OES: *params = mState.blendEquationRGB; break; - case GL_BLEND_EQUATION_ALPHA_OES: *params = mState.blendEquationAlpha; break; - case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break; - case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; - case GL_SUBPIXEL_BITS: *params = 4; break; - case GL_MAX_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; break; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = NUM_COMPRESSED_TEXTURE_FORMATS; break; - case GL_SAMPLE_BUFFERS: - case GL_SAMPLES: - { - Framebuffer *framebuffer = getFramebuffer(); - int width, height, samples; - - if(framebuffer->completeness(width, height, samples) == GL_FRAMEBUFFER_COMPLETE_OES) - { - switch(pname) - { - case GL_SAMPLE_BUFFERS: - if(samples > 1) - { - *params = 1; - } - else - { - *params = 0; - } - break; - case GL_SAMPLES: - *params = samples; - break; - } - } - else - { - *params = 0; - } - } - break; - case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: - { - Framebuffer *framebuffer = getFramebuffer(); - *params = framebuffer->getImplementationColorReadType(); - } - break; - case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: - { - Framebuffer *framebuffer = getFramebuffer(); - *params = framebuffer->getImplementationColorReadFormat(); - } - break; - case GL_MAX_VIEWPORT_DIMS: - { - int maxDimension = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE; - params[0] = maxDimension; - params[1] = maxDimension; - } - break; - case GL_COMPRESSED_TEXTURE_FORMATS: - { - for(int i = 0; i < NUM_COMPRESSED_TEXTURE_FORMATS; i++) - { - params[i] = compressedTextureFormats[i]; - } - } - break; - case GL_VIEWPORT: - params[0] = mState.viewportX; - params[1] = mState.viewportY; - params[2] = mState.viewportWidth; - params[3] = mState.viewportHeight; - break; - case GL_SCISSOR_BOX: - params[0] = mState.scissorX; - params[1] = mState.scissorY; - params[2] = mState.scissorWidth; - params[3] = mState.scissorHeight; - break; - case GL_CULL_FACE_MODE: *params = mState.cullMode; break; - case GL_FRONT_FACE: *params = mState.frontFace; break; - case GL_RED_BITS: - case GL_GREEN_BITS: - case GL_BLUE_BITS: - case GL_ALPHA_BITS: - { - Framebuffer *framebuffer = getFramebuffer(); - Renderbuffer *colorbuffer = framebuffer->getColorbuffer(); - - if(colorbuffer) - { - switch(pname) - { - case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; - case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; - case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; - case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; - } - } - else - { - *params = 0; - } - } - break; - case GL_DEPTH_BITS: - { - Framebuffer *framebuffer = getFramebuffer(); - Renderbuffer *depthbuffer = framebuffer->getDepthbuffer(); - - if(depthbuffer) - { - *params = depthbuffer->getDepthSize(); - } - else - { - *params = 0; - } - } - break; - case GL_STENCIL_BITS: - { - Framebuffer *framebuffer = getFramebuffer(); - Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer(); - - if(stencilbuffer) - { - *params = stencilbuffer->getStencilSize(); - } - else - { - *params = 0; - } - } - break; - case GL_TEXTURE_BINDING_2D: *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].name(); break; - case GL_TEXTURE_BINDING_CUBE_MAP_OES: *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].name(); break; - case GL_TEXTURE_BINDING_EXTERNAL_OES: *params = mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler].name(); break; - case GL_MAX_LIGHTS: *params = MAX_LIGHTS; break; - case GL_MAX_MODELVIEW_STACK_DEPTH: *params = MAX_MODELVIEW_STACK_DEPTH; break; - case GL_MAX_PROJECTION_STACK_DEPTH: *params = MAX_PROJECTION_STACK_DEPTH; break; - case GL_MAX_TEXTURE_STACK_DEPTH: *params = MAX_TEXTURE_STACK_DEPTH; break; - case GL_MAX_TEXTURE_UNITS: *params = MAX_TEXTURE_UNITS; break; - case GL_MAX_CLIP_PLANES: *params = MAX_CLIP_PLANES; break; - case GL_POINT_SIZE_ARRAY_TYPE_OES: *params = mState.vertexAttribute[sw::PointSize].mType; break; - case GL_POINT_SIZE_ARRAY_STRIDE_OES: *params = mState.vertexAttribute[sw::PointSize].mStride; break; - case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: *params = mState.vertexAttribute[sw::PointSize].mBoundBuffer.name(); break; - case GL_VERTEX_ARRAY_SIZE: *params = mState.vertexAttribute[sw::Position].mSize; break; - case GL_VERTEX_ARRAY_TYPE: *params = mState.vertexAttribute[sw::Position].mType; break; - case GL_VERTEX_ARRAY_STRIDE: *params = mState.vertexAttribute[sw::Position].mStride; break; - case GL_VERTEX_ARRAY_BUFFER_BINDING: *params = mState.vertexAttribute[sw::Position].mBoundBuffer.name(); break; - case GL_NORMAL_ARRAY_TYPE: *params = mState.vertexAttribute[sw::Normal].mType; break; - case GL_NORMAL_ARRAY_STRIDE: *params = mState.vertexAttribute[sw::Normal].mStride; break; - case GL_NORMAL_ARRAY_BUFFER_BINDING: *params = mState.vertexAttribute[sw::Normal].mBoundBuffer.name(); break; - case GL_COLOR_ARRAY_SIZE: *params = mState.vertexAttribute[sw::Color0].mSize; break; - case GL_COLOR_ARRAY_TYPE: *params = mState.vertexAttribute[sw::Color0].mType; break; - case GL_COLOR_ARRAY_STRIDE: *params = mState.vertexAttribute[sw::Color0].mStride; break; - case GL_COLOR_ARRAY_BUFFER_BINDING: *params = mState.vertexAttribute[sw::Color0].mBoundBuffer.name(); break; - case GL_TEXTURE_COORD_ARRAY_SIZE: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mSize; break; - case GL_TEXTURE_COORD_ARRAY_TYPE: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mType; break; - case GL_TEXTURE_COORD_ARRAY_STRIDE: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mStride; break; - case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mBoundBuffer.name(); break; - default: - return false; - } - - return true; -} - -bool Context::getPointerv(GLenum pname, const GLvoid **params) -{ - switch(pname) - { - case GL_VERTEX_ARRAY_POINTER: *params = mState.vertexAttribute[sw::Position].mPointer; break; - case GL_NORMAL_ARRAY_POINTER: *params = mState.vertexAttribute[sw::Normal].mPointer; break; - case GL_COLOR_ARRAY_POINTER: *params = mState.vertexAttribute[sw::Color0].mPointer; break; - case GL_POINT_SIZE_ARRAY_POINTER_OES: *params = mState.vertexAttribute[sw::PointSize].mPointer; break; - case GL_TEXTURE_COORD_ARRAY_POINTER: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mPointer; break; - default: - return false; - } - - return true; -} - -int Context::getQueryParameterNum(GLenum pname) -{ - // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation - // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due - // to the fact that it is stored internally as a float, and so would require conversion - // if returned from Context::getIntegerv. Since this conversion is already implemented - // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we - // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling - // application. - switch(pname) - { - case GL_COMPRESSED_TEXTURE_FORMATS: - return NUM_COMPRESSED_TEXTURE_FORMATS; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: - case GL_ARRAY_BUFFER_BINDING: - case GL_FRAMEBUFFER_BINDING_OES: - case GL_RENDERBUFFER_BINDING_OES: - case GL_PACK_ALIGNMENT: - case GL_UNPACK_ALIGNMENT: - case GL_GENERATE_MIPMAP_HINT: - case GL_RED_BITS: - case GL_GREEN_BITS: - case GL_BLUE_BITS: - case GL_ALPHA_BITS: - case GL_DEPTH_BITS: - case GL_STENCIL_BITS: - case GL_ELEMENT_ARRAY_BUFFER_BINDING: - case GL_CULL_FACE_MODE: - case GL_FRONT_FACE: - case GL_ACTIVE_TEXTURE: - case GL_STENCIL_FUNC: - case GL_STENCIL_VALUE_MASK: - case GL_STENCIL_REF: - case GL_STENCIL_FAIL: - case GL_STENCIL_PASS_DEPTH_FAIL: - case GL_STENCIL_PASS_DEPTH_PASS: - case GL_DEPTH_FUNC: - case GL_BLEND_SRC_RGB_OES: - case GL_BLEND_SRC_ALPHA_OES: - case GL_BLEND_DST_RGB_OES: - case GL_BLEND_DST_ALPHA_OES: - case GL_BLEND_EQUATION_RGB_OES: - case GL_BLEND_EQUATION_ALPHA_OES: - case GL_STENCIL_WRITEMASK: - case GL_STENCIL_CLEAR_VALUE: - case GL_SUBPIXEL_BITS: - case GL_MAX_TEXTURE_SIZE: - case GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES: - case GL_SAMPLE_BUFFERS: - case GL_SAMPLES: - case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: - case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: - case GL_TEXTURE_BINDING_2D: - case GL_TEXTURE_BINDING_CUBE_MAP_OES: - case GL_TEXTURE_BINDING_EXTERNAL_OES: - return 1; - case GL_MAX_VIEWPORT_DIMS: - return 2; - case GL_VIEWPORT: - case GL_SCISSOR_BOX: - return 4; - case GL_SAMPLE_COVERAGE_INVERT: - case GL_DEPTH_WRITEMASK: - case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled, - case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries. - case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural - case GL_SAMPLE_COVERAGE: - case GL_SCISSOR_TEST: - case GL_STENCIL_TEST: - case GL_DEPTH_TEST: - case GL_BLEND: - case GL_DITHER: - return 1; - case GL_COLOR_WRITEMASK: - return 4; - case GL_POLYGON_OFFSET_FACTOR: - case GL_POLYGON_OFFSET_UNITS: - case GL_SAMPLE_COVERAGE_VALUE: - case GL_DEPTH_CLEAR_VALUE: - case GL_LINE_WIDTH: - return 1; - case GL_ALIASED_LINE_WIDTH_RANGE: - case GL_ALIASED_POINT_SIZE_RANGE: - case GL_DEPTH_RANGE: - return 2; - case GL_COLOR_CLEAR_VALUE: - return 4; - case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - case GL_MAX_LIGHTS: - case GL_MAX_MODELVIEW_STACK_DEPTH: - case GL_MAX_PROJECTION_STACK_DEPTH: - case GL_MAX_TEXTURE_STACK_DEPTH: - case GL_MAX_TEXTURE_UNITS: - case GL_MAX_CLIP_PLANES: - case GL_POINT_SIZE_ARRAY_TYPE_OES: - case GL_POINT_SIZE_ARRAY_STRIDE_OES: - case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: - return 1; - case GL_CURRENT_COLOR: - return 4; - case GL_CURRENT_NORMAL: - return 3; - case GL_CURRENT_TEXTURE_COORDS: - return 4; - case GL_POINT_SIZE: - case GL_POINT_SIZE_MIN: - case GL_POINT_SIZE_MAX: - case GL_POINT_FADE_THRESHOLD_SIZE: - return 1; - case GL_POINT_DISTANCE_ATTENUATION: - return 3; - case GL_SMOOTH_POINT_SIZE_RANGE: - case GL_SMOOTH_LINE_WIDTH_RANGE: - return 2; - case GL_SHADE_MODEL: - case GL_MATRIX_MODE: - case GL_MODELVIEW_STACK_DEPTH: - case GL_PROJECTION_STACK_DEPTH: - case GL_TEXTURE_STACK_DEPTH: - return 1; - case GL_MODELVIEW_MATRIX: - case GL_PROJECTION_MATRIX: - case GL_TEXTURE_MATRIX: - return 16; - case GL_ALPHA_TEST_FUNC: - case GL_ALPHA_TEST_REF: - case GL_BLEND_DST: - case GL_BLEND_SRC: - case GL_LOGIC_OP_MODE: - case GL_VERTEX_ARRAY_SIZE: - case GL_VERTEX_ARRAY_TYPE: - case GL_VERTEX_ARRAY_STRIDE: - case GL_NORMAL_ARRAY_TYPE: - case GL_NORMAL_ARRAY_STRIDE: - case GL_COLOR_ARRAY_SIZE: - case GL_COLOR_ARRAY_TYPE: - case GL_COLOR_ARRAY_STRIDE: - case GL_TEXTURE_COORD_ARRAY_SIZE: - case GL_TEXTURE_COORD_ARRAY_TYPE: - case GL_TEXTURE_COORD_ARRAY_STRIDE: - case GL_VERTEX_ARRAY_POINTER: - case GL_NORMAL_ARRAY_POINTER: - case GL_COLOR_ARRAY_POINTER: - case GL_TEXTURE_COORD_ARRAY_POINTER: - case GL_LIGHT_MODEL_TWO_SIDE: - return 1; - default: - UNREACHABLE(pname); - } - - return -1; -} - -bool Context::isQueryParameterInt(GLenum pname) -{ - // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation - // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due - // to the fact that it is stored internally as a float, and so would require conversion - // if returned from Context::getIntegerv. Since this conversion is already implemented - // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we - // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling - // application. - switch(pname) - { - case GL_COMPRESSED_TEXTURE_FORMATS: - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: - case GL_ARRAY_BUFFER_BINDING: - case GL_FRAMEBUFFER_BINDING_OES: - case GL_RENDERBUFFER_BINDING_OES: - case GL_PACK_ALIGNMENT: - case GL_UNPACK_ALIGNMENT: - case GL_GENERATE_MIPMAP_HINT: - case GL_RED_BITS: - case GL_GREEN_BITS: - case GL_BLUE_BITS: - case GL_ALPHA_BITS: - case GL_DEPTH_BITS: - case GL_STENCIL_BITS: - case GL_ELEMENT_ARRAY_BUFFER_BINDING: - case GL_CULL_FACE_MODE: - case GL_FRONT_FACE: - case GL_ACTIVE_TEXTURE: - case GL_STENCIL_FUNC: - case GL_STENCIL_VALUE_MASK: - case GL_STENCIL_REF: - case GL_STENCIL_FAIL: - case GL_STENCIL_PASS_DEPTH_FAIL: - case GL_STENCIL_PASS_DEPTH_PASS: - case GL_DEPTH_FUNC: - case GL_BLEND_SRC_RGB_OES: - case GL_BLEND_SRC_ALPHA_OES: - case GL_BLEND_DST_RGB_OES: - case GL_BLEND_DST_ALPHA_OES: - case GL_BLEND_EQUATION_RGB_OES: - case GL_BLEND_EQUATION_ALPHA_OES: - case GL_STENCIL_WRITEMASK: - case GL_STENCIL_CLEAR_VALUE: - case GL_SUBPIXEL_BITS: - case GL_MAX_TEXTURE_SIZE: - case GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES: - case GL_SAMPLE_BUFFERS: - case GL_SAMPLES: - case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: - case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: - case GL_TEXTURE_BINDING_2D: - case GL_TEXTURE_BINDING_CUBE_MAP_OES: - case GL_TEXTURE_BINDING_EXTERNAL_OES: - case GL_MAX_VIEWPORT_DIMS: - case GL_VIEWPORT: - case GL_SCISSOR_BOX: - case GL_MAX_LIGHTS: - case GL_MAX_MODELVIEW_STACK_DEPTH: - case GL_MAX_PROJECTION_STACK_DEPTH: - case GL_MAX_TEXTURE_STACK_DEPTH: - case GL_MAX_TEXTURE_UNITS: - case GL_MAX_CLIP_PLANES: - case GL_POINT_SIZE_ARRAY_TYPE_OES: - case GL_POINT_SIZE_ARRAY_STRIDE_OES: - case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: - return true; - } - - return false; -} - -bool Context::isQueryParameterFloat(GLenum pname) -{ - // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation - // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due - // to the fact that it is stored internally as a float, and so would require conversion - // if returned from Context::getIntegerv. Since this conversion is already implemented - // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we - // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling - // application. - switch(pname) - { - case GL_POLYGON_OFFSET_FACTOR: - case GL_POLYGON_OFFSET_UNITS: - case GL_SAMPLE_COVERAGE_VALUE: - case GL_DEPTH_CLEAR_VALUE: - case GL_LINE_WIDTH: - case GL_ALIASED_LINE_WIDTH_RANGE: - case GL_ALIASED_POINT_SIZE_RANGE: - case GL_SMOOTH_LINE_WIDTH_RANGE: - case GL_SMOOTH_POINT_SIZE_RANGE: - case GL_DEPTH_RANGE: - case GL_COLOR_CLEAR_VALUE: - case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - case GL_LIGHT_MODEL_AMBIENT: - case GL_POINT_SIZE_MIN: - case GL_POINT_SIZE_MAX: - case GL_POINT_DISTANCE_ATTENUATION: - case GL_POINT_FADE_THRESHOLD_SIZE: - return true; - } - - return false; -} - -bool Context::isQueryParameterBool(GLenum pname) -{ - switch(pname) - { - case GL_SAMPLE_COVERAGE_INVERT: - case GL_DEPTH_WRITEMASK: - case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled, - case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries. - case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural - case GL_SAMPLE_COVERAGE: - case GL_SCISSOR_TEST: - case GL_STENCIL_TEST: - case GL_DEPTH_TEST: - case GL_BLEND: - case GL_DITHER: - case GL_COLOR_WRITEMASK: - case GL_LIGHT_MODEL_TWO_SIDE: - return true; - } - - return false; -} - -bool Context::isQueryParameterPointer(GLenum pname) -{ - switch(pname) - { - case GL_VERTEX_ARRAY_POINTER: - case GL_NORMAL_ARRAY_POINTER: - case GL_COLOR_ARRAY_POINTER: - case GL_TEXTURE_COORD_ARRAY_POINTER: - case GL_POINT_SIZE_ARRAY_POINTER_OES: - return true; - } - - return false; -} - -// Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle -bool Context::applyRenderTarget() -{ - Framebuffer *framebuffer = getFramebuffer(); - int width, height, samples; - - if(!framebuffer || framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE_OES) - { - return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES, false); - } - - egl::Image *renderTarget = framebuffer->getRenderTarget(); - device->setRenderTarget(0, renderTarget); - if(renderTarget) renderTarget->release(); - - egl::Image *depthBuffer = framebuffer->getDepthBuffer(); - device->setDepthBuffer(depthBuffer); - if(depthBuffer) depthBuffer->release(); - - egl::Image *stencilBuffer = framebuffer->getStencilBuffer(); - device->setStencilBuffer(stencilBuffer); - if(stencilBuffer) stencilBuffer->release(); - - Viewport viewport; - float zNear = clamp01(mState.zNear); - float zFar = clamp01(mState.zFar); - - viewport.x0 = mState.viewportX; - viewport.y0 = mState.viewportY; - viewport.width = mState.viewportWidth; - viewport.height = mState.viewportHeight; - viewport.minZ = zNear; - viewport.maxZ = zFar; - - device->setViewport(viewport); - - if(mState.scissorTestEnabled) - { - sw::Rect scissor = {mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight}; - scissor.clip(0, 0, width, height); - - device->setScissorRect(scissor); - device->setScissorEnable(true); - } - else - { - device->setScissorEnable(false); - } - - return true; -} - -// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) -void Context::applyState(GLenum drawMode) -{ - Framebuffer *framebuffer = getFramebuffer(); - - if(mState.cullFaceEnabled) - { - device->setCullMode(es2sw::ConvertCullMode(mState.cullMode, mState.frontFace)); - } - else - { - device->setCullMode(sw::CULL_NONE); - } - - if(mDepthStateDirty) - { - if(mState.depthTestEnabled) - { - device->setDepthBufferEnable(true); - device->setDepthCompare(es2sw::ConvertDepthComparison(mState.depthFunc)); - } - else - { - device->setDepthBufferEnable(false); - } - - mDepthStateDirty = false; - } - - if(mBlendStateDirty) - { - if(mState.blendEnabled) - { - device->setAlphaBlendEnable(true); - device->setSeparateAlphaBlendEnable(true); - - device->setSourceBlendFactor(es2sw::ConvertBlendFunc(mState.sourceBlendRGB)); - device->setDestBlendFactor(es2sw::ConvertBlendFunc(mState.destBlendRGB)); - device->setBlendOperation(es2sw::ConvertBlendOp(mState.blendEquationRGB)); - - device->setSourceBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.sourceBlendAlpha)); - device->setDestBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.destBlendAlpha)); - device->setBlendOperationAlpha(es2sw::ConvertBlendOp(mState.blendEquationAlpha)); - } - else - { - device->setAlphaBlendEnable(false); - } - - mBlendStateDirty = false; - } - - if(mStencilStateDirty || mFrontFaceDirty) - { - if(mState.stencilTestEnabled && framebuffer->hasStencil()) - { - device->setStencilEnable(true); - device->setTwoSidedStencil(true); - - // get the maximum size of the stencil ref - Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer(); - GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1; - - device->setStencilWriteMask(mState.stencilWritemask); - device->setStencilCompare(es2sw::ConvertStencilComparison(mState.stencilFunc)); - - device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); - device->setStencilMask(mState.stencilMask); - - device->setStencilFailOperation(es2sw::ConvertStencilOp(mState.stencilFail)); - device->setStencilZFailOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthFail)); - device->setStencilPassOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthPass)); - - device->setStencilWriteMaskCCW(mState.stencilWritemask); - device->setStencilCompareCCW(es2sw::ConvertStencilComparison(mState.stencilFunc)); - - device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); - device->setStencilMaskCCW(mState.stencilMask); - - device->setStencilFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilFail)); - device->setStencilZFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthFail)); - device->setStencilPassOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthPass)); - } - else - { - device->setStencilEnable(false); - } - - mStencilStateDirty = false; - mFrontFaceDirty = false; - } - - if(mMaskStateDirty) - { - device->setColorWriteMask(0, es2sw::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha)); - device->setDepthWriteEnable(mState.depthMask); - - mMaskStateDirty = false; - } - - if(mPolygonOffsetStateDirty) - { - if(mState.polygonOffsetFillEnabled) - { - Renderbuffer *depthbuffer = framebuffer->getDepthbuffer(); - if(depthbuffer) - { - device->setSlopeDepthBias(mState.polygonOffsetFactor); - float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize())); - device->setDepthBias(depthBias); - } - } - else - { - device->setSlopeDepthBias(0); - device->setDepthBias(0); - } - - mPolygonOffsetStateDirty = false; - } - - if(mSampleStateDirty) - { - if(mState.sampleAlphaToCoverageEnabled) - { - device->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE); - } - else - { - device->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE); - } - - if(mState.sampleCoverageEnabled) - { - unsigned int mask = 0; - if(mState.sampleCoverageValue != 0) - { - int width, height, samples; - framebuffer->completeness(width, height, samples); - - float threshold = 0.5f; - - for(int i = 0; i < samples; i++) - { - mask <<= 1; - - if((i + 1) * mState.sampleCoverageValue >= threshold) - { - threshold += 1.0f; - mask |= 1; - } - } - } - - if(mState.sampleCoverageInvert) - { - mask = ~mask; - } - - device->setMultiSampleMask(mask); - } - else - { - device->setMultiSampleMask(0xFFFFFFFF); - } - - mSampleStateDirty = false; - } - - if(mDitherStateDirty) - { - // UNIMPLEMENTED(); // FIXME - - mDitherStateDirty = false; - } - - switch(mState.shadeModel) - { - default: UNREACHABLE(mState.shadeModel); - case GL_SMOOTH: device->setShadingMode(sw::SHADING_GOURAUD); break; - case GL_FLAT: device->setShadingMode(sw::SHADING_FLAT); break; - } - - device->setLightingEnable(lightingEnabled); - device->setGlobalAmbient(sw::Color<float>(globalAmbient.red, globalAmbient.green, globalAmbient.blue, globalAmbient.alpha)); - - for(int i = 0; i < MAX_LIGHTS; i++) - { - device->setLightEnable(i, light[i].enabled); - device->setLightAmbient(i, sw::Color<float>(light[i].ambient.red, light[i].ambient.green, light[i].ambient.blue, light[i].ambient.alpha)); - device->setLightDiffuse(i, sw::Color<float>(light[i].diffuse.red, light[i].diffuse.green, light[i].diffuse.blue, light[i].diffuse.alpha)); - device->setLightSpecular(i, sw::Color<float>(light[i].specular.red, light[i].specular.green, light[i].specular.blue, light[i].specular.alpha)); - device->setLightAttenuation(i, light[i].attenuation.constant, light[i].attenuation.linear, light[i].attenuation.quadratic); - - if(light[i].position.w != 0.0f) - { - device->setLightPosition(i, sw::Point(light[i].position.x / light[i].position.w, light[i].position.y / light[i].position.w, light[i].position.z / light[i].position.w)); - } - else // Directional light - { - // Hack: set the position far way - float max = sw::max(abs(light[i].position.x), abs(light[i].position.y), abs(light[i].position.z)); - device->setLightPosition(i, sw::Point(1e10f * (light[i].position.x / max), 1e10f * (light[i].position.y / max), 1e10f * (light[i].position.z / max))); - } - } - - device->setMaterialAmbient(sw::Color<float>(materialAmbient.red, materialAmbient.green, materialAmbient.blue, materialAmbient.alpha)); - device->setMaterialDiffuse(sw::Color<float>(materialDiffuse.red, materialDiffuse.green, materialDiffuse.blue, materialDiffuse.alpha)); - device->setMaterialSpecular(sw::Color<float>(materialSpecular.red, materialSpecular.green, materialSpecular.blue, materialSpecular.alpha)); - device->setMaterialEmission(sw::Color<float>(materialEmission.red, materialEmission.green, materialEmission.blue, materialEmission.alpha)); - device->setMaterialShininess(materialShininess); - - device->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL); - device->setSpecularMaterialSource(sw::MATERIAL_MATERIAL); - device->setAmbientMaterialSource(sw::MATERIAL_MATERIAL); - device->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL); - - const sw::Matrix Z(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0.5, 0.5, - 0, 0, 0, 1); // Map depth range from [-1, 1] to [0, 1] - - device->setProjectionMatrix(Z * projectionStack.current()); - device->setModelMatrix(modelViewStack.current()); - device->setTextureMatrix(0, textureStack0.current()); - device->setTextureMatrix(1, textureStack1.current()); - device->setTextureTransform(0, textureStack0.isIdentity() ? 0 : 4, false); - device->setTextureTransform(1, textureStack1.isIdentity() ? 0 : 4, false); - device->setTexGen(0, sw::TEXGEN_NONE); - device->setTexGen(1, sw::TEXGEN_NONE); - - device->setAlphaTestEnable(alphaTestEnabled); - device->setAlphaCompare(es2sw::ConvertAlphaComparison(alphaTestFunc)); - device->setAlphaReference(alphaTestRef * 0xFF); - - device->setFogEnable(fogEnabled); - device->setFogColor(sw::Color<float>(fogColor.red, fogColor.green, fogColor.blue, fogColor.alpha)); - device->setFogDensity(fogDensity); - device->setFogStart(fogStart); - device->setFogEnd(fogEnd); - - switch(fogMode) - { - case GL_LINEAR: device->setVertexFogMode(sw::FOG_LINEAR); break; - case GL_EXP: device->setVertexFogMode(sw::FOG_EXP); break; - case GL_EXP2: device->setVertexFogMode(sw::FOG_EXP2); break; - default: UNREACHABLE(fogMode); - } - - device->setColorLogicOpEnabled(colorLogicOpEnabled); - device->setLogicalOperation(es2sw::ConvertLogicalOperation(logicalOperation)); - - device->setNormalizeNormals(normalizeEnabled || rescaleNormalEnabled); -} - -GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count) -{ - TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS]; - - GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes); - if(err != GL_NO_ERROR) - { - return err; - } - - device->resetInputStreams(false); - - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - sw::Resource *resource = attributes[i].vertexBuffer; - const void *buffer = (char*)resource->data() + attributes[i].offset; - - int stride = attributes[i].stride; - - buffer = (char*)buffer + stride * base; - - sw::Stream attribute(resource, buffer, stride); - - attribute.type = attributes[i].type; - attribute.count = attributes[i].count; - attribute.normalized = attributes[i].normalized; - - device->setInputStream(i, attribute); - } - - return GL_NO_ERROR; -} - -// Applies the indices and element array bindings -GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer, indices, indexInfo); - - if(err == GL_NO_ERROR) - { - device->setIndexBuffer(indexInfo->indexBuffer); - } - - return err; -} - -void Context::applyTextures() -{ - for(int unit = 0; unit < MAX_TEXTURE_UNITS; unit++) - { - Texture *texture = nullptr; - - if(textureExternalEnabled[unit]) - { - texture = getSamplerTexture(unit, TEXTURE_EXTERNAL); - } - else if(texture2Denabled[unit]) - { - texture = getSamplerTexture(unit, TEXTURE_2D); - } - - if(texture && texture->isSamplerComplete()) - { - texture->autoGenerateMipmaps(); - - GLenum wrapS = texture->getWrapS(); - GLenum wrapT = texture->getWrapT(); - GLenum minFilter = texture->getMinFilter(); - GLenum magFilter = texture->getMagFilter(); - GLfloat maxAnisotropy = texture->getMaxAnisotropy(); - - device->setAddressingModeU(sw::SAMPLER_PIXEL, unit, es2sw::ConvertTextureWrap(wrapS)); - device->setAddressingModeV(sw::SAMPLER_PIXEL, unit, es2sw::ConvertTextureWrap(wrapT)); - - device->setTextureFilter(sw::SAMPLER_PIXEL, unit, es2sw::ConvertTextureFilter(minFilter, magFilter, maxAnisotropy)); - device->setMipmapFilter(sw::SAMPLER_PIXEL, unit, es2sw::ConvertMipMapFilter(minFilter)); - device->setMaxAnisotropy(sw::SAMPLER_PIXEL, unit, maxAnisotropy); - - applyTexture(unit, texture); - - device->setConstantColor(unit, sw::Color<float>(mState.textureUnit[unit].color.red, mState.textureUnit[unit].color.green, mState.textureUnit[unit].color.blue, mState.textureUnit[unit].color.alpha)); - - if(mState.textureUnit[unit].environmentMode != GL_COMBINE) - { - device->setFirstArgument(unit, sw::TextureStage::SOURCE_TEXTURE); // Cs - device->setFirstModifier(unit, sw::TextureStage::MODIFIER_COLOR); - device->setSecondArgument(unit, sw::TextureStage::SOURCE_CURRENT); // Cp - device->setSecondModifier(unit, sw::TextureStage::MODIFIER_COLOR); - device->setThirdArgument(unit, sw::TextureStage::SOURCE_CONSTANT); // Cc - device->setThirdModifier(unit, sw::TextureStage::MODIFIER_COLOR); - - device->setFirstArgumentAlpha(unit, sw::TextureStage::SOURCE_TEXTURE); // As - device->setFirstModifierAlpha(unit, sw::TextureStage::MODIFIER_ALPHA); - device->setSecondArgumentAlpha(unit, sw::TextureStage::SOURCE_CURRENT); // Ap - device->setSecondModifierAlpha(unit, sw::TextureStage::MODIFIER_ALPHA); - device->setThirdArgumentAlpha(unit, sw::TextureStage::SOURCE_CONSTANT); // Ac - device->setThirdModifierAlpha(unit, sw::TextureStage::MODIFIER_ALPHA); - - GLenum texFormat = texture->getFormat(GL_TEXTURE_2D, 0); - - switch(mState.textureUnit[unit].environmentMode) - { - case GL_REPLACE: - if(IsAlpha(texFormat)) // GL_ALPHA - { - // Cv = Cp, Av = As - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG1); - } - else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) - { - // Cv = Cs, Av = Ap - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG1); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); - } - else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) - { - // Cv = Cs, Av = As - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG1); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG1); - } - else UNREACHABLE(texFormat); - break; - case GL_MODULATE: - if(IsAlpha(texFormat)) // GL_ALPHA - { - // Cv = Cp, Av = ApAs - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); - } - else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) - { - // Cv = CpCs, Av = Ap - device->setStageOperation(unit, sw::TextureStage::STAGE_MODULATE); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); - } - else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) - { - // Cv = CpCs, Av = ApAs - device->setStageOperation(unit, sw::TextureStage::STAGE_MODULATE); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); - } - else UNREACHABLE(texFormat); - break; - case GL_DECAL: - if(texFormat == GL_ALPHA || - texFormat == GL_LUMINANCE || - texFormat == GL_LUMINANCE_ALPHA) - { - // undefined // FIXME: Log - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); - } - else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) - { - // Cv = Cs, Av = Ap - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG1); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); - } - else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) - { - // Cv = Cp(1 - As) + CsAs, Av = Ap - device->setStageOperation(unit, sw::TextureStage::STAGE_BLENDTEXTUREALPHA); // Alpha * (Arg1 - Arg2) + Arg2 - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); - } - else UNREACHABLE(texFormat); - break; - case GL_BLEND: - if(IsAlpha(texFormat)) // GL_ALPHA - { - // Cv = Cp, Av = ApAs - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); - } - else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) - { - // Cv = Cp(1 - Cs) + CcCs, Av = Ap - device->setStageOperation(unit, sw::TextureStage::STAGE_LERP); // Arg3 * (Arg1 - Arg2) + Arg2 - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); - } - else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) - { - // Cv = Cp(1 - Cs) + CcCs, Av = ApAs - device->setStageOperation(unit, sw::TextureStage::STAGE_LERP); // Arg3 * (Arg1 - Arg2) + Arg2 - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); - } - else UNREACHABLE(texFormat); - break; - case GL_ADD: - if(IsAlpha(texFormat)) // GL_ALPHA - { - // Cv = Cp, Av = ApAs - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); - } - else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) - { - // Cv = Cp + Cs, Av = Ap - device->setStageOperation(unit, sw::TextureStage::STAGE_ADD); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); - } - else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) - { - // Cv = Cp + Cs, Av = ApAs - device->setStageOperation(unit, sw::TextureStage::STAGE_ADD); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); - } - else UNREACHABLE(texFormat); - break; - default: - UNREACHABLE(mState.textureUnit[unit].environmentMode); - } - } - else // GL_COMBINE - { - device->setFirstArgument(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src0RGB)); - device->setFirstModifier(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand0RGB)); - device->setSecondArgument(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src1RGB)); - device->setSecondModifier(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand1RGB)); - device->setThirdArgument(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src2RGB)); - device->setThirdModifier(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand2RGB)); - - device->setStageOperation(unit, es2sw::ConvertCombineOperation(mState.textureUnit[unit].combineRGB)); - - device->setFirstArgumentAlpha(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src0Alpha)); - device->setFirstModifierAlpha(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand0Alpha)); - device->setSecondArgumentAlpha(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src1Alpha)); - device->setSecondModifierAlpha(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand1Alpha)); - device->setThirdArgumentAlpha(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src2Alpha)); - device->setThirdModifierAlpha(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand2Alpha)); - - device->setStageOperationAlpha(unit, es2sw::ConvertCombineOperation(mState.textureUnit[unit].combineAlpha)); - } - } - else - { - applyTexture(unit, nullptr); - - device->setFirstArgument(unit, sw::TextureStage::SOURCE_CURRENT); - device->setFirstModifier(unit, sw::TextureStage::MODIFIER_COLOR); - device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG1); - - device->setFirstArgumentAlpha(unit, sw::TextureStage::SOURCE_CURRENT); - device->setFirstModifierAlpha(unit, sw::TextureStage::MODIFIER_ALPHA); - device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG1); - } - } -} - -void Context::setTextureEnvMode(GLenum texEnvMode) -{ - mState.textureUnit[mState.activeSampler].environmentMode = texEnvMode; -} - -void Context::setTextureEnvColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) -{ - mState.textureUnit[mState.activeSampler].color = {red, green, blue, alpha}; -} - -void Context::setCombineRGB(GLenum combineRGB) -{ - mState.textureUnit[mState.activeSampler].combineRGB = combineRGB; -} - -void Context::setCombineAlpha(GLenum combineAlpha) -{ - mState.textureUnit[mState.activeSampler].combineAlpha = combineAlpha; -} - -void Context::setOperand0RGB(GLenum operand) -{ - mState.textureUnit[mState.activeSampler].operand0RGB = operand; -} - -void Context::setOperand1RGB(GLenum operand) -{ - mState.textureUnit[mState.activeSampler].operand1RGB = operand; -} - -void Context::setOperand2RGB(GLenum operand) -{ - mState.textureUnit[mState.activeSampler].operand2RGB = operand; -} - -void Context::setOperand0Alpha(GLenum operand) -{ - mState.textureUnit[mState.activeSampler].operand0Alpha = operand; -} - -void Context::setOperand1Alpha(GLenum operand) -{ - mState.textureUnit[mState.activeSampler].operand1Alpha = operand; -} - -void Context::setOperand2Alpha(GLenum operand) -{ - mState.textureUnit[mState.activeSampler].operand2Alpha = operand; -} - -void Context::setSrc0RGB(GLenum src) -{ - mState.textureUnit[mState.activeSampler].src0RGB = src; -} - -void Context::setSrc1RGB(GLenum src) -{ - mState.textureUnit[mState.activeSampler].src1RGB = src; -} - -void Context::setSrc2RGB(GLenum src) -{ - mState.textureUnit[mState.activeSampler].src2RGB = src; -} - -void Context::setSrc0Alpha(GLenum src) -{ - mState.textureUnit[mState.activeSampler].src0Alpha = src; -} - -void Context::setSrc1Alpha(GLenum src) -{ - mState.textureUnit[mState.activeSampler].src1Alpha = src; -} - -void Context::setSrc2Alpha(GLenum src) -{ - mState.textureUnit[mState.activeSampler].src2Alpha = src; -} - -void Context::applyTexture(int index, Texture *baseTexture) -{ - sw::Resource *resource = 0; - - if(baseTexture) - { - resource = baseTexture->getResource(); - } - - device->setTextureResource(index, resource); - - if(baseTexture) - { - int levelCount = baseTexture->getLevelCount(); - - if(baseTexture->getTarget() == GL_TEXTURE_2D || baseTexture->getTarget() == GL_TEXTURE_EXTERNAL_OES) - { - Texture2D *texture = static_cast<Texture2D*>(baseTexture); - - for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) - { - int surfaceLevel = mipmapLevel; - - if(surfaceLevel < 0) - { - surfaceLevel = 0; - } - else if(surfaceLevel >= levelCount) - { - surfaceLevel = levelCount - 1; - } - - egl::Image *surface = texture->getImage(surfaceLevel); - device->setTextureLevel(index, 0, mipmapLevel, surface, sw::TEXTURE_2D); - } - } - else UNIMPLEMENTED(); - } - else - { - device->setTextureLevel(index, 0, 0, 0, sw::TEXTURE_NULL); - } -} - -void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) -{ - Framebuffer *framebuffer = getFramebuffer(); - int framebufferWidth, framebufferHeight, framebufferSamples; - - if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE_OES) - { - return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES); - } - - if(getFramebufferName() != 0 && framebufferSamples != 0) - { - return error(GL_INVALID_OPERATION); - } - - if(format != GL_RGBA || type != GL_UNSIGNED_BYTE) - { - if(format != framebuffer->getImplementationColorReadFormat() || type != framebuffer->getImplementationColorReadType()) - { - return error(GL_INVALID_OPERATION); - } - } - - GLsizei outputPitch = egl::ComputePitch(width, format, type, mState.packAlignment); - - // Sized query sanity check - if(bufSize) - { - int requiredSize = outputPitch * height; - if(requiredSize > *bufSize) - { - return error(GL_INVALID_OPERATION); - } - } - - egl::Image *renderTarget = framebuffer->getRenderTarget(); - - if(!renderTarget) - { - return error(GL_OUT_OF_MEMORY); - } - - sw::Rect rect = {x, y, x + width, y + height}; - rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight()); - - unsigned char *source = (unsigned char*)renderTarget->lock(rect.x0, rect.y0, sw::LOCK_READONLY); - unsigned char *dest = (unsigned char*)pixels; - int inputPitch = (int)renderTarget->getPitch(); - - for(int j = 0; j < rect.y1 - rect.y0; j++) - { - unsigned short *dest16 = (unsigned short*)dest; - unsigned int *dest32 = (unsigned int*)dest; - - if(renderTarget->getInternalFormat() == sw::FORMAT_A8B8G8R8 && - format == GL_RGBA && type == GL_UNSIGNED_BYTE) - { - memcpy(dest, source, (rect.x1 - rect.x0) * 4); - } - else if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 && - format == GL_RGBA && type == GL_UNSIGNED_BYTE) - { - for(int i = 0; i < rect.x1 - rect.x0; i++) - { - unsigned int argb = *(unsigned int*)(source + 4 * i); - - dest32[i] = (argb & 0xFF00FF00) | ((argb & 0x000000FF) << 16) | ((argb & 0x00FF0000) >> 16); - } - } - else if(renderTarget->getInternalFormat() == sw::FORMAT_X8R8G8B8 && - format == GL_RGBA && type == GL_UNSIGNED_BYTE) - { - for(int i = 0; i < rect.x1 - rect.x0; i++) - { - unsigned int xrgb = *(unsigned int*)(source + 4 * i); - - dest32[i] = (xrgb & 0xFF00FF00) | ((xrgb & 0x000000FF) << 16) | ((xrgb & 0x00FF0000) >> 16) | 0xFF000000; - } - } - else if(renderTarget->getInternalFormat() == sw::FORMAT_X8R8G8B8 && - format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE) - { - for(int i = 0; i < rect.x1 - rect.x0; i++) - { - unsigned int xrgb = *(unsigned int*)(source + 4 * i); - - dest32[i] = xrgb | 0xFF000000; - } - } - else if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 && - format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE) - { - memcpy(dest, source, (rect.x1 - rect.x0) * 4); - } - else if(renderTarget->getInternalFormat() == sw::FORMAT_A1R5G5B5 && - format == GL_BGRA_EXT && type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT) - { - memcpy(dest, source, (rect.x1 - rect.x0) * 2); - } - else if(renderTarget->getInternalFormat() == sw::FORMAT_R5G6B5 && - format == 0x80E0 && type == GL_UNSIGNED_SHORT_5_6_5) // GL_BGR_EXT - { - memcpy(dest, source, (rect.x1 - rect.x0) * 2); - } - else - { - for(int i = 0; i < rect.x1 - rect.x0; i++) - { - float r; - float g; - float b; - float a; - - switch(renderTarget->getInternalFormat()) - { - case sw::FORMAT_R5G6B5: - { - unsigned short rgb = *(unsigned short*)(source + 2 * i); - - a = 1.0f; - b = (rgb & 0x001F) * (1.0f / 0x001F); - g = (rgb & 0x07E0) * (1.0f / 0x07E0); - r = (rgb & 0xF800) * (1.0f / 0xF800); - } - break; - case sw::FORMAT_A1R5G5B5: - { - unsigned short argb = *(unsigned short*)(source + 2 * i); - - a = (argb & 0x8000) ? 1.0f : 0.0f; - b = (argb & 0x001F) * (1.0f / 0x001F); - g = (argb & 0x03E0) * (1.0f / 0x03E0); - r = (argb & 0x7C00) * (1.0f / 0x7C00); - } - break; - case sw::FORMAT_A8R8G8B8: - { - unsigned int argb = *(unsigned int*)(source + 4 * i); - - a = (argb & 0xFF000000) * (1.0f / 0xFF000000); - b = (argb & 0x000000FF) * (1.0f / 0x000000FF); - g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case sw::FORMAT_A8B8G8R8: - { - unsigned int abgr = *(unsigned int*)(source + 4 * i); - - a = (abgr & 0xFF000000) * (1.0f / 0xFF000000); - b = (abgr & 0x00FF0000) * (1.0f / 0x00FF0000); - g = (abgr & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (abgr & 0x000000FF) * (1.0f / 0x000000FF); - } - break; - case sw::FORMAT_X8R8G8B8: - { - unsigned int xrgb = *(unsigned int*)(source + 4 * i); - - a = 1.0f; - b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); - g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case sw::FORMAT_X8B8G8R8: - { - unsigned int xbgr = *(unsigned int*)(source + 4 * i); - - a = 1.0f; - b = (xbgr & 0x00FF0000) * (1.0f / 0x00FF0000); - g = (xbgr & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (xbgr & 0x000000FF) * (1.0f / 0x000000FF); - } - break; - case sw::FORMAT_A2R10G10B10: - { - unsigned int argb = *(unsigned int*)(source + 4 * i); - - a = (argb & 0xC0000000) * (1.0f / 0xC0000000); - b = (argb & 0x000003FF) * (1.0f / 0x000003FF); - g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); - r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); - } - break; - default: - UNIMPLEMENTED(); // FIXME - UNREACHABLE(renderTarget->getInternalFormat()); - } - - switch(format) - { - case GL_RGBA: - switch(type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + 0] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + 2] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + 3] = (unsigned char)(255 * a + 0.5f); - break; - default: UNREACHABLE(type); - } - break; - case GL_BGRA_EXT: - switch(type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + 0] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + 2] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + 3] = (unsigned char)(255 * a + 0.5f); - break; - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i] = - ((unsigned short)(15 * a + 0.5f) << 12)| - ((unsigned short)(15 * r + 0.5f) << 8) | - ((unsigned short)(15 * g + 0.5f) << 4) | - ((unsigned short)(15 * b + 0.5f) << 0); - break; - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i] = - ((unsigned short)( a + 0.5f) << 15) | - ((unsigned short)(31 * r + 0.5f) << 10) | - ((unsigned short)(31 * g + 0.5f) << 5) | - ((unsigned short)(31 * b + 0.5f) << 0); - break; - default: UNREACHABLE(type); - } - break; - case GL_RGB: - switch(type) - { - case GL_UNSIGNED_SHORT_5_6_5: - dest16[i] = - ((unsigned short)(31 * b + 0.5f) << 0) | - ((unsigned short)(63 * g + 0.5f) << 5) | - ((unsigned short)(31 * r + 0.5f) << 11); - break; - default: UNREACHABLE(type); - } - break; - default: UNREACHABLE(format); - } - } - } - - source += inputPitch; - dest += outputPitch; - } - - renderTarget->unlock(); - renderTarget->release(); -} - -void Context::clear(GLbitfield mask) -{ - Framebuffer *framebuffer = getFramebuffer(); - - if(!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE_OES) - { - return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES); - } - - if(!applyRenderTarget()) - { - return; - } - - float depth = clamp01(mState.depthClearValue); - int stencil = mState.stencilClearValue & 0x000000FF; - - if(mask & GL_COLOR_BUFFER_BIT) - { - unsigned int rgbaMask = (mState.colorMaskRed ? 0x1 : 0) | - (mState.colorMaskGreen ? 0x2 : 0) | - (mState.colorMaskBlue ? 0x4 : 0) | - (mState.colorMaskAlpha ? 0x8 : 0); - - if(rgbaMask != 0) - { - device->clearColor(mState.colorClearValue.red, mState.colorClearValue.green, mState.colorClearValue.blue, mState.colorClearValue.alpha, rgbaMask); - } - } - - if(mask & GL_DEPTH_BUFFER_BIT) - { - if(mState.depthMask != 0) - { - device->clearDepth(depth); - } - } - - if(mask & GL_STENCIL_BUFFER_BIT) - { - if(mState.stencilWritemask != 0) - { - device->clearStencil(stencil, mState.stencilWritemask); - } - } -} - -void Context::drawArrays(GLenum mode, GLint first, GLsizei count) -{ - sw::DrawType primitiveType; - int primitiveCount; - - if(!es2sw::ConvertPrimitiveType(mode, count, GL_NONE, primitiveType, primitiveCount)) - return error(GL_INVALID_ENUM); - - if(primitiveCount <= 0) - { - return; - } - - if(!applyRenderTarget()) - { - return; - } - - applyState(mode); - - GLenum err = applyVertexBuffer(0, first, count); - if(err != GL_NO_ERROR) - { - return error(err); - } - - applyTextures(); - - if(!cullSkipsDraw(mode)) - { - device->drawPrimitive(primitiveType, primitiveCount); - } -} - -void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) -{ - if(!indices && !mState.elementArrayBuffer) - { - return error(GL_INVALID_OPERATION); - } - - sw::DrawType primitiveType; - int primitiveCount; - - if(!es2sw::ConvertPrimitiveType(mode, count, type, primitiveType, primitiveCount)) - return error(GL_INVALID_ENUM); - - if(primitiveCount <= 0) - { - return; - } - - if(!applyRenderTarget()) - { - return; - } - - applyState(mode); - - TranslatedIndexData indexInfo; - GLenum err = applyIndexBuffer(indices, 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); - if(err != GL_NO_ERROR) - { - return error(err); - } - - applyTextures(); - - if(!cullSkipsDraw(mode)) - { - device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, primitiveCount); - } -} - -void Context::drawTexture(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) -{ - es1::Framebuffer *framebuffer = getFramebuffer(); - es1::Renderbuffer *renderbuffer = framebuffer->getColorbuffer(); - float targetWidth = (float)renderbuffer->getWidth(); - float targetHeight = (float)renderbuffer->getHeight(); - float x0 = 2.0f * x / targetWidth - 1.0f; - float y0 = 2.0f * y / targetHeight - 1.0f; - float x1 = 2.0f * (x + width) / targetWidth - 1.0f; - float y1 = 2.0f * (y + height) / targetHeight - 1.0f; - float Zw = sw::clamp(mState.zNear + z * (mState.zFar - mState.zNear), mState.zNear, mState.zFar); - - float vertices[][3] = {{x0, y0, Zw}, - {x0, y1, Zw}, - {x1, y0, Zw}, - {x1, y1, Zw}}; - - ASSERT(mState.samplerTexture[TEXTURE_2D][1].name() == 0); // Multi-texturing unimplemented - es1::Texture *texture = getSamplerTexture(0, TEXTURE_2D); - float textureWidth = (float)texture->getWidth(GL_TEXTURE_2D, 0); - float textureHeight = (float)texture->getHeight(GL_TEXTURE_2D, 0); - int Ucr = texture->getCropRectU(); - int Vcr = texture->getCropRectV(); - int Wcr = texture->getCropRectW(); - int Hcr = texture->getCropRectH(); - - float texCoords[][2] = {{Ucr / textureWidth, Vcr / textureHeight}, - {Ucr / textureWidth, (Vcr + Hcr) / textureHeight}, - {(Ucr + Wcr) / textureWidth, Vcr / textureHeight}, - {(Ucr + Wcr) / textureWidth, (Vcr + Hcr) / textureHeight}}; - - VertexAttribute oldPositionAttribute = mState.vertexAttribute[sw::Position]; - VertexAttribute oldTexCoord0Attribute = mState.vertexAttribute[sw::TexCoord0]; - gl::BindingPointer<Buffer> oldArrayBuffer = mState.arrayBuffer; - mState.arrayBuffer = nullptr; - - glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), vertices); - glEnableClientState(GL_VERTEX_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(float), texCoords); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - sw::Matrix P = projectionStack.current(); - sw::Matrix M = modelViewStack.current(); - sw::Matrix T = textureStack0.current(); - - projectionStack.identity(); - modelViewStack.identity(); - textureStack0.identity(); - - drawArrays(GL_TRIANGLE_STRIP, 0, 4); - - // Restore state - mState.vertexAttribute[sw::Position] = oldPositionAttribute; - mState.vertexAttribute[sw::TexCoord0] = oldTexCoord0Attribute; - mState.arrayBuffer = oldArrayBuffer; - oldArrayBuffer = nullptr; - oldPositionAttribute.mBoundBuffer = nullptr; - oldTexCoord0Attribute.mBoundBuffer = nullptr; - textureStack0.load(T); - modelViewStack.load(M); - projectionStack.load(P); -} - -void Context::finish() -{ - device->finish(); -} - -void Context::flush() -{ - // We don't queue anything without processing it as fast as possible -} - -void Context::recordInvalidEnum() -{ - mInvalidEnum = true; -} - -void Context::recordInvalidValue() -{ - mInvalidValue = true; -} - -void Context::recordInvalidOperation() -{ - mInvalidOperation = true; -} - -void Context::recordOutOfMemory() -{ - mOutOfMemory = true; -} - -void Context::recordInvalidFramebufferOperation() -{ - mInvalidFramebufferOperation = true; -} - -void Context::recordMatrixStackOverflow() -{ - mMatrixStackOverflow = true; -} - -void Context::recordMatrixStackUnderflow() -{ - mMatrixStackUnderflow = true; -} - -// Get one of the recorded errors and clear its flag, if any. -// [OpenGL ES 2.0.24] section 2.5 page 13. -GLenum Context::getError() -{ - if(mInvalidEnum) - { - mInvalidEnum = false; - - return GL_INVALID_ENUM; - } - - if(mInvalidValue) - { - mInvalidValue = false; - - return GL_INVALID_VALUE; - } - - if(mInvalidOperation) - { - mInvalidOperation = false; - - return GL_INVALID_OPERATION; - } - - if(mOutOfMemory) - { - mOutOfMemory = false; - - return GL_OUT_OF_MEMORY; - } - - if(mInvalidFramebufferOperation) - { - mInvalidFramebufferOperation = false; - - return GL_INVALID_FRAMEBUFFER_OPERATION_OES; - } - - if(mMatrixStackOverflow) - { - mMatrixStackOverflow = false; - - return GL_INVALID_FRAMEBUFFER_OPERATION_OES; - } - - if(mMatrixStackUnderflow) - { - mMatrixStackUnderflow = false; - - return GL_INVALID_FRAMEBUFFER_OPERATION_OES; - } - - return GL_NO_ERROR; -} - -int Context::getSupportedMultisampleCount(int requested) -{ - int supported = 0; - - for(int i = NUM_MULTISAMPLE_COUNTS - 1; i >= 0; i--) - { - if(supported >= requested) - { - return supported; - } - - supported = multisampleCount[i]; - } - - return supported; -} - -void Context::detachBuffer(GLuint buffer) -{ - // [OpenGL ES 2.0.24] section 2.9 page 22: - // If a buffer object is deleted while it is bound, all bindings to that object in the current context - // (i.e. in the thread that called Delete-Buffers) are reset to zero. - - if(mState.arrayBuffer.name() == buffer) - { - mState.arrayBuffer = nullptr; - } - - if(mState.elementArrayBuffer.name() == buffer) - { - mState.elementArrayBuffer = nullptr; - } - - for(int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) - { - if(mState.vertexAttribute[attribute].mBoundBuffer.name() == buffer) - { - mState.vertexAttribute[attribute].mBoundBuffer = nullptr; - } - } -} - -void Context::detachTexture(GLuint texture) -{ - // [OpenGL ES 2.0.24] section 3.8 page 84: - // If a texture object is deleted, it is as if all texture units which are bound to that texture object are - // rebound to texture object zero - - for(int type = 0; type < TEXTURE_TYPE_COUNT; type++) - { - for(int sampler = 0; sampler < MAX_TEXTURE_UNITS; sampler++) - { - if(mState.samplerTexture[type][sampler].name() == texture) - { - mState.samplerTexture[type][sampler] = nullptr; - } - } - } - - // [OpenGL ES 2.0.24] section 4.4 page 112: - // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is - // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this - // image was attached in the currently bound framebuffer. - - Framebuffer *framebuffer = getFramebuffer(); - - if(framebuffer) - { - framebuffer->detachTexture(texture); - } -} - -void Context::detachFramebuffer(GLuint framebuffer) -{ - // [OpenGL ES 2.0.24] section 4.4 page 107: - // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though - // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. - - if(mState.framebuffer == framebuffer) - { - bindFramebuffer(0); - } -} - -void Context::detachRenderbuffer(GLuint renderbuffer) -{ - // [OpenGL ES 2.0.24] section 4.4 page 109: - // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer - // had been executed with the target RENDERBUFFER and name of zero. - - if(mState.renderbuffer.name() == renderbuffer) - { - bindRenderbuffer(0); - } - - // [OpenGL ES 2.0.24] section 4.4 page 111: - // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, - // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment - // point to which this image was attached in the currently bound framebuffer. - - Framebuffer *framebuffer = getFramebuffer(); - - if(framebuffer) - { - framebuffer->detachRenderbuffer(renderbuffer); - } -} - -bool Context::cullSkipsDraw(GLenum drawMode) -{ - return mState.cullFaceEnabled && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode); -} - -bool Context::isTriangleMode(GLenum drawMode) -{ - switch(drawMode) - { - case GL_TRIANGLES: - case GL_TRIANGLE_FAN: - case GL_TRIANGLE_STRIP: - return true; - case GL_POINTS: - case GL_LINES: - case GL_LINE_LOOP: - case GL_LINE_STRIP: - return false; - default: UNREACHABLE(drawMode); - } - - return false; -} - -void Context::setVertexAttrib(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - ASSERT(index < MAX_VERTEX_ATTRIBS); - - mState.vertexAttribute[index].mCurrentValue[0] = x; - mState.vertexAttribute[index].mCurrentValue[1] = y; - mState.vertexAttribute[index].mCurrentValue[2] = z; - mState.vertexAttribute[index].mCurrentValue[3] = w; - - mVertexDataManager->dirtyCurrentValue(index); -} - -void Context::bindTexImage(egl::Surface *surface) -{ - es1::Texture2D *textureObject = getTexture2D(); - - if(textureObject) - { - textureObject->bindTexImage(surface); - } -} - -EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel) -{ - switch(target) - { - case EGL_GL_TEXTURE_2D_KHR: - break; - case EGL_GL_RENDERBUFFER_KHR: - break; - default: - return EGL_BAD_PARAMETER; - } - - if(textureLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - return EGL_BAD_MATCH; - } - - if(target == EGL_GL_TEXTURE_2D_KHR) - { - Texture *texture = getTexture(name); - - if(!texture || texture->getTarget() != GL_TEXTURE_2D) - { - return EGL_BAD_PARAMETER; - } - - if(texture->isShared(GL_TEXTURE_2D, textureLevel)) // Bound to an EGLSurface or already an EGLImage sibling - { - return EGL_BAD_ACCESS; - } - - if(textureLevel != 0 && !texture->isSamplerComplete()) - { - return EGL_BAD_PARAMETER; - } - - if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getLevelCount() == 1)) - { - return EGL_BAD_PARAMETER; - } - } - else if(target == EGL_GL_RENDERBUFFER_KHR) - { - Renderbuffer *renderbuffer = getRenderbuffer(name); - - if(!renderbuffer) - { - return EGL_BAD_PARAMETER; - } - - if(renderbuffer->isShared()) // Already an EGLImage sibling - { - return EGL_BAD_ACCESS; - } - } - else UNREACHABLE(target); - - return EGL_SUCCESS; -} - -egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textureLevel) -{ - if(target == EGL_GL_TEXTURE_2D_KHR) - { - es1::Texture *texture = getTexture(name); - - return texture->createSharedImage(GL_TEXTURE_2D, textureLevel); - } - else if(target == EGL_GL_RENDERBUFFER_KHR) - { - es1::Renderbuffer *renderbuffer = getRenderbuffer(name); - - return renderbuffer->createSharedImage(); - } - else UNREACHABLE(target); - - return 0; -} - -Device *Context::getDevice() -{ - return device; -} - -void Context::setMatrixMode(GLenum mode) -{ - matrixMode = mode; -} - -sw::MatrixStack &Context::currentMatrixStack() -{ - switch(matrixMode) - { - case GL_MODELVIEW: - return modelViewStack; - case GL_PROJECTION: - return projectionStack; - case GL_TEXTURE: - switch(mState.activeSampler) - { - case 0: return textureStack0; - case 1: return textureStack1; - } - break; - } - - UNREACHABLE(matrixMode); - return textureStack0; -} - -void Context::loadIdentity() -{ - currentMatrixStack().identity(); -} - -void Context::load(const GLfloat *m) -{ - currentMatrixStack().load(m); -} - -void Context::pushMatrix() -{ - if(!currentMatrixStack().push()) - { - return error(GL_STACK_OVERFLOW); - } -} - -void Context::popMatrix() -{ - if(!currentMatrixStack().pop()) - { - return error(GL_STACK_OVERFLOW); - } -} - -void Context::rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) -{ - currentMatrixStack().rotate(angle, x, y, z); -} - -void Context::translate(GLfloat x, GLfloat y, GLfloat z) -{ - currentMatrixStack().translate(x, y, z); -} - -void Context::scale(GLfloat x, GLfloat y, GLfloat z) -{ - currentMatrixStack().scale(x, y, z); -} - -void Context::multiply(const GLfloat *m) -{ - currentMatrixStack().multiply(m); -} - -void Context::frustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) -{ - currentMatrixStack().frustum(left, right, bottom, top, zNear, zFar); -} - -void Context::ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) -{ - currentMatrixStack().ortho(left, right, bottom, top, zNear, zFar); -} - -void Context::setClipPlane(int index, const float plane[4]) -{ - sw::Plane clipPlane = modelViewStack.current() * sw::Plane(plane); - device->setClipPlane(index, &clipPlane.A); -} - -void Context::setClipPlaneEnabled(int index, bool enable) -{ - clipFlags = (clipFlags & ~((int)!enable << index)) | ((int)enable << index); - device->setClipFlags(clipFlags); -} - -bool Context::isClipPlaneEnabled(int index) const -{ - return (clipFlags & (1 << index)) != 0; -} - -void Context::setColorLogicOpEnabled(bool enable) -{ - colorLogicOpEnabled = enable; -} - -bool Context::isColorLogicOpEnabled() const -{ - return colorLogicOpEnabled; -} - -void Context::setLogicalOperation(GLenum logicOp) -{ - logicalOperation = logicOp; -} - -void Context::setLineSmoothEnabled(bool enable) -{ - lineSmoothEnabled = enable; -} - -bool Context::isLineSmoothEnabled() const -{ - return lineSmoothEnabled; -} - -void Context::setColorMaterialEnabled(bool enable) -{ - colorMaterialEnabled = enable; -} - -bool Context::isColorMaterialEnabled() const -{ - return colorMaterialEnabled; -} - -void Context::setNormalizeEnabled(bool enable) -{ - normalizeEnabled = enable; -} - -bool Context::isNormalizeEnabled() const -{ - return normalizeEnabled; -} - -void Context::setRescaleNormalEnabled(bool enable) -{ - rescaleNormalEnabled = enable; -} - -bool Context::isRescaleNormalEnabled() const -{ - return rescaleNormalEnabled; -} - -void Context::setVertexArrayEnabled(bool enable) -{ - mState.vertexAttribute[sw::Position].mArrayEnabled = enable; -} - -bool Context::isVertexArrayEnabled() const -{ - return mState.vertexAttribute[sw::Position].mArrayEnabled; -} - -void Context::setNormalArrayEnabled(bool enable) -{ - mState.vertexAttribute[sw::Normal].mArrayEnabled = enable; -} - -bool Context::isNormalArrayEnabled() const -{ - return mState.vertexAttribute[sw::Normal].mArrayEnabled; -} - -void Context::setColorArrayEnabled(bool enable) -{ - mState.vertexAttribute[sw::Color0].mArrayEnabled = enable; -} - -bool Context::isColorArrayEnabled() const -{ - return mState.vertexAttribute[sw::Color0].mArrayEnabled; -} - -void Context::setPointSizeArrayEnabled(bool enable) -{ - mState.vertexAttribute[sw::PointSize].mArrayEnabled = enable; -} - -bool Context::isPointSizeArrayEnabled() const -{ - return mState.vertexAttribute[sw::PointSize].mArrayEnabled; -} - -void Context::setTextureCoordArrayEnabled(bool enable) -{ - mState.vertexAttribute[sw::TexCoord0 + clientTexture].mArrayEnabled = enable; -} - -bool Context::isTextureCoordArrayEnabled() const -{ - return mState.vertexAttribute[sw::TexCoord0 + clientTexture].mArrayEnabled; -} - -void Context::setMultisampleEnabled(bool enable) -{ - multisampleEnabled = enable; -} - -bool Context::isMultisampleEnabled() const -{ - return multisampleEnabled; -} - -void Context::setSampleAlphaToOneEnabled(bool enable) -{ - sampleAlphaToOneEnabled = enable; -} - -bool Context::isSampleAlphaToOneEnabled() const -{ - return sampleAlphaToOneEnabled; -} - -void Context::setPointSpriteEnabled(bool enable) -{ - pointSpriteEnabled = enable; -} - -bool Context::isPointSpriteEnabled() const -{ - return pointSpriteEnabled; -} - -void Context::setPointSmoothEnabled(bool enable) -{ - pointSmoothEnabled = enable; -} - -bool Context::isPointSmoothEnabled() const -{ - return pointSmoothEnabled; -} - - -void Context::setPointSizeMin(float min) -{ - pointSizeMin = min; -} - -void Context::setPointSizeMax(float max) -{ - pointSizeMax = max; -} - -void Context::setPointDistanceAttenuation(float a, float b, float c) -{ - pointDistanceAttenuation = {a, b, c}; -} - -void Context::setPointFadeThresholdSize(float threshold) -{ - pointFadeThresholdSize = threshold; -} - -void Context::clientActiveTexture(GLenum texture) -{ - clientTexture = texture; -} - -GLenum Context::getClientActiveTexture() const -{ - return clientTexture; -} - -unsigned int Context::getActiveTexture() const -{ - return mState.activeSampler; -} - -} - -egl::Context *es1CreateContext(const egl::Config *config, const egl::Context *shareContext) -{ - ASSERT(!shareContext || shareContext->getClientVersion() == 1); // Should be checked by eglCreateContext - return new es1::Context(config, static_cast<const es1::Context*>(shareContext)); -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Context.cpp: Implements the es1::Context class, managing all GL state and performing +// rendering operations. It is the GLES2 specific implementation of EGLContext. + +#include "Context.h" + +#include "main.h" +#include "mathutil.h" +#include "utilities.h" +#include "ResourceManager.h" +#include "Buffer.h" +#include "Framebuffer.h" +#include "Renderbuffer.h" +#include "Texture.h" +#include "VertexDataManager.h" +#include "IndexDataManager.h" +#include "libEGL/Display.h" +#include "libEGL/Surface.h" +#include "Common/Half.hpp" + +#include <EGL/eglext.h> + +using std::abs; + +namespace es1 +{ +Context::Context(const egl::Config *config, const Context *shareContext) + : modelViewStack(MAX_MODELVIEW_STACK_DEPTH), + projectionStack(MAX_PROJECTION_STACK_DEPTH), + textureStack0(MAX_TEXTURE_STACK_DEPTH), + textureStack1(MAX_TEXTURE_STACK_DEPTH) +{ + sw::Context *context = new sw::Context(); + device = new es1::Device(context); + + mVertexDataManager = new VertexDataManager(this); + mIndexDataManager = new IndexDataManager(); + + setClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + mState.depthClearValue = 1.0f; + mState.stencilClearValue = 0; + + mState.cullFaceEnabled = false; + mState.cullMode = GL_BACK; + mState.frontFace = GL_CCW; + mState.depthTestEnabled = false; + mState.depthFunc = GL_LESS; + mState.blendEnabled = false; + mState.sourceBlendRGB = GL_ONE; + mState.sourceBlendAlpha = GL_ONE; + mState.destBlendRGB = GL_ZERO; + mState.destBlendAlpha = GL_ZERO; + mState.blendEquationRGB = GL_FUNC_ADD_OES; + mState.blendEquationAlpha = GL_FUNC_ADD_OES; + mState.stencilTestEnabled = false; + mState.stencilFunc = GL_ALWAYS; + mState.stencilRef = 0; + mState.stencilMask = -1; + mState.stencilWritemask = -1; + mState.stencilFail = GL_KEEP; + mState.stencilPassDepthFail = GL_KEEP; + mState.stencilPassDepthPass = GL_KEEP; + mState.polygonOffsetFillEnabled = false; + mState.polygonOffsetFactor = 0.0f; + mState.polygonOffsetUnits = 0.0f; + mState.sampleAlphaToCoverageEnabled = false; + mState.sampleCoverageEnabled = false; + mState.sampleCoverageValue = 1.0f; + mState.sampleCoverageInvert = false; + mState.scissorTestEnabled = false; + mState.ditherEnabled = true; + mState.shadeModel = GL_SMOOTH; + mState.generateMipmapHint = GL_DONT_CARE; + mState.perspectiveCorrectionHint = GL_DONT_CARE; + mState.fogHint = GL_DONT_CARE; + + mState.lineWidth = 1.0f; + + mState.viewportX = 0; + mState.viewportY = 0; + mState.viewportWidth = 0; + mState.viewportHeight = 0; + mState.zNear = 0.0f; + mState.zFar = 1.0f; + + mState.scissorX = 0; + mState.scissorY = 0; + mState.scissorWidth = 0; + mState.scissorHeight = 0; + + mState.colorMaskRed = true; + mState.colorMaskGreen = true; + mState.colorMaskBlue = true; + mState.colorMaskAlpha = true; + mState.depthMask = true; + + for(int i = 0; i < MAX_TEXTURE_UNITS; i++) + { + mState.textureUnit[i].color = {0, 0, 0, 0}; + mState.textureUnit[i].environmentMode = GL_MODULATE; + mState.textureUnit[i].combineRGB = GL_MODULATE; + mState.textureUnit[i].combineAlpha = GL_MODULATE; + mState.textureUnit[i].src0RGB = GL_TEXTURE; + mState.textureUnit[i].src1RGB = GL_PREVIOUS; + mState.textureUnit[i].src2RGB = GL_CONSTANT; + mState.textureUnit[i].src0Alpha = GL_TEXTURE; + mState.textureUnit[i].src1Alpha = GL_PREVIOUS; + mState.textureUnit[i].src2Alpha = GL_CONSTANT; + mState.textureUnit[i].operand0RGB = GL_SRC_COLOR; + mState.textureUnit[i].operand1RGB = GL_SRC_COLOR; + mState.textureUnit[i].operand2RGB = GL_SRC_ALPHA; + mState.textureUnit[i].operand0Alpha = GL_SRC_ALPHA; + mState.textureUnit[i].operand1Alpha = GL_SRC_ALPHA; + mState.textureUnit[i].operand2Alpha = GL_SRC_ALPHA; + } + + if(shareContext) + { + mResourceManager = shareContext->mResourceManager; + mResourceManager->addRef(); + } + else + { + mResourceManager = new ResourceManager(); + } + + // [OpenGL ES 2.0.24] section 3.7 page 83: + // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional + // and cube map texture state vectors respectively associated with them. + // In order that access to these initial textures not be lost, they are treated as texture + // objects all of whose names are 0. + + mTexture2DZero = new Texture2D(0); + mTextureExternalZero = new TextureExternal(0); + + mState.activeSampler = 0; + bindArrayBuffer(0); + bindElementArrayBuffer(0); + bindTexture2D(0); + bindFramebuffer(0); + bindRenderbuffer(0); + + mState.packAlignment = 4; + mState.unpackAlignment = 4; + + mInvalidEnum = false; + mInvalidValue = false; + mInvalidOperation = false; + mOutOfMemory = false; + mInvalidFramebufferOperation = false; + mMatrixStackOverflow = false; + mMatrixStackUnderflow = false; + + lightingEnabled = false; + + for(int i = 0; i < MAX_LIGHTS; i++) + { + light[i].enabled = false; + light[i].ambient = {0.0f, 0.0f, 0.0f, 1.0f}; + light[i].diffuse = {0.0f, 0.0f, 0.0f, 1.0f}; + light[i].specular = {0.0f, 0.0f, 0.0f, 1.0f}; + light[i].position = {0.0f, 0.0f, 1.0f, 0.0f}; + light[i].direction = {0.0f, 0.0f, -1.0f}; + light[i].attenuation = {1.0f, 0.0f, 0.0f}; + light[i].spotExponent = 0.0f; + light[i].spotCutoffAngle = 180.0f; + } + + light[0].diffuse = {1.0f, 1.0f, 1.0f, 1.0f}; + light[0].specular = {1.0f, 1.0f, 1.0f, 1.0f}; + + globalAmbient = {0.2f, 0.2f, 0.2f, 1.0f}; + materialAmbient = {0.2f, 0.2f, 0.2f, 1.0f}; + materialDiffuse = {0.8f, 0.8f, 0.8f, 1.0f}; + materialSpecular = {0.0f, 0.0f, 0.0f, 1.0f}; + materialEmission = {0.0f, 0.0f, 0.0f, 1.0f}; + materialShininess = 0.0f; + lightModelTwoSide = false; + + matrixMode = GL_MODELVIEW; + + for(int i = 0; i < MAX_TEXTURE_UNITS; i++) + { + texture2Denabled[i] = false; + textureExternalEnabled[i] = false; + } + + clientTexture = GL_TEXTURE0; + + setVertexAttrib(sw::Color0, 1.0f, 1.0f, 1.0f, 1.0f); + + for(int i = 0; i < MAX_TEXTURE_UNITS; i++) + { + setVertexAttrib(sw::TexCoord0 + i, 0.0f, 0.0f, 0.0f, 1.0f); + } + + setVertexAttrib(sw::Normal, 0.0f, 0.0f, 1.0f, 1.0f); + setVertexAttrib(sw::PointSize, 1.0f, 1.0f, 1.0f, 1.0f); + + clipFlags = 0; + + alphaTestEnabled = false; + alphaTestFunc = GL_ALWAYS; + alphaTestRef = 0; + + fogEnabled = false; + fogMode = GL_EXP; + fogDensity = 1.0f; + fogStart = 0.0f; + fogEnd = 1.0f; + fogColor = {0, 0, 0, 0}; + + lineSmoothEnabled = false; + colorMaterialEnabled = false; + normalizeEnabled = false; + rescaleNormalEnabled = false; + multisampleEnabled = true; + sampleAlphaToOneEnabled = false; + + colorLogicOpEnabled = false; + logicalOperation = GL_COPY; + + pointSpriteEnabled = false; + pointSmoothEnabled = false; + pointSizeMin = 0.0f; + pointSizeMax = 1.0f; + pointDistanceAttenuation = {1.0f, 0.0f, 0.0f}; + pointFadeThresholdSize = 1.0f; + + mHasBeenCurrent = false; + + markAllStateDirty(); +} + +Context::~Context() +{ + while(!mFramebufferNameSpace.empty()) + { + deleteFramebuffer(mFramebufferNameSpace.firstName()); + } + + for(int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + for(int sampler = 0; sampler < MAX_TEXTURE_UNITS; sampler++) + { + mState.samplerTexture[type][sampler] = nullptr; + } + } + + for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + mState.vertexAttribute[i].mBoundBuffer = nullptr; + } + + mState.arrayBuffer = nullptr; + mState.elementArrayBuffer = nullptr; + mState.renderbuffer = nullptr; + + mTexture2DZero = nullptr; + mTextureExternalZero = nullptr; + + delete mVertexDataManager; + delete mIndexDataManager; + + mResourceManager->release(); + delete device; +} + +void Context::makeCurrent(egl::Surface *surface) +{ + if(!mHasBeenCurrent) + { + mState.viewportX = 0; + mState.viewportY = 0; + mState.viewportWidth = surface->getWidth(); + mState.viewportHeight = surface->getHeight(); + + mState.scissorX = 0; + mState.scissorY = 0; + mState.scissorWidth = surface->getWidth(); + mState.scissorHeight = surface->getHeight(); + + mHasBeenCurrent = true; + } + + // Wrap the existing resources into GL objects and assign them to the '0' names + egl::Image *defaultRenderTarget = surface->getRenderTarget(); + egl::Image *depthStencil = surface->getDepthStencil(); + + Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget); + DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil); + Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); + + setFramebufferZero(framebufferZero); + + if(defaultRenderTarget) + { + defaultRenderTarget->release(); + } + + if(depthStencil) + { + depthStencil->release(); + } + + markAllStateDirty(); +} + +int Context::getClientVersion() const +{ + return 1; +} + +// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw. +void Context::markAllStateDirty() +{ + mDepthStateDirty = true; + mMaskStateDirty = true; + mBlendStateDirty = true; + mStencilStateDirty = true; + mPolygonOffsetStateDirty = true; + mSampleStateDirty = true; + mDitherStateDirty = true; + mFrontFaceDirty = true; +} + +void Context::setClearColor(float red, float green, float blue, float alpha) +{ + mState.colorClearValue.red = red; + mState.colorClearValue.green = green; + mState.colorClearValue.blue = blue; + mState.colorClearValue.alpha = alpha; +} + +void Context::setClearDepth(float depth) +{ + mState.depthClearValue = depth; +} + +void Context::setClearStencil(int stencil) +{ + mState.stencilClearValue = stencil; +} + +void Context::setCullFaceEnabled(bool enabled) +{ + mState.cullFaceEnabled = enabled; +} + +bool Context::isCullFaceEnabled() const +{ + return mState.cullFaceEnabled; +} + +void Context::setCullMode(GLenum mode) +{ + mState.cullMode = mode; +} + +void Context::setFrontFace(GLenum front) +{ + if(mState.frontFace != front) + { + mState.frontFace = front; + mFrontFaceDirty = true; + } +} + +void Context::setDepthTestEnabled(bool enabled) +{ + if(mState.depthTestEnabled != enabled) + { + mState.depthTestEnabled = enabled; + mDepthStateDirty = true; + } +} + +bool Context::isDepthTestEnabled() const +{ + return mState.depthTestEnabled; +} + +void Context::setDepthFunc(GLenum depthFunc) +{ + if(mState.depthFunc != depthFunc) + { + mState.depthFunc = depthFunc; + mDepthStateDirty = true; + } +} + +void Context::setDepthRange(float zNear, float zFar) +{ + mState.zNear = zNear; + mState.zFar = zFar; +} + +void Context::setAlphaTestEnabled(bool enabled) +{ + alphaTestEnabled = enabled; +} + +bool Context::isAlphaTestEnabled() const +{ + return alphaTestEnabled; +} + +void Context::setAlphaFunc(GLenum alphaFunc, GLclampf reference) +{ + alphaTestFunc = alphaFunc; + alphaTestRef = reference; +} + +void Context::setBlendEnabled(bool enabled) +{ + if(mState.blendEnabled != enabled) + { + mState.blendEnabled = enabled; + mBlendStateDirty = true; + } +} + +bool Context::isBlendEnabled() const +{ + return mState.blendEnabled; +} + +void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) +{ + if(mState.sourceBlendRGB != sourceRGB || + mState.sourceBlendAlpha != sourceAlpha || + mState.destBlendRGB != destRGB || + mState.destBlendAlpha != destAlpha) + { + mState.sourceBlendRGB = sourceRGB; + mState.destBlendRGB = destRGB; + mState.sourceBlendAlpha = sourceAlpha; + mState.destBlendAlpha = destAlpha; + mBlendStateDirty = true; + } +} + +void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) +{ + if(mState.blendEquationRGB != rgbEquation || + mState.blendEquationAlpha != alphaEquation) + { + mState.blendEquationRGB = rgbEquation; + mState.blendEquationAlpha = alphaEquation; + mBlendStateDirty = true; + } +} + +void Context::setStencilTestEnabled(bool enabled) +{ + if(mState.stencilTestEnabled != enabled) + { + mState.stencilTestEnabled = enabled; + mStencilStateDirty = true; + } +} + +bool Context::isStencilTestEnabled() const +{ + return mState.stencilTestEnabled; +} + +void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) +{ + if(mState.stencilFunc != stencilFunc || + mState.stencilRef != stencilRef || + mState.stencilMask != stencilMask) + { + mState.stencilFunc = stencilFunc; + mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; + mState.stencilMask = stencilMask; + mStencilStateDirty = true; + } +} + +void Context::setStencilWritemask(GLuint stencilWritemask) +{ + if(mState.stencilWritemask != stencilWritemask) + { + mState.stencilWritemask = stencilWritemask; + mStencilStateDirty = true; + } +} + +void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) +{ + if(mState.stencilFail != stencilFail || + mState.stencilPassDepthFail != stencilPassDepthFail || + mState.stencilPassDepthPass != stencilPassDepthPass) + { + mState.stencilFail = stencilFail; + mState.stencilPassDepthFail = stencilPassDepthFail; + mState.stencilPassDepthPass = stencilPassDepthPass; + mStencilStateDirty = true; + } +} + +void Context::setPolygonOffsetFillEnabled(bool enabled) +{ + if(mState.polygonOffsetFillEnabled != enabled) + { + mState.polygonOffsetFillEnabled = enabled; + mPolygonOffsetStateDirty = true; + } +} + +bool Context::isPolygonOffsetFillEnabled() const +{ + return mState.polygonOffsetFillEnabled; +} + +void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) +{ + if(mState.polygonOffsetFactor != factor || + mState.polygonOffsetUnits != units) + { + mState.polygonOffsetFactor = factor; + mState.polygonOffsetUnits = units; + mPolygonOffsetStateDirty = true; + } +} + +void Context::setSampleAlphaToCoverageEnabled(bool enabled) +{ + if(mState.sampleAlphaToCoverageEnabled != enabled) + { + mState.sampleAlphaToCoverageEnabled = enabled; + mSampleStateDirty = true; + } +} + +bool Context::isSampleAlphaToCoverageEnabled() const +{ + return mState.sampleAlphaToCoverageEnabled; +} + +void Context::setSampleCoverageEnabled(bool enabled) +{ + if(mState.sampleCoverageEnabled != enabled) + { + mState.sampleCoverageEnabled = enabled; + mSampleStateDirty = true; + } +} + +bool Context::isSampleCoverageEnabled() const +{ + return mState.sampleCoverageEnabled; +} + +void Context::setSampleCoverageParams(GLclampf value, bool invert) +{ + if(mState.sampleCoverageValue != value || + mState.sampleCoverageInvert != invert) + { + mState.sampleCoverageValue = value; + mState.sampleCoverageInvert = invert; + mSampleStateDirty = true; + } +} + +void Context::setScissorTestEnabled(bool enabled) +{ + mState.scissorTestEnabled = enabled; +} + +bool Context::isScissorTestEnabled() const +{ + return mState.scissorTestEnabled; +} + +void Context::setShadeModel(GLenum mode) +{ + mState.shadeModel = mode; +} + +void Context::setDitherEnabled(bool enabled) +{ + if(mState.ditherEnabled != enabled) + { + mState.ditherEnabled = enabled; + mDitherStateDirty = true; + } +} + +bool Context::isDitherEnabled() const +{ + return mState.ditherEnabled; +} + +void Context::setLightingEnabled(bool enable) +{ + lightingEnabled = enable; +} + +bool Context::isLightingEnabled() const +{ + return lightingEnabled; +} + +void Context::setLightEnabled(int index, bool enable) +{ + light[index].enabled = enable; +} + +bool Context::isLightEnabled(int index) const +{ + return light[index].enabled; +} + +void Context::setLightAmbient(int index, float r, float g, float b, float a) +{ + light[index].ambient = {r, g, b, a}; +} + +void Context::setLightDiffuse(int index, float r, float g, float b, float a) +{ + light[index].diffuse = {r, g, b, a}; +} + +void Context::setLightSpecular(int index, float r, float g, float b, float a) +{ + light[index].specular = {r, g, b, a}; +} + +void Context::setLightPosition(int index, float x, float y, float z, float w) +{ + sw::float4 v = {x, y, z, w}; + + // Transform from object coordinates to eye coordinates + v = modelViewStack.current() * v; + + light[index].position = {v.x, v.y, v.z, v.w}; +} + +void Context::setLightDirection(int index, float x, float y, float z) +{ + // FIXME: Transform by inverse of 3x3 model-view matrix + light[index].direction = {x, y, z}; +} + +void Context::setLightAttenuationConstant(int index, float constant) +{ + light[index].attenuation.constant = constant; +} + +void Context::setLightAttenuationLinear(int index, float linear) +{ + light[index].attenuation.linear = linear; +} + +void Context::setLightAttenuationQuadratic(int index, float quadratic) +{ + light[index].attenuation.quadratic = quadratic; +} + +void Context::setSpotLightExponent(int index, float exponent) +{ + light[index].spotExponent = exponent; +} + +void Context::setSpotLightCutoff(int index, float cutoff) +{ + light[index].spotCutoffAngle = cutoff; +} + +void Context::setGlobalAmbient(float red, float green, float blue, float alpha) +{ + globalAmbient.red = red; + globalAmbient.green = green; + globalAmbient.blue = blue; + globalAmbient.alpha = alpha; +} + +void Context::setMaterialAmbient(float red, float green, float blue, float alpha) +{ + materialAmbient.red = red; + materialAmbient.green = green; + materialAmbient.blue = blue; + materialAmbient.alpha = alpha; +} + +void Context::setMaterialDiffuse(float red, float green, float blue, float alpha) +{ + materialDiffuse.red = red; + materialDiffuse.green = green; + materialDiffuse.blue = blue; + materialDiffuse.alpha = alpha; +} + +void Context::setMaterialSpecular(float red, float green, float blue, float alpha) +{ + materialSpecular.red = red; + materialSpecular.green = green; + materialSpecular.blue = blue; + materialSpecular.alpha = alpha; +} + +void Context::setMaterialEmission(float red, float green, float blue, float alpha) +{ + materialEmission.red = red; + materialEmission.green = green; + materialEmission.blue = blue; + materialEmission.alpha = alpha; +} + +void Context::setMaterialShininess(float shininess) +{ + materialShininess = shininess; +} + +void Context::setLightModelTwoSide(bool enable) +{ + lightModelTwoSide = enable; +} + +void Context::setFogEnabled(bool enable) +{ + fogEnabled = enable; +} + +bool Context::isFogEnabled() const +{ + return fogEnabled; +} + +void Context::setFogMode(GLenum mode) +{ + fogMode = mode; +} + +void Context::setFogDensity(float fogDensity) +{ + this->fogDensity = fogDensity; +} + +void Context::setFogStart(float fogStart) +{ + this->fogStart = fogStart; +} + +void Context::setFogEnd(float fogEnd) +{ + this->fogEnd = fogEnd; +} + +void Context::setFogColor(float r, float g, float b, float a) +{ + this->fogColor = {r, g, b, a}; +} + +void Context::setTexture2Denabled(bool enable) +{ + texture2Denabled[mState.activeSampler] = enable; +} + +bool Context::isTexture2Denabled() const +{ + return texture2Denabled[mState.activeSampler]; +} + +void Context::setTextureExternalEnabled(bool enable) +{ + textureExternalEnabled[mState.activeSampler] = enable; +} + +bool Context::isTextureExternalEnabled() const +{ + return textureExternalEnabled[mState.activeSampler]; +} + +void Context::setLineWidth(GLfloat width) +{ + mState.lineWidth = width; + device->setLineWidth(clamp(width, ALIASED_LINE_WIDTH_RANGE_MIN, ALIASED_LINE_WIDTH_RANGE_MAX)); +} + +void Context::setGenerateMipmapHint(GLenum hint) +{ + mState.generateMipmapHint = hint; +} + +void Context::setPerspectiveCorrectionHint(GLenum hint) +{ + mState.perspectiveCorrectionHint = hint; +} + +void Context::setFogHint(GLenum hint) +{ + mState.fogHint = hint; +} + +void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mState.viewportX = x; + mState.viewportY = y; + mState.viewportWidth = width; + mState.viewportHeight = height; +} + +void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mState.scissorX = x; + mState.scissorY = y; + mState.scissorWidth = width; + mState.scissorHeight = height; +} + +void Context::setColorMask(bool red, bool green, bool blue, bool alpha) +{ + if(mState.colorMaskRed != red || mState.colorMaskGreen != green || + mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha) + { + mState.colorMaskRed = red; + mState.colorMaskGreen = green; + mState.colorMaskBlue = blue; + mState.colorMaskAlpha = alpha; + mMaskStateDirty = true; + } +} + +void Context::setDepthMask(bool mask) +{ + if(mState.depthMask != mask) + { + mState.depthMask = mask; + mMaskStateDirty = true; + } +} + +void Context::setActiveSampler(unsigned int active) +{ + mState.activeSampler = active; +} + +GLuint Context::getFramebufferName() const +{ + return mState.framebuffer; +} + +GLuint Context::getRenderbufferName() const +{ + return mState.renderbuffer.name(); +} + +GLuint Context::getArrayBufferName() const +{ + return mState.arrayBuffer.name(); +} + +void Context::setVertexAttribArrayEnabled(unsigned int attribNum, bool enabled) +{ + mState.vertexAttribute[attribNum].mArrayEnabled = enabled; +} + +const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) +{ + return mState.vertexAttribute[attribNum]; +} + +void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, + GLsizei stride, const void *pointer) +{ + mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer; + mState.vertexAttribute[attribNum].mSize = size; + mState.vertexAttribute[attribNum].mType = type; + mState.vertexAttribute[attribNum].mNormalized = normalized; + mState.vertexAttribute[attribNum].mStride = stride; + mState.vertexAttribute[attribNum].mPointer = pointer; +} + +const void *Context::getVertexAttribPointer(unsigned int attribNum) const +{ + return mState.vertexAttribute[attribNum].mPointer; +} + +const VertexAttributeArray &Context::getVertexAttributes() +{ + return mState.vertexAttribute; +} + +void Context::setPackAlignment(GLint alignment) +{ + mState.packAlignment = alignment; +} + +GLint Context::getPackAlignment() const +{ + return mState.packAlignment; +} + +void Context::setUnpackAlignment(GLint alignment) +{ + mState.unpackAlignment = alignment; +} + +GLint Context::getUnpackAlignment() const +{ + return mState.unpackAlignment; +} + +GLuint Context::createBuffer() +{ + return mResourceManager->createBuffer(); +} + +GLuint Context::createTexture() +{ + return mResourceManager->createTexture(); +} + +GLuint Context::createRenderbuffer() +{ + return mResourceManager->createRenderbuffer(); +} + +// Returns an unused framebuffer name +GLuint Context::createFramebuffer() +{ + return mFramebufferNameSpace.allocate(); +} + +void Context::deleteBuffer(GLuint buffer) +{ + detachBuffer(buffer); + + mResourceManager->deleteBuffer(buffer); +} + +void Context::deleteTexture(GLuint texture) +{ + detachTexture(texture); + + mResourceManager->deleteTexture(texture); +} + +void Context::deleteRenderbuffer(GLuint renderbuffer) +{ + detachRenderbuffer(renderbuffer); + + mResourceManager->deleteRenderbuffer(renderbuffer); +} + +void Context::deleteFramebuffer(GLuint framebuffer) +{ + detachFramebuffer(framebuffer); + + Framebuffer *framebufferObject = mFramebufferNameSpace.remove(framebuffer); + + if(framebufferObject) + { + delete framebufferObject; + } +} + +Buffer *Context::getBuffer(GLuint handle) +{ + return mResourceManager->getBuffer(handle); +} + +Texture *Context::getTexture(GLuint handle) +{ + return mResourceManager->getTexture(handle); +} + +Renderbuffer *Context::getRenderbuffer(GLuint handle) +{ + return mResourceManager->getRenderbuffer(handle); +} + +Framebuffer *Context::getFramebuffer() +{ + return getFramebuffer(mState.framebuffer); +} + +void Context::bindArrayBuffer(unsigned int buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.arrayBuffer = getBuffer(buffer); +} + +void Context::bindElementArrayBuffer(unsigned int buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.elementArrayBuffer = getBuffer(buffer); +} + +void Context::bindTexture2D(GLuint texture) +{ + mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); + + mState.samplerTexture[TEXTURE_2D][mState.activeSampler] = getTexture(texture); +} + +void Context::bindTextureExternal(GLuint texture) +{ + mResourceManager->checkTextureAllocation(texture, TEXTURE_EXTERNAL); + + mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler] = getTexture(texture); +} + +void Context::bindFramebuffer(GLuint framebuffer) +{ + if(!getFramebuffer(framebuffer)) + { + mFramebufferNameSpace.insert(framebuffer, new Framebuffer()); + } + + mState.framebuffer = framebuffer; +} + +void Context::bindRenderbuffer(GLuint renderbuffer) +{ + mResourceManager->checkRenderbufferAllocation(renderbuffer); + + mState.renderbuffer = getRenderbuffer(renderbuffer); +} + +void Context::setFramebufferZero(Framebuffer *buffer) +{ + delete mFramebufferNameSpace.remove(0); + mFramebufferNameSpace.insert(0, buffer); +} + +void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer) +{ + Renderbuffer *renderbufferObject = mState.renderbuffer; + renderbufferObject->setStorage(renderbuffer); +} + +Framebuffer *Context::getFramebuffer(unsigned int handle) +{ + return mFramebufferNameSpace.find(handle); +} + +Buffer *Context::getArrayBuffer() +{ + return mState.arrayBuffer; +} + +Buffer *Context::getElementArrayBuffer() +{ + return mState.elementArrayBuffer; +} + +Texture2D *Context::getTexture2D() +{ + return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D)); +} + +TextureExternal *Context::getTextureExternal() +{ + return static_cast<TextureExternal*>(getSamplerTexture(mState.activeSampler, TEXTURE_EXTERNAL)); +} + +Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) +{ + GLuint texid = mState.samplerTexture[type][sampler].name(); + + if(texid == 0) // Special case: 0 refers to different initial textures based on the target + { + switch(type) + { + case TEXTURE_2D: return mTexture2DZero; + case TEXTURE_EXTERNAL: return mTextureExternalZero; + default: UNREACHABLE(type); + } + } + + return mState.samplerTexture[type][sampler]; +} + +bool Context::getBooleanv(GLenum pname, GLboolean *params) +{ + switch(pname) + { + case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; + case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break; + case GL_COLOR_WRITEMASK: + params[0] = mState.colorMaskRed; + params[1] = mState.colorMaskGreen; + params[2] = mState.colorMaskBlue; + params[3] = mState.colorMaskAlpha; + break; + case GL_CULL_FACE: *params = mState.cullFaceEnabled; break; + case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFillEnabled; break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverageEnabled; break; + case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverageEnabled; break; + case GL_SCISSOR_TEST: *params = mState.scissorTestEnabled; break; + case GL_STENCIL_TEST: *params = mState.stencilTestEnabled; break; + case GL_DEPTH_TEST: *params = mState.depthTestEnabled; break; + case GL_BLEND: *params = mState.blendEnabled; break; + case GL_DITHER: *params = mState.ditherEnabled; break; + case GL_LIGHT_MODEL_TWO_SIDE: *params = lightModelTwoSide; break; + default: + return false; + } + + return true; +} + +bool Context::getFloatv(GLenum pname, GLfloat *params) +{ + // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation + // because it is stored as a float, despite the fact that the GL ES 2.0 spec names + // GetIntegerv as its native query function. As it would require conversion in any + // case, this should make no difference to the calling application. + switch(pname) + { + case GL_LINE_WIDTH: *params = mState.lineWidth; break; + case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; + case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; + case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break; + case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break; + case GL_ALIASED_LINE_WIDTH_RANGE: + params[0] = ALIASED_LINE_WIDTH_RANGE_MIN; + params[1] = ALIASED_LINE_WIDTH_RANGE_MAX; + break; + case GL_ALIASED_POINT_SIZE_RANGE: + params[0] = ALIASED_POINT_SIZE_RANGE_MIN; + params[1] = ALIASED_POINT_SIZE_RANGE_MAX; + break; + case GL_SMOOTH_LINE_WIDTH_RANGE: + params[0] = SMOOTH_LINE_WIDTH_RANGE_MIN; + params[1] = SMOOTH_LINE_WIDTH_RANGE_MAX; + break; + case GL_SMOOTH_POINT_SIZE_RANGE: + params[0] = SMOOTH_POINT_SIZE_RANGE_MIN; + params[1] = SMOOTH_POINT_SIZE_RANGE_MAX; + break; + case GL_DEPTH_RANGE: + params[0] = mState.zNear; + params[1] = mState.zFar; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = mState.colorClearValue.red; + params[1] = mState.colorClearValue.green; + params[2] = mState.colorClearValue.blue; + params[3] = mState.colorClearValue.alpha; + break; + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + *params = MAX_TEXTURE_MAX_ANISOTROPY; + break; + case GL_MODELVIEW_MATRIX: + for(int i = 0; i < 16; i++) + { + params[i] = modelViewStack.current()[i % 4][i / 4]; + } + break; + case GL_PROJECTION_MATRIX: + for(int i = 0; i < 16; i++) + { + params[i] = projectionStack.current()[i % 4][i / 4]; + } + break; + default: + return false; + } + + return true; +} + +bool Context::getIntegerv(GLenum pname, GLint *params) +{ + // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation + // because it is stored as a float, despite the fact that the GL ES 2.0 spec names + // GetIntegerv as its native query function. As it would require conversion in any + // case, this should make no difference to the calling application. You may find it in + // Context::getFloatv. + switch(pname) + { + case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.name(); break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.name(); break; + case GL_FRAMEBUFFER_BINDING_OES: *params = mState.framebuffer; break; + case GL_RENDERBUFFER_BINDING_OES: *params = mState.renderbuffer.name(); break; + case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break; + case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break; + case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break; + case GL_PERSPECTIVE_CORRECTION_HINT: *params = mState.perspectiveCorrectionHint; break; + case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break; + case GL_STENCIL_FUNC: *params = mState.stencilFunc; break; + case GL_STENCIL_REF: *params = mState.stencilRef; break; + case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break; + case GL_STENCIL_FAIL: *params = mState.stencilFail; break; + case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break; + case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break; + case GL_DEPTH_FUNC: *params = mState.depthFunc; break; + case GL_BLEND_SRC_RGB_OES: *params = mState.sourceBlendRGB; break; + case GL_BLEND_SRC_ALPHA_OES: *params = mState.sourceBlendAlpha; break; + case GL_BLEND_DST_RGB_OES: *params = mState.destBlendRGB; break; + case GL_BLEND_DST_ALPHA_OES: *params = mState.destBlendAlpha; break; + case GL_BLEND_EQUATION_RGB_OES: *params = mState.blendEquationRGB; break; + case GL_BLEND_EQUATION_ALPHA_OES: *params = mState.blendEquationAlpha; break; + case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break; + case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; + case GL_SUBPIXEL_BITS: *params = 4; break; + case GL_MAX_TEXTURE_SIZE: *params = IMPLEMENTATION_MAX_TEXTURE_SIZE; break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = NUM_COMPRESSED_TEXTURE_FORMATS; break; + case GL_SAMPLE_BUFFERS: + case GL_SAMPLES: + { + Framebuffer *framebuffer = getFramebuffer(); + int width, height, samples; + + if(framebuffer->completeness(width, height, samples) == GL_FRAMEBUFFER_COMPLETE_OES) + { + switch(pname) + { + case GL_SAMPLE_BUFFERS: + if(samples > 1) + { + *params = 1; + } + else + { + *params = 0; + } + break; + case GL_SAMPLES: + *params = samples; + break; + } + } + else + { + *params = 0; + } + } + break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: + { + Framebuffer *framebuffer = getFramebuffer(); + *params = framebuffer->getImplementationColorReadType(); + } + break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: + { + Framebuffer *framebuffer = getFramebuffer(); + *params = framebuffer->getImplementationColorReadFormat(); + } + break; + case GL_MAX_VIEWPORT_DIMS: + { + int maxDimension = IMPLEMENTATION_MAX_RENDERBUFFER_SIZE; + params[0] = maxDimension; + params[1] = maxDimension; + } + break; + case GL_COMPRESSED_TEXTURE_FORMATS: + { + for(int i = 0; i < NUM_COMPRESSED_TEXTURE_FORMATS; i++) + { + params[i] = compressedTextureFormats[i]; + } + } + break; + case GL_VIEWPORT: + params[0] = mState.viewportX; + params[1] = mState.viewportY; + params[2] = mState.viewportWidth; + params[3] = mState.viewportHeight; + break; + case GL_SCISSOR_BOX: + params[0] = mState.scissorX; + params[1] = mState.scissorY; + params[2] = mState.scissorWidth; + params[3] = mState.scissorHeight; + break; + case GL_CULL_FACE_MODE: *params = mState.cullMode; break; + case GL_FRONT_FACE: *params = mState.frontFace; break; + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + case GL_ALPHA_BITS: + { + Framebuffer *framebuffer = getFramebuffer(); + Renderbuffer *colorbuffer = framebuffer->getColorbuffer(); + + if(colorbuffer) + { + switch(pname) + { + case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; + case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; + case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; + case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; + } + } + else + { + *params = 0; + } + } + break; + case GL_DEPTH_BITS: + { + Framebuffer *framebuffer = getFramebuffer(); + Renderbuffer *depthbuffer = framebuffer->getDepthbuffer(); + + if(depthbuffer) + { + *params = depthbuffer->getDepthSize(); + } + else + { + *params = 0; + } + } + break; + case GL_STENCIL_BITS: + { + Framebuffer *framebuffer = getFramebuffer(); + Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer(); + + if(stencilbuffer) + { + *params = stencilbuffer->getStencilSize(); + } + else + { + *params = 0; + } + } + break; + case GL_TEXTURE_BINDING_2D: *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].name(); break; + case GL_TEXTURE_BINDING_CUBE_MAP_OES: *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].name(); break; + case GL_TEXTURE_BINDING_EXTERNAL_OES: *params = mState.samplerTexture[TEXTURE_EXTERNAL][mState.activeSampler].name(); break; + case GL_MAX_LIGHTS: *params = MAX_LIGHTS; break; + case GL_MAX_MODELVIEW_STACK_DEPTH: *params = MAX_MODELVIEW_STACK_DEPTH; break; + case GL_MAX_PROJECTION_STACK_DEPTH: *params = MAX_PROJECTION_STACK_DEPTH; break; + case GL_MAX_TEXTURE_STACK_DEPTH: *params = MAX_TEXTURE_STACK_DEPTH; break; + case GL_MAX_TEXTURE_UNITS: *params = MAX_TEXTURE_UNITS; break; + case GL_MAX_CLIP_PLANES: *params = MAX_CLIP_PLANES; break; + case GL_POINT_SIZE_ARRAY_TYPE_OES: *params = mState.vertexAttribute[sw::PointSize].mType; break; + case GL_POINT_SIZE_ARRAY_STRIDE_OES: *params = mState.vertexAttribute[sw::PointSize].mStride; break; + case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: *params = mState.vertexAttribute[sw::PointSize].mBoundBuffer.name(); break; + case GL_VERTEX_ARRAY_SIZE: *params = mState.vertexAttribute[sw::Position].mSize; break; + case GL_VERTEX_ARRAY_TYPE: *params = mState.vertexAttribute[sw::Position].mType; break; + case GL_VERTEX_ARRAY_STRIDE: *params = mState.vertexAttribute[sw::Position].mStride; break; + case GL_VERTEX_ARRAY_BUFFER_BINDING: *params = mState.vertexAttribute[sw::Position].mBoundBuffer.name(); break; + case GL_NORMAL_ARRAY_TYPE: *params = mState.vertexAttribute[sw::Normal].mType; break; + case GL_NORMAL_ARRAY_STRIDE: *params = mState.vertexAttribute[sw::Normal].mStride; break; + case GL_NORMAL_ARRAY_BUFFER_BINDING: *params = mState.vertexAttribute[sw::Normal].mBoundBuffer.name(); break; + case GL_COLOR_ARRAY_SIZE: *params = mState.vertexAttribute[sw::Color0].mSize; break; + case GL_COLOR_ARRAY_TYPE: *params = mState.vertexAttribute[sw::Color0].mType; break; + case GL_COLOR_ARRAY_STRIDE: *params = mState.vertexAttribute[sw::Color0].mStride; break; + case GL_COLOR_ARRAY_BUFFER_BINDING: *params = mState.vertexAttribute[sw::Color0].mBoundBuffer.name(); break; + case GL_TEXTURE_COORD_ARRAY_SIZE: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mSize; break; + case GL_TEXTURE_COORD_ARRAY_TYPE: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mType; break; + case GL_TEXTURE_COORD_ARRAY_STRIDE: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mStride; break; + case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mBoundBuffer.name(); break; + default: + return false; + } + + return true; +} + +bool Context::getPointerv(GLenum pname, const GLvoid **params) +{ + switch(pname) + { + case GL_VERTEX_ARRAY_POINTER: *params = mState.vertexAttribute[sw::Position].mPointer; break; + case GL_NORMAL_ARRAY_POINTER: *params = mState.vertexAttribute[sw::Normal].mPointer; break; + case GL_COLOR_ARRAY_POINTER: *params = mState.vertexAttribute[sw::Color0].mPointer; break; + case GL_POINT_SIZE_ARRAY_POINTER_OES: *params = mState.vertexAttribute[sw::PointSize].mPointer; break; + case GL_TEXTURE_COORD_ARRAY_POINTER: *params = mState.vertexAttribute[sw::TexCoord0 + mState.activeSampler].mPointer; break; + default: + return false; + } + + return true; +} + +int Context::getQueryParameterNum(GLenum pname) +{ + // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation + // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due + // to the fact that it is stored internally as a float, and so would require conversion + // if returned from Context::getIntegerv. Since this conversion is already implemented + // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we + // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling + // application. + switch(pname) + { + case GL_COMPRESSED_TEXTURE_FORMATS: + return NUM_COMPRESSED_TEXTURE_FORMATS; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + case GL_ARRAY_BUFFER_BINDING: + case GL_FRAMEBUFFER_BINDING_OES: + case GL_RENDERBUFFER_BINDING_OES: + case GL_PACK_ALIGNMENT: + case GL_UNPACK_ALIGNMENT: + case GL_GENERATE_MIPMAP_HINT: + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + case GL_ALPHA_BITS: + case GL_DEPTH_BITS: + case GL_STENCIL_BITS: + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + case GL_CULL_FACE_MODE: + case GL_FRONT_FACE: + case GL_ACTIVE_TEXTURE: + case GL_STENCIL_FUNC: + case GL_STENCIL_VALUE_MASK: + case GL_STENCIL_REF: + case GL_STENCIL_FAIL: + case GL_STENCIL_PASS_DEPTH_FAIL: + case GL_STENCIL_PASS_DEPTH_PASS: + case GL_DEPTH_FUNC: + case GL_BLEND_SRC_RGB_OES: + case GL_BLEND_SRC_ALPHA_OES: + case GL_BLEND_DST_RGB_OES: + case GL_BLEND_DST_ALPHA_OES: + case GL_BLEND_EQUATION_RGB_OES: + case GL_BLEND_EQUATION_ALPHA_OES: + case GL_STENCIL_WRITEMASK: + case GL_STENCIL_CLEAR_VALUE: + case GL_SUBPIXEL_BITS: + case GL_MAX_TEXTURE_SIZE: + case GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES: + case GL_SAMPLE_BUFFERS: + case GL_SAMPLES: + case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: + case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: + case GL_TEXTURE_BINDING_2D: + case GL_TEXTURE_BINDING_CUBE_MAP_OES: + case GL_TEXTURE_BINDING_EXTERNAL_OES: + return 1; + case GL_MAX_VIEWPORT_DIMS: + return 2; + case GL_VIEWPORT: + case GL_SCISSOR_BOX: + return 4; + case GL_SAMPLE_COVERAGE_INVERT: + case GL_DEPTH_WRITEMASK: + case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled, + case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries. + case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + case GL_DEPTH_TEST: + case GL_BLEND: + case GL_DITHER: + return 1; + case GL_COLOR_WRITEMASK: + return 4; + case GL_POLYGON_OFFSET_FACTOR: + case GL_POLYGON_OFFSET_UNITS: + case GL_SAMPLE_COVERAGE_VALUE: + case GL_DEPTH_CLEAR_VALUE: + case GL_LINE_WIDTH: + return 1; + case GL_ALIASED_LINE_WIDTH_RANGE: + case GL_ALIASED_POINT_SIZE_RANGE: + case GL_DEPTH_RANGE: + return 2; + case GL_COLOR_CLEAR_VALUE: + return 4; + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + case GL_MAX_LIGHTS: + case GL_MAX_MODELVIEW_STACK_DEPTH: + case GL_MAX_PROJECTION_STACK_DEPTH: + case GL_MAX_TEXTURE_STACK_DEPTH: + case GL_MAX_TEXTURE_UNITS: + case GL_MAX_CLIP_PLANES: + case GL_POINT_SIZE_ARRAY_TYPE_OES: + case GL_POINT_SIZE_ARRAY_STRIDE_OES: + case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: + return 1; + case GL_CURRENT_COLOR: + return 4; + case GL_CURRENT_NORMAL: + return 3; + case GL_CURRENT_TEXTURE_COORDS: + return 4; + case GL_POINT_SIZE: + case GL_POINT_SIZE_MIN: + case GL_POINT_SIZE_MAX: + case GL_POINT_FADE_THRESHOLD_SIZE: + return 1; + case GL_POINT_DISTANCE_ATTENUATION: + return 3; + case GL_SMOOTH_POINT_SIZE_RANGE: + case GL_SMOOTH_LINE_WIDTH_RANGE: + return 2; + case GL_SHADE_MODEL: + case GL_MATRIX_MODE: + case GL_MODELVIEW_STACK_DEPTH: + case GL_PROJECTION_STACK_DEPTH: + case GL_TEXTURE_STACK_DEPTH: + return 1; + case GL_MODELVIEW_MATRIX: + case GL_PROJECTION_MATRIX: + case GL_TEXTURE_MATRIX: + return 16; + case GL_ALPHA_TEST_FUNC: + case GL_ALPHA_TEST_REF: + case GL_BLEND_DST: + case GL_BLEND_SRC: + case GL_LOGIC_OP_MODE: + case GL_VERTEX_ARRAY_SIZE: + case GL_VERTEX_ARRAY_TYPE: + case GL_VERTEX_ARRAY_STRIDE: + case GL_NORMAL_ARRAY_TYPE: + case GL_NORMAL_ARRAY_STRIDE: + case GL_COLOR_ARRAY_SIZE: + case GL_COLOR_ARRAY_TYPE: + case GL_COLOR_ARRAY_STRIDE: + case GL_TEXTURE_COORD_ARRAY_SIZE: + case GL_TEXTURE_COORD_ARRAY_TYPE: + case GL_TEXTURE_COORD_ARRAY_STRIDE: + case GL_VERTEX_ARRAY_POINTER: + case GL_NORMAL_ARRAY_POINTER: + case GL_COLOR_ARRAY_POINTER: + case GL_TEXTURE_COORD_ARRAY_POINTER: + case GL_LIGHT_MODEL_TWO_SIDE: + return 1; + default: + UNREACHABLE(pname); + } + + return -1; +} + +bool Context::isQueryParameterInt(GLenum pname) +{ + // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation + // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due + // to the fact that it is stored internally as a float, and so would require conversion + // if returned from Context::getIntegerv. Since this conversion is already implemented + // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we + // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling + // application. + switch(pname) + { + case GL_COMPRESSED_TEXTURE_FORMATS: + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + case GL_ARRAY_BUFFER_BINDING: + case GL_FRAMEBUFFER_BINDING_OES: + case GL_RENDERBUFFER_BINDING_OES: + case GL_PACK_ALIGNMENT: + case GL_UNPACK_ALIGNMENT: + case GL_GENERATE_MIPMAP_HINT: + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + case GL_ALPHA_BITS: + case GL_DEPTH_BITS: + case GL_STENCIL_BITS: + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + case GL_CULL_FACE_MODE: + case GL_FRONT_FACE: + case GL_ACTIVE_TEXTURE: + case GL_STENCIL_FUNC: + case GL_STENCIL_VALUE_MASK: + case GL_STENCIL_REF: + case GL_STENCIL_FAIL: + case GL_STENCIL_PASS_DEPTH_FAIL: + case GL_STENCIL_PASS_DEPTH_PASS: + case GL_DEPTH_FUNC: + case GL_BLEND_SRC_RGB_OES: + case GL_BLEND_SRC_ALPHA_OES: + case GL_BLEND_DST_RGB_OES: + case GL_BLEND_DST_ALPHA_OES: + case GL_BLEND_EQUATION_RGB_OES: + case GL_BLEND_EQUATION_ALPHA_OES: + case GL_STENCIL_WRITEMASK: + case GL_STENCIL_CLEAR_VALUE: + case GL_SUBPIXEL_BITS: + case GL_MAX_TEXTURE_SIZE: + case GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES: + case GL_SAMPLE_BUFFERS: + case GL_SAMPLES: + case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: + case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: + case GL_TEXTURE_BINDING_2D: + case GL_TEXTURE_BINDING_CUBE_MAP_OES: + case GL_TEXTURE_BINDING_EXTERNAL_OES: + case GL_MAX_VIEWPORT_DIMS: + case GL_VIEWPORT: + case GL_SCISSOR_BOX: + case GL_MAX_LIGHTS: + case GL_MAX_MODELVIEW_STACK_DEPTH: + case GL_MAX_PROJECTION_STACK_DEPTH: + case GL_MAX_TEXTURE_STACK_DEPTH: + case GL_MAX_TEXTURE_UNITS: + case GL_MAX_CLIP_PLANES: + case GL_POINT_SIZE_ARRAY_TYPE_OES: + case GL_POINT_SIZE_ARRAY_STRIDE_OES: + case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: + return true; + } + + return false; +} + +bool Context::isQueryParameterFloat(GLenum pname) +{ + // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation + // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due + // to the fact that it is stored internally as a float, and so would require conversion + // if returned from Context::getIntegerv. Since this conversion is already implemented + // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we + // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling + // application. + switch(pname) + { + case GL_POLYGON_OFFSET_FACTOR: + case GL_POLYGON_OFFSET_UNITS: + case GL_SAMPLE_COVERAGE_VALUE: + case GL_DEPTH_CLEAR_VALUE: + case GL_LINE_WIDTH: + case GL_ALIASED_LINE_WIDTH_RANGE: + case GL_ALIASED_POINT_SIZE_RANGE: + case GL_SMOOTH_LINE_WIDTH_RANGE: + case GL_SMOOTH_POINT_SIZE_RANGE: + case GL_DEPTH_RANGE: + case GL_COLOR_CLEAR_VALUE: + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + case GL_LIGHT_MODEL_AMBIENT: + case GL_POINT_SIZE_MIN: + case GL_POINT_SIZE_MAX: + case GL_POINT_DISTANCE_ATTENUATION: + case GL_POINT_FADE_THRESHOLD_SIZE: + return true; + } + + return false; +} + +bool Context::isQueryParameterBool(GLenum pname) +{ + switch(pname) + { + case GL_SAMPLE_COVERAGE_INVERT: + case GL_DEPTH_WRITEMASK: + case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled, + case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries. + case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + case GL_DEPTH_TEST: + case GL_BLEND: + case GL_DITHER: + case GL_COLOR_WRITEMASK: + case GL_LIGHT_MODEL_TWO_SIDE: + return true; + } + + return false; +} + +bool Context::isQueryParameterPointer(GLenum pname) +{ + switch(pname) + { + case GL_VERTEX_ARRAY_POINTER: + case GL_NORMAL_ARRAY_POINTER: + case GL_COLOR_ARRAY_POINTER: + case GL_TEXTURE_COORD_ARRAY_POINTER: + case GL_POINT_SIZE_ARRAY_POINTER_OES: + return true; + } + + return false; +} + +// Applies the render target surface, depth stencil surface, viewport rectangle and scissor rectangle +bool Context::applyRenderTarget() +{ + Framebuffer *framebuffer = getFramebuffer(); + int width, height, samples; + + if(!framebuffer || framebuffer->completeness(width, height, samples) != GL_FRAMEBUFFER_COMPLETE_OES) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES, false); + } + + egl::Image *renderTarget = framebuffer->getRenderTarget(); + device->setRenderTarget(0, renderTarget); + if(renderTarget) renderTarget->release(); + + egl::Image *depthBuffer = framebuffer->getDepthBuffer(); + device->setDepthBuffer(depthBuffer); + if(depthBuffer) depthBuffer->release(); + + egl::Image *stencilBuffer = framebuffer->getStencilBuffer(); + device->setStencilBuffer(stencilBuffer); + if(stencilBuffer) stencilBuffer->release(); + + Viewport viewport; + float zNear = clamp01(mState.zNear); + float zFar = clamp01(mState.zFar); + + viewport.x0 = mState.viewportX; + viewport.y0 = mState.viewportY; + viewport.width = mState.viewportWidth; + viewport.height = mState.viewportHeight; + viewport.minZ = zNear; + viewport.maxZ = zFar; + + device->setViewport(viewport); + + if(mState.scissorTestEnabled) + { + sw::Rect scissor = {mState.scissorX, mState.scissorY, mState.scissorX + mState.scissorWidth, mState.scissorY + mState.scissorHeight}; + scissor.clip(0, 0, width, height); + + device->setScissorRect(scissor); + device->setScissorEnable(true); + } + else + { + device->setScissorEnable(false); + } + + return true; +} + +// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) +void Context::applyState(GLenum drawMode) +{ + Framebuffer *framebuffer = getFramebuffer(); + + if(mState.cullFaceEnabled) + { + device->setCullMode(es2sw::ConvertCullMode(mState.cullMode, mState.frontFace)); + } + else + { + device->setCullMode(sw::CULL_NONE); + } + + if(mDepthStateDirty) + { + if(mState.depthTestEnabled) + { + device->setDepthBufferEnable(true); + device->setDepthCompare(es2sw::ConvertDepthComparison(mState.depthFunc)); + } + else + { + device->setDepthBufferEnable(false); + } + + mDepthStateDirty = false; + } + + if(mBlendStateDirty) + { + if(mState.blendEnabled) + { + device->setAlphaBlendEnable(true); + device->setSeparateAlphaBlendEnable(true); + + device->setSourceBlendFactor(es2sw::ConvertBlendFunc(mState.sourceBlendRGB)); + device->setDestBlendFactor(es2sw::ConvertBlendFunc(mState.destBlendRGB)); + device->setBlendOperation(es2sw::ConvertBlendOp(mState.blendEquationRGB)); + + device->setSourceBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.sourceBlendAlpha)); + device->setDestBlendFactorAlpha(es2sw::ConvertBlendFunc(mState.destBlendAlpha)); + device->setBlendOperationAlpha(es2sw::ConvertBlendOp(mState.blendEquationAlpha)); + } + else + { + device->setAlphaBlendEnable(false); + } + + mBlendStateDirty = false; + } + + if(mStencilStateDirty || mFrontFaceDirty) + { + if(mState.stencilTestEnabled && framebuffer->hasStencil()) + { + device->setStencilEnable(true); + device->setTwoSidedStencil(true); + + // get the maximum size of the stencil ref + Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer(); + GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1; + + device->setStencilWriteMask(mState.stencilWritemask); + device->setStencilCompare(es2sw::ConvertStencilComparison(mState.stencilFunc)); + + device->setStencilReference((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); + device->setStencilMask(mState.stencilMask); + + device->setStencilFailOperation(es2sw::ConvertStencilOp(mState.stencilFail)); + device->setStencilZFailOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthFail)); + device->setStencilPassOperation(es2sw::ConvertStencilOp(mState.stencilPassDepthPass)); + + device->setStencilWriteMaskCCW(mState.stencilWritemask); + device->setStencilCompareCCW(es2sw::ConvertStencilComparison(mState.stencilFunc)); + + device->setStencilReferenceCCW((mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); + device->setStencilMaskCCW(mState.stencilMask); + + device->setStencilFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilFail)); + device->setStencilZFailOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthFail)); + device->setStencilPassOperationCCW(es2sw::ConvertStencilOp(mState.stencilPassDepthPass)); + } + else + { + device->setStencilEnable(false); + } + + mStencilStateDirty = false; + mFrontFaceDirty = false; + } + + if(mMaskStateDirty) + { + device->setColorWriteMask(0, es2sw::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha)); + device->setDepthWriteEnable(mState.depthMask); + + mMaskStateDirty = false; + } + + if(mPolygonOffsetStateDirty) + { + if(mState.polygonOffsetFillEnabled) + { + Renderbuffer *depthbuffer = framebuffer->getDepthbuffer(); + if(depthbuffer) + { + device->setSlopeDepthBias(mState.polygonOffsetFactor); + float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize())); + device->setDepthBias(depthBias); + } + } + else + { + device->setSlopeDepthBias(0); + device->setDepthBias(0); + } + + mPolygonOffsetStateDirty = false; + } + + if(mSampleStateDirty) + { + if(mState.sampleAlphaToCoverageEnabled) + { + device->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE); + } + else + { + device->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE); + } + + if(mState.sampleCoverageEnabled) + { + unsigned int mask = 0; + if(mState.sampleCoverageValue != 0) + { + int width, height, samples; + framebuffer->completeness(width, height, samples); + + float threshold = 0.5f; + + for(int i = 0; i < samples; i++) + { + mask <<= 1; + + if((i + 1) * mState.sampleCoverageValue >= threshold) + { + threshold += 1.0f; + mask |= 1; + } + } + } + + if(mState.sampleCoverageInvert) + { + mask = ~mask; + } + + device->setMultiSampleMask(mask); + } + else + { + device->setMultiSampleMask(0xFFFFFFFF); + } + + mSampleStateDirty = false; + } + + if(mDitherStateDirty) + { + // UNIMPLEMENTED(); // FIXME + + mDitherStateDirty = false; + } + + switch(mState.shadeModel) + { + default: UNREACHABLE(mState.shadeModel); + case GL_SMOOTH: device->setShadingMode(sw::SHADING_GOURAUD); break; + case GL_FLAT: device->setShadingMode(sw::SHADING_FLAT); break; + } + + device->setLightingEnable(lightingEnabled); + device->setGlobalAmbient(sw::Color<float>(globalAmbient.red, globalAmbient.green, globalAmbient.blue, globalAmbient.alpha)); + + for(int i = 0; i < MAX_LIGHTS; i++) + { + device->setLightEnable(i, light[i].enabled); + device->setLightAmbient(i, sw::Color<float>(light[i].ambient.red, light[i].ambient.green, light[i].ambient.blue, light[i].ambient.alpha)); + device->setLightDiffuse(i, sw::Color<float>(light[i].diffuse.red, light[i].diffuse.green, light[i].diffuse.blue, light[i].diffuse.alpha)); + device->setLightSpecular(i, sw::Color<float>(light[i].specular.red, light[i].specular.green, light[i].specular.blue, light[i].specular.alpha)); + device->setLightAttenuation(i, light[i].attenuation.constant, light[i].attenuation.linear, light[i].attenuation.quadratic); + + if(light[i].position.w != 0.0f) + { + device->setLightPosition(i, sw::Point(light[i].position.x / light[i].position.w, light[i].position.y / light[i].position.w, light[i].position.z / light[i].position.w)); + } + else // Directional light + { + // Hack: set the position far way + float max = sw::max(abs(light[i].position.x), abs(light[i].position.y), abs(light[i].position.z)); + device->setLightPosition(i, sw::Point(1e10f * (light[i].position.x / max), 1e10f * (light[i].position.y / max), 1e10f * (light[i].position.z / max))); + } + } + + device->setMaterialAmbient(sw::Color<float>(materialAmbient.red, materialAmbient.green, materialAmbient.blue, materialAmbient.alpha)); + device->setMaterialDiffuse(sw::Color<float>(materialDiffuse.red, materialDiffuse.green, materialDiffuse.blue, materialDiffuse.alpha)); + device->setMaterialSpecular(sw::Color<float>(materialSpecular.red, materialSpecular.green, materialSpecular.blue, materialSpecular.alpha)); + device->setMaterialEmission(sw::Color<float>(materialEmission.red, materialEmission.green, materialEmission.blue, materialEmission.alpha)); + device->setMaterialShininess(materialShininess); + + device->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL); + device->setSpecularMaterialSource(sw::MATERIAL_MATERIAL); + device->setAmbientMaterialSource(sw::MATERIAL_MATERIAL); + device->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL); + + const sw::Matrix Z(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0.5, 0.5, + 0, 0, 0, 1); // Map depth range from [-1, 1] to [0, 1] + + device->setProjectionMatrix(Z * projectionStack.current()); + device->setModelMatrix(modelViewStack.current()); + device->setTextureMatrix(0, textureStack0.current()); + device->setTextureMatrix(1, textureStack1.current()); + device->setTextureTransform(0, textureStack0.isIdentity() ? 0 : 4, false); + device->setTextureTransform(1, textureStack1.isIdentity() ? 0 : 4, false); + device->setTexGen(0, sw::TEXGEN_NONE); + device->setTexGen(1, sw::TEXGEN_NONE); + + device->setAlphaTestEnable(alphaTestEnabled); + device->setAlphaCompare(es2sw::ConvertAlphaComparison(alphaTestFunc)); + device->setAlphaReference(alphaTestRef * 0xFF); + + device->setFogEnable(fogEnabled); + device->setFogColor(sw::Color<float>(fogColor.red, fogColor.green, fogColor.blue, fogColor.alpha)); + device->setFogDensity(fogDensity); + device->setFogStart(fogStart); + device->setFogEnd(fogEnd); + + switch(fogMode) + { + case GL_LINEAR: device->setVertexFogMode(sw::FOG_LINEAR); break; + case GL_EXP: device->setVertexFogMode(sw::FOG_EXP); break; + case GL_EXP2: device->setVertexFogMode(sw::FOG_EXP2); break; + default: UNREACHABLE(fogMode); + } + + device->setColorLogicOpEnabled(colorLogicOpEnabled); + device->setLogicalOperation(es2sw::ConvertLogicalOperation(logicalOperation)); + + device->setNormalizeNormals(normalizeEnabled || rescaleNormalEnabled); +} + +GLenum Context::applyVertexBuffer(GLint base, GLint first, GLsizei count) +{ + TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS]; + + GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes); + if(err != GL_NO_ERROR) + { + return err; + } + + device->resetInputStreams(false); + + for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + sw::Resource *resource = attributes[i].vertexBuffer; + const void *buffer = (char*)resource->data() + attributes[i].offset; + + int stride = attributes[i].stride; + + buffer = (char*)buffer + stride * base; + + sw::Stream attribute(resource, buffer, stride); + + attribute.type = attributes[i].type; + attribute.count = attributes[i].count; + attribute.normalized = attributes[i].normalized; + + device->setInputStream(i, attribute); + } + + return GL_NO_ERROR; +} + +// Applies the indices and element array bindings +GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer, indices, indexInfo); + + if(err == GL_NO_ERROR) + { + device->setIndexBuffer(indexInfo->indexBuffer); + } + + return err; +} + +void Context::applyTextures() +{ + for(int unit = 0; unit < MAX_TEXTURE_UNITS; unit++) + { + Texture *texture = nullptr; + + if(textureExternalEnabled[unit]) + { + texture = getSamplerTexture(unit, TEXTURE_EXTERNAL); + } + else if(texture2Denabled[unit]) + { + texture = getSamplerTexture(unit, TEXTURE_2D); + } + + if(texture && texture->isSamplerComplete()) + { + texture->autoGenerateMipmaps(); + + GLenum wrapS = texture->getWrapS(); + GLenum wrapT = texture->getWrapT(); + GLenum minFilter = texture->getMinFilter(); + GLenum magFilter = texture->getMagFilter(); + GLfloat maxAnisotropy = texture->getMaxAnisotropy(); + + device->setAddressingModeU(sw::SAMPLER_PIXEL, unit, es2sw::ConvertTextureWrap(wrapS)); + device->setAddressingModeV(sw::SAMPLER_PIXEL, unit, es2sw::ConvertTextureWrap(wrapT)); + + device->setTextureFilter(sw::SAMPLER_PIXEL, unit, es2sw::ConvertTextureFilter(minFilter, magFilter, maxAnisotropy)); + device->setMipmapFilter(sw::SAMPLER_PIXEL, unit, es2sw::ConvertMipMapFilter(minFilter)); + device->setMaxAnisotropy(sw::SAMPLER_PIXEL, unit, maxAnisotropy); + + applyTexture(unit, texture); + + device->setConstantColor(unit, sw::Color<float>(mState.textureUnit[unit].color.red, mState.textureUnit[unit].color.green, mState.textureUnit[unit].color.blue, mState.textureUnit[unit].color.alpha)); + + if(mState.textureUnit[unit].environmentMode != GL_COMBINE) + { + device->setFirstArgument(unit, sw::TextureStage::SOURCE_TEXTURE); // Cs + device->setFirstModifier(unit, sw::TextureStage::MODIFIER_COLOR); + device->setSecondArgument(unit, sw::TextureStage::SOURCE_CURRENT); // Cp + device->setSecondModifier(unit, sw::TextureStage::MODIFIER_COLOR); + device->setThirdArgument(unit, sw::TextureStage::SOURCE_CONSTANT); // Cc + device->setThirdModifier(unit, sw::TextureStage::MODIFIER_COLOR); + + device->setFirstArgumentAlpha(unit, sw::TextureStage::SOURCE_TEXTURE); // As + device->setFirstModifierAlpha(unit, sw::TextureStage::MODIFIER_ALPHA); + device->setSecondArgumentAlpha(unit, sw::TextureStage::SOURCE_CURRENT); // Ap + device->setSecondModifierAlpha(unit, sw::TextureStage::MODIFIER_ALPHA); + device->setThirdArgumentAlpha(unit, sw::TextureStage::SOURCE_CONSTANT); // Ac + device->setThirdModifierAlpha(unit, sw::TextureStage::MODIFIER_ALPHA); + + GLenum texFormat = texture->getFormat(GL_TEXTURE_2D, 0); + + switch(mState.textureUnit[unit].environmentMode) + { + case GL_REPLACE: + if(IsAlpha(texFormat)) // GL_ALPHA + { + // Cv = Cp, Av = As + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG1); + } + else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) + { + // Cv = Cs, Av = Ap + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG1); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); + } + else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) + { + // Cv = Cs, Av = As + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG1); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG1); + } + else UNREACHABLE(texFormat); + break; + case GL_MODULATE: + if(IsAlpha(texFormat)) // GL_ALPHA + { + // Cv = Cp, Av = ApAs + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); + } + else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) + { + // Cv = CpCs, Av = Ap + device->setStageOperation(unit, sw::TextureStage::STAGE_MODULATE); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); + } + else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) + { + // Cv = CpCs, Av = ApAs + device->setStageOperation(unit, sw::TextureStage::STAGE_MODULATE); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); + } + else UNREACHABLE(texFormat); + break; + case GL_DECAL: + if(texFormat == GL_ALPHA || + texFormat == GL_LUMINANCE || + texFormat == GL_LUMINANCE_ALPHA) + { + // undefined // FIXME: Log + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); + } + else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) + { + // Cv = Cs, Av = Ap + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG1); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); + } + else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) + { + // Cv = Cp(1 - As) + CsAs, Av = Ap + device->setStageOperation(unit, sw::TextureStage::STAGE_BLENDTEXTUREALPHA); // Alpha * (Arg1 - Arg2) + Arg2 + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); + } + else UNREACHABLE(texFormat); + break; + case GL_BLEND: + if(IsAlpha(texFormat)) // GL_ALPHA + { + // Cv = Cp, Av = ApAs + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); + } + else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) + { + // Cv = Cp(1 - Cs) + CcCs, Av = Ap + device->setStageOperation(unit, sw::TextureStage::STAGE_LERP); // Arg3 * (Arg1 - Arg2) + Arg2 + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); + } + else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) + { + // Cv = Cp(1 - Cs) + CcCs, Av = ApAs + device->setStageOperation(unit, sw::TextureStage::STAGE_LERP); // Arg3 * (Arg1 - Arg2) + Arg2 + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); + } + else UNREACHABLE(texFormat); + break; + case GL_ADD: + if(IsAlpha(texFormat)) // GL_ALPHA + { + // Cv = Cp, Av = ApAs + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG2); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); + } + else if(IsRGB(texFormat)) // GL_LUMINANCE (or 1) / GL_RGB (or 3) + { + // Cv = Cp + Cs, Av = Ap + device->setStageOperation(unit, sw::TextureStage::STAGE_ADD); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG2); + } + else if(IsRGBA(texFormat)) // GL_LUMINANCE_ALPHA (or 2) / GL_RGBA (or 4) + { + // Cv = Cp + Cs, Av = ApAs + device->setStageOperation(unit, sw::TextureStage::STAGE_ADD); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_MODULATE); + } + else UNREACHABLE(texFormat); + break; + default: + UNREACHABLE(mState.textureUnit[unit].environmentMode); + } + } + else // GL_COMBINE + { + device->setFirstArgument(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src0RGB)); + device->setFirstModifier(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand0RGB)); + device->setSecondArgument(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src1RGB)); + device->setSecondModifier(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand1RGB)); + device->setThirdArgument(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src2RGB)); + device->setThirdModifier(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand2RGB)); + + device->setStageOperation(unit, es2sw::ConvertCombineOperation(mState.textureUnit[unit].combineRGB)); + + device->setFirstArgumentAlpha(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src0Alpha)); + device->setFirstModifierAlpha(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand0Alpha)); + device->setSecondArgumentAlpha(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src1Alpha)); + device->setSecondModifierAlpha(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand1Alpha)); + device->setThirdArgumentAlpha(unit, es2sw::ConvertSourceArgument(mState.textureUnit[unit].src2Alpha)); + device->setThirdModifierAlpha(unit, es2sw::ConvertSourceOperand(mState.textureUnit[unit].operand2Alpha)); + + device->setStageOperationAlpha(unit, es2sw::ConvertCombineOperation(mState.textureUnit[unit].combineAlpha)); + } + } + else + { + applyTexture(unit, nullptr); + + device->setFirstArgument(unit, sw::TextureStage::SOURCE_CURRENT); + device->setFirstModifier(unit, sw::TextureStage::MODIFIER_COLOR); + device->setStageOperation(unit, sw::TextureStage::STAGE_SELECTARG1); + + device->setFirstArgumentAlpha(unit, sw::TextureStage::SOURCE_CURRENT); + device->setFirstModifierAlpha(unit, sw::TextureStage::MODIFIER_ALPHA); + device->setStageOperationAlpha(unit, sw::TextureStage::STAGE_SELECTARG1); + } + } +} + +void Context::setTextureEnvMode(GLenum texEnvMode) +{ + mState.textureUnit[mState.activeSampler].environmentMode = texEnvMode; +} + +void Context::setTextureEnvColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + mState.textureUnit[mState.activeSampler].color = {red, green, blue, alpha}; +} + +void Context::setCombineRGB(GLenum combineRGB) +{ + mState.textureUnit[mState.activeSampler].combineRGB = combineRGB; +} + +void Context::setCombineAlpha(GLenum combineAlpha) +{ + mState.textureUnit[mState.activeSampler].combineAlpha = combineAlpha; +} + +void Context::setOperand0RGB(GLenum operand) +{ + mState.textureUnit[mState.activeSampler].operand0RGB = operand; +} + +void Context::setOperand1RGB(GLenum operand) +{ + mState.textureUnit[mState.activeSampler].operand1RGB = operand; +} + +void Context::setOperand2RGB(GLenum operand) +{ + mState.textureUnit[mState.activeSampler].operand2RGB = operand; +} + +void Context::setOperand0Alpha(GLenum operand) +{ + mState.textureUnit[mState.activeSampler].operand0Alpha = operand; +} + +void Context::setOperand1Alpha(GLenum operand) +{ + mState.textureUnit[mState.activeSampler].operand1Alpha = operand; +} + +void Context::setOperand2Alpha(GLenum operand) +{ + mState.textureUnit[mState.activeSampler].operand2Alpha = operand; +} + +void Context::setSrc0RGB(GLenum src) +{ + mState.textureUnit[mState.activeSampler].src0RGB = src; +} + +void Context::setSrc1RGB(GLenum src) +{ + mState.textureUnit[mState.activeSampler].src1RGB = src; +} + +void Context::setSrc2RGB(GLenum src) +{ + mState.textureUnit[mState.activeSampler].src2RGB = src; +} + +void Context::setSrc0Alpha(GLenum src) +{ + mState.textureUnit[mState.activeSampler].src0Alpha = src; +} + +void Context::setSrc1Alpha(GLenum src) +{ + mState.textureUnit[mState.activeSampler].src1Alpha = src; +} + +void Context::setSrc2Alpha(GLenum src) +{ + mState.textureUnit[mState.activeSampler].src2Alpha = src; +} + +void Context::applyTexture(int index, Texture *baseTexture) +{ + sw::Resource *resource = 0; + + if(baseTexture) + { + resource = baseTexture->getResource(); + } + + device->setTextureResource(index, resource); + + if(baseTexture) + { + int levelCount = baseTexture->getLevelCount(); + + if(baseTexture->getTarget() == GL_TEXTURE_2D || baseTexture->getTarget() == GL_TEXTURE_EXTERNAL_OES) + { + Texture2D *texture = static_cast<Texture2D*>(baseTexture); + + for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) + { + int surfaceLevel = mipmapLevel; + + if(surfaceLevel < 0) + { + surfaceLevel = 0; + } + else if(surfaceLevel >= levelCount) + { + surfaceLevel = levelCount - 1; + } + + egl::Image *surface = texture->getImage(surfaceLevel); + device->setTextureLevel(index, 0, mipmapLevel, surface, sw::TEXTURE_2D); + } + } + else UNIMPLEMENTED(); + } + else + { + device->setTextureLevel(index, 0, 0, 0, sw::TEXTURE_NULL); + } +} + +void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, void* pixels) +{ + Framebuffer *framebuffer = getFramebuffer(); + int framebufferWidth, framebufferHeight, framebufferSamples; + + if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE_OES) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES); + } + + if(getFramebufferName() != 0 && framebufferSamples != 0) + { + return error(GL_INVALID_OPERATION); + } + + if(format != GL_RGBA || type != GL_UNSIGNED_BYTE) + { + if(format != framebuffer->getImplementationColorReadFormat() || type != framebuffer->getImplementationColorReadType()) + { + return error(GL_INVALID_OPERATION); + } + } + + GLsizei outputPitch = egl::ComputePitch(width, format, type, mState.packAlignment); + + // Sized query sanity check + if(bufSize) + { + int requiredSize = outputPitch * height; + if(requiredSize > *bufSize) + { + return error(GL_INVALID_OPERATION); + } + } + + egl::Image *renderTarget = framebuffer->getRenderTarget(); + + if(!renderTarget) + { + return error(GL_OUT_OF_MEMORY); + } + + sw::Rect rect = {x, y, x + width, y + height}; + rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight()); + + unsigned char *source = (unsigned char*)renderTarget->lock(rect.x0, rect.y0, sw::LOCK_READONLY); + unsigned char *dest = (unsigned char*)pixels; + int inputPitch = (int)renderTarget->getPitch(); + + for(int j = 0; j < rect.y1 - rect.y0; j++) + { + unsigned short *dest16 = (unsigned short*)dest; + unsigned int *dest32 = (unsigned int*)dest; + + if(renderTarget->getInternalFormat() == sw::FORMAT_A8B8G8R8 && + format == GL_RGBA && type == GL_UNSIGNED_BYTE) + { + memcpy(dest, source, (rect.x1 - rect.x0) * 4); + } + else if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 && + format == GL_RGBA && type == GL_UNSIGNED_BYTE) + { + for(int i = 0; i < rect.x1 - rect.x0; i++) + { + unsigned int argb = *(unsigned int*)(source + 4 * i); + + dest32[i] = (argb & 0xFF00FF00) | ((argb & 0x000000FF) << 16) | ((argb & 0x00FF0000) >> 16); + } + } + else if(renderTarget->getInternalFormat() == sw::FORMAT_X8R8G8B8 && + format == GL_RGBA && type == GL_UNSIGNED_BYTE) + { + for(int i = 0; i < rect.x1 - rect.x0; i++) + { + unsigned int xrgb = *(unsigned int*)(source + 4 * i); + + dest32[i] = (xrgb & 0xFF00FF00) | ((xrgb & 0x000000FF) << 16) | ((xrgb & 0x00FF0000) >> 16) | 0xFF000000; + } + } + else if(renderTarget->getInternalFormat() == sw::FORMAT_X8R8G8B8 && + format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE) + { + for(int i = 0; i < rect.x1 - rect.x0; i++) + { + unsigned int xrgb = *(unsigned int*)(source + 4 * i); + + dest32[i] = xrgb | 0xFF000000; + } + } + else if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 && + format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE) + { + memcpy(dest, source, (rect.x1 - rect.x0) * 4); + } + else if(renderTarget->getInternalFormat() == sw::FORMAT_A1R5G5B5 && + format == GL_BGRA_EXT && type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT) + { + memcpy(dest, source, (rect.x1 - rect.x0) * 2); + } + else if(renderTarget->getInternalFormat() == sw::FORMAT_R5G6B5 && + format == 0x80E0 && type == GL_UNSIGNED_SHORT_5_6_5) // GL_BGR_EXT + { + memcpy(dest, source, (rect.x1 - rect.x0) * 2); + } + else + { + for(int i = 0; i < rect.x1 - rect.x0; i++) + { + float r; + float g; + float b; + float a; + + switch(renderTarget->getInternalFormat()) + { + case sw::FORMAT_R5G6B5: + { + unsigned short rgb = *(unsigned short*)(source + 2 * i); + + a = 1.0f; + b = (rgb & 0x001F) * (1.0f / 0x001F); + g = (rgb & 0x07E0) * (1.0f / 0x07E0); + r = (rgb & 0xF800) * (1.0f / 0xF800); + } + break; + case sw::FORMAT_A1R5G5B5: + { + unsigned short argb = *(unsigned short*)(source + 2 * i); + + a = (argb & 0x8000) ? 1.0f : 0.0f; + b = (argb & 0x001F) * (1.0f / 0x001F); + g = (argb & 0x03E0) * (1.0f / 0x03E0); + r = (argb & 0x7C00) * (1.0f / 0x7C00); + } + break; + case sw::FORMAT_A8R8G8B8: + { + unsigned int argb = *(unsigned int*)(source + 4 * i); + + a = (argb & 0xFF000000) * (1.0f / 0xFF000000); + b = (argb & 0x000000FF) * (1.0f / 0x000000FF); + g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); + } + break; + case sw::FORMAT_A8B8G8R8: + { + unsigned int abgr = *(unsigned int*)(source + 4 * i); + + a = (abgr & 0xFF000000) * (1.0f / 0xFF000000); + b = (abgr & 0x00FF0000) * (1.0f / 0x00FF0000); + g = (abgr & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (abgr & 0x000000FF) * (1.0f / 0x000000FF); + } + break; + case sw::FORMAT_X8R8G8B8: + { + unsigned int xrgb = *(unsigned int*)(source + 4 * i); + + a = 1.0f; + b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); + g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); + } + break; + case sw::FORMAT_X8B8G8R8: + { + unsigned int xbgr = *(unsigned int*)(source + 4 * i); + + a = 1.0f; + b = (xbgr & 0x00FF0000) * (1.0f / 0x00FF0000); + g = (xbgr & 0x0000FF00) * (1.0f / 0x0000FF00); + r = (xbgr & 0x000000FF) * (1.0f / 0x000000FF); + } + break; + case sw::FORMAT_A2R10G10B10: + { + unsigned int argb = *(unsigned int*)(source + 4 * i); + + a = (argb & 0xC0000000) * (1.0f / 0xC0000000); + b = (argb & 0x000003FF) * (1.0f / 0x000003FF); + g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); + r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); + } + break; + default: + UNIMPLEMENTED(); // FIXME + UNREACHABLE(renderTarget->getInternalFormat()); + } + + switch(format) + { + case GL_RGBA: + switch(type) + { + case GL_UNSIGNED_BYTE: + dest[4 * i + 0] = (unsigned char)(255 * r + 0.5f); + dest[4 * i + 1] = (unsigned char)(255 * g + 0.5f); + dest[4 * i + 2] = (unsigned char)(255 * b + 0.5f); + dest[4 * i + 3] = (unsigned char)(255 * a + 0.5f); + break; + default: UNREACHABLE(type); + } + break; + case GL_BGRA_EXT: + switch(type) + { + case GL_UNSIGNED_BYTE: + dest[4 * i + 0] = (unsigned char)(255 * b + 0.5f); + dest[4 * i + 1] = (unsigned char)(255 * g + 0.5f); + dest[4 * i + 2] = (unsigned char)(255 * r + 0.5f); + dest[4 * i + 3] = (unsigned char)(255 * a + 0.5f); + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + dest16[i] = + ((unsigned short)(15 * a + 0.5f) << 12)| + ((unsigned short)(15 * r + 0.5f) << 8) | + ((unsigned short)(15 * g + 0.5f) << 4) | + ((unsigned short)(15 * b + 0.5f) << 0); + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section + // this type is packed as follows: + // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------- + // | 4th | 3rd | 2nd | 1st component | + // -------------------------------------------------------------------------------- + // in the case of BGRA_EXT, B is the first component, G the second, and so forth. + dest16[i] = + ((unsigned short)( a + 0.5f) << 15) | + ((unsigned short)(31 * r + 0.5f) << 10) | + ((unsigned short)(31 * g + 0.5f) << 5) | + ((unsigned short)(31 * b + 0.5f) << 0); + break; + default: UNREACHABLE(type); + } + break; + case GL_RGB: + switch(type) + { + case GL_UNSIGNED_SHORT_5_6_5: + dest16[i] = + ((unsigned short)(31 * b + 0.5f) << 0) | + ((unsigned short)(63 * g + 0.5f) << 5) | + ((unsigned short)(31 * r + 0.5f) << 11); + break; + default: UNREACHABLE(type); + } + break; + default: UNREACHABLE(format); + } + } + } + + source += inputPitch; + dest += outputPitch; + } + + renderTarget->unlock(); + renderTarget->release(); +} + +void Context::clear(GLbitfield mask) +{ + Framebuffer *framebuffer = getFramebuffer(); + + if(!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE_OES) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES); + } + + if(!applyRenderTarget()) + { + return; + } + + float depth = clamp01(mState.depthClearValue); + int stencil = mState.stencilClearValue & 0x000000FF; + + if(mask & GL_COLOR_BUFFER_BIT) + { + unsigned int rgbaMask = (mState.colorMaskRed ? 0x1 : 0) | + (mState.colorMaskGreen ? 0x2 : 0) | + (mState.colorMaskBlue ? 0x4 : 0) | + (mState.colorMaskAlpha ? 0x8 : 0); + + if(rgbaMask != 0) + { + device->clearColor(mState.colorClearValue.red, mState.colorClearValue.green, mState.colorClearValue.blue, mState.colorClearValue.alpha, rgbaMask); + } + } + + if(mask & GL_DEPTH_BUFFER_BIT) + { + if(mState.depthMask != 0) + { + device->clearDepth(depth); + } + } + + if(mask & GL_STENCIL_BUFFER_BIT) + { + if(mState.stencilWritemask != 0) + { + device->clearStencil(stencil, mState.stencilWritemask); + } + } +} + +void Context::drawArrays(GLenum mode, GLint first, GLsizei count) +{ + sw::DrawType primitiveType; + int primitiveCount; + + if(!es2sw::ConvertPrimitiveType(mode, count, GL_NONE, primitiveType, primitiveCount)) + return error(GL_INVALID_ENUM); + + if(primitiveCount <= 0) + { + return; + } + + if(!applyRenderTarget()) + { + return; + } + + applyState(mode); + + GLenum err = applyVertexBuffer(0, first, count); + if(err != GL_NO_ERROR) + { + return error(err); + } + + applyTextures(); + + if(!cullSkipsDraw(mode)) + { + device->drawPrimitive(primitiveType, primitiveCount); + } +} + +void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) +{ + if(!indices && !mState.elementArrayBuffer) + { + return error(GL_INVALID_OPERATION); + } + + sw::DrawType primitiveType; + int primitiveCount; + + if(!es2sw::ConvertPrimitiveType(mode, count, type, primitiveType, primitiveCount)) + return error(GL_INVALID_ENUM); + + if(primitiveCount <= 0) + { + return; + } + + if(!applyRenderTarget()) + { + return; + } + + applyState(mode); + + TranslatedIndexData indexInfo; + GLenum err = applyIndexBuffer(indices, 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); + if(err != GL_NO_ERROR) + { + return error(err); + } + + applyTextures(); + + if(!cullSkipsDraw(mode)) + { + device->drawIndexedPrimitive(primitiveType, indexInfo.indexOffset, primitiveCount); + } +} + +void Context::drawTexture(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) +{ + es1::Framebuffer *framebuffer = getFramebuffer(); + es1::Renderbuffer *renderbuffer = framebuffer->getColorbuffer(); + float targetWidth = (float)renderbuffer->getWidth(); + float targetHeight = (float)renderbuffer->getHeight(); + float x0 = 2.0f * x / targetWidth - 1.0f; + float y0 = 2.0f * y / targetHeight - 1.0f; + float x1 = 2.0f * (x + width) / targetWidth - 1.0f; + float y1 = 2.0f * (y + height) / targetHeight - 1.0f; + float Zw = sw::clamp(mState.zNear + z * (mState.zFar - mState.zNear), mState.zNear, mState.zFar); + + float vertices[][3] = {{x0, y0, Zw}, + {x0, y1, Zw}, + {x1, y0, Zw}, + {x1, y1, Zw}}; + + ASSERT(mState.samplerTexture[TEXTURE_2D][1].name() == 0); // Multi-texturing unimplemented + es1::Texture *texture = getSamplerTexture(0, TEXTURE_2D); + float textureWidth = (float)texture->getWidth(GL_TEXTURE_2D, 0); + float textureHeight = (float)texture->getHeight(GL_TEXTURE_2D, 0); + int Ucr = texture->getCropRectU(); + int Vcr = texture->getCropRectV(); + int Wcr = texture->getCropRectW(); + int Hcr = texture->getCropRectH(); + + float texCoords[][2] = {{Ucr / textureWidth, Vcr / textureHeight}, + {Ucr / textureWidth, (Vcr + Hcr) / textureHeight}, + {(Ucr + Wcr) / textureWidth, Vcr / textureHeight}, + {(Ucr + Wcr) / textureWidth, (Vcr + Hcr) / textureHeight}}; + + VertexAttribute oldPositionAttribute = mState.vertexAttribute[sw::Position]; + VertexAttribute oldTexCoord0Attribute = mState.vertexAttribute[sw::TexCoord0]; + gl::BindingPointer<Buffer> oldArrayBuffer = mState.arrayBuffer; + mState.arrayBuffer = nullptr; + + glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), vertices); + glEnableClientState(GL_VERTEX_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(float), texCoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + sw::Matrix P = projectionStack.current(); + sw::Matrix M = modelViewStack.current(); + sw::Matrix T = textureStack0.current(); + + projectionStack.identity(); + modelViewStack.identity(); + textureStack0.identity(); + + drawArrays(GL_TRIANGLE_STRIP, 0, 4); + + // Restore state + mState.vertexAttribute[sw::Position] = oldPositionAttribute; + mState.vertexAttribute[sw::TexCoord0] = oldTexCoord0Attribute; + mState.arrayBuffer = oldArrayBuffer; + oldArrayBuffer = nullptr; + oldPositionAttribute.mBoundBuffer = nullptr; + oldTexCoord0Attribute.mBoundBuffer = nullptr; + textureStack0.load(T); + modelViewStack.load(M); + projectionStack.load(P); +} + +void Context::finish() +{ + device->finish(); +} + +void Context::flush() +{ + // We don't queue anything without processing it as fast as possible +} + +void Context::recordInvalidEnum() +{ + mInvalidEnum = true; +} + +void Context::recordInvalidValue() +{ + mInvalidValue = true; +} + +void Context::recordInvalidOperation() +{ + mInvalidOperation = true; +} + +void Context::recordOutOfMemory() +{ + mOutOfMemory = true; +} + +void Context::recordInvalidFramebufferOperation() +{ + mInvalidFramebufferOperation = true; +} + +void Context::recordMatrixStackOverflow() +{ + mMatrixStackOverflow = true; +} + +void Context::recordMatrixStackUnderflow() +{ + mMatrixStackUnderflow = true; +} + +// Get one of the recorded errors and clear its flag, if any. +// [OpenGL ES 2.0.24] section 2.5 page 13. +GLenum Context::getError() +{ + if(mInvalidEnum) + { + mInvalidEnum = false; + + return GL_INVALID_ENUM; + } + + if(mInvalidValue) + { + mInvalidValue = false; + + return GL_INVALID_VALUE; + } + + if(mInvalidOperation) + { + mInvalidOperation = false; + + return GL_INVALID_OPERATION; + } + + if(mOutOfMemory) + { + mOutOfMemory = false; + + return GL_OUT_OF_MEMORY; + } + + if(mInvalidFramebufferOperation) + { + mInvalidFramebufferOperation = false; + + return GL_INVALID_FRAMEBUFFER_OPERATION_OES; + } + + if(mMatrixStackOverflow) + { + mMatrixStackOverflow = false; + + return GL_INVALID_FRAMEBUFFER_OPERATION_OES; + } + + if(mMatrixStackUnderflow) + { + mMatrixStackUnderflow = false; + + return GL_INVALID_FRAMEBUFFER_OPERATION_OES; + } + + return GL_NO_ERROR; +} + +int Context::getSupportedMultisampleCount(int requested) +{ + int supported = 0; + + for(int i = NUM_MULTISAMPLE_COUNTS - 1; i >= 0; i--) + { + if(supported >= requested) + { + return supported; + } + + supported = multisampleCount[i]; + } + + return supported; +} + +void Context::detachBuffer(GLuint buffer) +{ + // [OpenGL ES 2.0.24] section 2.9 page 22: + // If a buffer object is deleted while it is bound, all bindings to that object in the current context + // (i.e. in the thread that called Delete-Buffers) are reset to zero. + + if(mState.arrayBuffer.name() == buffer) + { + mState.arrayBuffer = nullptr; + } + + if(mState.elementArrayBuffer.name() == buffer) + { + mState.elementArrayBuffer = nullptr; + } + + for(int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) + { + if(mState.vertexAttribute[attribute].mBoundBuffer.name() == buffer) + { + mState.vertexAttribute[attribute].mBoundBuffer = nullptr; + } + } +} + +void Context::detachTexture(GLuint texture) +{ + // [OpenGL ES 2.0.24] section 3.8 page 84: + // If a texture object is deleted, it is as if all texture units which are bound to that texture object are + // rebound to texture object zero + + for(int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + for(int sampler = 0; sampler < MAX_TEXTURE_UNITS; sampler++) + { + if(mState.samplerTexture[type][sampler].name() == texture) + { + mState.samplerTexture[type][sampler] = nullptr; + } + } + } + + // [OpenGL ES 2.0.24] section 4.4 page 112: + // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is + // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this + // image was attached in the currently bound framebuffer. + + Framebuffer *framebuffer = getFramebuffer(); + + if(framebuffer) + { + framebuffer->detachTexture(texture); + } +} + +void Context::detachFramebuffer(GLuint framebuffer) +{ + // [OpenGL ES 2.0.24] section 4.4 page 107: + // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though + // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. + + if(mState.framebuffer == framebuffer) + { + bindFramebuffer(0); + } +} + +void Context::detachRenderbuffer(GLuint renderbuffer) +{ + // [OpenGL ES 2.0.24] section 4.4 page 109: + // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer + // had been executed with the target RENDERBUFFER and name of zero. + + if(mState.renderbuffer.name() == renderbuffer) + { + bindRenderbuffer(0); + } + + // [OpenGL ES 2.0.24] section 4.4 page 111: + // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, + // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment + // point to which this image was attached in the currently bound framebuffer. + + Framebuffer *framebuffer = getFramebuffer(); + + if(framebuffer) + { + framebuffer->detachRenderbuffer(renderbuffer); + } +} + +bool Context::cullSkipsDraw(GLenum drawMode) +{ + return mState.cullFaceEnabled && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode); +} + +bool Context::isTriangleMode(GLenum drawMode) +{ + switch(drawMode) + { + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + case GL_TRIANGLE_STRIP: + return true; + case GL_POINTS: + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + return false; + default: UNREACHABLE(drawMode); + } + + return false; +} + +void Context::setVertexAttrib(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + ASSERT(index < MAX_VERTEX_ATTRIBS); + + mState.vertexAttribute[index].mCurrentValue[0] = x; + mState.vertexAttribute[index].mCurrentValue[1] = y; + mState.vertexAttribute[index].mCurrentValue[2] = z; + mState.vertexAttribute[index].mCurrentValue[3] = w; + + mVertexDataManager->dirtyCurrentValue(index); +} + +void Context::bindTexImage(egl::Surface *surface) +{ + es1::Texture2D *textureObject = getTexture2D(); + + if(textureObject) + { + textureObject->bindTexImage(surface); + } +} + +EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel) +{ + switch(target) + { + case EGL_GL_TEXTURE_2D_KHR: + break; + case EGL_GL_RENDERBUFFER_KHR: + break; + default: + return EGL_BAD_PARAMETER; + } + + if(textureLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return EGL_BAD_MATCH; + } + + if(target == EGL_GL_TEXTURE_2D_KHR) + { + Texture *texture = getTexture(name); + + if(!texture || texture->getTarget() != GL_TEXTURE_2D) + { + return EGL_BAD_PARAMETER; + } + + if(texture->isShared(GL_TEXTURE_2D, textureLevel)) // Bound to an EGLSurface or already an EGLImage sibling + { + return EGL_BAD_ACCESS; + } + + if(textureLevel != 0 && !texture->isSamplerComplete()) + { + return EGL_BAD_PARAMETER; + } + + if(textureLevel == 0 && !(texture->isSamplerComplete() && texture->getLevelCount() == 1)) + { + return EGL_BAD_PARAMETER; + } + } + else if(target == EGL_GL_RENDERBUFFER_KHR) + { + Renderbuffer *renderbuffer = getRenderbuffer(name); + + if(!renderbuffer) + { + return EGL_BAD_PARAMETER; + } + + if(renderbuffer->isShared()) // Already an EGLImage sibling + { + return EGL_BAD_ACCESS; + } + } + else UNREACHABLE(target); + + return EGL_SUCCESS; +} + +egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textureLevel) +{ + if(target == EGL_GL_TEXTURE_2D_KHR) + { + es1::Texture *texture = getTexture(name); + + return texture->createSharedImage(GL_TEXTURE_2D, textureLevel); + } + else if(target == EGL_GL_RENDERBUFFER_KHR) + { + es1::Renderbuffer *renderbuffer = getRenderbuffer(name); + + return renderbuffer->createSharedImage(); + } + else UNREACHABLE(target); + + return 0; +} + +Device *Context::getDevice() +{ + return device; +} + +void Context::setMatrixMode(GLenum mode) +{ + matrixMode = mode; +} + +sw::MatrixStack &Context::currentMatrixStack() +{ + switch(matrixMode) + { + case GL_MODELVIEW: + return modelViewStack; + case GL_PROJECTION: + return projectionStack; + case GL_TEXTURE: + switch(mState.activeSampler) + { + case 0: return textureStack0; + case 1: return textureStack1; + } + break; + } + + UNREACHABLE(matrixMode); + return textureStack0; +} + +void Context::loadIdentity() +{ + currentMatrixStack().identity(); +} + +void Context::load(const GLfloat *m) +{ + currentMatrixStack().load(m); +} + +void Context::pushMatrix() +{ + if(!currentMatrixStack().push()) + { + return error(GL_STACK_OVERFLOW); + } +} + +void Context::popMatrix() +{ + if(!currentMatrixStack().pop()) + { + return error(GL_STACK_OVERFLOW); + } +} + +void Context::rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + currentMatrixStack().rotate(angle, x, y, z); +} + +void Context::translate(GLfloat x, GLfloat y, GLfloat z) +{ + currentMatrixStack().translate(x, y, z); +} + +void Context::scale(GLfloat x, GLfloat y, GLfloat z) +{ + currentMatrixStack().scale(x, y, z); +} + +void Context::multiply(const GLfloat *m) +{ + currentMatrixStack().multiply(m); +} + +void Context::frustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + currentMatrixStack().frustum(left, right, bottom, top, zNear, zFar); +} + +void Context::ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + currentMatrixStack().ortho(left, right, bottom, top, zNear, zFar); +} + +void Context::setClipPlane(int index, const float plane[4]) +{ + sw::Plane clipPlane = modelViewStack.current() * sw::Plane(plane); + device->setClipPlane(index, &clipPlane.A); +} + +void Context::setClipPlaneEnabled(int index, bool enable) +{ + clipFlags = (clipFlags & ~((int)!enable << index)) | ((int)enable << index); + device->setClipFlags(clipFlags); +} + +bool Context::isClipPlaneEnabled(int index) const +{ + return (clipFlags & (1 << index)) != 0; +} + +void Context::setColorLogicOpEnabled(bool enable) +{ + colorLogicOpEnabled = enable; +} + +bool Context::isColorLogicOpEnabled() const +{ + return colorLogicOpEnabled; +} + +void Context::setLogicalOperation(GLenum logicOp) +{ + logicalOperation = logicOp; +} + +void Context::setLineSmoothEnabled(bool enable) +{ + lineSmoothEnabled = enable; +} + +bool Context::isLineSmoothEnabled() const +{ + return lineSmoothEnabled; +} + +void Context::setColorMaterialEnabled(bool enable) +{ + colorMaterialEnabled = enable; +} + +bool Context::isColorMaterialEnabled() const +{ + return colorMaterialEnabled; +} + +void Context::setNormalizeEnabled(bool enable) +{ + normalizeEnabled = enable; +} + +bool Context::isNormalizeEnabled() const +{ + return normalizeEnabled; +} + +void Context::setRescaleNormalEnabled(bool enable) +{ + rescaleNormalEnabled = enable; +} + +bool Context::isRescaleNormalEnabled() const +{ + return rescaleNormalEnabled; +} + +void Context::setVertexArrayEnabled(bool enable) +{ + mState.vertexAttribute[sw::Position].mArrayEnabled = enable; +} + +bool Context::isVertexArrayEnabled() const +{ + return mState.vertexAttribute[sw::Position].mArrayEnabled; +} + +void Context::setNormalArrayEnabled(bool enable) +{ + mState.vertexAttribute[sw::Normal].mArrayEnabled = enable; +} + +bool Context::isNormalArrayEnabled() const +{ + return mState.vertexAttribute[sw::Normal].mArrayEnabled; +} + +void Context::setColorArrayEnabled(bool enable) +{ + mState.vertexAttribute[sw::Color0].mArrayEnabled = enable; +} + +bool Context::isColorArrayEnabled() const +{ + return mState.vertexAttribute[sw::Color0].mArrayEnabled; +} + +void Context::setPointSizeArrayEnabled(bool enable) +{ + mState.vertexAttribute[sw::PointSize].mArrayEnabled = enable; +} + +bool Context::isPointSizeArrayEnabled() const +{ + return mState.vertexAttribute[sw::PointSize].mArrayEnabled; +} + +void Context::setTextureCoordArrayEnabled(bool enable) +{ + mState.vertexAttribute[sw::TexCoord0 + clientTexture].mArrayEnabled = enable; +} + +bool Context::isTextureCoordArrayEnabled() const +{ + return mState.vertexAttribute[sw::TexCoord0 + clientTexture].mArrayEnabled; +} + +void Context::setMultisampleEnabled(bool enable) +{ + multisampleEnabled = enable; +} + +bool Context::isMultisampleEnabled() const +{ + return multisampleEnabled; +} + +void Context::setSampleAlphaToOneEnabled(bool enable) +{ + sampleAlphaToOneEnabled = enable; +} + +bool Context::isSampleAlphaToOneEnabled() const +{ + return sampleAlphaToOneEnabled; +} + +void Context::setPointSpriteEnabled(bool enable) +{ + pointSpriteEnabled = enable; +} + +bool Context::isPointSpriteEnabled() const +{ + return pointSpriteEnabled; +} + +void Context::setPointSmoothEnabled(bool enable) +{ + pointSmoothEnabled = enable; +} + +bool Context::isPointSmoothEnabled() const +{ + return pointSmoothEnabled; +} + +void Context::setPointSizeMin(float min) +{ + pointSizeMin = min; +} + +void Context::setPointSizeMax(float max) +{ + pointSizeMax = max; +} + +void Context::setPointDistanceAttenuation(float a, float b, float c) +{ + pointDistanceAttenuation = {a, b, c}; +} + +void Context::setPointFadeThresholdSize(float threshold) +{ + pointFadeThresholdSize = threshold; +} + +void Context::clientActiveTexture(GLenum texture) +{ + clientTexture = texture; +} + +GLenum Context::getClientActiveTexture() const +{ + return clientTexture; +} + +unsigned int Context::getActiveTexture() const +{ + return mState.activeSampler; +} + +} + +egl::Context *es1CreateContext(const egl::Config *config, const egl::Context *shareContext) +{ + ASSERT(!shareContext || shareContext->getClientVersion() == 1); // Should be checked by eglCreateContext + return new es1::Context(config, static_cast<const es1::Context*>(shareContext)); +}
diff --git a/src/OpenGL/libGLES_CM/Context.h b/src/OpenGL/libGLES_CM/Context.h index 90293e3..9051e02 100644 --- a/src/OpenGL/libGLES_CM/Context.h +++ b/src/OpenGL/libGLES_CM/Context.h
@@ -1,680 +1,683 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// Context.h: Defines the Context class, managing all GL state and performing -// rendering operations. It is the GLES2 specific implementation of EGLContext. - -#ifndef LIBGLES_CM_CONTEXT_H_ -#define LIBGLES_CM_CONTEXT_H_ - -#include "libEGL/Context.hpp" -#include "ResourceManager.h" -#include "common/NameSpace.hpp" -#include "common/Object.hpp" -#include "common/Image.hpp" -#include "Renderer/Sampler.hpp" -#include "common/MatrixStack.hpp" - -#include <GLES/gl.h> -#include <GLES/glext.h> -#include <EGL/egl.h> - -#include <map> -#include <string> - -namespace egl -{ -class Display; -class Surface; -class Config; -} - -namespace es1 -{ -struct TranslatedAttribute; -struct TranslatedIndexData; - -class Device; -class Buffer; -class Texture; -class Texture2D; -class TextureExternal; -class Framebuffer; -class Renderbuffer; -class RenderbufferStorage; -class Colorbuffer; -class Depthbuffer; -class StreamingIndexBuffer; -class Stencilbuffer; -class DepthStencilbuffer; -class VertexDataManager; -class IndexDataManager; - -enum -{ - MAX_VERTEX_ATTRIBS = sw::VERTEX_ATTRIBUTES, - MAX_VARYING_VECTORS = 10, - MAX_TEXTURE_UNITS = 2, - MAX_DRAW_BUFFERS = 1, - MAX_LIGHTS = 8, - MAX_CLIP_PLANES = sw::MAX_CLIP_PLANES, - - MAX_MODELVIEW_STACK_DEPTH = 32, - MAX_PROJECTION_STACK_DEPTH = 2, - MAX_TEXTURE_STACK_DEPTH = 2, -}; - -const GLenum compressedTextureFormats[] = -{ - GL_ETC1_RGB8_OES, -#if (S3TC_SUPPORT) - GL_COMPRESSED_RGB_S3TC_DXT1_EXT, - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, -#endif -}; - -const GLint NUM_COMPRESSED_TEXTURE_FORMATS = sizeof(compressedTextureFormats) / sizeof(compressedTextureFormats[0]); - -const GLint multisampleCount[] = {4, 2, 1}; -const GLint NUM_MULTISAMPLE_COUNTS = sizeof(multisampleCount) / sizeof(multisampleCount[0]); -const GLint IMPLEMENTATION_MAX_SAMPLES = multisampleCount[0]; - -const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f; -const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f; -const float ALIASED_POINT_SIZE_RANGE_MIN = 0.125f; -const float ALIASED_POINT_SIZE_RANGE_MAX = 8192.0f; -const float SMOOTH_LINE_WIDTH_RANGE_MIN = 1.0f; -const float SMOOTH_LINE_WIDTH_RANGE_MAX = 1.0f; -const float SMOOTH_POINT_SIZE_RANGE_MIN = 0.125f; -const float SMOOTH_POINT_SIZE_RANGE_MAX = 8192.0f; -const float MAX_TEXTURE_MAX_ANISOTROPY = 16.0f; - -struct Color -{ - float red; - float green; - float blue; - float alpha; -}; - -struct Point -{ - float x; - float y; - float z; - float w; -}; - -struct Vector -{ - float x; - float y; - float z; -}; - -struct Attenuation -{ - float constant; - float linear; - float quadratic; -}; - -struct Light -{ - bool enabled; - Color ambient; - Color diffuse; - Color specular; - Point position; - Vector direction; - Attenuation attenuation; - float spotExponent; - float spotCutoffAngle; -}; - -// Helper structure describing a single vertex attribute -class VertexAttribute -{ -public: - VertexAttribute() : mType(GL_FLOAT), mSize(4), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false) - { - mCurrentValue[0] = 0.0f; - mCurrentValue[1] = 0.0f; - mCurrentValue[2] = 0.0f; - mCurrentValue[3] = 1.0f; - } - - int typeSize() const - { - switch(mType) - { - case GL_BYTE: return mSize * sizeof(GLbyte); - case GL_UNSIGNED_BYTE: return mSize * sizeof(GLubyte); - case GL_SHORT: return mSize * sizeof(GLshort); - case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort); - case GL_FIXED: return mSize * sizeof(GLfixed); - case GL_FLOAT: return mSize * sizeof(GLfloat); - default: UNREACHABLE(mType); return mSize * sizeof(GLfloat); - } - } - - GLsizei stride() const - { - return mStride ? mStride : typeSize(); - } - - // From glVertexAttribPointer - GLenum mType; - GLint mSize; - bool mNormalized; - GLsizei mStride; // 0 means natural stride - - union - { - const void *mPointer; - intptr_t mOffset; - }; - - gl::BindingPointer<Buffer> mBoundBuffer; // Captured when glVertexAttribPointer is called. - - bool mArrayEnabled; // From glEnable/DisableVertexAttribArray - float mCurrentValue[4]; // From glVertexAttrib -}; - -typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS]; - -struct TextureUnit -{ - Color color; - GLenum environmentMode; - GLenum combineRGB; - GLenum combineAlpha; - GLenum src0RGB; - GLenum src0Alpha; - GLenum src1RGB; - GLenum src1Alpha; - GLenum src2RGB; - GLenum src2Alpha; - GLenum operand0RGB; - GLenum operand0Alpha; - GLenum operand1RGB; - GLenum operand1Alpha; - GLenum operand2RGB; - GLenum operand2Alpha; -}; - -// Helper structure to store all raw state -struct State -{ - Color colorClearValue; - GLclampf depthClearValue; - int stencilClearValue; - - bool cullFaceEnabled; - GLenum cullMode; - GLenum frontFace; - bool depthTestEnabled; - GLenum depthFunc; - bool blendEnabled; - GLenum sourceBlendRGB; - GLenum destBlendRGB; - GLenum sourceBlendAlpha; - GLenum destBlendAlpha; - GLenum blendEquationRGB; - GLenum blendEquationAlpha; - bool stencilTestEnabled; - GLenum stencilFunc; - GLint stencilRef; - GLuint stencilMask; - GLenum stencilFail; - GLenum stencilPassDepthFail; - GLenum stencilPassDepthPass; - GLuint stencilWritemask; - bool polygonOffsetFillEnabled; - GLfloat polygonOffsetFactor; - GLfloat polygonOffsetUnits; - bool sampleAlphaToCoverageEnabled; - bool sampleCoverageEnabled; - GLclampf sampleCoverageValue; - bool sampleCoverageInvert; - bool scissorTestEnabled; - bool ditherEnabled; - GLenum shadeModel; - - GLfloat lineWidth; - - GLenum generateMipmapHint; - GLenum perspectiveCorrectionHint; - GLenum fogHint; - - GLint viewportX; - GLint viewportY; - GLsizei viewportWidth; - GLsizei viewportHeight; - float zNear; - float zFar; - - GLint scissorX; - GLint scissorY; - GLsizei scissorWidth; - GLsizei scissorHeight; - - bool colorMaskRed; - bool colorMaskGreen; - bool colorMaskBlue; - bool colorMaskAlpha; - bool depthMask; - - unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0 - gl::BindingPointer<Buffer> arrayBuffer; - gl::BindingPointer<Buffer> elementArrayBuffer; - GLuint framebuffer; - gl::BindingPointer<Renderbuffer> renderbuffer; - - VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS]; - gl::BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_TEXTURE_UNITS]; - - GLint unpackAlignment; - GLint packAlignment; - - TextureUnit textureUnit[MAX_TEXTURE_UNITS]; -}; - -class Context : public egl::Context -{ -public: - Context(const egl::Config *config, const Context *shareContext); - - virtual void makeCurrent(egl::Surface *surface); - virtual int getClientVersion() const; - virtual void finish(); - - void markAllStateDirty(); - - // State manipulation - void setClearColor(float red, float green, float blue, float alpha); - void setClearDepth(float depth); - void setClearStencil(int stencil); - - void setCullFaceEnabled(bool enabled); - bool isCullFaceEnabled() const; - void setCullMode(GLenum mode); - void setFrontFace(GLenum front); - - void setDepthTestEnabled(bool enabled); - bool isDepthTestEnabled() const; - void setDepthFunc(GLenum depthFunc); - void setDepthRange(float zNear, float zFar); - - void setAlphaTestEnabled(bool enabled); - bool isAlphaTestEnabled() const; - void setAlphaFunc(GLenum alphaFunc, GLclampf reference); - - void setBlendEnabled(bool enabled); - bool isBlendEnabled() const; - void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); - void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); - - void setStencilTestEnabled(bool enabled); - bool isStencilTestEnabled() const; - void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); - void setStencilWritemask(GLuint stencilWritemask); - void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); - - void setPolygonOffsetFillEnabled(bool enabled); - bool isPolygonOffsetFillEnabled() const; - void setPolygonOffsetParams(GLfloat factor, GLfloat units); - - void setSampleAlphaToCoverageEnabled(bool enabled); - bool isSampleAlphaToCoverageEnabled() const; - void setSampleCoverageEnabled(bool enabled); - bool isSampleCoverageEnabled() const; - void setSampleCoverageParams(GLclampf value, bool invert); - - void setShadeModel(GLenum mode); - void setDitherEnabled(bool enabled); - bool isDitherEnabled() const; - void setLightingEnabled(bool enabled); - bool isLightingEnabled() const; - void setLightEnabled(int index, bool enable); - bool isLightEnabled(int index) const; - void setLightAmbient(int index, float r, float g, float b, float a); - void setLightDiffuse(int index, float r, float g, float b, float a); - void setLightSpecular(int index, float r, float g, float b, float a); - void setLightPosition(int index, float x, float y, float z, float w); - void setLightDirection(int index, float x, float y, float z); - void setLightAttenuationConstant(int index, float constant); - void setLightAttenuationLinear(int index, float linear); - void setLightAttenuationQuadratic(int index, float quadratic); - void setSpotLightExponent(int index, float exponent); - void setSpotLightCutoff(int index, float cutoff); - - void setGlobalAmbient(float red, float green, float blue, float alpha); - void setMaterialAmbient(float red, float green, float blue, float alpha); - void setMaterialDiffuse(float red, float green, float blue, float alpha); - void setMaterialSpecular(float red, float green, float blue, float alpha); - void setMaterialEmission(float red, float green, float blue, float alpha); - void setMaterialShininess(float shininess); - void setLightModelTwoSide(bool enable); - - void setFogEnabled(bool enabled); - bool isFogEnabled() const; - void setFogMode(GLenum mode); - void setFogDensity(float fogDensity); - void setFogStart(float fogStart); - void setFogEnd(float fogEnd); - void setFogColor(float r, float g, float b, float a); - - void setTexture2Denabled(bool enabled); - bool isTexture2Denabled() const; - void setTextureExternalEnabled(bool enabled); - bool isTextureExternalEnabled() const; - void clientActiveTexture(GLenum texture); - GLenum getClientActiveTexture() const; - unsigned int getActiveTexture() const; - - void setTextureEnvMode(GLenum texEnvMode); - void setTextureEnvColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); - void setCombineRGB(GLenum combineRGB); - void setCombineAlpha(GLenum combineAlpha); - void setOperand0RGB(GLenum operand); - void setOperand1RGB(GLenum operand); - void setOperand2RGB(GLenum operand); - void setOperand0Alpha(GLenum operand); - void setOperand1Alpha(GLenum operand); - void setOperand2Alpha(GLenum operand); - void setSrc0RGB(GLenum src); - void setSrc1RGB(GLenum src); - void setSrc2RGB(GLenum src); - void setSrc0Alpha(GLenum src); - void setSrc1Alpha(GLenum src); - void setSrc2Alpha(GLenum src); - - void setLineWidth(GLfloat width); - - void setGenerateMipmapHint(GLenum hint); - void setPerspectiveCorrectionHint(GLenum hint); - void setFogHint(GLenum hint); - - void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); - - void setScissorTestEnabled(bool enabled); - bool isScissorTestEnabled() const; - void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); - - void setColorMask(bool red, bool green, bool blue, bool alpha); - void setDepthMask(bool mask); - - void setActiveSampler(unsigned int active); - - GLuint getFramebufferName() const; - GLuint getRenderbufferName() const; - - GLuint getArrayBufferName() const; - - void setVertexAttribArrayEnabled(unsigned int attribNum, bool enabled); - const VertexAttribute &getVertexAttribState(unsigned int attribNum); - void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, - bool normalized, GLsizei stride, const void *pointer); - const void *getVertexAttribPointer(unsigned int attribNum) const; - - const VertexAttributeArray &getVertexAttributes(); - - void setUnpackAlignment(GLint alignment); - GLint getUnpackAlignment() const; - - void setPackAlignment(GLint alignment); - GLint getPackAlignment() const; - - // These create and destroy methods are merely pass-throughs to - // ResourceManager, which owns these object types - GLuint createBuffer(); - GLuint createTexture(); - GLuint createRenderbuffer(); - - void deleteBuffer(GLuint buffer); - void deleteTexture(GLuint texture); - void deleteRenderbuffer(GLuint renderbuffer); - - // Framebuffers are owned by the Context, so these methods do not pass through - GLuint createFramebuffer(); - void deleteFramebuffer(GLuint framebuffer); - - void bindArrayBuffer(GLuint buffer); - void bindElementArrayBuffer(GLuint buffer); - void bindTexture2D(GLuint texture); - void bindTextureExternal(GLuint texture); - void bindFramebuffer(GLuint framebuffer); - void bindRenderbuffer(GLuint renderbuffer); - - void setFramebufferZero(Framebuffer *framebuffer); - - void setRenderbufferStorage(RenderbufferStorage *renderbuffer); - - void setVertexAttrib(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - - Buffer *getBuffer(GLuint handle); - virtual Texture *getTexture(GLuint handle); - Framebuffer *getFramebuffer(GLuint handle); - virtual Renderbuffer *getRenderbuffer(GLuint handle); - - Buffer *getArrayBuffer(); - Buffer *getElementArrayBuffer(); - Texture2D *getTexture2D(); - TextureExternal *getTextureExternal(); - Texture *getSamplerTexture(unsigned int sampler, TextureType type); - Framebuffer *getFramebuffer(); - - bool getFloatv(GLenum pname, GLfloat *params); - bool getIntegerv(GLenum pname, GLint *params); - bool getBooleanv(GLenum pname, GLboolean *params); - bool getPointerv(GLenum pname, const GLvoid **params); - - int getQueryParameterNum(GLenum pname); - bool isQueryParameterInt(GLenum pname); - bool isQueryParameterFloat(GLenum pname); - bool isQueryParameterBool(GLenum pname); - bool isQueryParameterPointer(GLenum pname); - - void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); - void clear(GLbitfield mask); - void drawArrays(GLenum mode, GLint first, GLsizei count); - void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); - void drawTexture(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); - void flush(); - - void recordInvalidEnum(); - void recordInvalidValue(); - void recordInvalidOperation(); - void recordOutOfMemory(); - void recordInvalidFramebufferOperation(); - void recordMatrixStackOverflow(); - void recordMatrixStackUnderflow(); - - GLenum getError(); - - static int getSupportedMultisampleCount(int requested); - - virtual void bindTexImage(egl::Surface *surface); - virtual EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel); - virtual egl::Image *createSharedImage(EGLenum target, GLuint name, GLuint textureLevel); - - Device *getDevice(); - - void setMatrixMode(GLenum mode); - void loadIdentity(); - void load(const GLfloat *m); - void pushMatrix(); - void popMatrix(); - void rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); - void translate(GLfloat x, GLfloat y, GLfloat z); - void scale(GLfloat x, GLfloat y, GLfloat z); - void multiply(const GLfloat *m); - void frustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); - void ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); - - void setClipPlane(int index, const float plane[4]); - void setClipPlaneEnabled(int index, bool enable); - bool isClipPlaneEnabled(int index) const; - - void setColorLogicOpEnabled(bool enable); - bool isColorLogicOpEnabled() const; - void setLogicalOperation(GLenum logicOp); - - void setPointSmoothEnabled(bool enable); - bool isPointSmoothEnabled() const; - - void setLineSmoothEnabled(bool enable); - bool isLineSmoothEnabled() const; - - void setColorMaterialEnabled(bool enable); - bool isColorMaterialEnabled() const; - - void setNormalizeEnabled(bool enable); - bool isNormalizeEnabled() const; - - void setRescaleNormalEnabled(bool enable); - bool isRescaleNormalEnabled() const; - - void setVertexArrayEnabled(bool enable); - bool isVertexArrayEnabled() const; - - void setNormalArrayEnabled(bool enable); - bool isNormalArrayEnabled() const; - - void setColorArrayEnabled(bool enable); - bool isColorArrayEnabled() const; - - void setPointSizeArrayEnabled(bool enable); - bool isPointSizeArrayEnabled() const; - - void setTextureCoordArrayEnabled(bool enable); - bool isTextureCoordArrayEnabled() const; - - void setMultisampleEnabled(bool enable); - bool isMultisampleEnabled() const; - - void setSampleAlphaToOneEnabled(bool enable); - bool isSampleAlphaToOneEnabled() const; - - void setPointSpriteEnabled(bool enable); - bool isPointSpriteEnabled() const; - void setPointSizeMin(float min); - void setPointSizeMax(float max); - void setPointDistanceAttenuation(float a, float b, float c); - void setPointFadeThresholdSize(float threshold); - -private: - virtual ~Context(); - - bool applyRenderTarget(); - void applyState(GLenum drawMode); - GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count); - GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - void applyTextures(); - void applyTexture(int sampler, Texture *texture); - - void detachBuffer(GLuint buffer); - void detachTexture(GLuint texture); - void detachFramebuffer(GLuint framebuffer); - void detachRenderbuffer(GLuint renderbuffer); - - bool cullSkipsDraw(GLenum drawMode); - bool isTriangleMode(GLenum drawMode); - - State mState; - - gl::BindingPointer<Texture2D> mTexture2DZero; - gl::BindingPointer<TextureExternal> mTextureExternalZero; - - gl::NameSpace<Framebuffer> mFramebufferNameSpace; - - VertexDataManager *mVertexDataManager; - IndexDataManager *mIndexDataManager; - - bool lightingEnabled; - Light light[MAX_LIGHTS]; - Color globalAmbient; - Color materialAmbient; - Color materialDiffuse; - Color materialSpecular; - Color materialEmission; - GLfloat materialShininess; - bool lightModelTwoSide; - - // Recorded errors - bool mInvalidEnum; - bool mInvalidValue; - bool mInvalidOperation; - bool mOutOfMemory; - bool mInvalidFramebufferOperation; - bool mMatrixStackOverflow; - bool mMatrixStackUnderflow; - - bool mHasBeenCurrent; - - // state caching flags - bool mDepthStateDirty; - bool mMaskStateDirty; - bool mBlendStateDirty; - bool mStencilStateDirty; - bool mPolygonOffsetStateDirty; - bool mSampleStateDirty; - bool mFrontFaceDirty; - bool mDitherStateDirty; - - sw::MatrixStack ¤tMatrixStack(); - GLenum matrixMode; - sw::MatrixStack modelViewStack; - sw::MatrixStack projectionStack; - sw::MatrixStack textureStack0; - sw::MatrixStack textureStack1; - - bool texture2Denabled[MAX_TEXTURE_UNITS]; - bool textureExternalEnabled[MAX_TEXTURE_UNITS]; - GLenum clientTexture; - - int clipFlags; - - bool alphaTestEnabled; - GLenum alphaTestFunc; - float alphaTestRef; - - bool fogEnabled; - GLenum fogMode; - float fogDensity; - float fogStart; - float fogEnd; - Color fogColor; - - bool lineSmoothEnabled; - bool colorMaterialEnabled; - bool normalizeEnabled; - bool rescaleNormalEnabled; - bool multisampleEnabled; - bool sampleAlphaToOneEnabled; - - bool pointSpriteEnabled; - bool pointSmoothEnabled; - float pointSizeMin; - float pointSizeMax; - Attenuation pointDistanceAttenuation; - float pointFadeThresholdSize; - - bool colorLogicOpEnabled; - GLenum logicalOperation; - - Device *device; - ResourceManager *mResourceManager; -}; -} - -#endif // INCLUDE_CONTEXT_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Context.h: Defines the Context class, managing all GL state and performing +// rendering operations. It is the GLES2 specific implementation of EGLContext. + +#ifndef LIBGLES_CM_CONTEXT_H_ +#define LIBGLES_CM_CONTEXT_H_ + +#include "libEGL/Context.hpp" +#include "ResourceManager.h" +#include "common/NameSpace.hpp" +#include "common/Object.hpp" +#include "common/Image.hpp" +#include "Renderer/Sampler.hpp" +#include "common/MatrixStack.hpp" + +#include <GLES/gl.h> +#include <GLES/glext.h> +#include <EGL/egl.h> + +#include <map> +#include <string> + +namespace egl +{ +class Display; +class Surface; +class Config; +} + +namespace es1 +{ +struct TranslatedAttribute; +struct TranslatedIndexData; + +class Device; +class Buffer; +class Texture; +class Texture2D; +class TextureExternal; +class Framebuffer; +class Renderbuffer; +class RenderbufferStorage; +class Colorbuffer; +class Depthbuffer; +class StreamingIndexBuffer; +class Stencilbuffer; +class DepthStencilbuffer; +class VertexDataManager; +class IndexDataManager; + +enum +{ + MAX_VERTEX_ATTRIBS = sw::VERTEX_ATTRIBUTES, + MAX_VARYING_VECTORS = 10, + MAX_TEXTURE_UNITS = 2, + MAX_DRAW_BUFFERS = 1, + MAX_LIGHTS = 8, + MAX_CLIP_PLANES = sw::MAX_CLIP_PLANES, + + MAX_MODELVIEW_STACK_DEPTH = 32, + MAX_PROJECTION_STACK_DEPTH = 2, + MAX_TEXTURE_STACK_DEPTH = 2, +}; + +const GLenum compressedTextureFormats[] = +{ + GL_ETC1_RGB8_OES, +#if (S3TC_SUPPORT) + GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, +#endif +}; + +const GLint NUM_COMPRESSED_TEXTURE_FORMATS = sizeof(compressedTextureFormats) / sizeof(compressedTextureFormats[0]); + +const GLint multisampleCount[] = {4, 2, 1}; +const GLint NUM_MULTISAMPLE_COUNTS = sizeof(multisampleCount) / sizeof(multisampleCount[0]); +const GLint IMPLEMENTATION_MAX_SAMPLES = multisampleCount[0]; + +const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f; +const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f; +const float ALIASED_POINT_SIZE_RANGE_MIN = 0.125f; +const float ALIASED_POINT_SIZE_RANGE_MAX = 8192.0f; +const float SMOOTH_LINE_WIDTH_RANGE_MIN = 1.0f; +const float SMOOTH_LINE_WIDTH_RANGE_MAX = 1.0f; +const float SMOOTH_POINT_SIZE_RANGE_MIN = 0.125f; +const float SMOOTH_POINT_SIZE_RANGE_MAX = 8192.0f; +const float MAX_TEXTURE_MAX_ANISOTROPY = 16.0f; + +struct Color +{ + float red; + float green; + float blue; + float alpha; +}; + +struct Point +{ + float x; + float y; + float z; + float w; +}; + +struct Vector +{ + float x; + float y; + float z; +}; + +struct Attenuation +{ + float constant; + float linear; + float quadratic; +}; + +struct Light +{ + bool enabled; + Color ambient; + Color diffuse; + Color specular; + Point position; + Vector direction; + Attenuation attenuation; + float spotExponent; + float spotCutoffAngle; +}; + +// Helper structure describing a single vertex attribute +class VertexAttribute +{ +public: + VertexAttribute() : mType(GL_FLOAT), mSize(4), mNormalized(false), mStride(0), mPointer(nullptr), mArrayEnabled(false) + { + mCurrentValue[0] = 0.0f; + mCurrentValue[1] = 0.0f; + mCurrentValue[2] = 0.0f; + mCurrentValue[3] = 1.0f; + } + + int typeSize() const + { + switch(mType) + { + case GL_BYTE: return mSize * sizeof(GLbyte); + case GL_UNSIGNED_BYTE: return mSize * sizeof(GLubyte); + case GL_SHORT: return mSize * sizeof(GLshort); + case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort); + case GL_FIXED: return mSize * sizeof(GLfixed); + case GL_FLOAT: return mSize * sizeof(GLfloat); + default: UNREACHABLE(mType); return mSize * sizeof(GLfloat); + } + } + + GLsizei stride() const + { + return mStride ? mStride : typeSize(); + } + + // From glVertexAttribPointer + GLenum mType; + GLint mSize; + bool mNormalized; + GLsizei mStride; // 0 means natural stride + + union + { + const void *mPointer; + intptr_t mOffset; + }; + + gl::BindingPointer<Buffer> mBoundBuffer; // Captured when glVertexAttribPointer is called. + + bool mArrayEnabled; // From glEnable/DisableVertexAttribArray + float mCurrentValue[4]; // From glVertexAttrib +}; + +typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS]; + +struct TextureUnit +{ + Color color; + GLenum environmentMode; + GLenum combineRGB; + GLenum combineAlpha; + GLenum src0RGB; + GLenum src0Alpha; + GLenum src1RGB; + GLenum src1Alpha; + GLenum src2RGB; + GLenum src2Alpha; + GLenum operand0RGB; + GLenum operand0Alpha; + GLenum operand1RGB; + GLenum operand1Alpha; + GLenum operand2RGB; + GLenum operand2Alpha; +}; + +// Helper structure to store all raw state +struct State +{ + Color colorClearValue; + GLclampf depthClearValue; + int stencilClearValue; + + bool cullFaceEnabled; + GLenum cullMode; + GLenum frontFace; + bool depthTestEnabled; + GLenum depthFunc; + bool blendEnabled; + GLenum sourceBlendRGB; + GLenum destBlendRGB; + GLenum sourceBlendAlpha; + GLenum destBlendAlpha; + GLenum blendEquationRGB; + GLenum blendEquationAlpha; + bool stencilTestEnabled; + GLenum stencilFunc; + GLint stencilRef; + GLuint stencilMask; + GLenum stencilFail; + GLenum stencilPassDepthFail; + GLenum stencilPassDepthPass; + GLuint stencilWritemask; + bool polygonOffsetFillEnabled; + GLfloat polygonOffsetFactor; + GLfloat polygonOffsetUnits; + bool sampleAlphaToCoverageEnabled; + bool sampleCoverageEnabled; + GLclampf sampleCoverageValue; + bool sampleCoverageInvert; + bool scissorTestEnabled; + bool ditherEnabled; + GLenum shadeModel; + + GLfloat lineWidth; + + GLenum generateMipmapHint; + GLenum perspectiveCorrectionHint; + GLenum fogHint; + + GLint viewportX; + GLint viewportY; + GLsizei viewportWidth; + GLsizei viewportHeight; + float zNear; + float zFar; + + GLint scissorX; + GLint scissorY; + GLsizei scissorWidth; + GLsizei scissorHeight; + + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + bool depthMask; + + unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0 + gl::BindingPointer<Buffer> arrayBuffer; + gl::BindingPointer<Buffer> elementArrayBuffer; + GLuint framebuffer; + gl::BindingPointer<Renderbuffer> renderbuffer; + + VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS]; + gl::BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_TEXTURE_UNITS]; + + GLint unpackAlignment; + GLint packAlignment; + + TextureUnit textureUnit[MAX_TEXTURE_UNITS]; +}; + +class Context : public egl::Context +{ +public: + Context(const egl::Config *config, const Context *shareContext); + + virtual void makeCurrent(egl::Surface *surface); + virtual int getClientVersion() const; + virtual void finish(); + + void markAllStateDirty(); + + // State manipulation + void setClearColor(float red, float green, float blue, float alpha); + void setClearDepth(float depth); + void setClearStencil(int stencil); + + void setCullFaceEnabled(bool enabled); + bool isCullFaceEnabled() const; + void setCullMode(GLenum mode); + void setFrontFace(GLenum front); + + void setDepthTestEnabled(bool enabled); + bool isDepthTestEnabled() const; + void setDepthFunc(GLenum depthFunc); + void setDepthRange(float zNear, float zFar); + + void setAlphaTestEnabled(bool enabled); + bool isAlphaTestEnabled() const; + void setAlphaFunc(GLenum alphaFunc, GLclampf reference); + + void setBlendEnabled(bool enabled); + bool isBlendEnabled() const; + void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); + void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); + + void setStencilTestEnabled(bool enabled); + bool isStencilTestEnabled() const; + void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); + void setStencilWritemask(GLuint stencilWritemask); + void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); + + void setPolygonOffsetFillEnabled(bool enabled); + bool isPolygonOffsetFillEnabled() const; + void setPolygonOffsetParams(GLfloat factor, GLfloat units); + + void setSampleAlphaToCoverageEnabled(bool enabled); + bool isSampleAlphaToCoverageEnabled() const; + void setSampleCoverageEnabled(bool enabled); + bool isSampleCoverageEnabled() const; + void setSampleCoverageParams(GLclampf value, bool invert); + + void setShadeModel(GLenum mode); + void setDitherEnabled(bool enabled); + bool isDitherEnabled() const; + void setLightingEnabled(bool enabled); + bool isLightingEnabled() const; + void setLightEnabled(int index, bool enable); + bool isLightEnabled(int index) const; + void setLightAmbient(int index, float r, float g, float b, float a); + void setLightDiffuse(int index, float r, float g, float b, float a); + void setLightSpecular(int index, float r, float g, float b, float a); + void setLightPosition(int index, float x, float y, float z, float w); + void setLightDirection(int index, float x, float y, float z); + void setLightAttenuationConstant(int index, float constant); + void setLightAttenuationLinear(int index, float linear); + void setLightAttenuationQuadratic(int index, float quadratic); + void setSpotLightExponent(int index, float exponent); + void setSpotLightCutoff(int index, float cutoff); + + void setGlobalAmbient(float red, float green, float blue, float alpha); + void setMaterialAmbient(float red, float green, float blue, float alpha); + void setMaterialDiffuse(float red, float green, float blue, float alpha); + void setMaterialSpecular(float red, float green, float blue, float alpha); + void setMaterialEmission(float red, float green, float blue, float alpha); + void setMaterialShininess(float shininess); + void setLightModelTwoSide(bool enable); + + void setFogEnabled(bool enabled); + bool isFogEnabled() const; + void setFogMode(GLenum mode); + void setFogDensity(float fogDensity); + void setFogStart(float fogStart); + void setFogEnd(float fogEnd); + void setFogColor(float r, float g, float b, float a); + + void setTexture2Denabled(bool enabled); + bool isTexture2Denabled() const; + void setTextureExternalEnabled(bool enabled); + bool isTextureExternalEnabled() const; + void clientActiveTexture(GLenum texture); + GLenum getClientActiveTexture() const; + unsigned int getActiveTexture() const; + + void setTextureEnvMode(GLenum texEnvMode); + void setTextureEnvColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void setCombineRGB(GLenum combineRGB); + void setCombineAlpha(GLenum combineAlpha); + void setOperand0RGB(GLenum operand); + void setOperand1RGB(GLenum operand); + void setOperand2RGB(GLenum operand); + void setOperand0Alpha(GLenum operand); + void setOperand1Alpha(GLenum operand); + void setOperand2Alpha(GLenum operand); + void setSrc0RGB(GLenum src); + void setSrc1RGB(GLenum src); + void setSrc2RGB(GLenum src); + void setSrc0Alpha(GLenum src); + void setSrc1Alpha(GLenum src); + void setSrc2Alpha(GLenum src); + + void setLineWidth(GLfloat width); + + void setGenerateMipmapHint(GLenum hint); + void setPerspectiveCorrectionHint(GLenum hint); + void setFogHint(GLenum hint); + + void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); + + void setScissorTestEnabled(bool enabled); + bool isScissorTestEnabled() const; + void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); + + void setColorMask(bool red, bool green, bool blue, bool alpha); + void setDepthMask(bool mask); + + void setActiveSampler(unsigned int active); + + GLuint getFramebufferName() const; + GLuint getRenderbufferName() const; + + GLuint getArrayBufferName() const; + + void setVertexAttribArrayEnabled(unsigned int attribNum, bool enabled); + const VertexAttribute &getVertexAttribState(unsigned int attribNum); + void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, GLsizei stride, const void *pointer); + const void *getVertexAttribPointer(unsigned int attribNum) const; + + const VertexAttributeArray &getVertexAttributes(); + + void setUnpackAlignment(GLint alignment); + GLint getUnpackAlignment() const; + + void setPackAlignment(GLint alignment); + GLint getPackAlignment() const; + + // These create and destroy methods are merely pass-throughs to + // ResourceManager, which owns these object types + GLuint createBuffer(); + GLuint createTexture(); + GLuint createRenderbuffer(); + + void deleteBuffer(GLuint buffer); + void deleteTexture(GLuint texture); + void deleteRenderbuffer(GLuint renderbuffer); + + // Framebuffers are owned by the Context, so these methods do not pass through + GLuint createFramebuffer(); + void deleteFramebuffer(GLuint framebuffer); + + void bindArrayBuffer(GLuint buffer); + void bindElementArrayBuffer(GLuint buffer); + void bindTexture2D(GLuint texture); + void bindTextureExternal(GLuint texture); + void bindFramebuffer(GLuint framebuffer); + void bindRenderbuffer(GLuint renderbuffer); + + void setFramebufferZero(Framebuffer *framebuffer); + + void setRenderbufferStorage(RenderbufferStorage *renderbuffer); + + void setVertexAttrib(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + Buffer *getBuffer(GLuint handle); + virtual Texture *getTexture(GLuint handle); + Framebuffer *getFramebuffer(GLuint handle); + virtual Renderbuffer *getRenderbuffer(GLuint handle); + + Buffer *getArrayBuffer(); + Buffer *getElementArrayBuffer(); + Texture2D *getTexture2D(); + TextureExternal *getTextureExternal(); + Texture *getSamplerTexture(unsigned int sampler, TextureType type); + Framebuffer *getFramebuffer(); + + bool getFloatv(GLenum pname, GLfloat *params); + bool getIntegerv(GLenum pname, GLint *params); + bool getBooleanv(GLenum pname, GLboolean *params); + bool getPointerv(GLenum pname, const GLvoid **params); + + int getQueryParameterNum(GLenum pname); + bool isQueryParameterInt(GLenum pname); + bool isQueryParameterFloat(GLenum pname); + bool isQueryParameterBool(GLenum pname); + bool isQueryParameterPointer(GLenum pname); + + void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); + void clear(GLbitfield mask); + void drawArrays(GLenum mode, GLint first, GLsizei count); + void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); + void drawTexture(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); + void flush(); + + void recordInvalidEnum(); + void recordInvalidValue(); + void recordInvalidOperation(); + void recordOutOfMemory(); + void recordInvalidFramebufferOperation(); + void recordMatrixStackOverflow(); + void recordMatrixStackUnderflow(); + + GLenum getError(); + + static int getSupportedMultisampleCount(int requested); + + virtual void bindTexImage(egl::Surface *surface); + virtual EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel); + virtual egl::Image *createSharedImage(EGLenum target, GLuint name, GLuint textureLevel); + + Device *getDevice(); + + void setMatrixMode(GLenum mode); + void loadIdentity(); + void load(const GLfloat *m); + void pushMatrix(); + void popMatrix(); + void rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); + void translate(GLfloat x, GLfloat y, GLfloat z); + void scale(GLfloat x, GLfloat y, GLfloat z); + void multiply(const GLfloat *m); + void frustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); + void ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); + + void setClipPlane(int index, const float plane[4]); + void setClipPlaneEnabled(int index, bool enable); + bool isClipPlaneEnabled(int index) const; + + void setColorLogicOpEnabled(bool enable); + bool isColorLogicOpEnabled() const; + void setLogicalOperation(GLenum logicOp); + + void setPointSmoothEnabled(bool enable); + bool isPointSmoothEnabled() const; + + void setLineSmoothEnabled(bool enable); + bool isLineSmoothEnabled() const; + + void setColorMaterialEnabled(bool enable); + bool isColorMaterialEnabled() const; + + void setNormalizeEnabled(bool enable); + bool isNormalizeEnabled() const; + + void setRescaleNormalEnabled(bool enable); + bool isRescaleNormalEnabled() const; + + void setVertexArrayEnabled(bool enable); + bool isVertexArrayEnabled() const; + + void setNormalArrayEnabled(bool enable); + bool isNormalArrayEnabled() const; + + void setColorArrayEnabled(bool enable); + bool isColorArrayEnabled() const; + + void setPointSizeArrayEnabled(bool enable); + bool isPointSizeArrayEnabled() const; + + void setTextureCoordArrayEnabled(bool enable); + bool isTextureCoordArrayEnabled() const; + + void setMultisampleEnabled(bool enable); + bool isMultisampleEnabled() const; + + void setSampleAlphaToOneEnabled(bool enable); + bool isSampleAlphaToOneEnabled() const; + + void setPointSpriteEnabled(bool enable); + bool isPointSpriteEnabled() const; + void setPointSizeMin(float min); + void setPointSizeMax(float max); + void setPointDistanceAttenuation(float a, float b, float c); + void setPointFadeThresholdSize(float threshold); + +private: + virtual ~Context(); + + bool applyRenderTarget(); + void applyState(GLenum drawMode); + GLenum applyVertexBuffer(GLint base, GLint first, GLsizei count); + GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + void applyTextures(); + void applyTexture(int sampler, Texture *texture); + + void detachBuffer(GLuint buffer); + void detachTexture(GLuint texture); + void detachFramebuffer(GLuint framebuffer); + void detachRenderbuffer(GLuint renderbuffer); + + bool cullSkipsDraw(GLenum drawMode); + bool isTriangleMode(GLenum drawMode); + + State mState; + + gl::BindingPointer<Texture2D> mTexture2DZero; + gl::BindingPointer<TextureExternal> mTextureExternalZero; + + gl::NameSpace<Framebuffer> mFramebufferNameSpace; + + VertexDataManager *mVertexDataManager; + IndexDataManager *mIndexDataManager; + + bool lightingEnabled; + Light light[MAX_LIGHTS]; + Color globalAmbient; + Color materialAmbient; + Color materialDiffuse; + Color materialSpecular; + Color materialEmission; + GLfloat materialShininess; + bool lightModelTwoSide; + + // Recorded errors + bool mInvalidEnum; + bool mInvalidValue; + bool mInvalidOperation; + bool mOutOfMemory; + bool mInvalidFramebufferOperation; + bool mMatrixStackOverflow; + bool mMatrixStackUnderflow; + + bool mHasBeenCurrent; + + // state caching flags + bool mDepthStateDirty; + bool mMaskStateDirty; + bool mBlendStateDirty; + bool mStencilStateDirty; + bool mPolygonOffsetStateDirty; + bool mSampleStateDirty; + bool mFrontFaceDirty; + bool mDitherStateDirty; + + sw::MatrixStack ¤tMatrixStack(); + GLenum matrixMode; + sw::MatrixStack modelViewStack; + sw::MatrixStack projectionStack; + sw::MatrixStack textureStack0; + sw::MatrixStack textureStack1; + + bool texture2Denabled[MAX_TEXTURE_UNITS]; + bool textureExternalEnabled[MAX_TEXTURE_UNITS]; + GLenum clientTexture; + + int clipFlags; + + bool alphaTestEnabled; + GLenum alphaTestFunc; + float alphaTestRef; + + bool fogEnabled; + GLenum fogMode; + float fogDensity; + float fogStart; + float fogEnd; + Color fogColor; + + bool lineSmoothEnabled; + bool colorMaterialEnabled; + bool normalizeEnabled; + bool rescaleNormalEnabled; + bool multisampleEnabled; + bool sampleAlphaToOneEnabled; + + bool pointSpriteEnabled; + bool pointSmoothEnabled; + float pointSizeMin; + float pointSizeMax; + Attenuation pointDistanceAttenuation; + float pointFadeThresholdSize; + + bool colorLogicOpEnabled; + GLenum logicalOperation; + + Device *device; + ResourceManager *mResourceManager; +}; +} + +#endif // INCLUDE_CONTEXT_H_
diff --git a/src/OpenGL/libGLES_CM/Device.cpp b/src/OpenGL/libGLES_CM/Device.cpp index 65f29fc..7a7f022 100644 --- a/src/OpenGL/libGLES_CM/Device.cpp +++ b/src/OpenGL/libGLES_CM/Device.cpp
@@ -1,608 +1,611 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -#include "Device.hpp" - -#include "common/Image.hpp" -#include "Texture.h" - -#include "Renderer/Renderer.hpp" -#include "Renderer/Clipper.hpp" -#include "Shader/PixelShader.hpp" -#include "Shader/VertexShader.hpp" -#include "Main/Config.hpp" -#include "Main/FrameBuffer.hpp" -#include "Common/Math.hpp" -#include "Common/Configurator.hpp" -#include "Common/Timer.hpp" -#include "../common/debug.h" - -namespace es1 -{ - using namespace sw; - - Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context) - { - renderTarget = nullptr; - depthBuffer = nullptr; - stencilBuffer = nullptr; - - setDepthBufferEnable(true); - setFillMode(FILL_SOLID); - setShadingMode(SHADING_GOURAUD); - setDepthWriteEnable(true); - setAlphaTestEnable(false); - setSourceBlendFactor(BLEND_ONE); - setDestBlendFactor(BLEND_ZERO); - setCullMode(CULL_COUNTERCLOCKWISE); - setDepthCompare(DEPTH_LESSEQUAL); - setAlphaReference(0.0f); - setAlphaCompare(ALPHA_ALWAYS); - setAlphaBlendEnable(false); - setFogEnable(false); - setSpecularEnable(true); - setLocalViewer(false); - setFogColor(0); - setPixelFogMode(FOG_NONE); - setFogStart(0.0f); - setFogEnd(1.0f); - setFogDensity(1.0f); - setRangeFogEnable(false); - setStencilEnable(false); - setStencilFailOperation(OPERATION_KEEP); - setStencilZFailOperation(OPERATION_KEEP); - setStencilPassOperation(OPERATION_KEEP); - setStencilCompare(STENCIL_ALWAYS); - setStencilReference(0); - setStencilMask(0xFFFFFFFF); - setStencilWriteMask(0xFFFFFFFF); - setVertexFogMode(FOG_NONE); - setClipFlags(0); - setPointSize(1.0f); - setPointSizeMin(0.125f); - setPointSizeMax(8192.0f); - setColorWriteMask(0, 0x0000000F); - setBlendOperation(BLENDOP_ADD); - scissorEnable = false; - setSlopeDepthBias(0.0f); - setTwoSidedStencil(false); - setStencilFailOperationCCW(OPERATION_KEEP); - setStencilZFailOperationCCW(OPERATION_KEEP); - setStencilPassOperationCCW(OPERATION_KEEP); - setStencilCompareCCW(STENCIL_ALWAYS); - setColorWriteMask(1, 0x0000000F); - setColorWriteMask(2, 0x0000000F); - setColorWriteMask(3, 0x0000000F); - setBlendConstant(0xFFFFFFFF); - setWriteSRGB(false); - setDepthBias(0.0f); - setSeparateAlphaBlendEnable(false); - setSourceBlendFactorAlpha(BLEND_ONE); - setDestBlendFactorAlpha(BLEND_ZERO); - setBlendOperationAlpha(BLENDOP_ADD); - setPointSpriteEnable(true); - - for(int i = 0; i < 16; i++) - { - setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); - setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); - setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); - setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000); - setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT); - setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE); - setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f); - } - - for(int i = 0; i < 4; i++) - { - setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); - setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); - setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); - setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000); - setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT); - setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE); - setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f); - } - - for(int i = 0; i < 6; i++) - { - float plane[4] = {0, 0, 0, 0}; - - setClipPlane(i, plane); - } - } - - Device::~Device() - { - if(renderTarget) - { - renderTarget->release(); - renderTarget = nullptr; - } - - if(depthBuffer) - { - depthBuffer->release(); - depthBuffer = nullptr; - } - - if(stencilBuffer) - { - stencilBuffer->release(); - stencilBuffer = nullptr; - } - - delete context; - } - - void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask) - { - if(!renderTarget || !rgbaMask) - { - return; - } - - float rgba[4]; - rgba[0] = red; - rgba[1] = green; - rgba[2] = blue; - rgba[3] = alpha; - - sw::SliceRect clearRect = renderTarget->getRect(); - - if(scissorEnable) - { - clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); - } - - clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask); - } - - void Device::clearDepth(float z) - { - if(!depthBuffer) - { - return; - } - - z = clamp01(z); - sw::SliceRect clearRect = depthBuffer->getRect(); - - if(scissorEnable) - { - clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); - } - - depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); - } - - void Device::clearStencil(unsigned int stencil, unsigned int mask) - { - if(!stencilBuffer) - { - return; - } - - sw::SliceRect clearRect = stencilBuffer->getRect(); - - if(scissorEnable) - { - clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); - } - - stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); - } - - egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) - { - if(height > OUTLINE_RESOLUTION) - { - ERR("Invalid parameters: %dx%d", width, height); - return nullptr; - } - - bool lockable = true; - - switch(format) - { - // case FORMAT_D15S1: - case FORMAT_D24S8: - case FORMAT_D24X8: - // case FORMAT_D24X4S4: - case FORMAT_D24FS8: - case FORMAT_D32: - case FORMAT_D16: - lockable = false; - break; - // case FORMAT_S8_LOCKABLE: - // case FORMAT_D16_LOCKABLE: - case FORMAT_D32F_LOCKABLE: - // case FORMAT_D32_LOCKABLE: - case FORMAT_DF24S8: - case FORMAT_DF16S8: - lockable = true; - break; - default: - UNREACHABLE(format); - } - - egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); - - if(!surface) - { - ERR("Out of memory"); - return nullptr; - } - - return surface; - } - - egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable) - { - if(height > OUTLINE_RESOLUTION) - { - ERR("Invalid parameters: %dx%d", width, height); - return nullptr; - } - - egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); - - if(!surface) - { - ERR("Out of memory"); - return nullptr; - } - - return surface; - } - - void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount) - { - if(!bindResources() || !primitiveCount) - { - return; - } - - draw(type, indexOffset, primitiveCount); - } - - void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount) - { - if(!bindResources() || !primitiveCount) - { - return; - } - - setIndexBuffer(nullptr); - - draw(type, 0, primitiveCount); - } - - void Device::setScissorEnable(bool enable) - { - scissorEnable = enable; - } - - void Device::setRenderTarget(int index, egl::Image *renderTarget) - { - if(renderTarget) - { - renderTarget->addRef(); - } - - if(this->renderTarget) - { - this->renderTarget->release(); - } - - this->renderTarget = renderTarget; - - Renderer::setRenderTarget(index, renderTarget); - } - - void Device::setDepthBuffer(egl::Image *depthBuffer) - { - if(this->depthBuffer == depthBuffer) - { - return; - } - - if(depthBuffer) - { - depthBuffer->addRef(); - } - - if(this->depthBuffer) - { - this->depthBuffer->release(); - } - - this->depthBuffer = depthBuffer; - - Renderer::setDepthBuffer(depthBuffer); - } - - void Device::setStencilBuffer(egl::Image *stencilBuffer) - { - if(this->stencilBuffer == stencilBuffer) - { - return; - } - - if(stencilBuffer) - { - stencilBuffer->addRef(); - } - - if(this->stencilBuffer) - { - this->stencilBuffer->release(); - } - - this->stencilBuffer = stencilBuffer; - - Renderer::setStencilBuffer(stencilBuffer); - } - - void Device::setScissorRect(const sw::Rect &rect) - { - scissorRect = rect; - } - - void Device::setViewport(const Viewport &viewport) - { - this->viewport = viewport; - } - - bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter) - { - if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest)) - { - ERR("Invalid parameters"); - return false; - } - - int sWidth = source->getWidth(); - int sHeight = source->getHeight(); - int dWidth = dest->getWidth(); - int dHeight = dest->getHeight(); - - SliceRect sRect; - SliceRect dRect; - - if(sourceRect) - { - sRect = *sourceRect; - } - else - { - sRect.y0 = 0; - sRect.x0 = 0; - sRect.y1 = sHeight; - sRect.x1 = sWidth; - } - - if(destRect) - { - dRect = *destRect; - } - else - { - dRect.y0 = 0; - dRect.x0 = 0; - dRect.y1 = dHeight; - dRect.x1 = dWidth; - } - - bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0); - bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); - bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat()); - bool alpha0xFF = false; - - if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || - (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) - { - equalFormats = true; - alpha0xFF = true; - } - - if(depthStencil) // Copy entirely, internally // FIXME: Check - { - if(source->hasDepth()) - { - sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC); - sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC); - - unsigned int width = source->getWidth(); - unsigned int height = source->getHeight(); - unsigned int pitch = source->getInternalPitchB(); - - for(unsigned int y = 0; y < height; y++) - { - memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes - - sourceBuffer += pitch; - destBuffer += pitch; - } - - source->unlockInternal(); - dest->unlockInternal(); - } - - if(source->hasStencil()) - { - sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC); - sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC); - - unsigned int width = source->getWidth(); - unsigned int height = source->getHeight(); - unsigned int pitch = source->getStencilPitchB(); - - for(unsigned int y = 0; y < height; y++) - { - memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes - - sourceBuffer += pitch; - destBuffer += pitch; - } - - source->unlockStencil(); - dest->unlockStencil(); - } - } - else if(!scaling && equalFormats) - { - unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC); - unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC); - unsigned int sourcePitch = source->getInternalPitchB(); - unsigned int destPitch = dest->getInternalPitchB(); - - unsigned int width = dRect.x1 - dRect.x0; - unsigned int height = dRect.y1 - dRect.y0; - unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat()); - - for(unsigned int y = 0; y < height; y++) - { - memcpy(destBytes, sourceBytes, bytes); - - if(alpha0xFF) - { - for(unsigned int x = 0; x < width; x++) - { - destBytes[4 * x + 3] = 0xFF; - } - } - - sourceBytes += sourcePitch; - destBytes += destPitch; - } - - source->unlockInternal(); - dest->unlockInternal(); - } - else - { - blit(source, sRect, dest, dRect, scaling && filter); - } - - return true; - } - - bool Device::bindResources() - { - if(!bindViewport()) - { - return false; // Zero-area target region - } - - return true; - } - - bool Device::bindViewport() - { - if(viewport.width <= 0 || viewport.height <= 0) - { - return false; - } - - if(scissorEnable) - { - if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1) - { - return false; - } - - sw::Rect scissor; - scissor.x0 = scissorRect.x0; - scissor.x1 = scissorRect.x1; - scissor.y0 = scissorRect.y0; - scissor.y1 = scissorRect.y1; - - setScissor(scissor); - } - else - { - sw::Rect scissor; - scissor.x0 = viewport.x0; - scissor.x1 = viewport.x0 + viewport.width; - scissor.y0 = viewport.y0; - scissor.y1 = viewport.y0 + viewport.height; - - if(renderTarget) - { - scissor.x0 = max(scissor.x0, 0); - scissor.x1 = min(scissor.x1, renderTarget->getWidth()); - scissor.y0 = max(scissor.y0, 0); - scissor.y1 = min(scissor.y1, renderTarget->getHeight()); - } - - if(depthBuffer) - { - scissor.x0 = max(scissor.x0, 0); - scissor.x1 = min(scissor.x1, depthBuffer->getWidth()); - scissor.y0 = max(scissor.y0, 0); - scissor.y1 = min(scissor.y1, depthBuffer->getHeight()); - } - - if(stencilBuffer) - { - scissor.x0 = max(scissor.x0, 0); - scissor.x1 = min(scissor.x1, stencilBuffer->getWidth()); - scissor.y0 = max(scissor.y0, 0); - scissor.y1 = min(scissor.y1, stencilBuffer->getHeight()); - } - - setScissor(scissor); - } - - sw::Viewport view; - view.x0 = (float)viewport.x0; - view.y0 = (float)viewport.y0; - view.width = (float)viewport.width; - view.height = (float)viewport.height; - view.minZ = viewport.minZ; - view.maxZ = viewport.maxZ; - - Renderer::setViewport(view); - - return true; - } - - bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface) - { - if(!rect) - { - return true; - } - - if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0) - { - return false; - } - - if(rect->x0 < 0 || rect->y0 < 0) - { - return false; - } - - if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight()) - { - return false; - } - - return true; - } - - void Device::finish() - { - synchronize(); - } -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Device.hpp" + +#include "common/Image.hpp" +#include "Texture.h" + +#include "Renderer/Renderer.hpp" +#include "Renderer/Clipper.hpp" +#include "Shader/PixelShader.hpp" +#include "Shader/VertexShader.hpp" +#include "Main/Config.hpp" +#include "Main/FrameBuffer.hpp" +#include "Common/Math.hpp" +#include "Common/Configurator.hpp" +#include "Common/Timer.hpp" +#include "../common/debug.h" + +namespace es1 +{ + using namespace sw; + + Device::Device(Context *context) : Renderer(context, OpenGL, true), context(context) + { + renderTarget = nullptr; + depthBuffer = nullptr; + stencilBuffer = nullptr; + + setDepthBufferEnable(true); + setFillMode(FILL_SOLID); + setShadingMode(SHADING_GOURAUD); + setDepthWriteEnable(true); + setAlphaTestEnable(false); + setSourceBlendFactor(BLEND_ONE); + setDestBlendFactor(BLEND_ZERO); + setCullMode(CULL_COUNTERCLOCKWISE); + setDepthCompare(DEPTH_LESSEQUAL); + setAlphaReference(0.0f); + setAlphaCompare(ALPHA_ALWAYS); + setAlphaBlendEnable(false); + setFogEnable(false); + setSpecularEnable(true); + setLocalViewer(false); + setFogColor(0); + setPixelFogMode(FOG_NONE); + setFogStart(0.0f); + setFogEnd(1.0f); + setFogDensity(1.0f); + setRangeFogEnable(false); + setStencilEnable(false); + setStencilFailOperation(OPERATION_KEEP); + setStencilZFailOperation(OPERATION_KEEP); + setStencilPassOperation(OPERATION_KEEP); + setStencilCompare(STENCIL_ALWAYS); + setStencilReference(0); + setStencilMask(0xFFFFFFFF); + setStencilWriteMask(0xFFFFFFFF); + setVertexFogMode(FOG_NONE); + setClipFlags(0); + setPointSize(1.0f); + setPointSizeMin(0.125f); + setPointSizeMax(8192.0f); + setColorWriteMask(0, 0x0000000F); + setBlendOperation(BLENDOP_ADD); + scissorEnable = false; + setSlopeDepthBias(0.0f); + setTwoSidedStencil(false); + setStencilFailOperationCCW(OPERATION_KEEP); + setStencilZFailOperationCCW(OPERATION_KEEP); + setStencilPassOperationCCW(OPERATION_KEEP); + setStencilCompareCCW(STENCIL_ALWAYS); + setColorWriteMask(1, 0x0000000F); + setColorWriteMask(2, 0x0000000F); + setColorWriteMask(3, 0x0000000F); + setBlendConstant(0xFFFFFFFF); + setWriteSRGB(false); + setDepthBias(0.0f); + setSeparateAlphaBlendEnable(false); + setSourceBlendFactorAlpha(BLEND_ONE); + setDestBlendFactorAlpha(BLEND_ZERO); + setBlendOperationAlpha(BLENDOP_ADD); + setPointSpriteEnable(true); + + for(int i = 0; i < 16; i++) + { + setAddressingModeU(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); + setAddressingModeV(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); + setAddressingModeW(sw::SAMPLER_PIXEL, i, ADDRESSING_WRAP); + setBorderColor(sw::SAMPLER_PIXEL, i, 0x00000000); + setTextureFilter(sw::SAMPLER_PIXEL, i, FILTER_POINT); + setMipmapFilter(sw::SAMPLER_PIXEL, i, MIPMAP_NONE); + setMipmapLOD(sw::SAMPLER_PIXEL, i, 0.0f); + } + + for(int i = 0; i < 4; i++) + { + setAddressingModeU(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); + setAddressingModeV(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); + setAddressingModeW(sw::SAMPLER_VERTEX, i, ADDRESSING_WRAP); + setBorderColor(sw::SAMPLER_VERTEX, i, 0x00000000); + setTextureFilter(sw::SAMPLER_VERTEX, i, FILTER_POINT); + setMipmapFilter(sw::SAMPLER_VERTEX, i, MIPMAP_NONE); + setMipmapLOD(sw::SAMPLER_VERTEX, i, 0.0f); + } + + for(int i = 0; i < 6; i++) + { + float plane[4] = {0, 0, 0, 0}; + + setClipPlane(i, plane); + } + } + + Device::~Device() + { + if(renderTarget) + { + renderTarget->release(); + renderTarget = nullptr; + } + + if(depthBuffer) + { + depthBuffer->release(); + depthBuffer = nullptr; + } + + if(stencilBuffer) + { + stencilBuffer->release(); + stencilBuffer = nullptr; + } + + delete context; + } + + void Device::clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask) + { + if(!renderTarget || !rgbaMask) + { + return; + } + + float rgba[4]; + rgba[0] = red; + rgba[1] = green; + rgba[2] = blue; + rgba[3] = alpha; + + sw::SliceRect clearRect = renderTarget->getRect(); + + if(scissorEnable) + { + clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); + } + + clear(rgba, FORMAT_A32B32G32R32F, renderTarget, clearRect, rgbaMask); + } + + void Device::clearDepth(float z) + { + if(!depthBuffer) + { + return; + } + + z = clamp01(z); + sw::SliceRect clearRect = depthBuffer->getRect(); + + if(scissorEnable) + { + clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); + } + + depthBuffer->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); + } + + void Device::clearStencil(unsigned int stencil, unsigned int mask) + { + if(!stencilBuffer) + { + return; + } + + sw::SliceRect clearRect = stencilBuffer->getRect(); + + if(scissorEnable) + { + clearRect.clip(scissorRect.x0, scissorRect.y0, scissorRect.x1, scissorRect.y1); + } + + stencilBuffer->clearStencil(stencil, mask, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); + } + + egl::Image *Device::createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) + { + if(height > OUTLINE_RESOLUTION) + { + ERR("Invalid parameters: %dx%d", width, height); + return nullptr; + } + + bool lockable = true; + + switch(format) + { + // case FORMAT_D15S1: + case FORMAT_D24S8: + case FORMAT_D24X8: + // case FORMAT_D24X4S4: + case FORMAT_D24FS8: + case FORMAT_D32: + case FORMAT_D16: + lockable = false; + break; + // case FORMAT_S8_LOCKABLE: + // case FORMAT_D16_LOCKABLE: + case FORMAT_D32F_LOCKABLE: + // case FORMAT_D32_LOCKABLE: + case FORMAT_DF24S8: + case FORMAT_DF16S8: + lockable = true; + break; + default: + UNREACHABLE(format); + } + + egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); + + if(!surface) + { + ERR("Out of memory"); + return nullptr; + } + + return surface; + } + + egl::Image *Device::createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable) + { + if(height > OUTLINE_RESOLUTION) + { + ERR("Invalid parameters: %dx%d", width, height); + return nullptr; + } + + egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); + + if(!surface) + { + ERR("Out of memory"); + return nullptr; + } + + return surface; + } + + void Device::drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount) + { + if(!bindResources() || !primitiveCount) + { + return; + } + + draw(type, indexOffset, primitiveCount); + } + + void Device::drawPrimitive(sw::DrawType type, unsigned int primitiveCount) + { + if(!bindResources() || !primitiveCount) + { + return; + } + + setIndexBuffer(nullptr); + + draw(type, 0, primitiveCount); + } + + void Device::setScissorEnable(bool enable) + { + scissorEnable = enable; + } + + void Device::setRenderTarget(int index, egl::Image *renderTarget) + { + if(renderTarget) + { + renderTarget->addRef(); + } + + if(this->renderTarget) + { + this->renderTarget->release(); + } + + this->renderTarget = renderTarget; + + Renderer::setRenderTarget(index, renderTarget); + } + + void Device::setDepthBuffer(egl::Image *depthBuffer) + { + if(this->depthBuffer == depthBuffer) + { + return; + } + + if(depthBuffer) + { + depthBuffer->addRef(); + } + + if(this->depthBuffer) + { + this->depthBuffer->release(); + } + + this->depthBuffer = depthBuffer; + + Renderer::setDepthBuffer(depthBuffer); + } + + void Device::setStencilBuffer(egl::Image *stencilBuffer) + { + if(this->stencilBuffer == stencilBuffer) + { + return; + } + + if(stencilBuffer) + { + stencilBuffer->addRef(); + } + + if(this->stencilBuffer) + { + this->stencilBuffer->release(); + } + + this->stencilBuffer = stencilBuffer; + + Renderer::setStencilBuffer(stencilBuffer); + } + + void Device::setScissorRect(const sw::Rect &rect) + { + scissorRect = rect; + } + + void Device::setViewport(const Viewport &viewport) + { + this->viewport = viewport; + } + + bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter) + { + if(!source || !dest || !validRectangle(sourceRect, source) || !validRectangle(destRect, dest)) + { + ERR("Invalid parameters"); + return false; + } + + int sWidth = source->getWidth(); + int sHeight = source->getHeight(); + int dWidth = dest->getWidth(); + int dHeight = dest->getHeight(); + + SliceRect sRect; + SliceRect dRect; + + if(sourceRect) + { + sRect = *sourceRect; + } + else + { + sRect.y0 = 0; + sRect.x0 = 0; + sRect.y1 = sHeight; + sRect.x1 = sWidth; + } + + if(destRect) + { + dRect = *destRect; + } + else + { + dRect.y0 = 0; + dRect.x0 = 0; + dRect.y1 = dHeight; + dRect.x1 = dWidth; + } + + bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0); + bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); + bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat()); + bool alpha0xFF = false; + + if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || + (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) + { + equalFormats = true; + alpha0xFF = true; + } + + if(depthStencil) // Copy entirely, internally // FIXME: Check + { + if(source->hasDepth()) + { + sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sRect.slice, LOCK_READONLY, PUBLIC); + sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, dRect.slice, LOCK_DISCARD, PUBLIC); + + unsigned int width = source->getWidth(); + unsigned int height = source->getHeight(); + unsigned int pitch = source->getInternalPitchB(); + + for(unsigned int y = 0; y < height; y++) + { + memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes + + sourceBuffer += pitch; + destBuffer += pitch; + } + + source->unlockInternal(); + dest->unlockInternal(); + } + + if(source->hasStencil()) + { + sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, PUBLIC); + sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, PUBLIC); + + unsigned int width = source->getWidth(); + unsigned int height = source->getHeight(); + unsigned int pitch = source->getStencilPitchB(); + + for(unsigned int y = 0; y < height; y++) + { + memcpy(destBuffer, sourceBuffer, pitch); // FIXME: Only copy width * bytes + + sourceBuffer += pitch; + destBuffer += pitch; + } + + source->unlockStencil(); + dest->unlockStencil(); + } + } + else if(!scaling && equalFormats) + { + unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sRect.slice, LOCK_READONLY, PUBLIC); + unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, LOCK_READWRITE, PUBLIC); + unsigned int sourcePitch = source->getInternalPitchB(); + unsigned int destPitch = dest->getInternalPitchB(); + + unsigned int width = dRect.x1 - dRect.x0; + unsigned int height = dRect.y1 - dRect.y0; + unsigned int bytes = width * egl::Image::bytes(source->getInternalFormat()); + + for(unsigned int y = 0; y < height; y++) + { + memcpy(destBytes, sourceBytes, bytes); + + if(alpha0xFF) + { + for(unsigned int x = 0; x < width; x++) + { + destBytes[4 * x + 3] = 0xFF; + } + } + + sourceBytes += sourcePitch; + destBytes += destPitch; + } + + source->unlockInternal(); + dest->unlockInternal(); + } + else + { + blit(source, sRect, dest, dRect, scaling && filter); + } + + return true; + } + + bool Device::bindResources() + { + if(!bindViewport()) + { + return false; // Zero-area target region + } + + return true; + } + + bool Device::bindViewport() + { + if(viewport.width <= 0 || viewport.height <= 0) + { + return false; + } + + if(scissorEnable) + { + if(scissorRect.x0 >= scissorRect.x1 || scissorRect.y0 >= scissorRect.y1) + { + return false; + } + + sw::Rect scissor; + scissor.x0 = scissorRect.x0; + scissor.x1 = scissorRect.x1; + scissor.y0 = scissorRect.y0; + scissor.y1 = scissorRect.y1; + + setScissor(scissor); + } + else + { + sw::Rect scissor; + scissor.x0 = viewport.x0; + scissor.x1 = viewport.x0 + viewport.width; + scissor.y0 = viewport.y0; + scissor.y1 = viewport.y0 + viewport.height; + + if(renderTarget) + { + scissor.x0 = max(scissor.x0, 0); + scissor.x1 = min(scissor.x1, renderTarget->getWidth()); + scissor.y0 = max(scissor.y0, 0); + scissor.y1 = min(scissor.y1, renderTarget->getHeight()); + } + + if(depthBuffer) + { + scissor.x0 = max(scissor.x0, 0); + scissor.x1 = min(scissor.x1, depthBuffer->getWidth()); + scissor.y0 = max(scissor.y0, 0); + scissor.y1 = min(scissor.y1, depthBuffer->getHeight()); + } + + if(stencilBuffer) + { + scissor.x0 = max(scissor.x0, 0); + scissor.x1 = min(scissor.x1, stencilBuffer->getWidth()); + scissor.y0 = max(scissor.y0, 0); + scissor.y1 = min(scissor.y1, stencilBuffer->getHeight()); + } + + setScissor(scissor); + } + + sw::Viewport view; + view.x0 = (float)viewport.x0; + view.y0 = (float)viewport.y0; + view.width = (float)viewport.width; + view.height = (float)viewport.height; + view.minZ = viewport.minZ; + view.maxZ = viewport.maxZ; + + Renderer::setViewport(view); + + return true; + } + + bool Device::validRectangle(const sw::Rect *rect, sw::Surface *surface) + { + if(!rect) + { + return true; + } + + if(rect->x1 <= rect->x0 || rect->y1 <= rect->y0) + { + return false; + } + + if(rect->x0 < 0 || rect->y0 < 0) + { + return false; + } + + if(rect->x1 > (int)surface->getWidth() || rect->y1 > (int)surface->getHeight()) + { + return false; + } + + return true; + } + + void Device::finish() + { + synchronize(); + } +}
diff --git a/src/OpenGL/libGLES_CM/Device.hpp b/src/OpenGL/libGLES_CM/Device.hpp index 15872ca..8b6ea46 100644 --- a/src/OpenGL/libGLES_CM/Device.hpp +++ b/src/OpenGL/libGLES_CM/Device.hpp
@@ -1,78 +1,81 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -#ifndef gl_Device_hpp -#define gl_Device_hpp - -#include "Renderer/Renderer.hpp" - -namespace egl -{ - class Image; -} - -namespace es1 -{ - class Texture; - - struct Viewport - { - int x0; - int y0; - unsigned int width; - unsigned int height; - float minZ; - float maxZ; - }; - - class Device : public sw::Renderer - { - public: - explicit Device(sw::Context *context); - - virtual ~Device(); - - virtual void clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask); - virtual void clearDepth(float z); - virtual void clearStencil(unsigned int stencil, unsigned int mask); - virtual egl::Image *createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard); - virtual egl::Image *createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable); - virtual void drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount); - virtual void drawPrimitive(sw::DrawType type, unsigned int primiveCount); - virtual void setScissorEnable(bool enable); - virtual void setRenderTarget(int index, egl::Image *renderTarget); - virtual void setDepthBuffer(egl::Image *depthBuffer); - virtual void setStencilBuffer(egl::Image *stencilBuffer); - virtual void setScissorRect(const sw::Rect &rect); - virtual void setViewport(const Viewport &viewport); - - virtual bool stretchRect(sw::Surface *sourceSurface, const sw::SliceRect *sourceRect, sw::Surface *destSurface, const sw::SliceRect *destRect, bool filter); - virtual void finish(); - - private: - sw::Context *const context; - - bool bindResources(); - bool bindViewport(); // Also adjusts for scissoring - - bool validRectangle(const sw::Rect *rect, sw::Surface *surface); - - Viewport viewport; - sw::Rect scissorRect; - bool scissorEnable; - - egl::Image *renderTarget; - egl::Image *depthBuffer; - egl::Image *stencilBuffer; - }; -} - -#endif // gl_Device_hpp +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef gl_Device_hpp +#define gl_Device_hpp + +#include "Renderer/Renderer.hpp" + +namespace egl +{ + class Image; +} + +namespace es1 +{ + class Texture; + + struct Viewport + { + int x0; + int y0; + unsigned int width; + unsigned int height; + float minZ; + float maxZ; + }; + + class Device : public sw::Renderer + { + public: + explicit Device(sw::Context *context); + + virtual ~Device(); + + virtual void clearColor(float red, float green, float blue, float alpha, unsigned int rgbaMask); + virtual void clearDepth(float z); + virtual void clearStencil(unsigned int stencil, unsigned int mask); + virtual egl::Image *createDepthStencilSurface(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard); + virtual egl::Image *createRenderTarget(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool lockable); + virtual void drawIndexedPrimitive(sw::DrawType type, unsigned int indexOffset, unsigned int primitiveCount); + virtual void drawPrimitive(sw::DrawType type, unsigned int primiveCount); + virtual void setScissorEnable(bool enable); + virtual void setRenderTarget(int index, egl::Image *renderTarget); + virtual void setDepthBuffer(egl::Image *depthBuffer); + virtual void setStencilBuffer(egl::Image *stencilBuffer); + virtual void setScissorRect(const sw::Rect &rect); + virtual void setViewport(const Viewport &viewport); + + virtual bool stretchRect(sw::Surface *sourceSurface, const sw::SliceRect *sourceRect, sw::Surface *destSurface, const sw::SliceRect *destRect, bool filter); + virtual void finish(); + + private: + sw::Context *const context; + + bool bindResources(); + bool bindViewport(); // Also adjusts for scissoring + + bool validRectangle(const sw::Rect *rect, sw::Surface *surface); + + Viewport viewport; + sw::Rect scissorRect; + bool scissorEnable; + + egl::Image *renderTarget; + egl::Image *depthBuffer; + egl::Image *stencilBuffer; + }; +} + +#endif // gl_Device_hpp
diff --git a/src/OpenGL/libGLES_CM/Framebuffer.cpp b/src/OpenGL/libGLES_CM/Framebuffer.cpp index 25db3d6..5dfa67c 100644 --- a/src/OpenGL/libGLES_CM/Framebuffer.cpp +++ b/src/OpenGL/libGLES_CM/Framebuffer.cpp
@@ -1,13 +1,16 @@ -// SwiftShader Software Renderer +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright(c) 2005-2013 TransGaming Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Framebuffer.cpp: Implements the Framebuffer class. Implements GL framebuffer // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
diff --git a/src/OpenGL/libGLES_CM/Framebuffer.h b/src/OpenGL/libGLES_CM/Framebuffer.h index fa9a684..39f227c 100644 --- a/src/OpenGL/libGLES_CM/Framebuffer.h +++ b/src/OpenGL/libGLES_CM/Framebuffer.h
@@ -1,91 +1,94 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// Framebuffer.h: Defines the Framebuffer class. Implements GL framebuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. - -#ifndef LIBGLES_CM_FRAMEBUFFER_H_ -#define LIBGLES_CM_FRAMEBUFFER_H_ - -#include "common/Object.hpp" -#include "common/Image.hpp" - -#include <GLES/gl.h> - -namespace es1 -{ -class Renderbuffer; -class Colorbuffer; -class Depthbuffer; -class Stencilbuffer; -class DepthStencilbuffer; - -class Framebuffer -{ -public: - Framebuffer(); - - virtual ~Framebuffer(); - - void setColorbuffer(GLenum type, GLuint colorbuffer); - void setDepthbuffer(GLenum type, GLuint depthbuffer); - void setStencilbuffer(GLenum type, GLuint stencilbuffer); - - void detachTexture(GLuint texture); - void detachRenderbuffer(GLuint renderbuffer); - - egl::Image *getRenderTarget(); - egl::Image *getDepthBuffer(); - egl::Image *getStencilBuffer(); - - Renderbuffer *getColorbuffer(); - Renderbuffer *getDepthbuffer(); - Renderbuffer *getStencilbuffer(); - - GLenum getColorbufferType(); - GLenum getDepthbufferType(); - GLenum getStencilbufferType(); - - GLuint getColorbufferName(); - GLuint getDepthbufferName(); - GLuint getStencilbufferName(); - - bool hasStencil(); - - virtual GLenum completeness(); - GLenum completeness(int &width, int &height, int &samples); - - GLenum getImplementationColorReadFormat(); - GLenum getImplementationColorReadType(); - -protected: - GLenum mColorbufferType; - gl::BindingPointer<Renderbuffer> mColorbufferPointer; - - GLenum mDepthbufferType; - gl::BindingPointer<Renderbuffer> mDepthbufferPointer; - - GLenum mStencilbufferType; - gl::BindingPointer<Renderbuffer> mStencilbufferPointer; - -private: - Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const; -}; - -class DefaultFramebuffer : public Framebuffer -{ -public: - DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); -}; - -} - -#endif // LIBGLES_CM_FRAMEBUFFER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Framebuffer.h: Defines the Framebuffer class. Implements GL framebuffer +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. + +#ifndef LIBGLES_CM_FRAMEBUFFER_H_ +#define LIBGLES_CM_FRAMEBUFFER_H_ + +#include "common/Object.hpp" +#include "common/Image.hpp" + +#include <GLES/gl.h> + +namespace es1 +{ +class Renderbuffer; +class Colorbuffer; +class Depthbuffer; +class Stencilbuffer; +class DepthStencilbuffer; + +class Framebuffer +{ +public: + Framebuffer(); + + virtual ~Framebuffer(); + + void setColorbuffer(GLenum type, GLuint colorbuffer); + void setDepthbuffer(GLenum type, GLuint depthbuffer); + void setStencilbuffer(GLenum type, GLuint stencilbuffer); + + void detachTexture(GLuint texture); + void detachRenderbuffer(GLuint renderbuffer); + + egl::Image *getRenderTarget(); + egl::Image *getDepthBuffer(); + egl::Image *getStencilBuffer(); + + Renderbuffer *getColorbuffer(); + Renderbuffer *getDepthbuffer(); + Renderbuffer *getStencilbuffer(); + + GLenum getColorbufferType(); + GLenum getDepthbufferType(); + GLenum getStencilbufferType(); + + GLuint getColorbufferName(); + GLuint getDepthbufferName(); + GLuint getStencilbufferName(); + + bool hasStencil(); + + virtual GLenum completeness(); + GLenum completeness(int &width, int &height, int &samples); + + GLenum getImplementationColorReadFormat(); + GLenum getImplementationColorReadType(); + +protected: + GLenum mColorbufferType; + gl::BindingPointer<Renderbuffer> mColorbufferPointer; + + GLenum mDepthbufferType; + gl::BindingPointer<Renderbuffer> mDepthbufferPointer; + + GLenum mStencilbufferType; + gl::BindingPointer<Renderbuffer> mStencilbufferPointer; + +private: + Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const; +}; + +class DefaultFramebuffer : public Framebuffer +{ +public: + DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); +}; + +} + +#endif // LIBGLES_CM_FRAMEBUFFER_H_
diff --git a/src/OpenGL/libGLES_CM/IndexDataManager.cpp b/src/OpenGL/libGLES_CM/IndexDataManager.cpp index 3e31314..874e17a 100644 --- a/src/OpenGL/libGLES_CM/IndexDataManager.cpp +++ b/src/OpenGL/libGLES_CM/IndexDataManager.cpp
@@ -1,241 +1,244 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// IndexDataManager.cpp: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#include "IndexDataManager.h" - -#include "Buffer.h" -#include "common/debug.h" - -#include <string.h> -#include <algorithm> - -namespace -{ - enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; -} - -namespace es1 -{ - -IndexDataManager::IndexDataManager() -{ - mStreamingBuffer = new StreamingIndexBuffer(INITIAL_INDEX_BUFFER_SIZE); - - if(!mStreamingBuffer) - { - ERR("Failed to allocate the streaming index buffer."); - } -} - -IndexDataManager::~IndexDataManager() -{ - delete mStreamingBuffer; -} - -void copyIndices(GLenum type, const void *input, GLsizei count, void *output) -{ - if(type == GL_UNSIGNED_BYTE) - { - memcpy(output, input, count * sizeof(GLubyte)); - } - else if(type == GL_UNSIGNED_SHORT) - { - memcpy(output, input, count * sizeof(GLushort)); - } - else UNREACHABLE(type); -} - -template<class IndexType> -void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) -{ - *minIndex = indices[0]; - *maxIndex = indices[0]; - - for(GLsizei i = 0; i < count; i++) - { - if(*minIndex > indices[i]) *minIndex = indices[i]; - if(*maxIndex < indices[i]) *maxIndex = indices[i]; - } -} - -void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) -{ - if(type == GL_UNSIGNED_BYTE) - { - computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex); - } - else if(type == GL_UNSIGNED_SHORT) - { - computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex); - } - else UNREACHABLE(type); -} - -GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated) -{ - if(!mStreamingBuffer) - { - return GL_OUT_OF_MEMORY; - } - - intptr_t offset = reinterpret_cast<intptr_t>(indices); - - if(buffer != NULL) - { - if(typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size())) - { - return GL_INVALID_OPERATION; - } - - indices = static_cast<const GLubyte*>(buffer->data()) + offset; - } - - StreamingIndexBuffer *streamingBuffer = mStreamingBuffer; - - sw::Resource *staticBuffer = buffer ? buffer->getResource() : NULL; - - if(staticBuffer) - { - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - - translated->indexBuffer = staticBuffer; - translated->indexOffset = offset; - } - else - { - unsigned int streamOffset = 0; - int convertCount = count; - - streamingBuffer->reserveSpace(convertCount * typeSize(type), type); - void *output = streamingBuffer->map(typeSize(type) * convertCount, &streamOffset); - - if(output == NULL) - { - ERR("Failed to map index buffer."); - return GL_OUT_OF_MEMORY; - } - - copyIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output); - streamingBuffer->unmap(); - - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - - translated->indexBuffer = streamingBuffer->getResource(); - translated->indexOffset = streamOffset; - } - - return GL_NO_ERROR; -} - -std::size_t IndexDataManager::typeSize(GLenum type) -{ - switch(type) - { - case GL_UNSIGNED_SHORT: return sizeof(GLushort); - case GL_UNSIGNED_BYTE: return sizeof(GLubyte); - default: UNREACHABLE(type); return sizeof(GLushort); - } -} - -StreamingIndexBuffer::StreamingIndexBuffer(unsigned int initialSize) : mIndexBuffer(nullptr), mBufferSize(initialSize) -{ - if(initialSize > 0) - { - mIndexBuffer = new sw::Resource(initialSize + 16); - - if(!mIndexBuffer) - { - ERR("Out of memory allocating an index buffer of size %u.", initialSize); - } - } - - mWritePosition = 0; -} - -StreamingIndexBuffer::~StreamingIndexBuffer() -{ - if(mIndexBuffer) - { - mIndexBuffer->destruct(); - } -} - -void *StreamingIndexBuffer::map(unsigned int requiredSpace, unsigned int *offset) -{ - void *mapPtr = NULL; - - if(mIndexBuffer) - { - mapPtr = (char*)mIndexBuffer->lock(sw::PUBLIC) + mWritePosition; - - if(!mapPtr) - { - ERR(" Lock failed"); - return NULL; - } - - *offset = mWritePosition; - mWritePosition += requiredSpace; - } - - return mapPtr; -} - -void StreamingIndexBuffer::unmap() -{ - if(mIndexBuffer) - { - mIndexBuffer->unlock(); - } -} - -void StreamingIndexBuffer::reserveSpace(unsigned int requiredSpace, GLenum type) -{ - if(requiredSpace > mBufferSize) - { - if(mIndexBuffer) - { - mIndexBuffer->destruct(); - mIndexBuffer = 0; - } - - mBufferSize = std::max(requiredSpace, 2 * mBufferSize); - - mIndexBuffer = new sw::Resource(mBufferSize + 16); - - if(!mIndexBuffer) - { - ERR("Out of memory allocating an index buffer of size %u.", mBufferSize); - } - - mWritePosition = 0; - } - else if(mWritePosition + requiredSpace > mBufferSize) // Recycle - { - if(mIndexBuffer) - { - mIndexBuffer->destruct(); - mIndexBuffer = new sw::Resource(mBufferSize + 16); - } - - mWritePosition = 0; - } -} - -sw::Resource *StreamingIndexBuffer::getResource() const -{ - return mIndexBuffer; -} - -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// IndexDataManager.cpp: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#include "IndexDataManager.h" + +#include "Buffer.h" +#include "common/debug.h" + +#include <string.h> +#include <algorithm> + +namespace +{ + enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +} + +namespace es1 +{ + +IndexDataManager::IndexDataManager() +{ + mStreamingBuffer = new StreamingIndexBuffer(INITIAL_INDEX_BUFFER_SIZE); + + if(!mStreamingBuffer) + { + ERR("Failed to allocate the streaming index buffer."); + } +} + +IndexDataManager::~IndexDataManager() +{ + delete mStreamingBuffer; +} + +void copyIndices(GLenum type, const void *input, GLsizei count, void *output) +{ + if(type == GL_UNSIGNED_BYTE) + { + memcpy(output, input, count * sizeof(GLubyte)); + } + else if(type == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else UNREACHABLE(type); +} + +template<class IndexType> +void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + *minIndex = indices[0]; + *maxIndex = indices[0]; + + for(GLsizei i = 0; i < count; i++) + { + if(*minIndex > indices[i]) *minIndex = indices[i]; + if(*maxIndex < indices[i]) *maxIndex = indices[i]; + } +} + +void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + if(type == GL_UNSIGNED_BYTE) + { + computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex); + } + else if(type == GL_UNSIGNED_SHORT) + { + computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex); + } + else UNREACHABLE(type); +} + +GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated) +{ + if(!mStreamingBuffer) + { + return GL_OUT_OF_MEMORY; + } + + intptr_t offset = reinterpret_cast<intptr_t>(indices); + + if(buffer != NULL) + { + if(typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size())) + { + return GL_INVALID_OPERATION; + } + + indices = static_cast<const GLubyte*>(buffer->data()) + offset; + } + + StreamingIndexBuffer *streamingBuffer = mStreamingBuffer; + + sw::Resource *staticBuffer = buffer ? buffer->getResource() : NULL; + + if(staticBuffer) + { + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + + translated->indexBuffer = staticBuffer; + translated->indexOffset = offset; + } + else + { + unsigned int streamOffset = 0; + int convertCount = count; + + streamingBuffer->reserveSpace(convertCount * typeSize(type), type); + void *output = streamingBuffer->map(typeSize(type) * convertCount, &streamOffset); + + if(output == NULL) + { + ERR("Failed to map index buffer."); + return GL_OUT_OF_MEMORY; + } + + copyIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output); + streamingBuffer->unmap(); + + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + + translated->indexBuffer = streamingBuffer->getResource(); + translated->indexOffset = streamOffset; + } + + return GL_NO_ERROR; +} + +std::size_t IndexDataManager::typeSize(GLenum type) +{ + switch(type) + { + case GL_UNSIGNED_SHORT: return sizeof(GLushort); + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + default: UNREACHABLE(type); return sizeof(GLushort); + } +} + +StreamingIndexBuffer::StreamingIndexBuffer(unsigned int initialSize) : mIndexBuffer(nullptr), mBufferSize(initialSize) +{ + if(initialSize > 0) + { + mIndexBuffer = new sw::Resource(initialSize + 16); + + if(!mIndexBuffer) + { + ERR("Out of memory allocating an index buffer of size %u.", initialSize); + } + } + + mWritePosition = 0; +} + +StreamingIndexBuffer::~StreamingIndexBuffer() +{ + if(mIndexBuffer) + { + mIndexBuffer->destruct(); + } +} + +void *StreamingIndexBuffer::map(unsigned int requiredSpace, unsigned int *offset) +{ + void *mapPtr = NULL; + + if(mIndexBuffer) + { + mapPtr = (char*)mIndexBuffer->lock(sw::PUBLIC) + mWritePosition; + + if(!mapPtr) + { + ERR(" Lock failed"); + return NULL; + } + + *offset = mWritePosition; + mWritePosition += requiredSpace; + } + + return mapPtr; +} + +void StreamingIndexBuffer::unmap() +{ + if(mIndexBuffer) + { + mIndexBuffer->unlock(); + } +} + +void StreamingIndexBuffer::reserveSpace(unsigned int requiredSpace, GLenum type) +{ + if(requiredSpace > mBufferSize) + { + if(mIndexBuffer) + { + mIndexBuffer->destruct(); + mIndexBuffer = 0; + } + + mBufferSize = std::max(requiredSpace, 2 * mBufferSize); + + mIndexBuffer = new sw::Resource(mBufferSize + 16); + + if(!mIndexBuffer) + { + ERR("Out of memory allocating an index buffer of size %u.", mBufferSize); + } + + mWritePosition = 0; + } + else if(mWritePosition + requiredSpace > mBufferSize) // Recycle + { + if(mIndexBuffer) + { + mIndexBuffer->destruct(); + mIndexBuffer = new sw::Resource(mBufferSize + 16); + } + + mWritePosition = 0; + } +} + +sw::Resource *StreamingIndexBuffer::getResource() const +{ + return mIndexBuffer; +} + +}
diff --git a/src/OpenGL/libGLES_CM/IndexDataManager.h b/src/OpenGL/libGLES_CM/IndexDataManager.h index 9ef6a96..d7e83d6 100644 --- a/src/OpenGL/libGLES_CM/IndexDataManager.h +++ b/src/OpenGL/libGLES_CM/IndexDataManager.h
@@ -1,68 +1,71 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// IndexDataManager.h: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#ifndef LIBGLES_CM_INDEXDATAMANAGER_H_ -#define LIBGLES_CM_INDEXDATAMANAGER_H_ - -#include "Context.h" - -#include <GLES/gl.h> - -namespace es1 -{ - -struct TranslatedIndexData -{ - unsigned int minIndex; - unsigned int maxIndex; - unsigned int indexOffset; - - sw::Resource *indexBuffer; -}; - -class StreamingIndexBuffer -{ - public: - StreamingIndexBuffer(unsigned int initialSize); - virtual ~StreamingIndexBuffer(); - - void *map(unsigned int requiredSpace, unsigned int *offset); - void unmap(); - void reserveSpace(unsigned int requiredSpace, GLenum type); - - sw::Resource *getResource() const; - - private: - sw::Resource *mIndexBuffer; - unsigned int mBufferSize; - unsigned int mWritePosition; -}; - -class IndexDataManager -{ - public: - IndexDataManager(); - virtual ~IndexDataManager(); - - GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated); - - static std::size_t typeSize(GLenum type); - - private: - StreamingIndexBuffer *mStreamingBuffer; -}; - -} - -#endif // LIBGLES_CM_INDEXDATAMANAGER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// IndexDataManager.h: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#ifndef LIBGLES_CM_INDEXDATAMANAGER_H_ +#define LIBGLES_CM_INDEXDATAMANAGER_H_ + +#include "Context.h" + +#include <GLES/gl.h> + +namespace es1 +{ + +struct TranslatedIndexData +{ + unsigned int minIndex; + unsigned int maxIndex; + unsigned int indexOffset; + + sw::Resource *indexBuffer; +}; + +class StreamingIndexBuffer +{ +public: + StreamingIndexBuffer(unsigned int initialSize); + virtual ~StreamingIndexBuffer(); + + void *map(unsigned int requiredSpace, unsigned int *offset); + void unmap(); + void reserveSpace(unsigned int requiredSpace, GLenum type); + + sw::Resource *getResource() const; + +private: + sw::Resource *mIndexBuffer; + unsigned int mBufferSize; + unsigned int mWritePosition; +}; + +class IndexDataManager +{ +public: + IndexDataManager(); + virtual ~IndexDataManager(); + + GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices, TranslatedIndexData *translated); + + static std::size_t typeSize(GLenum type); + +private: + StreamingIndexBuffer *mStreamingBuffer; +}; + +} + +#endif // LIBGLES_CM_INDEXDATAMANAGER_H_
diff --git a/src/OpenGL/libGLES_CM/Renderbuffer.cpp b/src/OpenGL/libGLES_CM/Renderbuffer.cpp index fccb011..96bf733 100644 --- a/src/OpenGL/libGLES_CM/Renderbuffer.cpp +++ b/src/OpenGL/libGLES_CM/Renderbuffer.cpp
@@ -1,13 +1,16 @@ -// SwiftShader Software Renderer +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright(c) 2005-2013 TransGaming Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // Renderbuffer.cpp: the Renderbuffer class and its derived classes // Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer @@ -27,7 +30,7 @@ // The default case for classes inherited from RenderbufferInterface is not to // need to do anything upon the reference count to the parent Renderbuffer incrementing -// or decrementing. +// or decrementing. void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy) { } @@ -75,19 +78,19 @@ RenderbufferTexture2D::~RenderbufferTexture2D() { - mTexture2D = NULL; + mTexture2D = nullptr; } // Textures need to maintain their own reference count for references via // Renderbuffers acting as proxies. Here, we notify the texture of a reference. void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy) { - mTexture2D->addProxyRef(proxy); + mTexture2D->addProxyRef(proxy); } void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy) { - mTexture2D->releaseProxy(proxy); + mTexture2D->releaseProxy(proxy); } // Increments refcount on image. @@ -101,12 +104,12 @@ // caller must release() the returned image egl::Image *RenderbufferTexture2D::createSharedImage() { - return mTexture2D->createSharedImage(GL_TEXTURE_2D, 0); + return mTexture2D->createSharedImage(GL_TEXTURE_2D, 0); } bool RenderbufferTexture2D::isShared() const { - return mTexture2D->isShared(GL_TEXTURE_2D, 0); + return mTexture2D->isShared(GL_TEXTURE_2D, 0); } GLsizei RenderbufferTexture2D::getWidth() const @@ -138,7 +141,7 @@ Renderbuffer::Renderbuffer(GLuint name, RenderbufferInterface *instance) : NamedObject(name) { - ASSERT(instance != NULL); + ASSERT(instance); mInstance = instance; } @@ -151,16 +154,16 @@ // its own reference count, so we pass it on here. void Renderbuffer::addRef() { - mInstance->addProxyRef(this); + mInstance->addProxyRef(this); - Object::addRef(); + Object::addRef(); } void Renderbuffer::release() { - mInstance->releaseProxy(this); + mInstance->releaseProxy(this); - Object::release(); + Object::release(); } // Increments refcount on image. @@ -174,12 +177,12 @@ // caller must Release() the returned image egl::Image *Renderbuffer::createSharedImage() { - return mInstance->createSharedImage(); + return mInstance->createSharedImage(); } bool Renderbuffer::isShared() const { - return mInstance->isShared(); + return mInstance->isShared(); } GLsizei Renderbuffer::getWidth() const @@ -239,7 +242,7 @@ void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { - ASSERT(newStorage != NULL); + ASSERT(newStorage); delete mInstance; mInstance = newStorage; @@ -288,7 +291,7 @@ if(renderTarget) { renderTarget->addRef(); - + mWidth = renderTarget->getWidth(); mHeight = renderTarget->getHeight(); internalFormat = renderTarget->getInternalFormat(); @@ -346,18 +349,18 @@ // caller must release() the returned image egl::Image *Colorbuffer::createSharedImage() { - if(mRenderTarget) - { - mRenderTarget->addRef(); - mRenderTarget->markShared(); - } + if(mRenderTarget) + { + mRenderTarget->addRef(); + mRenderTarget->markShared(); + } - return mRenderTarget; + return mRenderTarget; } bool Colorbuffer::isShared() const { - return mRenderTarget->isShared(); + return mRenderTarget->isShared(); } DepthStencilbuffer::DepthStencilbuffer(egl::Image *depthStencil) : mDepthStencil(depthStencil) @@ -377,7 +380,7 @@ DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) : mDepthStencil(nullptr) { Device *device = getDevice(); - + int supportedSamples = Context::getSupportedMultisampleCount(samples); if(width > 0 && height > 0) @@ -422,18 +425,18 @@ // caller must release() the returned image egl::Image *DepthStencilbuffer::createSharedImage() { - if(mDepthStencil) - { - mDepthStencil->addRef(); - mDepthStencil->markShared(); - } + if(mDepthStencil) + { + mDepthStencil->addRef(); + mDepthStencil->markShared(); + } - return mDepthStencil; + return mDepthStencil; } bool DepthStencilbuffer::isShared() const { - return mDepthStencil->isShared(); + return mDepthStencil->isShared(); } Depthbuffer::Depthbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil) @@ -441,7 +444,7 @@ if(depthStencil) { format = GL_DEPTH_COMPONENT16_OES; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in + // will expect one of the valid renderbuffer formats for use in // glRenderbufferStorage } } @@ -451,7 +454,7 @@ if(mDepthStencil) { format = GL_DEPTH_COMPONENT16_OES; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in + // will expect one of the valid renderbuffer formats for use in // glRenderbufferStorage } } @@ -465,7 +468,7 @@ if(depthStencil) { format = GL_STENCIL_INDEX8_OES; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in + // will expect one of the valid renderbuffer formats for use in // glRenderbufferStorage } } @@ -475,7 +478,7 @@ if(mDepthStencil) { format = GL_STENCIL_INDEX8_OES; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in + // will expect one of the valid renderbuffer formats for use in // glRenderbufferStorage } }
diff --git a/src/OpenGL/libGLES_CM/Renderbuffer.h b/src/OpenGL/libGLES_CM/Renderbuffer.h index a0b1709..6bb462f 100644 --- a/src/OpenGL/libGLES_CM/Renderbuffer.h +++ b/src/OpenGL/libGLES_CM/Renderbuffer.h
@@ -1,202 +1,205 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// Renderbuffer.h: Defines the wrapper class Renderbuffer, as well as the -// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer, -// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. - -#ifndef LIBGLES_CM_RENDERBUFFER_H_ -#define LIBGLES_CM_RENDERBUFFER_H_ - -#include "common/Object.hpp" -#include "common/Image.hpp" - -#include <GLES/gl.h> - -namespace es1 -{ -class Texture2D; -class Renderbuffer; -class Colorbuffer; -class DepthStencilbuffer; - -class RenderbufferInterface -{ -public: - RenderbufferInterface(); - - virtual ~RenderbufferInterface() {}; - - virtual void addProxyRef(const Renderbuffer *proxy); - virtual void releaseProxy(const Renderbuffer *proxy); - - virtual egl::Image *getRenderTarget() = 0; - virtual egl::Image *createSharedImage() = 0; - virtual bool isShared() const = 0; - - virtual GLsizei getWidth() const = 0; - virtual GLsizei getHeight() const = 0; - virtual GLenum getFormat() const = 0; - virtual sw::Format getInternalFormat() const = 0; - virtual GLsizei getSamples() const = 0; - - GLuint getRedSize() const; - GLuint getGreenSize() const; - GLuint getBlueSize() const; - GLuint getAlphaSize() const; - GLuint getDepthSize() const; - GLuint getStencilSize() const; -}; - -class RenderbufferTexture2D : public RenderbufferInterface -{ -public: - RenderbufferTexture2D(Texture2D *texture); - - virtual ~RenderbufferTexture2D(); - - virtual void addProxyRef(const Renderbuffer *proxy); - virtual void releaseProxy(const Renderbuffer *proxy); - - virtual egl::Image *getRenderTarget(); - virtual egl::Image *createSharedImage(); - virtual bool isShared() const; - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getFormat() const; - virtual sw::Format getInternalFormat() const; - virtual GLsizei getSamples() const; - -private: - gl::BindingPointer<Texture2D> mTexture2D; -}; - -// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage -// is called. The specific concrete type depends on whether the internal format is -// colour depth, stencil or packed depth/stencil. -class RenderbufferStorage : public RenderbufferInterface -{ -public: - RenderbufferStorage(); - - virtual ~RenderbufferStorage() = 0; - - virtual egl::Image *getRenderTarget() = 0; - virtual egl::Image *createSharedImage() = 0; - virtual bool isShared() const = 0; - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getFormat() const; - virtual sw::Format getInternalFormat() const; - virtual GLsizei getSamples() const; - -protected: - GLsizei mWidth; - GLsizei mHeight; - GLenum format; - sw::Format internalFormat; - GLsizei mSamples; -}; - -// Renderbuffer implements the GL renderbuffer object. -// It's only a proxy for a RenderbufferInterface instance; the internal object -// can change whenever glRenderbufferStorage is called. -class Renderbuffer : public gl::NamedObject -{ -public: - Renderbuffer(GLuint name, RenderbufferInterface *storage); - - virtual ~Renderbuffer(); - - // These functions from Object are overloaded here because - // Textures need to maintain their own count of references to them via - // Renderbuffers/RenderbufferTextures. These functions invoke those - // reference counting functions on the RenderbufferInterface. - virtual void addRef(); - virtual void release(); - - egl::Image *getRenderTarget(); - virtual egl::Image *createSharedImage(); - virtual bool isShared() const; - - GLsizei getWidth() const; - GLsizei getHeight() const; - GLenum getFormat() const; - sw::Format getInternalFormat() const; - GLuint getRedSize() const; - GLuint getGreenSize() const; - GLuint getBlueSize() const; - GLuint getAlphaSize() const; - GLuint getDepthSize() const; - GLuint getStencilSize() const; - GLsizei getSamples() const; - - void setStorage(RenderbufferStorage *newStorage); - -private: - RenderbufferInterface *mInstance; -}; - -class Colorbuffer : public RenderbufferStorage -{ -public: - explicit Colorbuffer(egl::Image *renderTarget); - Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples); - - virtual ~Colorbuffer(); - - virtual egl::Image *getRenderTarget(); - virtual egl::Image *createSharedImage(); - virtual bool isShared() const; - -private: - egl::Image *mRenderTarget; -}; - -class DepthStencilbuffer : public RenderbufferStorage -{ -public: - explicit DepthStencilbuffer(egl::Image *depthStencil); - DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples); - - ~DepthStencilbuffer(); - - virtual egl::Image *getRenderTarget(); - virtual egl::Image *createSharedImage(); - virtual bool isShared() const; - -protected: - egl::Image *mDepthStencil; -}; - -class Depthbuffer : public DepthStencilbuffer -{ -public: - explicit Depthbuffer(egl::Image *depthStencil); - Depthbuffer(GLsizei width, GLsizei height, GLsizei samples); - - virtual ~Depthbuffer(); -}; - -class Stencilbuffer : public DepthStencilbuffer -{ -public: - explicit Stencilbuffer(egl::Image *depthStencil); - Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples); - - virtual ~Stencilbuffer(); -}; -} - -#endif // LIBGLES_CM_RENDERBUFFER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Renderbuffer.h: Defines the wrapper class Renderbuffer, as well as the +// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer, +// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#ifndef LIBGLES_CM_RENDERBUFFER_H_ +#define LIBGLES_CM_RENDERBUFFER_H_ + +#include "common/Object.hpp" +#include "common/Image.hpp" + +#include <GLES/gl.h> + +namespace es1 +{ +class Texture2D; +class Renderbuffer; +class Colorbuffer; +class DepthStencilbuffer; + +class RenderbufferInterface +{ +public: + RenderbufferInterface(); + + virtual ~RenderbufferInterface() {}; + + virtual void addProxyRef(const Renderbuffer *proxy); + virtual void releaseProxy(const Renderbuffer *proxy); + + virtual egl::Image *getRenderTarget() = 0; + virtual egl::Image *createSharedImage() = 0; + virtual bool isShared() const = 0; + + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLenum getFormat() const = 0; + virtual sw::Format getInternalFormat() const = 0; + virtual GLsizei getSamples() const = 0; + + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; +}; + +class RenderbufferTexture2D : public RenderbufferInterface +{ +public: + RenderbufferTexture2D(Texture2D *texture); + + virtual ~RenderbufferTexture2D(); + + virtual void addProxyRef(const Renderbuffer *proxy); + virtual void releaseProxy(const Renderbuffer *proxy); + + virtual egl::Image *getRenderTarget(); + virtual egl::Image *createSharedImage(); + virtual bool isShared() const; + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getFormat() const; + virtual sw::Format getInternalFormat() const; + virtual GLsizei getSamples() const; + +private: + gl::BindingPointer<Texture2D> mTexture2D; +}; + +// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage +// is called. The specific concrete type depends on whether the internal format is +// colour depth, stencil or packed depth/stencil. +class RenderbufferStorage : public RenderbufferInterface +{ +public: + RenderbufferStorage(); + + virtual ~RenderbufferStorage() = 0; + + virtual egl::Image *getRenderTarget() = 0; + virtual egl::Image *createSharedImage() = 0; + virtual bool isShared() const = 0; + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getFormat() const; + virtual sw::Format getInternalFormat() const; + virtual GLsizei getSamples() const; + +protected: + GLsizei mWidth; + GLsizei mHeight; + GLenum format; + sw::Format internalFormat; + GLsizei mSamples; +}; + +// Renderbuffer implements the GL renderbuffer object. +// It's only a proxy for a RenderbufferInterface instance; the internal object +// can change whenever glRenderbufferStorage is called. +class Renderbuffer : public gl::NamedObject +{ +public: + Renderbuffer(GLuint name, RenderbufferInterface *storage); + + virtual ~Renderbuffer(); + + // These functions from Object are overloaded here because + // Textures need to maintain their own count of references to them via + // Renderbuffers/RenderbufferTextures. These functions invoke those + // reference counting functions on the RenderbufferInterface. + virtual void addRef(); + virtual void release(); + + egl::Image *getRenderTarget(); + virtual egl::Image *createSharedImage(); + virtual bool isShared() const; + + GLsizei getWidth() const; + GLsizei getHeight() const; + GLenum getFormat() const; + sw::Format getInternalFormat() const; + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; + GLsizei getSamples() const; + + void setStorage(RenderbufferStorage *newStorage); + +private: + RenderbufferInterface *mInstance; +}; + +class Colorbuffer : public RenderbufferStorage +{ +public: + explicit Colorbuffer(egl::Image *renderTarget); + Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples); + + virtual ~Colorbuffer(); + + virtual egl::Image *getRenderTarget(); + virtual egl::Image *createSharedImage(); + virtual bool isShared() const; + +private: + egl::Image *mRenderTarget; +}; + +class DepthStencilbuffer : public RenderbufferStorage +{ +public: + explicit DepthStencilbuffer(egl::Image *depthStencil); + DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples); + + ~DepthStencilbuffer(); + + virtual egl::Image *getRenderTarget(); + virtual egl::Image *createSharedImage(); + virtual bool isShared() const; + +protected: + egl::Image *mDepthStencil; +}; + +class Depthbuffer : public DepthStencilbuffer +{ +public: + explicit Depthbuffer(egl::Image *depthStencil); + Depthbuffer(GLsizei width, GLsizei height, GLsizei samples); + + virtual ~Depthbuffer(); +}; + +class Stencilbuffer : public DepthStencilbuffer +{ +public: + explicit Stencilbuffer(egl::Image *depthStencil); + Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples); + + virtual ~Stencilbuffer(); +}; +} + +#endif // LIBGLES_CM_RENDERBUFFER_H_
diff --git a/src/OpenGL/libGLES_CM/ResourceManager.cpp b/src/OpenGL/libGLES_CM/ResourceManager.cpp index 54d71b9..7f0936c 100644 --- a/src/OpenGL/libGLES_CM/ResourceManager.cpp +++ b/src/OpenGL/libGLES_CM/ResourceManager.cpp
@@ -1,13 +1,16 @@ -// SwiftShader Software Renderer +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright(c) 2005-2012 TransGaming Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // ResourceManager.cpp: Implements the ResourceManager class, which tracks and // retrieves objects which may be shared by multiple Contexts. @@ -22,138 +25,138 @@ { ResourceManager::ResourceManager() { - mRefCount = 1; + mRefCount = 1; } ResourceManager::~ResourceManager() { - while(!mBufferNameSpace.empty()) - { - deleteBuffer(mBufferNameSpace.firstName()); - } + while(!mBufferNameSpace.empty()) + { + deleteBuffer(mBufferNameSpace.firstName()); + } - while(!mRenderbufferNameSpace.empty()) - { - deleteRenderbuffer(mRenderbufferNameSpace.firstName()); - } + while(!mRenderbufferNameSpace.empty()) + { + deleteRenderbuffer(mRenderbufferNameSpace.firstName()); + } - while(!mTextureNameSpace.empty()) - { - deleteTexture(mTextureNameSpace.firstName()); - } + while(!mTextureNameSpace.empty()) + { + deleteTexture(mTextureNameSpace.firstName()); + } } void ResourceManager::addRef() { - mRefCount++; + mRefCount++; } void ResourceManager::release() { - if(--mRefCount == 0) - { - delete this; - } + if(--mRefCount == 0) + { + delete this; + } } // Returns an unused buffer name GLuint ResourceManager::createBuffer() { - return mBufferNameSpace.allocate(); + return mBufferNameSpace.allocate(); } // Returns an unused texture name GLuint ResourceManager::createTexture() { - return mTextureNameSpace.allocate(); + return mTextureNameSpace.allocate(); } // Returns an unused renderbuffer name GLuint ResourceManager::createRenderbuffer() { - return mRenderbufferNameSpace.allocate(); + return mRenderbufferNameSpace.allocate(); } void ResourceManager::deleteBuffer(GLuint buffer) { - Buffer *bufferObject = mBufferNameSpace.remove(buffer); + Buffer *bufferObject = mBufferNameSpace.remove(buffer); - if(bufferObject) - { + if(bufferObject) + { bufferObject->release(); - } + } } void ResourceManager::deleteTexture(GLuint texture) { - Texture *textureObject = mTextureNameSpace.remove(texture); + Texture *textureObject = mTextureNameSpace.remove(texture); - if(textureObject) - { + if(textureObject) + { textureObject->release(); - } + } } void ResourceManager::deleteRenderbuffer(GLuint renderbuffer) { - Renderbuffer *renderbufferObject = mRenderbufferNameSpace.remove(renderbuffer); + Renderbuffer *renderbufferObject = mRenderbufferNameSpace.remove(renderbuffer); - if(renderbufferObject) - { + if(renderbufferObject) + { renderbufferObject->release(); - } + } } Buffer *ResourceManager::getBuffer(unsigned int handle) { - return mBufferNameSpace.find(handle); + return mBufferNameSpace.find(handle); } Texture *ResourceManager::getTexture(unsigned int handle) { - return mTextureNameSpace.find(handle); + return mTextureNameSpace.find(handle); } Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle) { - return mRenderbufferNameSpace.find(handle); + return mRenderbufferNameSpace.find(handle); } void ResourceManager::checkBufferAllocation(unsigned int buffer) { - if(buffer != 0 && !getBuffer(buffer)) - { - Buffer *bufferObject = new Buffer(buffer); + if(buffer != 0 && !getBuffer(buffer)) + { + Buffer *bufferObject = new Buffer(buffer); bufferObject->addRef(); mBufferNameSpace.insert(buffer, bufferObject); - } + } } void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) { - if(!getTexture(texture) && texture != 0) - { - Texture *textureObject; + if(!getTexture(texture) && texture != 0) + { + Texture *textureObject; - if(type == TEXTURE_2D) - { - textureObject = new Texture2D(texture); - } - else if(type == TEXTURE_EXTERNAL) - { - textureObject = new TextureExternal(texture); - } - else - { - UNREACHABLE(type); - return; - } + if(type == TEXTURE_2D) + { + textureObject = new Texture2D(texture); + } + else if(type == TEXTURE_EXTERNAL) + { + textureObject = new TextureExternal(texture); + } + else + { + UNREACHABLE(type); + return; + } textureObject->addRef(); mTextureNameSpace.insert(texture, textureObject); - } + } } void ResourceManager::checkRenderbufferAllocation(GLuint handle)
diff --git a/src/OpenGL/libGLES_CM/ResourceManager.h b/src/OpenGL/libGLES_CM/ResourceManager.h index 22d719f..7520580 100644 --- a/src/OpenGL/libGLES_CM/ResourceManager.h +++ b/src/OpenGL/libGLES_CM/ResourceManager.h
@@ -1,75 +1,78 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// ResourceManager.h : Defines the ResourceManager class, which tracks objects -// shared by multiple GL contexts. - -#ifndef LIBGLES_CM_RESOURCEMANAGER_H_ -#define LIBGLES_CM_RESOURCEMANAGER_H_ - -#include "common/NameSpace.hpp" - -#include <GLES/gl.h> - -#include <map> - -namespace es1 -{ -class Buffer; -class Texture; -class Renderbuffer; - -enum TextureType -{ - TEXTURE_2D, - TEXTURE_CUBE, - TEXTURE_EXTERNAL, - - TEXTURE_TYPE_COUNT, - TEXTURE_UNKNOWN -}; - -class ResourceManager -{ -public: - ResourceManager(); - ~ResourceManager(); - - void addRef(); - void release(); - - GLuint createBuffer(); - GLuint createTexture(); - GLuint createRenderbuffer(); - - void deleteBuffer(GLuint buffer); - void deleteTexture(GLuint texture); - void deleteRenderbuffer(GLuint renderbuffer); - - Buffer *getBuffer(GLuint handle); - Texture *getTexture(GLuint handle); - Renderbuffer *getRenderbuffer(GLuint handle); - - void checkBufferAllocation(unsigned int buffer); - void checkTextureAllocation(GLuint texture, TextureType type); - void checkRenderbufferAllocation(GLuint handle); - -private: - std::size_t mRefCount; - - gl::NameSpace<Buffer> mBufferNameSpace; - gl::NameSpace<Texture> mTextureNameSpace; - gl::NameSpace<Renderbuffer> mRenderbufferNameSpace; -}; - -} - -#endif // LIBGLES_CM_RESOURCEMANAGER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ResourceManager.h : Defines the ResourceManager class, which tracks objects +// shared by multiple GL contexts. + +#ifndef LIBGLES_CM_RESOURCEMANAGER_H_ +#define LIBGLES_CM_RESOURCEMANAGER_H_ + +#include "common/NameSpace.hpp" + +#include <GLES/gl.h> + +#include <map> + +namespace es1 +{ +class Buffer; +class Texture; +class Renderbuffer; + +enum TextureType +{ + TEXTURE_2D, + TEXTURE_CUBE, + TEXTURE_EXTERNAL, + + TEXTURE_TYPE_COUNT, + TEXTURE_UNKNOWN +}; + +class ResourceManager +{ +public: + ResourceManager(); + ~ResourceManager(); + + void addRef(); + void release(); + + GLuint createBuffer(); + GLuint createTexture(); + GLuint createRenderbuffer(); + + void deleteBuffer(GLuint buffer); + void deleteTexture(GLuint texture); + void deleteRenderbuffer(GLuint renderbuffer); + + Buffer *getBuffer(GLuint handle); + Texture *getTexture(GLuint handle); + Renderbuffer *getRenderbuffer(GLuint handle); + + void checkBufferAllocation(unsigned int buffer); + void checkTextureAllocation(GLuint texture, TextureType type); + void checkRenderbufferAllocation(GLuint handle); + +private: + std::size_t mRefCount; + + gl::NameSpace<Buffer> mBufferNameSpace; + gl::NameSpace<Texture> mTextureNameSpace; + gl::NameSpace<Renderbuffer> mRenderbufferNameSpace; +}; + +} + +#endif // LIBGLES_CM_RESOURCEMANAGER_H_
diff --git a/src/OpenGL/libGLES_CM/Texture.cpp b/src/OpenGL/libGLES_CM/Texture.cpp index 3729d9b..b8817a0 100644 --- a/src/OpenGL/libGLES_CM/Texture.cpp +++ b/src/OpenGL/libGLES_CM/Texture.cpp
@@ -1,860 +1,863 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// Texture.cpp: Implements the Texture class and its derived classes -// Texture2D and TextureCubeMap. Implements GL texture objects and related -// functionality. [OpenGL ES 2.0.24] section 3.7 page 63. - -#include "Texture.h" - -#include "main.h" -#include "mathutil.h" -#include "Framebuffer.h" -#include "Device.hpp" -#include "libEGL/Display.h" -#include "libEGL/Surface.h" -#include "common/debug.h" - -#include <algorithm> - -namespace es1 -{ - -Texture::Texture(GLuint name) : egl::Texture(name) -{ - mMinFilter = GL_NEAREST_MIPMAP_LINEAR; - mMagFilter = GL_LINEAR; - mWrapS = GL_REPEAT; - mWrapT = GL_REPEAT; - mMaxAnisotropy = 1.0f; - generateMipmap = GL_FALSE; - cropRectU = 0; - cropRectV = 0; - cropRectW = 0; - cropRectH = 0; - - resource = new sw::Resource(0); -} - -Texture::~Texture() -{ - resource->destruct(); -} - -sw::Resource *Texture::getResource() const -{ - return resource; -} - -// Returns true on successful filter state update (valid enum parameter) -bool Texture::setMinFilter(GLenum filter) -{ - switch(filter) - { - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - if(getTarget() == GL_TEXTURE_EXTERNAL_OES) - { - return false; - } - // Fall through - case GL_NEAREST: - case GL_LINEAR: - mMinFilter = filter; - return true; - default: - return false; - } -} - -// Returns true on successful filter state update (valid enum parameter) -bool Texture::setMagFilter(GLenum filter) -{ - switch(filter) - { - case GL_NEAREST: - case GL_LINEAR: - mMagFilter = filter; - return true; - default: - return false; - } -} - -// Returns true on successful wrap state update (valid enum parameter) -bool Texture::setWrapS(GLenum wrap) -{ - switch(wrap) - { - case GL_REPEAT: - case GL_MIRRORED_REPEAT_OES: - if(getTarget() == GL_TEXTURE_EXTERNAL_OES) - { - return false; - } - // Fall through - case GL_CLAMP_TO_EDGE: - mWrapS = wrap; - return true; - default: - return false; - } -} - -// Returns true on successful wrap state update (valid enum parameter) -bool Texture::setWrapT(GLenum wrap) -{ - switch(wrap) - { - case GL_REPEAT: - case GL_MIRRORED_REPEAT_OES: - if(getTarget() == GL_TEXTURE_EXTERNAL_OES) - { - return false; - } - // Fall through - case GL_CLAMP_TO_EDGE: - mWrapT = wrap; - return true; - default: - return false; - } -} - -// Returns true on successful max anisotropy update (valid anisotropy value) -bool Texture::setMaxAnisotropy(float textureMaxAnisotropy) -{ - textureMaxAnisotropy = std::min(textureMaxAnisotropy, MAX_TEXTURE_MAX_ANISOTROPY); - - if(textureMaxAnisotropy < 1.0f) - { - return false; - } - - if(mMaxAnisotropy != textureMaxAnisotropy) - { - mMaxAnisotropy = textureMaxAnisotropy; - } - - return true; -} - -void Texture::setGenerateMipmap(GLboolean enable) -{ - generateMipmap = enable; -} - -void Texture::setCropRect(GLint u, GLint v, GLint w, GLint h) -{ - cropRectU = u; - cropRectV = v; - cropRectW = w; - cropRectH = h; -} - -GLenum Texture::getMinFilter() const -{ - return mMinFilter; -} - -GLenum Texture::getMagFilter() const -{ - return mMagFilter; -} - -GLenum Texture::getWrapS() const -{ - return mWrapS; -} - -GLenum Texture::getWrapT() const -{ - return mWrapT; -} - -GLfloat Texture::getMaxAnisotropy() const -{ - return mMaxAnisotropy; -} - -GLboolean Texture::getGenerateMipmap() const -{ - return generateMipmap; -} - -GLint Texture::getCropRectU() const -{ - return cropRectU; -} - -GLint Texture::getCropRectV() const -{ - return cropRectV; -} - -GLint Texture::getCropRectW() const -{ - return cropRectW; -} - -GLint Texture::getCropRectH() const -{ - return cropRectH; -} - -egl::Image *Texture::createSharedImage(GLenum target, unsigned int level) -{ - egl::Image *image = getRenderTarget(target, level); // Increments reference count - - if(image) - { - image->markShared(); - } - - return image; -} - -void Texture::setImage(GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image) -{ - if(pixels && image) - { - egl::Image::UnpackInfo unpackInfo; - unpackInfo.alignment = unpackAlignment; - image->loadImageData(0, 0, 0, image->getWidth(), image->getHeight(), 1, format, type, unpackInfo, pixels); - } -} - -void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, egl::Image *image) -{ - if(pixels && image) - { - image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), 1, imageSize, pixels); - } -} - -void Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image) -{ - if(!image) - { - return error(GL_INVALID_OPERATION); - } - - if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight()) - { - return error(GL_INVALID_VALUE); - } - - if(IsCompressed(image->getFormat())) - { - return error(GL_INVALID_OPERATION); - } - - if(format != image->getFormat()) - { - return error(GL_INVALID_OPERATION); - } - - if(pixels) - { - egl::Image::UnpackInfo unpackInfo; - unpackInfo.alignment = unpackAlignment; - image->loadImageData(xoffset, yoffset, 0, width, height, 1, format, type, unpackInfo, pixels); - } -} - -void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, egl::Image *image) -{ - if(!image) - { - return error(GL_INVALID_OPERATION); - } - - if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight()) - { - return error(GL_INVALID_VALUE); - } - - if(format != image->getFormat()) - { - return error(GL_INVALID_OPERATION); - } - - if(pixels) - { - image->loadCompressedData(xoffset, yoffset, 0, width, height, 1, imageSize, pixels); - } -} - -bool Texture::copy(egl::Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, egl::Image *dest) -{ - Device *device = getDevice(); - - sw::SliceRect destRect(xoffset, yoffset, xoffset + (sourceRect.x1 - sourceRect.x0), yoffset + (sourceRect.y1 - sourceRect.y0), 0); - sw::SliceRect sourceSliceRect(sourceRect); - bool success = device->stretchRect(source, &sourceSliceRect, dest, &destRect, false); - - if(!success) - { - return error(GL_OUT_OF_MEMORY, false); - } - - return true; -} - -bool Texture::isMipmapFiltered() const -{ - switch(mMinFilter) - { - case GL_NEAREST: - case GL_LINEAR: - return false; - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return true; - default: UNREACHABLE(mMinFilter); - } - - return false; -} - -Texture2D::Texture2D(GLuint name) : Texture(name) -{ - for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - image[i] = nullptr; - } - - mSurface = nullptr; - - mColorbufferProxy = nullptr; - mProxyRefs = 0; -} - -Texture2D::~Texture2D() -{ - resource->lock(sw::DESTRUCT); - - for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - if(image[i]) - { - image[i]->unbind(this); - image[i] = nullptr; - } - } - - resource->unlock(); - - if(mSurface) - { - mSurface->setBoundTexture(nullptr); - mSurface = nullptr; - } - - mColorbufferProxy = nullptr; -} - -// We need to maintain a count of references to renderbuffers acting as -// proxies for this texture, so that we do not attempt to use a pointer -// to a renderbuffer proxy which has been deleted. -void Texture2D::addProxyRef(const Renderbuffer *proxy) -{ - mProxyRefs++; -} - -void Texture2D::releaseProxy(const Renderbuffer *proxy) -{ - if(mProxyRefs > 0) - { - mProxyRefs--; - } - - if(mProxyRefs == 0) - { - mColorbufferProxy = nullptr; - } -} - -void Texture2D::sweep() -{ - int imageCount = 0; - - for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - if(image[i] && image[i]->isChildOf(this)) - { - if(!image[i]->hasSingleReference()) - { - return; - } - - imageCount++; - } - } - - if(imageCount == referenceCount) - { - destroy(); - } -} - -GLenum Texture2D::getTarget() const -{ - return GL_TEXTURE_2D; -} - -GLsizei Texture2D::getWidth(GLenum target, GLint level) const -{ - ASSERT(target == GL_TEXTURE_2D); - return image[level] ? image[level]->getWidth() : 0; -} - -GLsizei Texture2D::getHeight(GLenum target, GLint level) const -{ - ASSERT(target == GL_TEXTURE_2D); - return image[level] ? image[level]->getHeight() : 0; -} - -GLenum Texture2D::getFormat(GLenum target, GLint level) const -{ - ASSERT(target == GL_TEXTURE_2D); - return image[level] ? image[level]->getFormat() : GL_NONE; -} - -GLenum Texture2D::getType(GLenum target, GLint level) const -{ - ASSERT(target == GL_TEXTURE_2D); - return image[level] ? image[level]->getType() : GL_NONE; -} - -sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const -{ - ASSERT(target == GL_TEXTURE_2D); - return image[level] ? image[level]->getInternalFormat() : sw::FORMAT_NULL; -} - -int Texture2D::getLevelCount() const -{ - ASSERT(isSamplerComplete()); - int levels = 0; - - while(levels < IMPLEMENTATION_MAX_TEXTURE_LEVELS && image[levels]) - { - levels++; - } - - return levels; -} - -void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) -{ - if(image[level]) - { - image[level]->release(); - } - - image[level] = new egl::Image(this, width, height, format, type); - - if(!image[level]) - { - return error(GL_OUT_OF_MEMORY); - } - - Texture::setImage(format, type, unpackAlignment, pixels, image[level]); -} - -void Texture2D::bindTexImage(egl::Surface *surface) -{ - GLenum format; - - switch(surface->getInternalFormat()) - { - case sw::FORMAT_A8R8G8B8: - format = GL_BGRA_EXT; - break; - case sw::FORMAT_A8B8G8R8: - format = GL_RGBA; - break; - case sw::FORMAT_X8B8G8R8: - case sw::FORMAT_X8R8G8B8: - format = GL_RGB; - break; - default: - UNIMPLEMENTED(); - return; - } - - for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - if(image[level]) - { - image[level]->release(); - image[level] = nullptr; - } - } - - image[0] = surface->getRenderTarget(); - - mSurface = surface; - mSurface->setBoundTexture(this); -} - -void Texture2D::releaseTexImage() -{ - for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - if(image[level]) - { - image[level]->release(); - image[level] = nullptr; - } - } -} - -void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) -{ - if(image[level]) - { - image[level]->release(); - } - - image[level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE); - - if(!image[level]) - { - return error(GL_OUT_OF_MEMORY); - } - - Texture::setCompressedImage(imageSize, pixels, image[level]); -} - -void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) -{ - Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, image[level]); -} - -void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) -{ - Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, image[level]); -} - -void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - egl::Image *renderTarget = source->getRenderTarget(); - - if(!renderTarget) - { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); - } - - if(image[level]) - { - image[level]->release(); - } - - image[level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE); - - if(!image[level]) - { - return error(GL_OUT_OF_MEMORY); - } - - if(width != 0 && height != 0) - { - sw::Rect sourceRect = {x, y, x + width, y + height}; - sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); - - copy(renderTarget, sourceRect, format, 0, 0, image[level]); - } - - renderTarget->release(); -} - -void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - if(!image[level]) - { - return error(GL_INVALID_OPERATION); - } - - if(xoffset + width > image[level]->getWidth() || yoffset + height > image[level]->getHeight()) - { - return error(GL_INVALID_VALUE); - } - - egl::Image *renderTarget = source->getRenderTarget(); - - if(!renderTarget) - { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); - } - - sw::Rect sourceRect = {x, y, x + width, y + height}; - sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); - - copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, image[level]); - - renderTarget->release(); -} - -void Texture2D::setImage(egl::Image *sharedImage) -{ - sharedImage->addRef(); - - if(image[0]) - { - image[0]->release(); - } - - image[0] = sharedImage; -} - -// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. -bool Texture2D::isSamplerComplete() const -{ - if(!image[0]) - { - return false; - } - - GLsizei width = image[0]->getWidth(); - GLsizei height = image[0]->getHeight(); - - if(width <= 0 || height <= 0) - { - return false; - } - - if(isMipmapFiltered()) - { - if(!generateMipmap && !isMipmapComplete()) - { - return false; - } - } - - return true; -} - -// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. -bool Texture2D::isMipmapComplete() const -{ - GLsizei width = image[0]->getWidth(); - GLsizei height = image[0]->getHeight(); - - int q = log2(std::max(width, height)); - - for(int level = 1; level <= q; level++) - { - if(!image[level]) - { - return false; - } - - if(image[level]->getFormat() != image[0]->getFormat()) - { - return false; - } - - if(image[level]->getType() != image[0]->getType()) - { - return false; - } - - if(image[level]->getWidth() != std::max(1, width >> level)) - { - return false; - } - - if(image[level]->getHeight() != std::max(1, height >> level)) - { - return false; - } - } - - return true; -} - -bool Texture2D::isCompressed(GLenum target, GLint level) const -{ - return IsCompressed(getFormat(target, level)); -} - -bool Texture2D::isDepth(GLenum target, GLint level) const -{ - return IsDepthTexture(getFormat(target, level)); -} - -void Texture2D::generateMipmaps() -{ - if(!image[0]) - { - return; // FIXME: error? - } - - unsigned int q = log2(std::max(image[0]->getWidth(), image[0]->getHeight())); - - for(unsigned int i = 1; i <= q; i++) - { - if(image[i]) - { - image[i]->release(); - } - - image[i] = new egl::Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat(), image[0]->getType()); - - if(!image[i]) - { - return error(GL_OUT_OF_MEMORY); - } - - getDevice()->stretchRect(image[i - 1], 0, image[i], 0, true); - } -} - -void Texture2D::autoGenerateMipmaps() -{ - if(generateMipmap && image[0]->hasDirtyMipmaps()) - { - generateMipmaps(); - image[0]->cleanMipmaps(); - } -} - -egl::Image *Texture2D::getImage(unsigned int level) -{ - return image[level]; -} - -Renderbuffer *Texture2D::getRenderbuffer(GLenum target) -{ - if(target != GL_TEXTURE_2D) - { - return error(GL_INVALID_OPERATION, (Renderbuffer*)nullptr); - } - - if(!mColorbufferProxy) - { - mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this)); - } - - return mColorbufferProxy; -} - -egl::Image *Texture2D::getRenderTarget(GLenum target, unsigned int level) -{ - ASSERT(target == GL_TEXTURE_2D); - ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if(image[level]) - { - image[level]->addRef(); - } - - return image[level]; -} - -bool Texture2D::isShared(GLenum target, unsigned int level) const -{ - ASSERT(target == GL_TEXTURE_2D); - ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if(mSurface) // Bound to an EGLSurface - { - return true; - } - - if(!image[level]) - { - return false; - } - - return image[level]->isShared(); -} - -TextureExternal::TextureExternal(GLuint name) : Texture2D(name) -{ - mMinFilter = GL_LINEAR; - mMagFilter = GL_LINEAR; - mWrapS = GL_CLAMP_TO_EDGE; - mWrapT = GL_CLAMP_TO_EDGE; -} - -TextureExternal::~TextureExternal() -{ -} - -GLenum TextureExternal::getTarget() const -{ - return GL_TEXTURE_EXTERNAL_OES; -} - -} - -egl::Image *createBackBuffer(int width, int height, const egl::Config *config) -{ - if(config) - { - return new egl::Image(width, height, config->mRenderTargetFormat, config->mSamples, false); - } - - return nullptr; -} - -egl::Image *createDepthStencil(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) -{ - if(height > sw::OUTLINE_RESOLUTION) - { - ERR("Invalid parameters: %dx%d", width, height); - return 0; - } - - bool lockable = true; - - switch(format) - { -// case sw::FORMAT_D15S1: - case sw::FORMAT_D24S8: - case sw::FORMAT_D24X8: -// case sw::FORMAT_D24X4S4: - case sw::FORMAT_D24FS8: - case sw::FORMAT_D32: - case sw::FORMAT_D16: - lockable = false; - break; -// case sw::FORMAT_S8_LOCKABLE: -// case sw::FORMAT_D16_LOCKABLE: - case sw::FORMAT_D32F_LOCKABLE: -// case sw::FORMAT_D32_LOCKABLE: - case sw::FORMAT_DF24S8: - case sw::FORMAT_DF16S8: - lockable = true; - break; - default: - UNREACHABLE(format); - } - - egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); - - if(!surface) - { - ERR("Out of memory"); - return nullptr; - } - - return surface; -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Texture.cpp: Implements the Texture class and its derived classes +// Texture2D and TextureCubeMap. Implements GL texture objects and related +// functionality. [OpenGL ES 2.0.24] section 3.7 page 63. + +#include "Texture.h" + +#include "main.h" +#include "mathutil.h" +#include "Framebuffer.h" +#include "Device.hpp" +#include "libEGL/Display.h" +#include "libEGL/Surface.h" +#include "common/debug.h" + +#include <algorithm> + +namespace es1 +{ + +Texture::Texture(GLuint name) : egl::Texture(name) +{ + mMinFilter = GL_NEAREST_MIPMAP_LINEAR; + mMagFilter = GL_LINEAR; + mWrapS = GL_REPEAT; + mWrapT = GL_REPEAT; + mMaxAnisotropy = 1.0f; + generateMipmap = GL_FALSE; + cropRectU = 0; + cropRectV = 0; + cropRectW = 0; + cropRectH = 0; + + resource = new sw::Resource(0); +} + +Texture::~Texture() +{ + resource->destruct(); +} + +sw::Resource *Texture::getResource() const +{ + return resource; +} + +// Returns true on successful filter state update (valid enum parameter) +bool Texture::setMinFilter(GLenum filter) +{ + switch(filter) + { + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + if(getTarget() == GL_TEXTURE_EXTERNAL_OES) + { + return false; + } + // Fall through + case GL_NEAREST: + case GL_LINEAR: + mMinFilter = filter; + return true; + default: + return false; + } +} + +// Returns true on successful filter state update (valid enum parameter) +bool Texture::setMagFilter(GLenum filter) +{ + switch(filter) + { + case GL_NEAREST: + case GL_LINEAR: + mMagFilter = filter; + return true; + default: + return false; + } +} + +// Returns true on successful wrap state update (valid enum parameter) +bool Texture::setWrapS(GLenum wrap) +{ + switch(wrap) + { + case GL_REPEAT: + case GL_MIRRORED_REPEAT_OES: + if(getTarget() == GL_TEXTURE_EXTERNAL_OES) + { + return false; + } + // Fall through + case GL_CLAMP_TO_EDGE: + mWrapS = wrap; + return true; + default: + return false; + } +} + +// Returns true on successful wrap state update (valid enum parameter) +bool Texture::setWrapT(GLenum wrap) +{ + switch(wrap) + { + case GL_REPEAT: + case GL_MIRRORED_REPEAT_OES: + if(getTarget() == GL_TEXTURE_EXTERNAL_OES) + { + return false; + } + // Fall through + case GL_CLAMP_TO_EDGE: + mWrapT = wrap; + return true; + default: + return false; + } +} + +// Returns true on successful max anisotropy update (valid anisotropy value) +bool Texture::setMaxAnisotropy(float textureMaxAnisotropy) +{ + textureMaxAnisotropy = std::min(textureMaxAnisotropy, MAX_TEXTURE_MAX_ANISOTROPY); + + if(textureMaxAnisotropy < 1.0f) + { + return false; + } + + if(mMaxAnisotropy != textureMaxAnisotropy) + { + mMaxAnisotropy = textureMaxAnisotropy; + } + + return true; +} + +void Texture::setGenerateMipmap(GLboolean enable) +{ + generateMipmap = enable; +} + +void Texture::setCropRect(GLint u, GLint v, GLint w, GLint h) +{ + cropRectU = u; + cropRectV = v; + cropRectW = w; + cropRectH = h; +} + +GLenum Texture::getMinFilter() const +{ + return mMinFilter; +} + +GLenum Texture::getMagFilter() const +{ + return mMagFilter; +} + +GLenum Texture::getWrapS() const +{ + return mWrapS; +} + +GLenum Texture::getWrapT() const +{ + return mWrapT; +} + +GLfloat Texture::getMaxAnisotropy() const +{ + return mMaxAnisotropy; +} + +GLboolean Texture::getGenerateMipmap() const +{ + return generateMipmap; +} + +GLint Texture::getCropRectU() const +{ + return cropRectU; +} + +GLint Texture::getCropRectV() const +{ + return cropRectV; +} + +GLint Texture::getCropRectW() const +{ + return cropRectW; +} + +GLint Texture::getCropRectH() const +{ + return cropRectH; +} + +egl::Image *Texture::createSharedImage(GLenum target, unsigned int level) +{ + egl::Image *image = getRenderTarget(target, level); // Increments reference count + + if(image) + { + image->markShared(); + } + + return image; +} + +void Texture::setImage(GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image) +{ + if(pixels && image) + { + egl::Image::UnpackInfo unpackInfo; + unpackInfo.alignment = unpackAlignment; + image->loadImageData(0, 0, 0, image->getWidth(), image->getHeight(), 1, format, type, unpackInfo, pixels); + } +} + +void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, egl::Image *image) +{ + if(pixels && image) + { + image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), 1, imageSize, pixels); + } +} + +void Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image) +{ + if(!image) + { + return error(GL_INVALID_OPERATION); + } + + if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight()) + { + return error(GL_INVALID_VALUE); + } + + if(IsCompressed(image->getFormat())) + { + return error(GL_INVALID_OPERATION); + } + + if(format != image->getFormat()) + { + return error(GL_INVALID_OPERATION); + } + + if(pixels) + { + egl::Image::UnpackInfo unpackInfo; + unpackInfo.alignment = unpackAlignment; + image->loadImageData(xoffset, yoffset, 0, width, height, 1, format, type, unpackInfo, pixels); + } +} + +void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, egl::Image *image) +{ + if(!image) + { + return error(GL_INVALID_OPERATION); + } + + if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight()) + { + return error(GL_INVALID_VALUE); + } + + if(format != image->getFormat()) + { + return error(GL_INVALID_OPERATION); + } + + if(pixels) + { + image->loadCompressedData(xoffset, yoffset, 0, width, height, 1, imageSize, pixels); + } +} + +bool Texture::copy(egl::Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, egl::Image *dest) +{ + Device *device = getDevice(); + + sw::SliceRect destRect(xoffset, yoffset, xoffset + (sourceRect.x1 - sourceRect.x0), yoffset + (sourceRect.y1 - sourceRect.y0), 0); + sw::SliceRect sourceSliceRect(sourceRect); + bool success = device->stretchRect(source, &sourceSliceRect, dest, &destRect, false); + + if(!success) + { + return error(GL_OUT_OF_MEMORY, false); + } + + return true; +} + +bool Texture::isMipmapFiltered() const +{ + switch(mMinFilter) + { + case GL_NEAREST: + case GL_LINEAR: + return false; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return true; + default: UNREACHABLE(mMinFilter); + } + + return false; +} + +Texture2D::Texture2D(GLuint name) : Texture(name) +{ + for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + image[i] = nullptr; + } + + mSurface = nullptr; + + mColorbufferProxy = nullptr; + mProxyRefs = 0; +} + +Texture2D::~Texture2D() +{ + resource->lock(sw::DESTRUCT); + + for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if(image[i]) + { + image[i]->unbind(this); + image[i] = nullptr; + } + } + + resource->unlock(); + + if(mSurface) + { + mSurface->setBoundTexture(nullptr); + mSurface = nullptr; + } + + mColorbufferProxy = nullptr; +} + +// We need to maintain a count of references to renderbuffers acting as +// proxies for this texture, so that we do not attempt to use a pointer +// to a renderbuffer proxy which has been deleted. +void Texture2D::addProxyRef(const Renderbuffer *proxy) +{ + mProxyRefs++; +} + +void Texture2D::releaseProxy(const Renderbuffer *proxy) +{ + if(mProxyRefs > 0) + { + mProxyRefs--; + } + + if(mProxyRefs == 0) + { + mColorbufferProxy = nullptr; + } +} + +void Texture2D::sweep() +{ + int imageCount = 0; + + for(int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if(image[i] && image[i]->isChildOf(this)) + { + if(!image[i]->hasSingleReference()) + { + return; + } + + imageCount++; + } + } + + if(imageCount == referenceCount) + { + destroy(); + } +} + +GLenum Texture2D::getTarget() const +{ + return GL_TEXTURE_2D; +} + +GLsizei Texture2D::getWidth(GLenum target, GLint level) const +{ + ASSERT(target == GL_TEXTURE_2D); + return image[level] ? image[level]->getWidth() : 0; +} + +GLsizei Texture2D::getHeight(GLenum target, GLint level) const +{ + ASSERT(target == GL_TEXTURE_2D); + return image[level] ? image[level]->getHeight() : 0; +} + +GLenum Texture2D::getFormat(GLenum target, GLint level) const +{ + ASSERT(target == GL_TEXTURE_2D); + return image[level] ? image[level]->getFormat() : GL_NONE; +} + +GLenum Texture2D::getType(GLenum target, GLint level) const +{ + ASSERT(target == GL_TEXTURE_2D); + return image[level] ? image[level]->getType() : GL_NONE; +} + +sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const +{ + ASSERT(target == GL_TEXTURE_2D); + return image[level] ? image[level]->getInternalFormat() : sw::FORMAT_NULL; +} + +int Texture2D::getLevelCount() const +{ + ASSERT(isSamplerComplete()); + int levels = 0; + + while(levels < IMPLEMENTATION_MAX_TEXTURE_LEVELS && image[levels]) + { + levels++; + } + + return levels; +} + +void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + if(image[level]) + { + image[level]->release(); + } + + image[level] = new egl::Image(this, width, height, format, type); + + if(!image[level]) + { + return error(GL_OUT_OF_MEMORY); + } + + Texture::setImage(format, type, unpackAlignment, pixels, image[level]); +} + +void Texture2D::bindTexImage(egl::Surface *surface) +{ + GLenum format; + + switch(surface->getInternalFormat()) + { + case sw::FORMAT_A8R8G8B8: + format = GL_BGRA_EXT; + break; + case sw::FORMAT_A8B8G8R8: + format = GL_RGBA; + break; + case sw::FORMAT_X8B8G8R8: + case sw::FORMAT_X8R8G8B8: + format = GL_RGB; + break; + default: + UNIMPLEMENTED(); + return; + } + + for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + if(image[level]) + { + image[level]->release(); + image[level] = nullptr; + } + } + + image[0] = surface->getRenderTarget(); + + mSurface = surface; + mSurface->setBoundTexture(this); +} + +void Texture2D::releaseTexImage() +{ + for(int level = 0; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + if(image[level]) + { + image[level]->release(); + image[level] = nullptr; + } + } +} + +void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +{ + if(image[level]) + { + image[level]->release(); + } + + image[level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE); + + if(!image[level]) + { + return error(GL_OUT_OF_MEMORY); + } + + Texture::setCompressedImage(imageSize, pixels, image[level]); +} + +void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +{ + Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, image[level]); +} + +void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +{ + Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, image[level]); +} + +void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + egl::Image *renderTarget = source->getRenderTarget(); + + if(!renderTarget) + { + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); + } + + if(image[level]) + { + image[level]->release(); + } + + image[level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE); + + if(!image[level]) + { + return error(GL_OUT_OF_MEMORY); + } + + if(width != 0 && height != 0) + { + sw::Rect sourceRect = {x, y, x + width, y + height}; + sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); + + copy(renderTarget, sourceRect, format, 0, 0, image[level]); + } + + renderTarget->release(); +} + +void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + if(!image[level]) + { + return error(GL_INVALID_OPERATION); + } + + if(xoffset + width > image[level]->getWidth() || yoffset + height > image[level]->getHeight()) + { + return error(GL_INVALID_VALUE); + } + + egl::Image *renderTarget = source->getRenderTarget(); + + if(!renderTarget) + { + ERR("Failed to retrieve the render target."); + return error(GL_OUT_OF_MEMORY); + } + + sw::Rect sourceRect = {x, y, x + width, y + height}; + sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); + + copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, image[level]); + + renderTarget->release(); +} + +void Texture2D::setImage(egl::Image *sharedImage) +{ + sharedImage->addRef(); + + if(image[0]) + { + image[0]->release(); + } + + image[0] = sharedImage; +} + +// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. +bool Texture2D::isSamplerComplete() const +{ + if(!image[0]) + { + return false; + } + + GLsizei width = image[0]->getWidth(); + GLsizei height = image[0]->getHeight(); + + if(width <= 0 || height <= 0) + { + return false; + } + + if(isMipmapFiltered()) + { + if(!generateMipmap && !isMipmapComplete()) + { + return false; + } + } + + return true; +} + +// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool Texture2D::isMipmapComplete() const +{ + GLsizei width = image[0]->getWidth(); + GLsizei height = image[0]->getHeight(); + + int q = log2(std::max(width, height)); + + for(int level = 1; level <= q; level++) + { + if(!image[level]) + { + return false; + } + + if(image[level]->getFormat() != image[0]->getFormat()) + { + return false; + } + + if(image[level]->getType() != image[0]->getType()) + { + return false; + } + + if(image[level]->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if(image[level]->getHeight() != std::max(1, height >> level)) + { + return false; + } + } + + return true; +} + +bool Texture2D::isCompressed(GLenum target, GLint level) const +{ + return IsCompressed(getFormat(target, level)); +} + +bool Texture2D::isDepth(GLenum target, GLint level) const +{ + return IsDepthTexture(getFormat(target, level)); +} + +void Texture2D::generateMipmaps() +{ + if(!image[0]) + { + return; // FIXME: error? + } + + unsigned int q = log2(std::max(image[0]->getWidth(), image[0]->getHeight())); + + for(unsigned int i = 1; i <= q; i++) + { + if(image[i]) + { + image[i]->release(); + } + + image[i] = new egl::Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat(), image[0]->getType()); + + if(!image[i]) + { + return error(GL_OUT_OF_MEMORY); + } + + getDevice()->stretchRect(image[i - 1], 0, image[i], 0, true); + } +} + +void Texture2D::autoGenerateMipmaps() +{ + if(generateMipmap && image[0]->hasDirtyMipmaps()) + { + generateMipmaps(); + image[0]->cleanMipmaps(); + } +} + +egl::Image *Texture2D::getImage(unsigned int level) +{ + return image[level]; +} + +Renderbuffer *Texture2D::getRenderbuffer(GLenum target) +{ + if(target != GL_TEXTURE_2D) + { + return error(GL_INVALID_OPERATION, (Renderbuffer*)nullptr); + } + + if(!mColorbufferProxy) + { + mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this)); + } + + return mColorbufferProxy; +} + +egl::Image *Texture2D::getRenderTarget(GLenum target, unsigned int level) +{ + ASSERT(target == GL_TEXTURE_2D); + ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if(image[level]) + { + image[level]->addRef(); + } + + return image[level]; +} + +bool Texture2D::isShared(GLenum target, unsigned int level) const +{ + ASSERT(target == GL_TEXTURE_2D); + ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if(mSurface) // Bound to an EGLSurface + { + return true; + } + + if(!image[level]) + { + return false; + } + + return image[level]->isShared(); +} + +TextureExternal::TextureExternal(GLuint name) : Texture2D(name) +{ + mMinFilter = GL_LINEAR; + mMagFilter = GL_LINEAR; + mWrapS = GL_CLAMP_TO_EDGE; + mWrapT = GL_CLAMP_TO_EDGE; +} + +TextureExternal::~TextureExternal() +{ +} + +GLenum TextureExternal::getTarget() const +{ + return GL_TEXTURE_EXTERNAL_OES; +} + +} + +egl::Image *createBackBuffer(int width, int height, const egl::Config *config) +{ + if(config) + { + return new egl::Image(width, height, config->mRenderTargetFormat, config->mSamples, false); + } + + return nullptr; +} + +egl::Image *createDepthStencil(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard) +{ + if(height > sw::OUTLINE_RESOLUTION) + { + ERR("Invalid parameters: %dx%d", width, height); + return 0; + } + + bool lockable = true; + + switch(format) + { +// case sw::FORMAT_D15S1: + case sw::FORMAT_D24S8: + case sw::FORMAT_D24X8: +// case sw::FORMAT_D24X4S4: + case sw::FORMAT_D24FS8: + case sw::FORMAT_D32: + case sw::FORMAT_D16: + lockable = false; + break; +// case sw::FORMAT_S8_LOCKABLE: +// case sw::FORMAT_D16_LOCKABLE: + case sw::FORMAT_D32F_LOCKABLE: +// case sw::FORMAT_D32_LOCKABLE: + case sw::FORMAT_DF24S8: + case sw::FORMAT_DF16S8: + lockable = true; + break; + default: + UNREACHABLE(format); + } + + egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable); + + if(!surface) + { + ERR("Out of memory"); + return nullptr; + } + + return surface; +}
diff --git a/src/OpenGL/libGLES_CM/Texture.h b/src/OpenGL/libGLES_CM/Texture.h index 6d53711..f28022d 100644 --- a/src/OpenGL/libGLES_CM/Texture.h +++ b/src/OpenGL/libGLES_CM/Texture.h
@@ -1,197 +1,200 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// Texture.h: Defines the abstract Texture class and its concrete derived -// classes Texture2D and TextureCubeMap. Implements GL texture objects and -// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63. - -#ifndef LIBGLES_CM_TEXTURE_H_ -#define LIBGLES_CM_TEXTURE_H_ - -#include "Renderbuffer.h" -#include "common/Object.hpp" -#include "utilities.h" -#include "libEGL/Texture.hpp" -#include "common/debug.h" - -#include <GLES/gl.h> - -#include <vector> - -namespace egl -{ -class Surface; -class Config; -} - -namespace es1 -{ -class Framebuffer; - -enum -{ - IMPLEMENTATION_MAX_TEXTURE_LEVELS = sw::MIPMAP_LEVELS, - IMPLEMENTATION_MAX_TEXTURE_SIZE = 1 << (IMPLEMENTATION_MAX_TEXTURE_LEVELS - 1), - IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 1 << (IMPLEMENTATION_MAX_TEXTURE_LEVELS - 1), - IMPLEMENTATION_MAX_RENDERBUFFER_SIZE = sw::OUTLINE_RESOLUTION, -}; - -class Texture : public egl::Texture -{ -public: - explicit Texture(GLuint name); - - sw::Resource *getResource() const; - - virtual void addProxyRef(const Renderbuffer *proxy) = 0; - virtual void releaseProxy(const Renderbuffer *proxy) = 0; - - virtual GLenum getTarget() const = 0; - - bool setMinFilter(GLenum filter); - bool setMagFilter(GLenum filter); - bool setWrapS(GLenum wrap); - bool setWrapT(GLenum wrap); - bool setMaxAnisotropy(GLfloat textureMaxAnisotropy); - void setGenerateMipmap(GLboolean enable); - void setCropRect(GLint u, GLint v, GLint w, GLint h); - - GLenum getMinFilter() const; - GLenum getMagFilter() const; - GLenum getWrapS() const; - GLenum getWrapT() const; - GLfloat getMaxAnisotropy() const; - GLboolean getGenerateMipmap() const; - GLint getCropRectU() const; - GLint getCropRectV() const; - GLint getCropRectW() const; - GLint getCropRectH() const; - - virtual GLsizei getWidth(GLenum target, GLint level) const = 0; - virtual GLsizei getHeight(GLenum target, GLint level) const = 0; - virtual GLenum getFormat(GLenum target, GLint level) const = 0; - virtual GLenum getType(GLenum target, GLint level) const = 0; - virtual sw::Format getInternalFormat(GLenum target, GLint level) const = 0; - virtual int getLevelCount() const = 0; - - virtual bool isSamplerComplete() const = 0; - virtual bool isCompressed(GLenum target, GLint level) const = 0; - virtual bool isDepth(GLenum target, GLint level) const = 0; - - virtual Renderbuffer *getRenderbuffer(GLenum target) = 0; - virtual egl::Image *getRenderTarget(GLenum target, unsigned int level) = 0; - virtual egl::Image *createSharedImage(GLenum target, unsigned int level); - virtual bool isShared(GLenum target, unsigned int level) const = 0; - - virtual void generateMipmaps() = 0; - virtual void autoGenerateMipmaps() = 0; - - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0; - -protected: - virtual ~Texture(); - - void setImage(GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image); - void subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image); - void setCompressedImage(GLsizei imageSize, const void *pixels, egl::Image *image); - void subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, egl::Image *image); - - bool copy(egl::Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, egl::Image *dest); - - bool isMipmapFiltered() const; - - GLenum mMinFilter; - GLenum mMagFilter; - GLenum mWrapS; - GLenum mWrapT; - GLfloat mMaxAnisotropy; - GLboolean generateMipmap; - GLint cropRectU; - GLint cropRectV; - GLint cropRectW; - GLint cropRectH; - - sw::Resource *resource; -}; - -class Texture2D : public Texture -{ -public: - explicit Texture2D(GLuint name); - - void addProxyRef(const Renderbuffer *proxy) override; - void releaseProxy(const Renderbuffer *proxy) override; - void sweep() override; - - virtual GLenum getTarget() const; - - virtual GLsizei getWidth(GLenum target, GLint level) const; - virtual GLsizei getHeight(GLenum target, GLint level) const; - virtual GLenum getFormat(GLenum target, GLint level) const; - virtual GLenum getType(GLenum target, GLint level) const; - virtual sw::Format getInternalFormat(GLenum target, GLint level) const; - virtual int getLevelCount() const; - - void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); - void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - - void setImage(egl::Image *image); - - virtual bool isSamplerComplete() const; - virtual bool isCompressed(GLenum target, GLint level) const; - virtual bool isDepth(GLenum target, GLint level) const; - virtual void bindTexImage(egl::Surface *surface); - virtual void releaseTexImage(); - - virtual void generateMipmaps(); - virtual void autoGenerateMipmaps(); - - virtual Renderbuffer *getRenderbuffer(GLenum target); - virtual egl::Image *getRenderTarget(GLenum target, unsigned int level); - virtual bool isShared(GLenum target, unsigned int level) const; - - egl::Image *getImage(unsigned int level); - -protected: - virtual ~Texture2D(); - - bool isMipmapComplete() const; - - egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - egl::Surface *mSurface; - - // A specific internal reference count is kept for colorbuffer proxy references, - // because, as the renderbuffer acting as proxy will maintain a binding pointer - // back to this texture, there would be a circular reference if we used a binding - // pointer here. This reference count will cause the pointer to be set to NULL if - // the count drops to zero, but will not cause deletion of the Renderbuffer. - Renderbuffer *mColorbufferProxy; - unsigned int mProxyRefs; -}; - -class TextureExternal : public Texture2D -{ -public: - explicit TextureExternal(GLuint name); - - virtual GLenum getTarget() const; - -protected: - virtual ~TextureExternal(); -}; -} - -#endif // LIBGLES_CM_TEXTURE_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Texture.h: Defines the abstract Texture class and its concrete derived +// classes Texture2D and TextureCubeMap. Implements GL texture objects and +// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63. + +#ifndef LIBGLES_CM_TEXTURE_H_ +#define LIBGLES_CM_TEXTURE_H_ + +#include "Renderbuffer.h" +#include "common/Object.hpp" +#include "utilities.h" +#include "libEGL/Texture.hpp" +#include "common/debug.h" + +#include <GLES/gl.h> + +#include <vector> + +namespace egl +{ +class Surface; +class Config; +} + +namespace es1 +{ +class Framebuffer; + +enum +{ + IMPLEMENTATION_MAX_TEXTURE_LEVELS = sw::MIPMAP_LEVELS, + IMPLEMENTATION_MAX_TEXTURE_SIZE = 1 << (IMPLEMENTATION_MAX_TEXTURE_LEVELS - 1), + IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 1 << (IMPLEMENTATION_MAX_TEXTURE_LEVELS - 1), + IMPLEMENTATION_MAX_RENDERBUFFER_SIZE = sw::OUTLINE_RESOLUTION, +}; + +class Texture : public egl::Texture +{ +public: + explicit Texture(GLuint name); + + sw::Resource *getResource() const; + + virtual void addProxyRef(const Renderbuffer *proxy) = 0; + virtual void releaseProxy(const Renderbuffer *proxy) = 0; + + virtual GLenum getTarget() const = 0; + + bool setMinFilter(GLenum filter); + bool setMagFilter(GLenum filter); + bool setWrapS(GLenum wrap); + bool setWrapT(GLenum wrap); + bool setMaxAnisotropy(GLfloat textureMaxAnisotropy); + void setGenerateMipmap(GLboolean enable); + void setCropRect(GLint u, GLint v, GLint w, GLint h); + + GLenum getMinFilter() const; + GLenum getMagFilter() const; + GLenum getWrapS() const; + GLenum getWrapT() const; + GLfloat getMaxAnisotropy() const; + GLboolean getGenerateMipmap() const; + GLint getCropRectU() const; + GLint getCropRectV() const; + GLint getCropRectW() const; + GLint getCropRectH() const; + + virtual GLsizei getWidth(GLenum target, GLint level) const = 0; + virtual GLsizei getHeight(GLenum target, GLint level) const = 0; + virtual GLenum getFormat(GLenum target, GLint level) const = 0; + virtual GLenum getType(GLenum target, GLint level) const = 0; + virtual sw::Format getInternalFormat(GLenum target, GLint level) const = 0; + virtual int getLevelCount() const = 0; + + virtual bool isSamplerComplete() const = 0; + virtual bool isCompressed(GLenum target, GLint level) const = 0; + virtual bool isDepth(GLenum target, GLint level) const = 0; + + virtual Renderbuffer *getRenderbuffer(GLenum target) = 0; + virtual egl::Image *getRenderTarget(GLenum target, unsigned int level) = 0; + virtual egl::Image *createSharedImage(GLenum target, unsigned int level); + virtual bool isShared(GLenum target, unsigned int level) const = 0; + + virtual void generateMipmaps() = 0; + virtual void autoGenerateMipmaps() = 0; + + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0; + +protected: + virtual ~Texture(); + + void setImage(GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image); + void subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, egl::Image *image); + void setCompressedImage(GLsizei imageSize, const void *pixels, egl::Image *image); + void subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, egl::Image *image); + + bool copy(egl::Image *source, const sw::Rect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, egl::Image *dest); + + bool isMipmapFiltered() const; + + GLenum mMinFilter; + GLenum mMagFilter; + GLenum mWrapS; + GLenum mWrapT; + GLfloat mMaxAnisotropy; + GLboolean generateMipmap; + GLint cropRectU; + GLint cropRectV; + GLint cropRectW; + GLint cropRectH; + + sw::Resource *resource; +}; + +class Texture2D : public Texture +{ +public: + explicit Texture2D(GLuint name); + + void addProxyRef(const Renderbuffer *proxy) override; + void releaseProxy(const Renderbuffer *proxy) override; + void sweep() override; + + virtual GLenum getTarget() const; + + virtual GLsizei getWidth(GLenum target, GLint level) const; + virtual GLsizei getHeight(GLenum target, GLint level) const; + virtual GLenum getFormat(GLenum target, GLint level) const; + virtual GLenum getType(GLenum target, GLint level) const; + virtual sw::Format getInternalFormat(GLenum target, GLint level) const; + virtual int getLevelCount() const; + + void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); + void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); + void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + + void setImage(egl::Image *image); + + virtual bool isSamplerComplete() const; + virtual bool isCompressed(GLenum target, GLint level) const; + virtual bool isDepth(GLenum target, GLint level) const; + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual void generateMipmaps(); + virtual void autoGenerateMipmaps(); + + virtual Renderbuffer *getRenderbuffer(GLenum target); + virtual egl::Image *getRenderTarget(GLenum target, unsigned int level); + virtual bool isShared(GLenum target, unsigned int level) const; + + egl::Image *getImage(unsigned int level); + +protected: + virtual ~Texture2D(); + + bool isMipmapComplete() const; + + egl::Image *image[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + egl::Surface *mSurface; + + // A specific internal reference count is kept for colorbuffer proxy references, + // because, as the renderbuffer acting as proxy will maintain a binding pointer + // back to this texture, there would be a circular reference if we used a binding + // pointer here. This reference count will cause the pointer to be set to null if + // the count drops to zero, but will not cause deletion of the Renderbuffer. + Renderbuffer *mColorbufferProxy; + unsigned int mProxyRefs; +}; + +class TextureExternal : public Texture2D +{ +public: + explicit TextureExternal(GLuint name); + + virtual GLenum getTarget() const; + +protected: + virtual ~TextureExternal(); +}; +} + +#endif // LIBGLES_CM_TEXTURE_H_
diff --git a/src/OpenGL/libGLES_CM/VertexDataManager.cpp b/src/OpenGL/libGLES_CM/VertexDataManager.cpp index 99e8a7f..20eb6b9 100644 --- a/src/OpenGL/libGLES_CM/VertexDataManager.cpp +++ b/src/OpenGL/libGLES_CM/VertexDataManager.cpp
@@ -1,328 +1,331 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// VertexDataManager.h: Defines the VertexDataManager, a class that -// runs the Buffer translation process. - -#include "VertexDataManager.h" - -#include "Buffer.h" -#include "IndexDataManager.h" -#include "common/debug.h" - -#include <algorithm> - -namespace -{ - enum {INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024}; -} - -namespace es1 -{ - -VertexDataManager::VertexDataManager(Context *context) : mContext(context) -{ - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mDirtyCurrentValue[i] = true; - mCurrentValueBuffer[i] = NULL; - } - - mStreamingBuffer = new StreamingVertexBuffer(INITIAL_STREAM_BUFFER_SIZE); - - if(!mStreamingBuffer) - { - ERR("Failed to allocate the streaming vertex buffer."); - } -} - -VertexDataManager::~VertexDataManager() -{ - delete mStreamingBuffer; - - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - delete mCurrentValueBuffer[i]; - } -} - -unsigned int VertexDataManager::writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute) -{ - Buffer *buffer = attribute.mBoundBuffer; - - int inputStride = attribute.stride(); - int elementSize = attribute.typeSize(); - unsigned int streamOffset = 0; - - char *output = nullptr; - - if(vertexBuffer) - { - output = (char*)vertexBuffer->map(attribute, attribute.typeSize() * count, &streamOffset); - } - - if(!output) - { - ERR("Failed to map vertex buffer."); - return ~0u; - } - - const char *input = nullptr; - - if(buffer) - { - int offset = attribute.mOffset; - - input = static_cast<const char*>(buffer->data()) + offset; - } - else - { - input = static_cast<const char*>(attribute.mPointer); - } - - input += inputStride * start; - - if(inputStride == elementSize) - { - memcpy(output, input, count * inputStride); - } - else - { - for(int i = 0; i < count; i++) - { - memcpy(output, input, elementSize); - output += elementSize; - input += inputStride; - } - } - - vertexBuffer->unmap(); - - return streamOffset; -} - -GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated) -{ - if(!mStreamingBuffer) - { - return GL_OUT_OF_MEMORY; - } - - const VertexAttributeArray &attribs = mContext->getVertexAttributes(); - - // Determine the required storage size per used buffer - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if(attribs[i].mArrayEnabled) - { - if(!attribs[i].mBoundBuffer) - { - mStreamingBuffer->addRequiredSpace(attribs[i].typeSize() * count); - } - } - } - - mStreamingBuffer->reserveRequiredSpace(); - - // Perform the vertex data translations - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if(attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer; - - if(!buffer && attribs[i].mPointer == NULL) - { - // This is an application error that would normally result in a crash, but we catch it and return an error - ERR("An enabled vertex array has no buffer and no pointer."); - return GL_INVALID_OPERATION; - } - - sw::Resource *staticBuffer = buffer ? buffer->getResource() : NULL; - - if(staticBuffer) - { - translated[i].vertexBuffer = staticBuffer; - translated[i].offset = start * attribs[i].stride() + attribs[i].mOffset; - translated[i].stride = attribs[i].stride(); - } - else - { - unsigned int streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]); - - if(streamOffset == ~0u) - { - return GL_OUT_OF_MEMORY; - } - - translated[i].vertexBuffer = mStreamingBuffer->getResource(); - translated[i].offset = streamOffset; - translated[i].stride = attribs[i].typeSize(); - } - - switch(attribs[i].mType) - { - case GL_BYTE: translated[i].type = sw::STREAMTYPE_SBYTE; break; - case GL_UNSIGNED_BYTE: translated[i].type = sw::STREAMTYPE_BYTE; break; - case GL_SHORT: translated[i].type = sw::STREAMTYPE_SHORT; break; - case GL_UNSIGNED_SHORT: translated[i].type = sw::STREAMTYPE_USHORT; break; - case GL_INT: translated[i].type = sw::STREAMTYPE_INT; break; - case GL_UNSIGNED_INT: translated[i].type = sw::STREAMTYPE_UINT; break; - case GL_FIXED: translated[i].type = sw::STREAMTYPE_FIXED; break; - case GL_FLOAT: translated[i].type = sw::STREAMTYPE_FLOAT; break; - default: UNREACHABLE(attribs[i].mType); translated[i].type = sw::STREAMTYPE_FLOAT; break; - } - - translated[i].count = attribs[i].mSize; - translated[i].normalized = attribs[i].mNormalized; - } - else - { - if(mDirtyCurrentValue[i]) - { - delete mCurrentValueBuffer[i]; - mCurrentValueBuffer[i] = new ConstantVertexBuffer(attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]); - mDirtyCurrentValue[i] = false; - } - - translated[i].vertexBuffer = mCurrentValueBuffer[i]->getResource(); - - translated[i].type = sw::STREAMTYPE_FLOAT; - translated[i].count = 4; - translated[i].stride = 0; - translated[i].offset = 0; - } - } - - return GL_NO_ERROR; -} - -VertexBuffer::VertexBuffer(unsigned int size) : mVertexBuffer(NULL) -{ - if(size > 0) - { - mVertexBuffer = new sw::Resource(size + 1024); - - if(!mVertexBuffer) - { - ERR("Out of memory allocating a vertex buffer of size %u.", size); - } - } -} - -VertexBuffer::~VertexBuffer() -{ - if(mVertexBuffer) - { - mVertexBuffer->destruct(); - } -} - -void VertexBuffer::unmap() -{ - if(mVertexBuffer) - { - mVertexBuffer->unlock(); - } -} - -sw::Resource *VertexBuffer::getResource() const -{ - return mVertexBuffer; -} - -ConstantVertexBuffer::ConstantVertexBuffer(float x, float y, float z, float w) : VertexBuffer(4 * sizeof(float)) -{ - if(mVertexBuffer) - { - float *vector = (float*)mVertexBuffer->lock(sw::PUBLIC); - - vector[0] = x; - vector[1] = y; - vector[2] = z; - vector[3] = w; - - mVertexBuffer->unlock(); - } -} - -ConstantVertexBuffer::~ConstantVertexBuffer() -{ -} - -StreamingVertexBuffer::StreamingVertexBuffer(unsigned int size) : VertexBuffer(size) -{ - mBufferSize = size; - mWritePosition = 0; - mRequiredSpace = 0; -} - -StreamingVertexBuffer::~StreamingVertexBuffer() -{ -} - -void StreamingVertexBuffer::addRequiredSpace(unsigned int requiredSpace) -{ - mRequiredSpace += requiredSpace; -} - -void *StreamingVertexBuffer::map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *offset) -{ - void *mapPtr = NULL; - - if(mVertexBuffer) - { - // We can use a private lock because we never overwrite the content - mapPtr = (char*)mVertexBuffer->lock(sw::PRIVATE) + mWritePosition; - - *offset = mWritePosition; - mWritePosition += requiredSpace; - } - - return mapPtr; -} - -void StreamingVertexBuffer::reserveRequiredSpace() -{ - if(mRequiredSpace > mBufferSize) - { - if(mVertexBuffer) - { - mVertexBuffer->destruct(); - mVertexBuffer = 0; - } - - mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2); // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations. - - mVertexBuffer = new sw::Resource(mBufferSize); - - if(!mVertexBuffer) - { - ERR("Out of memory allocating a vertex buffer of size %u.", mBufferSize); - } - - mWritePosition = 0; - } - else if(mWritePosition + mRequiredSpace > mBufferSize) // Recycle - { - if(mVertexBuffer) - { - mVertexBuffer->destruct(); - mVertexBuffer = new sw::Resource(mBufferSize); - } - - mWritePosition = 0; - } - - mRequiredSpace = 0; -} - -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#include "VertexDataManager.h" + +#include "Buffer.h" +#include "IndexDataManager.h" +#include "common/debug.h" + +#include <algorithm> + +namespace +{ + enum {INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024}; +} + +namespace es1 +{ + +VertexDataManager::VertexDataManager(Context *context) : mContext(context) +{ + for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + mDirtyCurrentValue[i] = true; + mCurrentValueBuffer[i] = nullptr; + } + + mStreamingBuffer = new StreamingVertexBuffer(INITIAL_STREAM_BUFFER_SIZE); + + if(!mStreamingBuffer) + { + ERR("Failed to allocate the streaming vertex buffer."); + } +} + +VertexDataManager::~VertexDataManager() +{ + delete mStreamingBuffer; + + for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + delete mCurrentValueBuffer[i]; + } +} + +unsigned int VertexDataManager::writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute) +{ + Buffer *buffer = attribute.mBoundBuffer; + + int inputStride = attribute.stride(); + int elementSize = attribute.typeSize(); + unsigned int streamOffset = 0; + + char *output = nullptr; + + if(vertexBuffer) + { + output = (char*)vertexBuffer->map(attribute, attribute.typeSize() * count, &streamOffset); + } + + if(!output) + { + ERR("Failed to map vertex buffer."); + return ~0u; + } + + const char *input = nullptr; + + if(buffer) + { + int offset = attribute.mOffset; + + input = static_cast<const char*>(buffer->data()) + offset; + } + else + { + input = static_cast<const char*>(attribute.mPointer); + } + + input += inputStride * start; + + if(inputStride == elementSize) + { + memcpy(output, input, count * inputStride); + } + else + { + for(int i = 0; i < count; i++) + { + memcpy(output, input, elementSize); + output += elementSize; + input += inputStride; + } + } + + vertexBuffer->unmap(); + + return streamOffset; +} + +GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated) +{ + if(!mStreamingBuffer) + { + return GL_OUT_OF_MEMORY; + } + + const VertexAttributeArray &attribs = mContext->getVertexAttributes(); + + // Determine the required storage size per used buffer + for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if(attribs[i].mArrayEnabled) + { + if(!attribs[i].mBoundBuffer) + { + mStreamingBuffer->addRequiredSpace(attribs[i].typeSize() * count); + } + } + } + + mStreamingBuffer->reserveRequiredSpace(); + + // Perform the vertex data translations + for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + if(attribs[i].mArrayEnabled) + { + Buffer *buffer = attribs[i].mBoundBuffer; + + if(!buffer && attribs[i].mPointer == nullptr) + { + // This is an application error that would normally result in a crash, but we catch it and return an error + ERR("An enabled vertex array has no buffer and no pointer."); + return GL_INVALID_OPERATION; + } + + sw::Resource *staticBuffer = buffer ? buffer->getResource() : nullptr; + + if(staticBuffer) + { + translated[i].vertexBuffer = staticBuffer; + translated[i].offset = start * attribs[i].stride() + attribs[i].mOffset; + translated[i].stride = attribs[i].stride(); + } + else + { + unsigned int streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]); + + if(streamOffset == ~0u) + { + return GL_OUT_OF_MEMORY; + } + + translated[i].vertexBuffer = mStreamingBuffer->getResource(); + translated[i].offset = streamOffset; + translated[i].stride = attribs[i].typeSize(); + } + + switch(attribs[i].mType) + { + case GL_BYTE: translated[i].type = sw::STREAMTYPE_SBYTE; break; + case GL_UNSIGNED_BYTE: translated[i].type = sw::STREAMTYPE_BYTE; break; + case GL_SHORT: translated[i].type = sw::STREAMTYPE_SHORT; break; + case GL_UNSIGNED_SHORT: translated[i].type = sw::STREAMTYPE_USHORT; break; + case GL_INT: translated[i].type = sw::STREAMTYPE_INT; break; + case GL_UNSIGNED_INT: translated[i].type = sw::STREAMTYPE_UINT; break; + case GL_FIXED: translated[i].type = sw::STREAMTYPE_FIXED; break; + case GL_FLOAT: translated[i].type = sw::STREAMTYPE_FLOAT; break; + default: UNREACHABLE(attribs[i].mType); translated[i].type = sw::STREAMTYPE_FLOAT; break; + } + + translated[i].count = attribs[i].mSize; + translated[i].normalized = attribs[i].mNormalized; + } + else + { + if(mDirtyCurrentValue[i]) + { + delete mCurrentValueBuffer[i]; + mCurrentValueBuffer[i] = new ConstantVertexBuffer(attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]); + mDirtyCurrentValue[i] = false; + } + + translated[i].vertexBuffer = mCurrentValueBuffer[i]->getResource(); + + translated[i].type = sw::STREAMTYPE_FLOAT; + translated[i].count = 4; + translated[i].stride = 0; + translated[i].offset = 0; + } + } + + return GL_NO_ERROR; +} + +VertexBuffer::VertexBuffer(unsigned int size) : mVertexBuffer(nullptr) +{ + if(size > 0) + { + mVertexBuffer = new sw::Resource(size + 1024); + + if(!mVertexBuffer) + { + ERR("Out of memory allocating a vertex buffer of size %u.", size); + } + } +} + +VertexBuffer::~VertexBuffer() +{ + if(mVertexBuffer) + { + mVertexBuffer->destruct(); + } +} + +void VertexBuffer::unmap() +{ + if(mVertexBuffer) + { + mVertexBuffer->unlock(); + } +} + +sw::Resource *VertexBuffer::getResource() const +{ + return mVertexBuffer; +} + +ConstantVertexBuffer::ConstantVertexBuffer(float x, float y, float z, float w) : VertexBuffer(4 * sizeof(float)) +{ + if(mVertexBuffer) + { + float *vector = (float*)mVertexBuffer->lock(sw::PUBLIC); + + vector[0] = x; + vector[1] = y; + vector[2] = z; + vector[3] = w; + + mVertexBuffer->unlock(); + } +} + +ConstantVertexBuffer::~ConstantVertexBuffer() +{ +} + +StreamingVertexBuffer::StreamingVertexBuffer(unsigned int size) : VertexBuffer(size) +{ + mBufferSize = size; + mWritePosition = 0; + mRequiredSpace = 0; +} + +StreamingVertexBuffer::~StreamingVertexBuffer() +{ +} + +void StreamingVertexBuffer::addRequiredSpace(unsigned int requiredSpace) +{ + mRequiredSpace += requiredSpace; +} + +void *StreamingVertexBuffer::map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *offset) +{ + void *mapPtr = nullptr; + + if(mVertexBuffer) + { + // We can use a private lock because we never overwrite the content + mapPtr = (char*)mVertexBuffer->lock(sw::PRIVATE) + mWritePosition; + + *offset = mWritePosition; + mWritePosition += requiredSpace; + } + + return mapPtr; +} + +void StreamingVertexBuffer::reserveRequiredSpace() +{ + if(mRequiredSpace > mBufferSize) + { + if(mVertexBuffer) + { + mVertexBuffer->destruct(); + mVertexBuffer = 0; + } + + mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2); // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations. + + mVertexBuffer = new sw::Resource(mBufferSize); + + if(!mVertexBuffer) + { + ERR("Out of memory allocating a vertex buffer of size %u.", mBufferSize); + } + + mWritePosition = 0; + } + else if(mWritePosition + mRequiredSpace > mBufferSize) // Recycle + { + if(mVertexBuffer) + { + mVertexBuffer->destruct(); + mVertexBuffer = new sw::Resource(mBufferSize); + } + + mWritePosition = 0; + } + + mRequiredSpace = 0; +} + +}
diff --git a/src/OpenGL/libGLES_CM/VertexDataManager.h b/src/OpenGL/libGLES_CM/VertexDataManager.h index cce6865..55ab849 100644 --- a/src/OpenGL/libGLES_CM/VertexDataManager.h +++ b/src/OpenGL/libGLES_CM/VertexDataManager.h
@@ -1,98 +1,101 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2012 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// VertexDataManager.h: Defines the VertexDataManager, a class that -// runs the Buffer translation process. - -#ifndef LIBGLES_CM_VERTEXDATAMANAGER_H_ -#define LIBGLES_CM_VERTEXDATAMANAGER_H_ - -#include "Context.h" -#include "Device.hpp" - -#include <GLES/gl.h> - -namespace es1 -{ - -struct TranslatedAttribute -{ - sw::StreamType type; - int count; - bool normalized; - - unsigned int offset; - unsigned int stride; // 0 means not to advance the read pointer at all - - sw::Resource *vertexBuffer; -}; - -class VertexBuffer -{ - public: - VertexBuffer(unsigned int size); - virtual ~VertexBuffer(); - - void unmap(); - - sw::Resource *getResource() const; - - protected: - sw::Resource *mVertexBuffer; -}; - -class ConstantVertexBuffer : public VertexBuffer -{ - public: - ConstantVertexBuffer(float x, float y, float z, float w); - ~ConstantVertexBuffer(); -}; - -class StreamingVertexBuffer : public VertexBuffer -{ - public: - StreamingVertexBuffer(unsigned int size); - ~StreamingVertexBuffer(); - - void *map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *streamOffset); - void reserveRequiredSpace(); - void addRequiredSpace(unsigned int requiredSpace); - - protected: - unsigned int mBufferSize; - unsigned int mWritePosition; - unsigned int mRequiredSpace; -}; - -class VertexDataManager -{ - public: - VertexDataManager(Context *context); - virtual ~VertexDataManager(); - - void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; } - - GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs); - - private: - unsigned int writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute); - - Context *const mContext; - - StreamingVertexBuffer *mStreamingBuffer; - - bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS]; - ConstantVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS]; -}; - -} - -#endif // LIBGLES_CM_VERTEXDATAMANAGER_H_ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#ifndef LIBGLES_CM_VERTEXDATAMANAGER_H_ +#define LIBGLES_CM_VERTEXDATAMANAGER_H_ + +#include "Context.h" +#include "Device.hpp" + +#include <GLES/gl.h> + +namespace es1 +{ + +struct TranslatedAttribute +{ + sw::StreamType type; + int count; + bool normalized; + + unsigned int offset; + unsigned int stride; // 0 means not to advance the read pointer at all + + sw::Resource *vertexBuffer; +}; + +class VertexBuffer +{ +public: + VertexBuffer(unsigned int size); + virtual ~VertexBuffer(); + + void unmap(); + + sw::Resource *getResource() const; + +protected: + sw::Resource *mVertexBuffer; +}; + +class ConstantVertexBuffer : public VertexBuffer +{ +public: + ConstantVertexBuffer(float x, float y, float z, float w); + ~ConstantVertexBuffer(); +}; + +class StreamingVertexBuffer : public VertexBuffer +{ +public: + StreamingVertexBuffer(unsigned int size); + ~StreamingVertexBuffer(); + + void *map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *streamOffset); + void reserveRequiredSpace(); + void addRequiredSpace(unsigned int requiredSpace); + +protected: + unsigned int mBufferSize; + unsigned int mWritePosition; + unsigned int mRequiredSpace; +}; + +class VertexDataManager +{ +public: + VertexDataManager(Context *context); + virtual ~VertexDataManager(); + + void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; } + + GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs); + +private: + unsigned int writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute); + + Context *const mContext; + + StreamingVertexBuffer *mStreamingBuffer; + + bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS]; + ConstantVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS]; +}; + +} + +#endif // LIBGLES_CM_VERTEXDATAMANAGER_H_
diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.cpp b/src/OpenGL/libGLES_CM/libGLES_CM.cpp index 0c9dd62..1f01fb3 100644 --- a/src/OpenGL/libGLES_CM/libGLES_CM.cpp +++ b/src/OpenGL/libGLES_CM/libGLES_CM.cpp
@@ -1,4770 +1,4773 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// -// libGLES_CM.cpp: Implements the exported OpenGL ES 1.1 functions. - -#include "main.h" -#include "mathutil.h" -#include "utilities.h" -#include "Buffer.h" -#include "Context.h" -#include "Framebuffer.h" -#include "Renderbuffer.h" -#include "Texture.h" -#include "common/debug.h" -#include "Common/SharedLibrary.hpp" -#include "Common/Version.h" - -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include <GLES/gl.h> -#include <GLES/glext.h> - -#include <limits> - -namespace es1 -{ - -static bool validImageSize(GLint level, GLsizei width, GLsizei height) -{ - if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0) - { - return false; - } - - return true; -} - -static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, es1::Texture *texture) -{ - if(!texture) - { - return error(GL_INVALID_OPERATION, false); - } - - if(compressed != texture->isCompressed(target, level)) - { - return error(GL_INVALID_OPERATION, false); - } - - if(format != GL_NONE_OES && format != texture->getFormat(target, level)) - { - return error(GL_INVALID_OPERATION, false); - } - - if(compressed) - { - if((width % 4 != 0 && width != texture->getWidth(target, 0)) || - (height % 4 != 0 && height != texture->getHeight(target, 0))) - { - return error(GL_INVALID_OPERATION, false); - } - } - - if(xoffset + width > texture->getWidth(target, level) || - yoffset + height > texture->getHeight(target, level)) - { - return error(GL_INVALID_VALUE, false); - } - - return true; -} - -void ActiveTexture(GLenum texture) -{ - TRACE("(GLenum texture = 0x%X)", texture); - - es1::Context *context = es1::getContext(); - - if(context) - { - if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es1::MAX_TEXTURE_UNITS - 1) - { - return error(GL_INVALID_ENUM); - } - - context->setActiveSampler(texture - GL_TEXTURE0); - } -} - -void AlphaFunc(GLenum func, GLclampf ref) -{ - TRACE("(GLenum func = 0x%X, GLclampf ref = %f)", func, ref); - - switch(func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GEQUAL: - case GL_GREATER: - case GL_NOTEQUAL: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setAlphaFunc(func, clamp01(ref)); - } -} - -void AlphaFuncx(GLenum func, GLclampx ref) -{ - AlphaFunc(func, (float)ref / 0x10000); -} - -void BindBuffer(GLenum target, GLuint buffer) -{ - TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(target) - { - case GL_ARRAY_BUFFER: - context->bindArrayBuffer(buffer); - return; - case GL_ELEMENT_ARRAY_BUFFER: - context->bindElementArrayBuffer(buffer); - return; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void BindFramebuffer(GLenum target, GLuint framebuffer) -{ - TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - - if(target != GL_FRAMEBUFFER_OES) - { - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->bindFramebuffer(framebuffer); - } -} - -void BindFramebufferOES(GLenum target, GLuint framebuffer) -{ - TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - - if(target != GL_FRAMEBUFFER_OES) - { - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->bindFramebuffer(framebuffer); - } -} - -void BindRenderbufferOES(GLenum target, GLuint renderbuffer) -{ - TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); - - if(target != GL_RENDERBUFFER_OES) - { - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - if(renderbuffer != 0 && !context->getRenderbuffer(renderbuffer)) - { - // [OpenGL ES 2.0.25] Section 4.4.3 page 112 - // [OpenGL ES 3.0.2] Section 4.4.2 page 201 - // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of - // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated. - return error(GL_INVALID_OPERATION); - } - - context->bindRenderbuffer(renderbuffer); - } -} - -void BindTexture(GLenum target, GLuint texture) -{ - TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Texture *textureObject = context->getTexture(texture); - - if(textureObject && textureObject->getTarget() != target && texture != 0) - { - return error(GL_INVALID_OPERATION); - } - - switch(target) - { - case GL_TEXTURE_2D: - context->bindTexture2D(texture); - return; - case GL_TEXTURE_EXTERNAL_OES: - context->bindTextureExternal(texture); - return; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha); - -void BlendEquationOES(GLenum mode) -{ - BlendEquationSeparateOES(mode, mode); -} - -void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha) -{ - TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); - - switch(modeRGB) - { - case GL_FUNC_ADD_OES: - case GL_FUNC_SUBTRACT_OES: - case GL_FUNC_REVERSE_SUBTRACT_OES: - case GL_MIN_EXT: - case GL_MAX_EXT: - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(modeAlpha) - { - case GL_FUNC_ADD_OES: - case GL_FUNC_SUBTRACT_OES: - case GL_FUNC_REVERSE_SUBTRACT_OES: - case GL_MIN_EXT: - case GL_MAX_EXT: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setBlendEquation(modeRGB, modeAlpha); - } -} - -void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); - -void BlendFunc(GLenum sfactor, GLenum dfactor) -{ - BlendFuncSeparateOES(sfactor, dfactor, sfactor, dfactor); -} - -void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) -{ - TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", - srcRGB, dstRGB, srcAlpha, dstAlpha); - - switch(srcRGB) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(dstRGB) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(srcAlpha) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(dstAlpha) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); - } -} - -void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) -{ - size = static_cast<GLint>(size); // Work around issues with some 64-bit applications - - TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)", - target, size, data, usage); - - if(size < 0) - { - return error(GL_INVALID_VALUE); - } - - switch(usage) - { - case GL_STATIC_DRAW: - case GL_DYNAMIC_DRAW: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Buffer *buffer; - - switch(target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: - return error(GL_INVALID_ENUM); - } - - if(!buffer) - { - return error(GL_INVALID_OPERATION); - } - - buffer->bufferData(data, size, usage); - } -} - -void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) -{ - size = static_cast<GLint>(size); // Work around issues with some 64-bit applications - offset = static_cast<GLint>(offset); - - TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)", - target, offset, size, data); - - if(size < 0 || offset < 0) - { - return error(GL_INVALID_VALUE); - } - - if(data == NULL) - { - return; - } - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Buffer *buffer; - - switch(target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: - return error(GL_INVALID_ENUM); - } - - if(!buffer) - { - return error(GL_INVALID_OPERATION); - } - - if((size_t)size + offset > buffer->size()) - { - return error(GL_INVALID_VALUE); - } - - buffer->bufferSubData(data, size, offset); - } -} - -GLenum CheckFramebufferStatusOES(GLenum target) -{ - TRACE("(GLenum target = 0x%X)", target); - - if(target != GL_FRAMEBUFFER_OES) - { - return error(GL_INVALID_ENUM, 0); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Framebuffer *framebuffer = context->getFramebuffer(); - - return framebuffer->completeness(); - } - - return 0; -} - -void Clear(GLbitfield mask) -{ - TRACE("(GLbitfield mask = %X)", mask); - - if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->clear(mask); - } -} - -void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) -{ - TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", - red, green, blue, alpha); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setClearColor(red, green, blue, alpha); - } -} - -void ClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) -{ - ClearColor((float)red / 0x10000, (float)green / 0x10000, (float)blue / 0x10000, (float)alpha / 0x10000); -} - -void ClearDepthf(GLclampf depth) -{ - TRACE("(GLclampf depth = %f)", depth); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setClearDepth(depth); - } -} - -void ClearDepthx(GLclampx depth) -{ - ClearDepthf((float)depth / 0x10000); -} - -void ClearStencil(GLint s) -{ - TRACE("(GLint s = %d)", s); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setClearStencil(s); - } -} - -void ClientActiveTexture(GLenum texture) -{ - TRACE("(GLenum texture = 0x%X)", texture); - - switch(texture) - { - case GL_TEXTURE0: - case GL_TEXTURE1: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->clientActiveTexture(texture); - } -} - -void ClipPlanef(GLenum plane, const GLfloat *equation) -{ - TRACE("(GLenum plane = 0x%X, const GLfloat *equation)", plane); - - int index = plane - GL_CLIP_PLANE0; - - if(index < 0 || index >= MAX_CLIP_PLANES) - { - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setClipPlane(index, equation); - } -} - -void ClipPlanex(GLenum plane, const GLfixed *equation) -{ - GLfloat equationf[4] = - { - (float)equation[0] / 0x10000, - (float)equation[1] / 0x10000, - (float)equation[2] / 0x10000, - (float)equation[3] / 0x10000, - }; - - ClipPlanef(plane, equationf); -} - -void Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) -{ - TRACE("(GLfloat red = %f, GLfloat green = %f, GLfloat blue = %f, GLfloat alpha = %f)", red, green, blue, alpha); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setVertexAttrib(sw::Color0, red, green, blue, alpha); - } -} - -void Color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) -{ - Color4f((float)red / 0xFF, (float)green / 0xFF, (float)blue / 0xFF, (float)alpha / 0xFF); -} - -void Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) -{ - Color4f((float)red / 0x10000, (float)green / 0x10000, (float)blue / 0x10000, (float)alpha / 0x10000); -} - -void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) -{ - TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)", - red, green, blue, alpha); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); - } -} - -void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) -{ - TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " - "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)", - index, size, type, normalized, stride, ptr); - - if(index >= es1::MAX_VERTEX_ATTRIBS) - { - return error(GL_INVALID_VALUE); - } - - if(size < 1 || size > 4) - { - return error(GL_INVALID_VALUE); - } - - switch(type) - { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_FIXED: - case GL_FLOAT: - break; - default: - return error(GL_INVALID_ENUM); - } - - if(stride < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr); - } -} - -void ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer); - - if(size != 4) - { - return error(GL_INVALID_VALUE); - } - - VertexAttribPointer(sw::Color0, size, type, true, stride, pointer); -} - -void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid* data) -{ - TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " - "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)", - target, level, internalformat, width, height, border, imageSize, data); - - if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - return error(GL_INVALID_VALUE); - } - - if(!validImageSize(level, width, height) || imageSize < 0) - { - return error(GL_INVALID_VALUE); - } - - switch(internalformat) - { - case GL_ETC1_RGB8_OES: - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if(!S3TC_SUPPORT) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_DEPTH_COMPONENT16_OES: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH_STENCIL_OES: - case GL_DEPTH24_STENCIL8_OES: - return error(GL_INVALID_OPERATION); - default: - return error(GL_INVALID_ENUM); - } - - if(border != 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(target) - { - case GL_TEXTURE_2D: - if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) || - height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - default: - return error(GL_INVALID_ENUM); - } - - if(imageSize != egl::ComputeCompressedSize(width, height, internalformat)) - { - return error(GL_INVALID_VALUE); - } - - if(target == GL_TEXTURE_2D) - { - es1::Texture2D *texture = context->getTexture2D(); - - if(!texture) - { - return error(GL_INVALID_OPERATION); - } - - texture->setCompressedImage(level, internalformat, width, height, imageSize, data); - } - else UNREACHABLE(target); - } -} - -void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const GLvoid* data) -{ - TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, " - "GLsizei imageSize = %d, const GLvoid* data = %p)", - target, level, xoffset, yoffset, width, height, format, imageSize, data); - - if(!es1::IsTextureTarget(target)) - { - return error(GL_INVALID_ENUM); - } - - if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - return error(GL_INVALID_VALUE); - } - - if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0) - { - return error(GL_INVALID_VALUE); - } - - switch(format) - { - case GL_ETC1_RGB8_OES: - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if(!S3TC_SUPPORT) - { - return error(GL_INVALID_ENUM); - } - break; - default: - return error(GL_INVALID_ENUM); - } - - if(width == 0 || height == 0 || !data) - { - return; - } - - es1::Context *context = es1::getContext(); - - if(context) - { - if(imageSize != egl::ComputeCompressedSize(width, height, format)) - { - return error(GL_INVALID_VALUE); - } - - if(xoffset % 4 != 0 || yoffset % 4 != 0) - { - // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported - return error(GL_INVALID_OPERATION); - } - - if(target == GL_TEXTURE_2D) - { - es1::Texture2D *texture = context->getTexture2D(); - - if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture)) - { - texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); - } - } - else UNREACHABLE(target); - } -} - -void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) -{ - TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " - "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", - target, level, internalformat, x, y, width, height, border); - - if(!validImageSize(level, width, height)) - { - return error(GL_INVALID_VALUE); - } - - if(border != 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(target) - { - case GL_TEXTURE_2D: - if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) || - height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Framebuffer *framebuffer = context->getFramebuffer(); - - if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE_OES) - { - return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES); - } - - if(context->getFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1) - { - return error(GL_INVALID_OPERATION); - } - - es1::Renderbuffer *source = framebuffer->getColorbuffer(); - GLenum colorbufferFormat = source->getFormat(); - - // [OpenGL ES 2.0.24] table 3.9 - switch(internalformat) - { - case GL_ALPHA: - if(colorbufferFormat != GL_ALPHA && - colorbufferFormat != GL_RGBA && - colorbufferFormat != GL_RGBA4_OES && - colorbufferFormat != GL_RGB5_A1_OES && - colorbufferFormat != GL_RGBA8_OES) - { - return error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE: - case GL_RGB: - if(colorbufferFormat != GL_RGB && - colorbufferFormat != GL_RGB565_OES && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA && - colorbufferFormat != GL_RGBA4_OES && - colorbufferFormat != GL_RGB5_A1_OES && - colorbufferFormat != GL_RGBA8_OES) - { - return error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE_ALPHA: - case GL_RGBA: - if(colorbufferFormat != GL_RGBA && - colorbufferFormat != GL_RGBA4_OES && - colorbufferFormat != GL_RGB5_A1_OES && - colorbufferFormat != GL_RGBA8_OES) - { - return error(GL_INVALID_OPERATION); - } - break; - case GL_ETC1_RGB8_OES: - return error(GL_INVALID_OPERATION); - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if(S3TC_SUPPORT) - { - return error(GL_INVALID_OPERATION); - } - else - { - return error(GL_INVALID_ENUM); - } - default: - return error(GL_INVALID_ENUM); - } - - if(target == GL_TEXTURE_2D) - { - es1::Texture2D *texture = context->getTexture2D(); - - if(!texture) - { - return error(GL_INVALID_OPERATION); - } - - texture->copyImage(level, internalformat, x, y, width, height, framebuffer); - } - else UNREACHABLE(target); - } -} - -void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) -{ - TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", - target, level, xoffset, yoffset, x, y, width, height); - - if(!es1::IsTextureTarget(target)) - { - return error(GL_INVALID_ENUM); - } - - if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - return error(GL_INVALID_VALUE); - } - - if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0) - { - return error(GL_INVALID_VALUE); - } - - if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) - { - return error(GL_INVALID_VALUE); - } - - if(width == 0 || height == 0) - { - return; - } - - es1::Context *context = es1::getContext(); - - if(context) - { - - es1::Framebuffer *framebuffer = context->getFramebuffer(); - - if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE_OES) - { - return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES); - } - - es1::Renderbuffer *source = framebuffer->getColorbuffer(); - - if(context->getFramebufferName() != 0 && (!source || source->getSamples() > 1)) - { - return error(GL_INVALID_OPERATION); - } - - es1::Texture *texture = NULL; - - if(target == GL_TEXTURE_2D) - { - texture = context->getTexture2D(); - } - else UNREACHABLE(target); - - if(!validateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE_OES, texture)) - { - return; - } - - texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer); - } -} - -void CullFace(GLenum mode) -{ - TRACE("(GLenum mode = 0x%X)", mode); - - switch(mode) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - { - es1::Context *context = es1::getContext(); - - if(context) - { - context->setCullMode(mode); - } - } - break; - default: - return error(GL_INVALID_ENUM); - } -} - -void DeleteBuffers(GLsizei n, const GLuint* buffers) -{ - TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers); - - if(n < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - for(int i = 0; i < n; i++) - { - context->deleteBuffer(buffers[i]); - } - } -} - -void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers) -{ - TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers); - - if(n < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - for(int i = 0; i < n; i++) - { - if(framebuffers[i] != 0) - { - context->deleteFramebuffer(framebuffers[i]); - } - } - } -} - -void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers) -{ - TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers); - - if(n < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - for(int i = 0; i < n; i++) - { - context->deleteRenderbuffer(renderbuffers[i]); - } - } -} - -void DeleteTextures(GLsizei n, const GLuint* textures) -{ - TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures); - - if(n < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - for(int i = 0; i < n; i++) - { - if(textures[i] != 0) - { - context->deleteTexture(textures[i]); - } - } - } -} - -void DepthFunc(GLenum func) -{ - TRACE("(GLenum func = 0x%X)", func); - - switch(func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GREATER: - case GL_GEQUAL: - case GL_NOTEQUAL: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setDepthFunc(func); - } -} - -void DepthMask(GLboolean flag) -{ - TRACE("(GLboolean flag = %d)", flag); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setDepthMask(flag != GL_FALSE); - } -} - -void DepthRangef(GLclampf zNear, GLclampf zFar) -{ - TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setDepthRange(zNear, zFar); - } -} - -void DepthRangex(GLclampx zNear, GLclampx zFar) -{ - DepthRangef((float)zNear / 0x10000, (float)zFar / 0x10000); -} - -void Disable(GLenum cap) -{ - TRACE("(GLenum cap = 0x%X)", cap); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(cap) - { - case GL_CULL_FACE: context->setCullFaceEnabled(false); break; - case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break; - case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break; - case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break; - case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break; - case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break; - case GL_BLEND: context->setBlendEnabled(false); break; - case GL_DITHER: context->setDitherEnabled(false); break; - case GL_LIGHTING: context->setLightingEnabled(false); break; - case GL_LIGHT0: context->setLightEnabled(0, false); break; - case GL_LIGHT1: context->setLightEnabled(1, false); break; - case GL_LIGHT2: context->setLightEnabled(2, false); break; - case GL_LIGHT3: context->setLightEnabled(3, false); break; - case GL_LIGHT4: context->setLightEnabled(4, false); break; - case GL_LIGHT5: context->setLightEnabled(5, false); break; - case GL_LIGHT6: context->setLightEnabled(6, false); break; - case GL_LIGHT7: context->setLightEnabled(7, false); break; - case GL_FOG: context->setFogEnabled(false); break; - case GL_TEXTURE_2D: context->setTexture2Denabled(false); break; - case GL_TEXTURE_EXTERNAL_OES: context->setTextureExternalEnabled(false); break; - case GL_ALPHA_TEST: context->setAlphaTestEnabled(false); break; - case GL_COLOR_LOGIC_OP: context->setColorLogicOpEnabled(false); break; - case GL_POINT_SMOOTH: context->setPointSmoothEnabled(false); break; - case GL_LINE_SMOOTH: context->setLineSmoothEnabled(false); break; - case GL_COLOR_MATERIAL: context->setColorMaterialEnabled(false); break; - case GL_NORMALIZE: context->setNormalizeEnabled(false); break; - case GL_RESCALE_NORMAL: context->setRescaleNormalEnabled(false); break; - case GL_VERTEX_ARRAY: context->setVertexArrayEnabled(false); break; - case GL_NORMAL_ARRAY: context->setNormalArrayEnabled(false); break; - case GL_COLOR_ARRAY: context->setColorArrayEnabled(false); break; - case GL_POINT_SIZE_ARRAY_OES: context->setPointSizeArrayEnabled(false); break; - case GL_TEXTURE_COORD_ARRAY: context->setTextureCoordArrayEnabled(false); break; - case GL_MULTISAMPLE: context->setMultisampleEnabled(false); break; - case GL_SAMPLE_ALPHA_TO_ONE: context->setSampleAlphaToOneEnabled(false); break; - case GL_CLIP_PLANE0: context->setClipPlaneEnabled(0, false); break; - case GL_CLIP_PLANE1: context->setClipPlaneEnabled(1, false); break; - case GL_CLIP_PLANE2: context->setClipPlaneEnabled(2, false); break; - case GL_CLIP_PLANE3: context->setClipPlaneEnabled(3, false); break; - case GL_CLIP_PLANE4: context->setClipPlaneEnabled(4, false); break; - case GL_CLIP_PLANE5: context->setClipPlaneEnabled(5, false); break; - case GL_POINT_SPRITE_OES: context->setPointSpriteEnabled(false); break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void DisableClientState(GLenum array) -{ - TRACE("(GLenum array = 0x%X)", array); - - switch(array) - { - case GL_VERTEX_ARRAY: - case GL_NORMAL_ARRAY: - case GL_COLOR_ARRAY: - case GL_POINT_SIZE_ARRAY_OES: - case GL_TEXTURE_COORD_ARRAY: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - GLenum texture = context->getClientActiveTexture(); - - switch(array) - { - case GL_VERTEX_ARRAY: context->setVertexAttribArrayEnabled(sw::Position, false); break; - case GL_NORMAL_ARRAY: context->setVertexAttribArrayEnabled(sw::Normal, false); break; - case GL_COLOR_ARRAY: context->setVertexAttribArrayEnabled(sw::Color0, false); break; - case GL_POINT_SIZE_ARRAY_OES: context->setVertexAttribArrayEnabled(sw::PointSize, false); break; - case GL_TEXTURE_COORD_ARRAY: context->setVertexAttribArrayEnabled(sw::TexCoord0 + (texture - GL_TEXTURE0), false); break; - default: UNREACHABLE(array); - } - } -} - -void DrawArrays(GLenum mode, GLint first, GLsizei count) -{ - TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); - - if(count < 0 || first < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->drawArrays(mode, first, count); - } -} - -void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) -{ - TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)", - mode, count, type, indices); - - if(count < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - break; - default: - return error(GL_INVALID_ENUM); - } - - context->drawElements(mode, count, type, indices); - } -} - -void Enable(GLenum cap) -{ - TRACE("(GLenum cap = 0x%X)", cap); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(cap) - { - case GL_CULL_FACE: context->setCullFaceEnabled(true); break; - case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break; - case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break; - case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break; - case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break; - case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break; - case GL_BLEND: context->setBlendEnabled(true); break; - case GL_DITHER: context->setDitherEnabled(true); break; - case GL_LIGHTING: context->setLightingEnabled(true); break; - case GL_LIGHT0: context->setLightEnabled(0, true); break; - case GL_LIGHT1: context->setLightEnabled(1, true); break; - case GL_LIGHT2: context->setLightEnabled(2, true); break; - case GL_LIGHT3: context->setLightEnabled(3, true); break; - case GL_LIGHT4: context->setLightEnabled(4, true); break; - case GL_LIGHT5: context->setLightEnabled(5, true); break; - case GL_LIGHT6: context->setLightEnabled(6, true); break; - case GL_LIGHT7: context->setLightEnabled(7, true); break; - case GL_FOG: context->setFogEnabled(true); break; - case GL_TEXTURE_2D: context->setTexture2Denabled(true); break; - case GL_TEXTURE_EXTERNAL_OES: context->setTextureExternalEnabled(true); break; - case GL_ALPHA_TEST: context->setAlphaTestEnabled(true); break; - case GL_COLOR_LOGIC_OP: context->setColorLogicOpEnabled(true); break; - case GL_POINT_SMOOTH: context->setPointSmoothEnabled(true); break; - case GL_LINE_SMOOTH: context->setLineSmoothEnabled(true); break; - case GL_COLOR_MATERIAL: context->setColorMaterialEnabled(true); break; - case GL_NORMALIZE: context->setNormalizeEnabled(true); break; - case GL_RESCALE_NORMAL: context->setRescaleNormalEnabled(true); break; - case GL_VERTEX_ARRAY: context->setVertexArrayEnabled(true); break; - case GL_NORMAL_ARRAY: context->setNormalArrayEnabled(true); break; - case GL_COLOR_ARRAY: context->setColorArrayEnabled(true); break; - case GL_POINT_SIZE_ARRAY_OES: context->setPointSizeArrayEnabled(true); break; - case GL_TEXTURE_COORD_ARRAY: context->setTextureCoordArrayEnabled(true); break; - case GL_MULTISAMPLE: context->setMultisampleEnabled(true); break; - case GL_SAMPLE_ALPHA_TO_ONE: context->setSampleAlphaToOneEnabled(true); break; - case GL_CLIP_PLANE0: context->setClipPlaneEnabled(0, true); break; - case GL_CLIP_PLANE1: context->setClipPlaneEnabled(1, true); break; - case GL_CLIP_PLANE2: context->setClipPlaneEnabled(2, true); break; - case GL_CLIP_PLANE3: context->setClipPlaneEnabled(3, true); break; - case GL_CLIP_PLANE4: context->setClipPlaneEnabled(4, true); break; - case GL_CLIP_PLANE5: context->setClipPlaneEnabled(5, true); break; - case GL_POINT_SPRITE_OES: context->setPointSpriteEnabled(true); break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void EnableClientState(GLenum array) -{ - TRACE("(GLenum array = 0x%X)", array); - - switch(array) - { - case GL_VERTEX_ARRAY: - case GL_NORMAL_ARRAY: - case GL_COLOR_ARRAY: - case GL_POINT_SIZE_ARRAY_OES: - case GL_TEXTURE_COORD_ARRAY: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - GLenum texture = context->getClientActiveTexture(); - - switch(array) - { - case GL_VERTEX_ARRAY: context->setVertexAttribArrayEnabled(sw::Position, true); break; - case GL_NORMAL_ARRAY: context->setVertexAttribArrayEnabled(sw::Normal, true); break; - case GL_COLOR_ARRAY: context->setVertexAttribArrayEnabled(sw::Color0, true); break; - case GL_POINT_SIZE_ARRAY_OES: context->setVertexAttribArrayEnabled(sw::PointSize, true); break; - case GL_TEXTURE_COORD_ARRAY: context->setVertexAttribArrayEnabled(sw::TexCoord0 + (texture - GL_TEXTURE0), true); break; - default: UNREACHABLE(array); - } - } -} - -void Finish(void) -{ - TRACE("()"); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->finish(); - } -} - -void Flush(void) -{ - TRACE("()"); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->flush(); - } -} - -void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) -{ - TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " - "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); - - if(target != GL_FRAMEBUFFER_OES || (renderbuffertarget != GL_RENDERBUFFER_OES && renderbuffer != 0)) - { - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Framebuffer *framebuffer = context->getFramebuffer(); - GLuint framebufferName = context->getFramebufferName(); - - if(!framebuffer || (framebufferName == 0 && renderbuffer != 0)) - { - return error(GL_INVALID_OPERATION); - } - - switch(attachment) - { - case GL_COLOR_ATTACHMENT0_OES: - framebuffer->setColorbuffer(GL_RENDERBUFFER_OES, renderbuffer); - break; - case GL_DEPTH_ATTACHMENT_OES: - framebuffer->setDepthbuffer(GL_RENDERBUFFER_OES, renderbuffer); - break; - case GL_STENCIL_ATTACHMENT_OES: - framebuffer->setStencilbuffer(GL_RENDERBUFFER_OES, renderbuffer); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) -{ - TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " - "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); - - if(target != GL_FRAMEBUFFER_OES) - { - return error(GL_INVALID_ENUM); - } - - switch(attachment) - { - case GL_COLOR_ATTACHMENT0_OES: - case GL_DEPTH_ATTACHMENT_OES: - case GL_STENCIL_ATTACHMENT_OES: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - if(texture == 0) - { - textarget = GL_NONE_OES; - } - else - { - es1::Texture *tex = context->getTexture(texture); - - if(tex == NULL) - { - return error(GL_INVALID_OPERATION); - } - - if(tex->isCompressed(textarget, level)) - { - return error(GL_INVALID_OPERATION); - } - - switch(textarget) - { - case GL_TEXTURE_2D: - if(tex->getTarget() != GL_TEXTURE_2D) - { - return error(GL_INVALID_OPERATION); - } - break; - default: - return error(GL_INVALID_ENUM); - } - - if(level != 0) - { - return error(GL_INVALID_VALUE); - } - } - - es1::Framebuffer *framebuffer = context->getFramebuffer(); - GLuint framebufferName = context->getFramebufferName(); - - if(framebufferName == 0 || !framebuffer) - { - return error(GL_INVALID_OPERATION); - } - - switch(attachment) - { - case GL_COLOR_ATTACHMENT0_OES: framebuffer->setColorbuffer(textarget, texture); break; - case GL_DEPTH_ATTACHMENT_OES: framebuffer->setDepthbuffer(textarget, texture); break; - case GL_STENCIL_ATTACHMENT_OES: framebuffer->setStencilbuffer(textarget, texture); break; - } - } -} - -void Fogf(GLenum pname, GLfloat param) -{ - TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_FOG_MODE: - switch((GLenum)param) - { - case GL_LINEAR: - case GL_EXP: - case GL_EXP2: - context->setFogMode((GLenum)param); - break; - default: - return error(GL_INVALID_ENUM); - } - break; - case GL_FOG_DENSITY: - if(param < 0) - { - return error(GL_INVALID_VALUE); - } - context->setFogDensity(param); - break; - case GL_FOG_START: - context->setFogStart(param); - break; - case GL_FOG_END: - context->setFogEnd(param); - break; - case GL_FOG_COLOR: - return error(GL_INVALID_ENUM); // Need four values, should call glFogfv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Fogfv(GLenum pname, const GLfloat *params) -{ - TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_FOG_MODE: - switch((GLenum)params[0]) - { - case GL_LINEAR: - case GL_EXP: - case GL_EXP2: - context->setFogMode((GLenum)params[0]); - break; - default: - return error(GL_INVALID_ENUM); - } - break; - case GL_FOG_DENSITY: - if(params[0] < 0) - { - return error(GL_INVALID_VALUE); - } - context->setFogDensity(params[0]); - break; - case GL_FOG_START: - context->setFogStart(params[0]); - break; - case GL_FOG_END: - context->setFogEnd(params[0]); - break; - case GL_FOG_COLOR: - context->setFogColor(params[0], params[1], params[2], params[3]); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Fogx(GLenum pname, GLfixed param) -{ - TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_FOG_MODE: - switch((GLenum)param) - { - case GL_LINEAR: - case GL_EXP: - case GL_EXP2: - context->setFogMode((GLenum)param); - break; - default: - return error(GL_INVALID_ENUM); - } - break; - case GL_FOG_DENSITY: - if(param < 0) - { - return error(GL_INVALID_VALUE); - } - context->setFogDensity((float)param / 0x10000); - break; - case GL_FOG_START: - context->setFogStart((float)param / 0x10000); - break; - case GL_FOG_END: - context->setFogEnd((float)param / 0x10000); - break; - case GL_FOG_COLOR: - return error(GL_INVALID_ENUM); // Need four values, should call glFogxv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Fogxv(GLenum pname, const GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void FrontFace(GLenum mode) -{ - TRACE("(GLenum mode = 0x%X)", mode); - - switch(mode) - { - case GL_CW: - case GL_CCW: - { - es1::Context *context = es1::getContext(); - - if(context) - { - context->setFrontFace(mode); - } - } - break; - default: - return error(GL_INVALID_ENUM); - } -} - -void Frustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) -{ - TRACE("(GLfloat left = %f, GLfloat right = %f, GLfloat bottom = %f, GLfloat top = %f, GLfloat zNear = %f, GLfloat zFar = %f)", left, right, bottom, top, zNear, zFar); - - if(zNear <= 0.0f || zFar <= 0.0f || left == right || bottom == top || zNear == zFar) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->frustum(left, right, bottom, top, zNear, zFar); - } -} - -void Frustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) -{ - Frustumf((float)left / 0x10000, (float)right / 0x10000, (float)bottom / 0x10000, (float)top / 0x10000, (float)zNear / 0x10000, (float)zFar / 0x10000); -} - -void GenerateMipmapOES(GLenum target) -{ - TRACE("(GLenum target = 0x%X)", target); - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Texture *texture; - - switch(target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - default: - return error(GL_INVALID_ENUM); - } - - if(texture->isCompressed(target, 0) || texture->isDepth(target, 0)) - { - return error(GL_INVALID_OPERATION); - } - - texture->generateMipmaps(); - } -} - -void GenBuffers(GLsizei n, GLuint* buffers) -{ - TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers); - - if(n < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - for(int i = 0; i < n; i++) - { - buffers[i] = context->createBuffer(); - } - } -} - -void GenFramebuffersOES(GLsizei n, GLuint* framebuffers) -{ - TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers); - - if(n < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - for(int i = 0; i < n; i++) - { - framebuffers[i] = context->createFramebuffer(); - } - } -} - -void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers) -{ - TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers); - - if(n < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - for(int i = 0; i < n; i++) - { - renderbuffers[i] = context->createRenderbuffer(); - } - } -} - -void GenTextures(GLsizei n, GLuint* textures) -{ - TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures); - - if(n < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - for(int i = 0; i < n; i++) - { - textures[i] = context->createTexture(); - } - } -} - -void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - if(target != GL_RENDERBUFFER_OES) - { - return error(GL_INVALID_ENUM); - } - - if(context->getRenderbufferName() == 0) - { - return error(GL_INVALID_OPERATION); - } - - es1::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName()); - - switch(pname) - { - case GL_RENDERBUFFER_WIDTH_OES: *params = renderbuffer->getWidth(); break; - case GL_RENDERBUFFER_HEIGHT_OES: *params = renderbuffer->getHeight(); break; - case GL_RENDERBUFFER_INTERNAL_FORMAT_OES: *params = renderbuffer->getFormat(); break; - case GL_RENDERBUFFER_RED_SIZE_OES: *params = renderbuffer->getRedSize(); break; - case GL_RENDERBUFFER_GREEN_SIZE_OES: *params = renderbuffer->getGreenSize(); break; - case GL_RENDERBUFFER_BLUE_SIZE_OES: *params = renderbuffer->getBlueSize(); break; - case GL_RENDERBUFFER_ALPHA_SIZE_OES: *params = renderbuffer->getAlphaSize(); break; - case GL_RENDERBUFFER_DEPTH_SIZE_OES: *params = renderbuffer->getDepthSize(); break; - case GL_RENDERBUFFER_STENCIL_SIZE_OES: *params = renderbuffer->getStencilSize(); break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void GetBooleanv(GLenum pname, GLboolean* params) -{ - TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - if(!(context->getBooleanv(pname, params))) - { - int numParams = context->getQueryParameterNum(pname); - - if(numParams < 0) - { - return error(GL_INVALID_ENUM); - } - - if(numParams == 0) - { - return; - } - - if(context->isQueryParameterFloat(pname)) - { - GLfloat *floatParams = NULL; - floatParams = new GLfloat[numParams]; - - context->getFloatv(pname, floatParams); - - for(int i = 0; i < numParams; ++i) - { - if(floatParams[i] == 0.0f) - params[i] = GL_FALSE; - else - params[i] = GL_TRUE; - } - - delete [] floatParams; - } - else if(context->isQueryParameterInt(pname)) - { - GLint *intParams = NULL; - intParams = new GLint[numParams]; - - context->getIntegerv(pname, intParams); - - for(int i = 0; i < numParams; ++i) - { - if(intParams[i] == 0) - params[i] = GL_FALSE; - else - params[i] = GL_TRUE; - } - - delete [] intParams; - } - else UNREACHABLE(pname); - } - } -} - -void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Buffer *buffer; - - switch(target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: - return error(GL_INVALID_ENUM); - } - - if(!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - return error(GL_INVALID_OPERATION); - } - - switch(pname) - { - case GL_BUFFER_USAGE: - *params = buffer->usage(); - break; - case GL_BUFFER_SIZE: - *params = buffer->size(); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void GetClipPlanef(GLenum pname, GLfloat eqn[4]) -{ - UNIMPLEMENTED(); -} - -void GetClipPlanex(GLenum pname, GLfixed eqn[4]) -{ - UNIMPLEMENTED(); -} - -GLenum GetError(void) -{ - TRACE("()"); - - es1::Context *context = es1::getContext(); - - if(context) - { - return context->getError(); - } - - return GL_NO_ERROR; -} - -void GetFixedv(GLenum pname, GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void GetFloatv(GLenum pname, GLfloat* params) -{ - TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - if(!(context->getFloatv(pname, params))) - { - int numParams = context->getQueryParameterNum(pname); - - if(numParams < 0) - { - return error(GL_INVALID_ENUM); - } - - if(numParams == 0) - { - return; - } - - if(context->isQueryParameterBool(pname)) - { - GLboolean *boolParams = NULL; - boolParams = new GLboolean[numParams]; - - context->getBooleanv(pname, boolParams); - - for(int i = 0; i < numParams; ++i) - { - if(boolParams[i] == GL_FALSE) - params[i] = 0.0f; - else - params[i] = 1.0f; - } - - delete [] boolParams; - } - else if(context->isQueryParameterInt(pname)) - { - GLint *intParams = NULL; - intParams = new GLint[numParams]; - - context->getIntegerv(pname, intParams); - - for(int i = 0; i < numParams; ++i) - { - params[i] = (GLfloat)intParams[i]; - } - - delete [] intParams; - } - else UNREACHABLE(pname); - } - } -} - -void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params) -{ - TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", - target, attachment, pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - if(target != GL_FRAMEBUFFER_OES) - { - return error(GL_INVALID_ENUM); - } - - if(context->getFramebufferName() == 0) - { - return error(GL_INVALID_OPERATION); - } - - es1::Framebuffer *framebuffer = context->getFramebuffer(); - - GLenum attachmentType; - GLuint attachmentHandle; - switch(attachment) - { - case GL_COLOR_ATTACHMENT0_OES: - attachmentType = framebuffer->getColorbufferType(); - attachmentHandle = framebuffer->getColorbufferName(); - break; - case GL_DEPTH_ATTACHMENT_OES: - attachmentType = framebuffer->getDepthbufferType(); - attachmentHandle = framebuffer->getDepthbufferName(); - break; - case GL_STENCIL_ATTACHMENT_OES: - attachmentType = framebuffer->getStencilbufferType(); - attachmentHandle = framebuffer->getStencilbufferName(); - break; - default: - return error(GL_INVALID_ENUM); - } - - GLenum attachmentObjectType; // Type category - if(attachmentType == GL_NONE_OES || attachmentType == GL_RENDERBUFFER_OES) - { - attachmentObjectType = attachmentType; - } - else if(es1::IsTextureTarget(attachmentType)) - { - attachmentObjectType = GL_TEXTURE; - } - else UNREACHABLE(attachmentType); - - switch(pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES: - *params = attachmentObjectType; - break; - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES: - if(attachmentObjectType == GL_RENDERBUFFER_OES || attachmentObjectType == GL_TEXTURE) - { - *params = attachmentHandle; - } - else - { - return error(GL_INVALID_ENUM); - } - break; - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES: - if(attachmentObjectType == GL_TEXTURE) - { - *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0 - } - else - { - return error(GL_INVALID_ENUM); - } - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void GetIntegerv(GLenum pname, GLint* params) -{ - TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - if(!(context->getIntegerv(pname, params))) - { - int numParams = context->getQueryParameterNum(pname); - - if(numParams < 0) - { - return error(GL_INVALID_ENUM); - } - - if(numParams == 0) - { - return; - } - - if(context->isQueryParameterBool(pname)) - { - GLboolean *boolParams = NULL; - boolParams = new GLboolean[numParams]; - - context->getBooleanv(pname, boolParams); - - for(int i = 0; i < numParams; ++i) - { - if(boolParams[i] == GL_FALSE) - params[i] = 0; - else - params[i] = 1; - } - - delete [] boolParams; - } - else if(context->isQueryParameterFloat(pname)) - { - GLfloat *floatParams = NULL; - floatParams = new GLfloat[numParams]; - - context->getFloatv(pname, floatParams); - - for(int i = 0; i < numParams; ++i) - { - if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE) - { - params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f); - } - else - { - params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5)); - } - } - - delete [] floatParams; - } - else UNREACHABLE(pname); - } - } -} - -void GetLightfv(GLenum light, GLenum pname, GLfloat *params) -{ - UNIMPLEMENTED(); -} - -void GetLightxv(GLenum light, GLenum pname, GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void GetMaterialfv(GLenum face, GLenum pname, GLfloat *params) -{ - UNIMPLEMENTED(); -} - -void GetMaterialxv(GLenum face, GLenum pname, GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void GetPointerv(GLenum pname, GLvoid **params) -{ - TRACE("(GLenum pname = 0x%X, GLvoid **params = %p)", pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - if(!(context->getPointerv(pname, const_cast<const GLvoid**>(params)))) - { - return error(GL_INVALID_ENUM); - } - } -} - -const GLubyte* GetString(GLenum name) -{ - TRACE("(GLenum name = 0x%X)", name); - - switch(name) - { - case GL_VENDOR: - return (GLubyte*)"TransGaming Inc."; - case GL_RENDERER: - return (GLubyte*)"Google SwiftShader"; - case GL_VERSION: - return (GLubyte*)"OpenGL ES 1.1 SwiftShader " VERSION_STRING; - case GL_EXTENSIONS: - // Keep list sorted in following order: - // OES extensions - // EXT extensions - // Vendor extensions - return (GLubyte*) - "GL_OES_blend_equation_separate " - "GL_OES_blend_func_separate " - "GL_OES_blend_subtract " - "GL_OES_compressed_ETC1_RGB8_texture " - "GL_OES_depth_texture " - "GL_OES_EGL_image " - "GL_OES_EGL_image_external " - "GL_OES_EGL_sync " - "GL_OES_element_index_uint " - "GL_OES_framebuffer_object " - "GL_OES_packed_depth_stencil " - "GL_OES_read_format " - "GL_OES_rgb8_rgba8 " - "GL_OES_stencil8 " - "GL_OES_stencil_wrap " - "GL_OES_texture_mirrored_repeat " - "GL_OES_texture_npot " - "GL_EXT_blend_minmax " - "GL_EXT_read_format_bgra " - #if (S3TC_SUPPORT) - "GL_EXT_texture_compression_dxt1 " - "GL_ANGLE_texture_compression_dxt3 " - "GL_ANGLE_texture_compression_dxt5 " - #endif - "GL_EXT_texture_filter_anisotropic " - "GL_EXT_texture_format_BGRA8888"; - default: - return error(GL_INVALID_ENUM, (GLubyte*)NULL); - } -} - -void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Texture *texture; - - switch(target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_EXTERNAL_OES: - texture = context->getTextureExternal(); - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(pname) - { - case GL_TEXTURE_MAG_FILTER: - *params = (GLfloat)texture->getMagFilter(); - break; - case GL_TEXTURE_MIN_FILTER: - *params = (GLfloat)texture->getMinFilter(); - break; - case GL_TEXTURE_WRAP_S: - *params = (GLfloat)texture->getWrapS(); - break; - case GL_TEXTURE_WRAP_T: - *params = (GLfloat)texture->getWrapT(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - *params = texture->getMaxAnisotropy(); - break; - case GL_GENERATE_MIPMAP: - *params = (GLfloat)texture->getGenerateMipmap(); - break; - case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: - *params = (GLfloat)1; - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params); - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Texture *texture; - - switch(target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_EXTERNAL_OES: - texture = context->getTextureExternal(); - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(pname) - { - case GL_TEXTURE_MAG_FILTER: - *params = texture->getMagFilter(); - break; - case GL_TEXTURE_MIN_FILTER: - *params = texture->getMinFilter(); - break; - case GL_TEXTURE_WRAP_S: - *params = texture->getWrapS(); - break; - case GL_TEXTURE_WRAP_T: - *params = texture->getWrapT(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - *params = (GLint)texture->getMaxAnisotropy(); - break; - case GL_GENERATE_MIPMAP: - *params = (GLint)texture->getGenerateMipmap(); - break; - case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: - *params = 1; - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void GetTexEnvfv(GLenum env, GLenum pname, GLfloat *params) -{ - UNIMPLEMENTED(); -} - -void GetTexEnviv(GLenum env, GLenum pname, GLint *params) -{ - UNIMPLEMENTED(); -} - -void GetTexEnvxv(GLenum env, GLenum pname, GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void GetTexParameterxv(GLenum target, GLenum pname, GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void Hint(GLenum target, GLenum mode) -{ - TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); - - switch(mode) - { - case GL_FASTEST: - case GL_NICEST: - case GL_DONT_CARE: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(target) - { - case GL_GENERATE_MIPMAP_HINT: - context->setGenerateMipmapHint(mode); - break; - case GL_PERSPECTIVE_CORRECTION_HINT: - context->setPerspectiveCorrectionHint(mode); - break; - case GL_FOG_HINT: - context->setFogHint(mode); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -GLboolean IsBuffer(GLuint buffer) -{ - TRACE("(GLuint buffer = %d)", buffer); - - es1::Context *context = es1::getContext(); - - if(context && buffer) - { - es1::Buffer *bufferObject = context->getBuffer(buffer); - - if(bufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; -} - -GLboolean IsEnabled(GLenum cap) -{ - TRACE("(GLenum cap = 0x%X)", cap); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(cap) - { - case GL_CULL_FACE: return context->isCullFaceEnabled(); break; - case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled(); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled(); break; - case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled(); break; - case GL_SCISSOR_TEST: return context->isScissorTestEnabled(); break; - case GL_STENCIL_TEST: return context->isStencilTestEnabled(); break; - case GL_DEPTH_TEST: return context->isDepthTestEnabled(); break; - case GL_BLEND: return context->isBlendEnabled(); break; - case GL_DITHER: return context->isDitherEnabled(); break; - case GL_LIGHTING: return context->isLightingEnabled(); break; - case GL_LIGHT0: return context->isLightEnabled(0); break; - case GL_LIGHT1: return context->isLightEnabled(1); break; - case GL_LIGHT2: return context->isLightEnabled(2); break; - case GL_LIGHT3: return context->isLightEnabled(3); break; - case GL_LIGHT4: return context->isLightEnabled(4); break; - case GL_LIGHT5: return context->isLightEnabled(5); break; - case GL_LIGHT6: return context->isLightEnabled(6); break; - case GL_LIGHT7: return context->isLightEnabled(7); break; - case GL_FOG: return context->isFogEnabled(); break; - case GL_TEXTURE_2D: return context->isTexture2Denabled(); break; - case GL_TEXTURE_EXTERNAL_OES: return context->isTextureExternalEnabled(); break; - case GL_ALPHA_TEST: return context->isAlphaTestEnabled(); break; - case GL_COLOR_LOGIC_OP: return context->isColorLogicOpEnabled(); break; - case GL_POINT_SMOOTH: return context->isPointSmoothEnabled(); break; - case GL_LINE_SMOOTH: return context->isLineSmoothEnabled(); break; - case GL_COLOR_MATERIAL: return context->isColorMaterialEnabled(); break; - case GL_NORMALIZE: return context->isNormalizeEnabled(); break; - case GL_RESCALE_NORMAL: return context->isRescaleNormalEnabled(); break; - case GL_VERTEX_ARRAY: return context->isVertexArrayEnabled(); break; - case GL_NORMAL_ARRAY: return context->isNormalArrayEnabled(); break; - case GL_COLOR_ARRAY: return context->isColorArrayEnabled(); break; - case GL_POINT_SIZE_ARRAY_OES: return context->isPointSizeArrayEnabled(); break; - case GL_TEXTURE_COORD_ARRAY: return context->isTextureCoordArrayEnabled(); break; - case GL_MULTISAMPLE: return context->isMultisampleEnabled(); break; - case GL_SAMPLE_ALPHA_TO_ONE: return context->isSampleAlphaToOneEnabled(); break; - case GL_CLIP_PLANE0: return context->isClipPlaneEnabled(0); break; - case GL_CLIP_PLANE1: return context->isClipPlaneEnabled(1); break; - case GL_CLIP_PLANE2: return context->isClipPlaneEnabled(2); break; - case GL_CLIP_PLANE3: return context->isClipPlaneEnabled(3); break; - case GL_CLIP_PLANE4: return context->isClipPlaneEnabled(4); break; - case GL_CLIP_PLANE5: return context->isClipPlaneEnabled(5); break; - case GL_POINT_SPRITE_OES: return context->isPointSpriteEnabled(); break; - default: - return error(GL_INVALID_ENUM, GL_FALSE); - } - } - - return GL_FALSE; -} - -GLboolean IsFramebufferOES(GLuint framebuffer) -{ - TRACE("(GLuint framebuffer = %d)", framebuffer); - - es1::Context *context = es1::getContext(); - - if(context && framebuffer) - { - es1::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - - if(framebufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; -} - -GLboolean IsTexture(GLuint texture) -{ - TRACE("(GLuint texture = %d)", texture); - - es1::Context *context = es1::getContext(); - - if(context && texture) - { - es1::Texture *textureObject = context->getTexture(texture); - - if(textureObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; -} - -GLboolean IsRenderbufferOES(GLuint renderbuffer) -{ - TRACE("(GLuint renderbuffer = %d)", renderbuffer); - - es1::Context *context = es1::getContext(); - - if(context && renderbuffer) - { - es1::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - - if(renderbufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; -} - -void LightModelf(GLenum pname, GLfloat param) -{ - TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_LIGHT_MODEL_TWO_SIDE: - context->setLightModelTwoSide(param != 0.0f); - break; - case GL_LIGHT_MODEL_AMBIENT: - return error(GL_INVALID_ENUM); // Need four values, should call glLightModelfv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void LightModelfv(GLenum pname, const GLfloat *params) -{ - TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_LIGHT_MODEL_AMBIENT: - context->setGlobalAmbient(params[0], params[1], params[2], params[3]); - break; - case GL_LIGHT_MODEL_TWO_SIDE: - context->setLightModelTwoSide(params[0] != 0.0f); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void LightModelx(GLenum pname, GLfixed param) -{ - TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_LIGHT_MODEL_TWO_SIDE: - context->setLightModelTwoSide(param != 0); - break; - case GL_LIGHT_MODEL_AMBIENT: - return error(GL_INVALID_ENUM); // Need four values, should call glLightModelxv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void LightModelxv(GLenum pname, const GLfixed *params) -{ - TRACE("(GLenum pname = 0x%X, const GLfixed *params)", pname); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_LIGHT_MODEL_AMBIENT: - context->setGlobalAmbient((float)params[0] / 0x10000, (float)params[1] / 0x10000, (float)params[2] / 0x10000, (float)params[3] / 0x10000); - break; - case GL_LIGHT_MODEL_TWO_SIDE: - context->setLightModelTwoSide(params[0] != 0); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Lightf(GLenum light, GLenum pname, GLfloat param) -{ - TRACE("(GLenum light = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", light, pname, param); - - int index = light - GL_LIGHT0; - - if(index < 0 || index >= es1::MAX_LIGHTS) - { - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_SPOT_EXPONENT: - if(param < 0.0f || param > 128.0f) - { - return error(GL_INVALID_VALUE); - } - context->setSpotLightExponent(index, param); - break; - case GL_SPOT_CUTOFF: - if((param < 0.0f || param > 90.0f) && param != 180.0f) - { - return error(GL_INVALID_VALUE); - } - context->setSpotLightCutoff(index, param); - break; - case GL_CONSTANT_ATTENUATION: - if(param < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setLightAttenuationConstant(index, param); - break; - case GL_LINEAR_ATTENUATION: - if(param < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setLightAttenuationLinear(index, param); - break; - case GL_QUADRATIC_ATTENUATION: - if(param < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setLightAttenuationQuadratic(index, param); - break; - case GL_AMBIENT: - case GL_DIFFUSE: - case GL_SPECULAR: - case GL_POSITION: - case GL_SPOT_DIRECTION: - return error(GL_INVALID_ENUM); // Need four values, should call glLightfv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Lightfv(GLenum light, GLenum pname, const GLfloat *params) -{ - TRACE("(GLenum light = 0x%X, GLenum pname = 0x%X, const GLint *params)", light, pname); - - es1::Context *context = es1::getContext(); - - if(context) - { - int index = light - GL_LIGHT0; - - if(index < 0 || index > es1::MAX_LIGHTS) - { - return error(GL_INVALID_ENUM); - } - - switch(pname) - { - case GL_AMBIENT: context->setLightAmbient(index, params[0], params[1], params[2], params[3]); break; - case GL_DIFFUSE: context->setLightDiffuse(index, params[0], params[1], params[2], params[3]); break; - case GL_SPECULAR: context->setLightSpecular(index, params[0], params[1], params[2], params[3]); break; - case GL_POSITION: context->setLightPosition(index, params[0], params[1], params[2], params[3]); break; - case GL_SPOT_DIRECTION: context->setLightDirection(index, params[0], params[1], params[2]); break; - case GL_SPOT_EXPONENT: - if(params[0] < 0.0f || params[0] > 128.0f) - { - return error(GL_INVALID_VALUE); - } - context->setSpotLightExponent(index, params[0]); - break; - case GL_SPOT_CUTOFF: - if((params[0] < 0.0f || params[0] > 90.0f) && params[0] != 180.0f) - { - return error(GL_INVALID_VALUE); - } - context->setSpotLightCutoff(index, params[0]); - break; - case GL_CONSTANT_ATTENUATION: - if(params[0] < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setLightAttenuationConstant(index, params[0]); - break; - case GL_LINEAR_ATTENUATION: - if(params[0] < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setLightAttenuationLinear(index, params[0]); - break; - case GL_QUADRATIC_ATTENUATION: - if(params[0] < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setLightAttenuationQuadratic(index, params[0]); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Lightx(GLenum light, GLenum pname, GLfixed param) -{ - UNIMPLEMENTED(); -} - -void Lightxv(GLenum light, GLenum pname, const GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void LineWidth(GLfloat width) -{ - TRACE("(GLfloat width = %f)", width); - - if(width <= 0.0f) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setLineWidth(width); - } -} - -void LineWidthx(GLfixed width) -{ - LineWidth((float)width / 0x10000); -} - -void LoadIdentity(void) -{ - TRACE("()"); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->loadIdentity(); - } -} - -void LoadMatrixf(const GLfloat *m) -{ - TRACE("(const GLfloat *m)"); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->load(m); - } -} - -void LoadMatrixx(const GLfixed *m) -{ - GLfloat matrix[16] = - { - (float)m[0] / 0x10000, (float)m[1] / 0x10000, (float)m[2] / 0x10000, (float)m[3] / 0x10000, - (float)m[4] / 0x10000, (float)m[5] / 0x10000, (float)m[6] / 0x10000, (float)m[7] / 0x10000, - (float)m[8] / 0x10000, (float)m[9] / 0x10000, (float)m[10] / 0x10000, (float)m[11] / 0x10000, - (float)m[12] / 0x10000, (float)m[13] / 0x10000, (float)m[14] / 0x10000, (float)m[15] / 0x10000 - }; - - LoadMatrixf(matrix); -} - -void LogicOp(GLenum opcode) -{ - TRACE("(GLenum opcode = 0x%X)", opcode); - - switch(opcode) - { - case GL_CLEAR: - case GL_SET: - case GL_COPY: - case GL_COPY_INVERTED: - case GL_NOOP: - case GL_INVERT: - case GL_AND: - case GL_NAND: - case GL_OR: - case GL_NOR: - case GL_XOR: - case GL_EQUIV: - case GL_AND_REVERSE: - case GL_AND_INVERTED: - case GL_OR_REVERSE: - case GL_OR_INVERTED: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setLogicalOperation(opcode); - } -} - -void Materialf(GLenum face, GLenum pname, GLfloat param) -{ - TRACE("(GLenum face = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", face, pname, param); - - if(face != GL_FRONT_AND_BACK) - { - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_SHININESS: - if(param < 0.0f || param > 128.0f) - { - return error(GL_INVALID_VALUE); - } - context->setMaterialShininess(param); - break; - case GL_AMBIENT: - case GL_DIFFUSE: - case GL_AMBIENT_AND_DIFFUSE: - case GL_SPECULAR: - case GL_EMISSION: - return error(GL_INVALID_ENUM); // Need four values, should call glMaterialfv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Materialfv(GLenum face, GLenum pname, const GLfloat *params) -{ - TRACE("(GLenum face = 0x%X, GLenum pname = 0x%X, GLfloat params)", face, pname); - - if(face != GL_FRONT_AND_BACK) - { - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_AMBIENT: - context->setMaterialAmbient(params[0], params[1], params[2], params[3]); - break; - case GL_DIFFUSE: - context->setMaterialDiffuse(params[0], params[1], params[2], params[3]); - break; - case GL_AMBIENT_AND_DIFFUSE: - context->setMaterialAmbient(params[0], params[1], params[2], params[3]); - context->setMaterialDiffuse(params[0], params[1], params[2], params[3]); - break; - case GL_SPECULAR: - context->setMaterialSpecular(params[0], params[1], params[2], params[3]); - break; - case GL_EMISSION: - context->setMaterialEmission(params[0], params[1], params[2], params[3]); - break; - case GL_SHININESS: - context->setMaterialShininess(params[0]); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Materialx(GLenum face, GLenum pname, GLfixed param) -{ - UNIMPLEMENTED(); -} - -void Materialxv(GLenum face, GLenum pname, const GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void MatrixMode(GLenum mode) -{ - TRACE("(GLenum mode = 0x%X)", mode); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setMatrixMode(mode); - } -} - -void MultMatrixf(const GLfloat *m) -{ - TRACE("(const GLfloat *m)"); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->multiply(m); - } -} - -void MultMatrixx(const GLfixed *m) -{ - GLfloat matrix[16] = - { - (float)m[0] / 0x10000, (float)m[1] / 0x10000, (float)m[2] / 0x10000, (float)m[3] / 0x10000, - (float)m[4] / 0x10000, (float)m[5] / 0x10000, (float)m[6] / 0x10000, (float)m[7] / 0x10000, - (float)m[8] / 0x10000, (float)m[9] / 0x10000, (float)m[10] / 0x10000, (float)m[11] / 0x10000, - (float)m[12] / 0x10000, (float)m[13] / 0x10000, (float)m[14] / 0x10000, (float)m[15] / 0x10000 - }; - - MultMatrixf(matrix); -} - -void MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) -{ - TRACE("(GLenum target = 0x%X, GLfloat s = %f, GLfloat t = %f, GLfloat r = %f, GLfloat q = %f)", target, s, t, r, q); - - switch(target) - { - case GL_TEXTURE0: - case GL_TEXTURE1: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setVertexAttrib(sw::TexCoord0 + (target - GL_TEXTURE0), s, t, r, q); - } -} - -void MultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) -{ - UNIMPLEMENTED(); -} - -void Normal3f(GLfloat nx, GLfloat ny, GLfloat nz) -{ - TRACE("(GLfloat nx, GLfloat ny, GLfloat nz)", nx, ny, nz); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setVertexAttrib(sw::Normal, nx, ny, nz, 0); - } -} - -void Normal3x(GLfixed nx, GLfixed ny, GLfixed nz) -{ - UNIMPLEMENTED(); -} - -void NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) -{ - TRACE("(GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", type, stride, pointer); - - VertexAttribPointer(sw::Normal, 3, type, true, stride, pointer); -} - -void Orthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) -{ - TRACE("(GLfloat left = %f, GLfloat right = %f, GLfloat bottom = %f, GLfloat top = %f, GLfloat zNear = %f, GLfloat zFar = %f)", left, right, bottom, top, zNear, zFar); - - if(left == right || bottom == top || zNear == zFar) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->ortho(left, right, bottom, top, zNear, zFar); - } -} - -void Orthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) -{ - Orthof((float)left / 0x10000, (float)right / 0x10000, (float)bottom / 0x10000, (float)top / 0x10000, (float)zNear / 0x10000, (float)zFar / 0x10000); -} - -void PixelStorei(GLenum pname, GLint param) -{ - TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_UNPACK_ALIGNMENT: - if(param != 1 && param != 2 && param != 4 && param != 8) - { - return error(GL_INVALID_VALUE); - } - - context->setUnpackAlignment(param); - break; - case GL_PACK_ALIGNMENT: - if(param != 1 && param != 2 && param != 4 && param != 8) - { - return error(GL_INVALID_VALUE); - } - - context->setPackAlignment(param); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void PointParameterf(GLenum pname, GLfloat param) -{ - TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_POINT_SIZE_MIN: - if(param < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setPointSizeMin(param); - break; - case GL_POINT_SIZE_MAX: - if(param < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setPointSizeMax(param); - break; - case GL_POINT_FADE_THRESHOLD_SIZE: - if(param < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setPointFadeThresholdSize(param); - break; - case GL_POINT_DISTANCE_ATTENUATION: - return error(GL_INVALID_ENUM); // Needs three values, should call glPointParameterfv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void PointParameterfv(GLenum pname, const GLfloat *params) -{ - TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_POINT_SIZE_MIN: - if(params[0] < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setPointSizeMin(params[0]); - break; - case GL_POINT_SIZE_MAX: - if(params[0] < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setPointSizeMax(params[0]); - break; - case GL_POINT_DISTANCE_ATTENUATION: - context->setPointDistanceAttenuation(params[0], params[1], params[2]); - break; - case GL_POINT_FADE_THRESHOLD_SIZE: - if(params[0] < 0.0f) - { - return error(GL_INVALID_VALUE); - } - context->setPointFadeThresholdSize(params[0]); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void PointParameterx(GLenum pname, GLfixed param) -{ - TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_POINT_SIZE_MIN: - if(param < 0) - { - return error(GL_INVALID_VALUE); - } - context->setPointSizeMin((float)param / 0x10000); - break; - case GL_POINT_SIZE_MAX: - if(param < 0) - { - return error(GL_INVALID_VALUE); - } - context->setPointSizeMax((float)param / 0x10000); - break; - case GL_POINT_FADE_THRESHOLD_SIZE: - if(param < 0) - { - return error(GL_INVALID_VALUE); - } - context->setPointFadeThresholdSize((float)param / 0x10000); - break; - case GL_POINT_DISTANCE_ATTENUATION: - return error(GL_INVALID_ENUM); // Needs three parameters, should call glPointParameterxv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void PointParameterxv(GLenum pname, const GLfixed *params) -{ - TRACE("(GLenum pname = 0x%X, const GLfixed *params)", pname); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(pname) - { - case GL_POINT_SIZE_MIN: - if(params[0] < 0) - { - return error(GL_INVALID_VALUE); - } - context->setPointSizeMin((float)params[0] / 0x10000); - break; - case GL_POINT_SIZE_MAX: - if(params[0] < 0) - { - return error(GL_INVALID_VALUE); - } - context->setPointSizeMax((float)params[0] / 0x10000); - break; - case GL_POINT_DISTANCE_ATTENUATION: - context->setPointDistanceAttenuation((float)params[0] / 0x10000, (float)params[1] / 0x10000, (float)params[2] / 0x10000); - break; - case GL_POINT_FADE_THRESHOLD_SIZE: - if(params[0] < 0) - { - return error(GL_INVALID_VALUE); - } - context->setPointFadeThresholdSize((float)params[0] / 0x10000); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void PointSize(GLfloat size) -{ - TRACE("(GLfloat size = %f)", size); - - if(size <= 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setVertexAttrib(sw::PointSize, size, size, size, size); - } -} - -void PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer) -{ - TRACE("(GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", type, stride, pointer); - - switch(type) - { - case GL_FIXED: - case GL_FLOAT: - break; - default: - return error(GL_INVALID_ENUM); - } - - VertexAttribPointer(sw::PointSize, 1, type, true, stride, pointer); -} - -void PointSizex(GLfixed size) -{ - PointSize((float)size / 0x10000); -} - -void PolygonOffset(GLfloat factor, GLfloat units) -{ - TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setPolygonOffsetParams(factor, units); - } -} - -void PolygonOffsetx(GLfixed factor, GLfixed units) -{ - PolygonOffset((float)factor / 0x10000, (float)units / 0x10000); -} - -void PopMatrix(void) -{ - TRACE("()"); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->popMatrix(); - } -} - -void PushMatrix(void) -{ - TRACE("()"); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->pushMatrix(); - } -} - -void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) -{ - TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " - "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)", - x, y, width, height, format, type, pixels); - - if(width < 0 || height < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->readPixels(x, y, width, height, format, type, NULL, pixels); - } -} - -void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) -{ - TRACE("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, internalformat, width, height); - - switch(target) - { - case GL_RENDERBUFFER_OES: - break; - default: - return error(GL_INVALID_ENUM); - } - - if(!es1::IsColorRenderable(internalformat) && !es1::IsDepthRenderable(internalformat) && !es1::IsStencilRenderable(internalformat)) - { - return error(GL_INVALID_ENUM); - } - - if(width < 0 || height < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - if(width > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE || - height > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE) - { - return error(GL_INVALID_VALUE); - } - - GLuint handle = context->getRenderbufferName(); - if(handle == 0) - { - return error(GL_INVALID_OPERATION); - } - - switch(internalformat) - { - case GL_DEPTH_COMPONENT16_OES: - context->setRenderbufferStorage(new es1::Depthbuffer(width, height, 0)); - break; - case GL_RGBA4_OES: - case GL_RGB5_A1_OES: - case GL_RGB565_OES: - case GL_RGB8_OES: - case GL_RGBA8_OES: - context->setRenderbufferStorage(new es1::Colorbuffer(width, height, internalformat, 0)); - break; - case GL_STENCIL_INDEX8_OES: - context->setRenderbufferStorage(new es1::Stencilbuffer(width, height, 0)); - break; - case GL_DEPTH24_STENCIL8_OES: - context->setRenderbufferStorage(new es1::DepthStencilbuffer(width, height, 0)); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) -{ - TRACE("(GLfloat angle = %f, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", angle, x, y, z); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->rotate(angle, x, y, z); - } -} - -void Rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) -{ - Rotatef((float)angle / 0x10000, (float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000); -} - -void SampleCoverage(GLclampf value, GLboolean invert) -{ - TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert); - - es1::Context* context = es1::getContext(); - - if(context) - { - context->setSampleCoverageParams(es1::clamp01(value), invert == GL_TRUE); - } -} - -void SampleCoveragex(GLclampx value, GLboolean invert) -{ - SampleCoverage((float)value / 0x10000, invert); -} - -void Scalef(GLfloat x, GLfloat y, GLfloat z) -{ - TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", x, y, z); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->scale(x, y, z); - } -} - -void Scalex(GLfixed x, GLfixed y, GLfixed z) -{ - Scalef((float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000); -} - -void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) -{ - TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - - if(width < 0 || height < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context* context = es1::getContext(); - - if(context) - { - context->setScissorParams(x, y, width, height); - } -} - -void ShadeModel(GLenum mode) -{ - switch(mode) - { - case GL_FLAT: - case GL_SMOOTH: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setShadeModel(mode); - } -} - -void StencilFunc(GLenum func, GLint ref, GLuint mask) -{ - TRACE("(GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", func, ref, mask); - - switch(func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GEQUAL: - case GL_GREATER: - case GL_NOTEQUAL: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setStencilParams(func, ref, mask); - } -} - -void StencilMask(GLuint mask) -{ - TRACE("(GLuint mask = %d)", mask); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setStencilWritemask(mask); - } -} - -void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) -{ - TRACE("(GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", fail, zfail, zpass); - - switch(fail) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP_OES: - case GL_DECR_WRAP_OES: - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(zfail) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP_OES: - case GL_DECR_WRAP_OES: - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(zpass) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP_OES: - case GL_DECR_WRAP_OES: - break; - default: - return error(GL_INVALID_ENUM); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setStencilOperations(fail, zfail, zpass); - } -} - -void TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer); - - if(size < 2 || size > 4) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - GLenum texture = context->getClientActiveTexture(); - VertexAttribPointer(sw::TexCoord0 + (texture - GL_TEXTURE0), size, type, false, stride, pointer); - } -} - -void TexEnvi(GLenum target, GLenum pname, GLint param); - -void TexEnvf(GLenum target, GLenum pname, GLfloat param) -{ - TexEnvi(target, pname, (GLint)param); -} - -void TexEnvfv(GLenum target, GLenum pname, const GLfloat *params) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLfloat *params)", target, pname); - - es1::Context *context = es1::getContext(); - - if(context) - { - GLint iParam = (GLint)roundf(params[0]); - - switch(target) - { - case GL_POINT_SPRITE_OES: - UNIMPLEMENTED(); - break; - case GL_TEXTURE_ENV: - switch(pname) - { - case GL_TEXTURE_ENV_MODE: - switch(iParam) - { - case GL_REPLACE: - case GL_MODULATE: - case GL_DECAL: - case GL_BLEND: - case GL_ADD: - case GL_COMBINE: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setTextureEnvMode(iParam); - break; - case GL_TEXTURE_ENV_COLOR: - context->setTextureEnvColor(clamp01(params[0]), clamp01(params[1]), clamp01(params[2]), clamp01(params[3])); - break; - case GL_COMBINE_RGB: - switch(iParam) - { - case GL_REPLACE: - case GL_MODULATE: - case GL_ADD: - case GL_ADD_SIGNED: - case GL_INTERPOLATE: - case GL_SUBTRACT: - case GL_DOT3_RGB: - case GL_DOT3_RGBA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setCombineRGB(iParam); - break; - case GL_COMBINE_ALPHA: - switch(iParam) - { - case GL_REPLACE: - case GL_MODULATE: - case GL_ADD: - case GL_ADD_SIGNED: - case GL_INTERPOLATE: - case GL_SUBTRACT: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setCombineAlpha(iParam); - break; - case GL_RGB_SCALE: - if(iParam != 1 && iParam != 2 && iParam != 4) - { - return error(GL_INVALID_VALUE); - } - if(iParam != 1) UNIMPLEMENTED(); - break; - case GL_ALPHA_SCALE: - if(iParam != 1 && iParam != 2 && iParam != 4) - { - return error(GL_INVALID_VALUE); - } - if(iParam != 1) UNIMPLEMENTED(); - break; - case GL_OPERAND0_RGB: - switch(iParam) - { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand0RGB(iParam); - break; - case GL_OPERAND1_RGB: - switch(iParam) - { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand1RGB(iParam); - break; - case GL_OPERAND2_RGB: - switch(iParam) - { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand2RGB(iParam); - break; - case GL_OPERAND0_ALPHA: - switch(iParam) - { - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand0Alpha(iParam); - break; - case GL_OPERAND1_ALPHA: - switch(iParam) - { - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand1Alpha(iParam); - break; - case GL_OPERAND2_ALPHA: - switch(iParam) - { - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand2Alpha(iParam); - break; - case GL_SRC0_RGB: - switch(iParam) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc0RGB(iParam); - break; - case GL_SRC1_RGB: - switch(iParam) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc1RGB(iParam); - break; - case GL_SRC2_RGB: - switch(iParam) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc2RGB(iParam); - break; - case GL_SRC0_ALPHA: - switch(iParam) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc0Alpha(iParam); - break; - case GL_SRC1_ALPHA: - switch(iParam) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc1Alpha(iParam); - break; - case GL_SRC2_ALPHA: - switch(iParam) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc2Alpha(iParam); - break; - default: - return error(GL_INVALID_ENUM); - } - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void TexEnvi(GLenum target, GLenum pname, GLint param) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(target) - { - case GL_POINT_SPRITE_OES: - UNIMPLEMENTED(); - break; - case GL_TEXTURE_ENV: - switch(pname) - { - case GL_TEXTURE_ENV_MODE: - switch((GLenum)param) - { - case GL_REPLACE: - case GL_MODULATE: - case GL_DECAL: - case GL_BLEND: - case GL_ADD: - case GL_COMBINE: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setTextureEnvMode((GLenum)param); - break; - case GL_TEXTURE_ENV_COLOR: - return error(GL_INVALID_ENUM); // Needs four values, should call glTexEnviv() instead - break; - case GL_COMBINE_RGB: - switch((GLenum)param) - { - case GL_REPLACE: - case GL_MODULATE: - case GL_ADD: - case GL_ADD_SIGNED: - case GL_INTERPOLATE: - case GL_SUBTRACT: - case GL_DOT3_RGB: - case GL_DOT3_RGBA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setCombineRGB((GLenum)param); - break; - case GL_COMBINE_ALPHA: - switch((GLenum)param) - { - case GL_REPLACE: - case GL_MODULATE: - case GL_ADD: - case GL_ADD_SIGNED: - case GL_INTERPOLATE: - case GL_SUBTRACT: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setCombineAlpha((GLenum)param); - break; - case GL_RGB_SCALE: - if(param != 1 && param != 2 && param != 4) - { - return error(GL_INVALID_VALUE); - } - if(param != 1) UNIMPLEMENTED(); - break; - case GL_ALPHA_SCALE: - if(param != 1 && param != 2 && param != 4) - { - return error(GL_INVALID_VALUE); - } - if(param != 1) UNIMPLEMENTED(); - break; - case GL_OPERAND0_RGB: - switch((GLenum)param) - { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand0RGB((GLenum)param); - break; - case GL_OPERAND1_RGB: - switch((GLenum)param) - { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand1RGB((GLenum)param); - break; - case GL_OPERAND2_RGB: - switch((GLenum)param) - { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand2RGB((GLenum)param); - break; - case GL_OPERAND0_ALPHA: - switch((GLenum)param) - { - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand0Alpha((GLenum)param); - break; - case GL_OPERAND1_ALPHA: - switch((GLenum)param) - { - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand1Alpha((GLenum)param); - break; - case GL_OPERAND2_ALPHA: - switch((GLenum)param) - { - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setOperand2Alpha((GLenum)param); - break; - case GL_SRC0_RGB: - switch((GLenum)param) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc0RGB((GLenum)param); - break; - case GL_SRC1_RGB: - switch((GLenum)param) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc1RGB((GLenum)param); - break; - case GL_SRC2_RGB: - switch((GLenum)param) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc2RGB((GLenum)param); - break; - case GL_SRC0_ALPHA: - switch((GLenum)param) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc0Alpha((GLenum)param); - break; - case GL_SRC1_ALPHA: - switch((GLenum)param) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc1Alpha((GLenum)param); - break; - case GL_SRC2_ALPHA: - switch((GLenum)param) - { - case GL_TEXTURE: - case GL_CONSTANT: - case GL_PRIMARY_COLOR: - case GL_PREVIOUS: - break; - default: - error(GL_INVALID_ENUM); - } - - context->setSrc2Alpha((GLenum)param); - break; - default: - return error(GL_INVALID_ENUM); - } - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void TexEnvx(GLenum target, GLenum pname, GLfixed param) -{ - TexEnvi(target, pname, (GLint)param); -} - -void TexEnviv(GLenum target, GLenum pname, const GLint *params) -{ - UNIMPLEMENTED(); -} - -void TexEnvxv(GLenum target, GLenum pname, const GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid* pixels) -{ - TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " - "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = %p)", - target, level, internalformat, width, height, border, format, type, pixels); - - if(!validImageSize(level, width, height)) - { - return error(GL_INVALID_VALUE); - } - - if(internalformat != (GLint)format) - { - return error(GL_INVALID_OPERATION); - } - - switch(format) - { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - switch(type) - { - case GL_UNSIGNED_BYTE: - case GL_FLOAT: - break; - default: - return error(GL_INVALID_ENUM); - } - break; - case GL_RGB: - switch(type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_FLOAT: - break; - default: - return error(GL_INVALID_ENUM); - } - break; - case GL_RGBA: - switch(type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_FLOAT: - break; - default: - return error(GL_INVALID_ENUM); - } - break; - case GL_BGRA_EXT: - switch(type) - { - case GL_UNSIGNED_BYTE: - break; - default: - return error(GL_INVALID_ENUM); - } - break; - case GL_ETC1_RGB8_OES: - return error(GL_INVALID_OPERATION); - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if(S3TC_SUPPORT) - { - return error(GL_INVALID_OPERATION); - } - else - { - return error(GL_INVALID_ENUM); - } - case GL_DEPTH_STENCIL_OES: - switch(type) - { - case GL_UNSIGNED_INT_24_8_OES: - break; - default: - return error(GL_INVALID_ENUM); - } - break; - default: - return error(GL_INVALID_VALUE); - } - - if(border != 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - switch(target) - { - case GL_TEXTURE_2D: - if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) || - height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level)) - { - return error(GL_INVALID_VALUE); - } - break; - default: - return error(GL_INVALID_ENUM); - } - - if(target == GL_TEXTURE_2D) - { - es1::Texture2D *texture = context->getTexture2D(); - - if(!texture) - { - return error(GL_INVALID_OPERATION); - } - - texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels); - } - else UNREACHABLE(target); - } -} - -void TexParameterf(GLenum target, GLenum pname, GLfloat param) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Texture *texture; - - switch(target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_EXTERNAL_OES: - texture = context->getTextureExternal(); - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(pname) - { - case GL_TEXTURE_WRAP_S: - if(!texture->setWrapS((GLenum)param)) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_WRAP_T: - if(!texture->setWrapT((GLenum)param)) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MIN_FILTER: - if(!texture->setMinFilter((GLenum)param)) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAG_FILTER: - if(!texture->setMagFilter((GLenum)param)) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if(!texture->setMaxAnisotropy(param)) - { - return error(GL_INVALID_VALUE); - } - break; - case GL_GENERATE_MIPMAP: - texture->setGenerateMipmap((GLboolean)param); - break; - case GL_TEXTURE_CROP_RECT_OES: - return error(GL_INVALID_ENUM); // Needs four values, should call glTexParameterfv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) -{ - TexParameterf(target, pname, *params); -} - -void TexParameteri(GLenum target, GLenum pname, GLint param) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Texture *texture; - - switch(target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_EXTERNAL_OES: - texture = context->getTextureExternal(); - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(pname) - { - case GL_TEXTURE_WRAP_S: - if(!texture->setWrapS((GLenum)param)) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_WRAP_T: - if(!texture->setWrapT((GLenum)param)) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MIN_FILTER: - if(!texture->setMinFilter((GLenum)param)) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAG_FILTER: - if(!texture->setMagFilter((GLenum)param)) - { - return error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if(!texture->setMaxAnisotropy((GLfloat)param)) - { - return error(GL_INVALID_VALUE); - } - break; - case GL_GENERATE_MIPMAP: - texture->setGenerateMipmap((GLboolean)param); - break; - case GL_TEXTURE_CROP_RECT_OES: - return error(GL_INVALID_ENUM); // Needs four values, should call glTexParameteriv() instead - default: - return error(GL_INVALID_ENUM); - } - } -} - -void TexParameteriv(GLenum target, GLenum pname, const GLint* params) -{ - TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %p)", target, pname, params); - - switch(pname) - { - case GL_TEXTURE_CROP_RECT_OES: - break; - default: - return TexParameteri(target, pname, params[0]); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Texture *texture; - - switch(target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - default: - return error(GL_INVALID_ENUM); - } - - switch(pname) - { - case GL_TEXTURE_CROP_RECT_OES: - texture->setCropRect(params[0], params[1], params[2], params[3]); - break; - default: - return error(GL_INVALID_ENUM); - } - } -} - -void TexParameterx(GLenum target, GLenum pname, GLfixed param) -{ - TexParameteri(target, pname, (GLint)param); -} - -void TexParameterxv(GLenum target, GLenum pname, const GLfixed *params) -{ - UNIMPLEMENTED(); -} - -void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid* pixels) -{ - TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " - "const GLvoid* pixels = %p)", - target, level, xoffset, yoffset, width, height, format, type, pixels); - - if(!es1::IsTextureTarget(target)) - { - return error(GL_INVALID_ENUM); - } - - if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - return error(GL_INVALID_VALUE); - } - - if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0) - { - return error(GL_INVALID_VALUE); - } - - if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) - { - return error(GL_INVALID_VALUE); - } - - if(!es1::CheckTextureFormatType(format, type)) - { - return error(GL_INVALID_ENUM); - } - - if(width == 0 || height == 0 || !pixels) - { - return; - } - - es1::Context *context = es1::getContext(); - - if(context) - { - if(target == GL_TEXTURE_2D) - { - es1::Texture2D *texture = context->getTexture2D(); - - if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture)) - { - texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); - } - } - else UNREACHABLE(target); - } -} - -void Translatef(GLfloat x, GLfloat y, GLfloat z) -{ - TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", x, y, z); - - es1::Context *context = es1::getContext(); - - if(context) - { - context->translate(x, y, z); - } -} - -void Translatex(GLfixed x, GLfixed y, GLfixed z) -{ - Translatef((float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000); -} - -void VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer); - - if(size < 2 || size > 4) - { - return error(GL_INVALID_VALUE); - } - - VertexAttribPointer(sw::Position, size, type, false, stride, pointer); -} - -void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) -{ - TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - - if(width < 0 || height < 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->setViewportParams(x, y, width, height); - } -} - -void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) -{ - TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image); - - switch(target) - { - case GL_TEXTURE_2D: - case GL_TEXTURE_EXTERNAL_OES: - break; - default: - return error(GL_INVALID_ENUM); - } - - if(!image) - { - return error(GL_INVALID_OPERATION); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - es1::Texture2D *texture = 0; - - switch(target) - { - case GL_TEXTURE_2D: texture = context->getTexture2D(); break; - case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break; - default: UNREACHABLE(target); - } - - if(!texture) - { - return error(GL_INVALID_OPERATION); - } - - egl::Image *glImage = static_cast<egl::Image*>(image); - - texture->setImage(glImage); - } -} - -void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) -{ - TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image); - - UNIMPLEMENTED(); -} - -void DrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) -{ - UNIMPLEMENTED(); -} - -void DrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) -{ - TRACE("(GLint x = %d, GLint y = %d, GLint z = %d, GLint width = %d, GLint height = %d)", x, y, z, width, height); - - if(width <= 0 || height <= 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->drawTexture((GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)width, (GLfloat)height); - } -} - -void DrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) -{ - UNIMPLEMENTED(); -} - -void DrawTexsvOES(const GLshort *coords) -{ - UNIMPLEMENTED(); -} - -void DrawTexivOES(const GLint *coords) -{ - UNIMPLEMENTED(); -} - -void DrawTexxvOES(const GLfixed *coords) -{ - UNIMPLEMENTED(); -} - -void DrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) -{ - TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat width = %f, GLfloat height = %f)", x, y, z, width, height); - - if(width <= 0 || height <= 0) - { - return error(GL_INVALID_VALUE); - } - - es1::Context *context = es1::getContext(); - - if(context) - { - context->drawTexture(x, y, z, width, height); - } -} - -void DrawTexfvOES(const GLfloat *coords) -{ - UNIMPLEMENTED(); -} - -} - -extern "C" __eglMustCastToProperFunctionPointerType es1GetProcAddress(const char *procname) -{ - struct Extension - { - const char *name; - __eglMustCastToProperFunctionPointerType address; - }; - - static const Extension glExtensions[] = - { - #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name} - - EXTENSION(glEGLImageTargetTexture2DOES), - EXTENSION(glEGLImageTargetRenderbufferStorageOES), - EXTENSION(glIsRenderbufferOES), - EXTENSION(glBindRenderbufferOES), - EXTENSION(glDeleteRenderbuffersOES), - EXTENSION(glGenRenderbuffersOES), - EXTENSION(glRenderbufferStorageOES), - EXTENSION(glGetRenderbufferParameterivOES), - EXTENSION(glIsFramebufferOES), - EXTENSION(glBindFramebufferOES), - EXTENSION(glDeleteFramebuffersOES), - EXTENSION(glGenFramebuffersOES), - EXTENSION(glCheckFramebufferStatusOES), - EXTENSION(glFramebufferRenderbufferOES), - EXTENSION(glFramebufferTexture2DOES), - EXTENSION(glGetFramebufferAttachmentParameterivOES), - EXTENSION(glGenerateMipmapOES), - EXTENSION(glBlendEquationOES), - EXTENSION(glBlendEquationSeparateOES), - EXTENSION(glBlendFuncSeparateOES), - EXTENSION(glPointSizePointerOES), - - #undef EXTENSION - }; - - for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++) - { - if(strcmp(procname, glExtensions[ext].name) == 0) - { - return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address; - } - } - - return NULL; -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// libGLES_CM.cpp: Implements the exported OpenGL ES 1.1 functions. + +#include "main.h" +#include "mathutil.h" +#include "utilities.h" +#include "Buffer.h" +#include "Context.h" +#include "Framebuffer.h" +#include "Renderbuffer.h" +#include "Texture.h" +#include "common/debug.h" +#include "Common/SharedLibrary.hpp" +#include "Common/Version.h" + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <GLES/gl.h> +#include <GLES/glext.h> + +#include <limits> + +namespace es1 +{ + +static bool validImageSize(GLint level, GLsizei width, GLsizei height) +{ + if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0) + { + return false; + } + + return true; +} + +static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, es1::Texture *texture) +{ + if(!texture) + { + return error(GL_INVALID_OPERATION, false); + } + + if(compressed != texture->isCompressed(target, level)) + { + return error(GL_INVALID_OPERATION, false); + } + + if(format != GL_NONE_OES && format != texture->getFormat(target, level)) + { + return error(GL_INVALID_OPERATION, false); + } + + if(compressed) + { + if((width % 4 != 0 && width != texture->getWidth(target, 0)) || + (height % 4 != 0 && height != texture->getHeight(target, 0))) + { + return error(GL_INVALID_OPERATION, false); + } + } + + if(xoffset + width > texture->getWidth(target, level) || + yoffset + height > texture->getHeight(target, level)) + { + return error(GL_INVALID_VALUE, false); + } + + return true; +} + +void ActiveTexture(GLenum texture) +{ + TRACE("(GLenum texture = 0x%X)", texture); + + es1::Context *context = es1::getContext(); + + if(context) + { + if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es1::MAX_TEXTURE_UNITS - 1) + { + return error(GL_INVALID_ENUM); + } + + context->setActiveSampler(texture - GL_TEXTURE0); + } +} + +void AlphaFunc(GLenum func, GLclampf ref) +{ + TRACE("(GLenum func = 0x%X, GLclampf ref = %f)", func, ref); + + switch(func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setAlphaFunc(func, clamp01(ref)); + } +} + +void AlphaFuncx(GLenum func, GLclampx ref) +{ + AlphaFunc(func, (float)ref / 0x10000); +} + +void BindBuffer(GLenum target, GLuint buffer) +{ + TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(target) + { + case GL_ARRAY_BUFFER: + context->bindArrayBuffer(buffer); + return; + case GL_ELEMENT_ARRAY_BUFFER: + context->bindElementArrayBuffer(buffer); + return; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void BindFramebuffer(GLenum target, GLuint framebuffer) +{ + TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); + + if(target != GL_FRAMEBUFFER_OES) + { + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->bindFramebuffer(framebuffer); + } +} + +void BindFramebufferOES(GLenum target, GLuint framebuffer) +{ + TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); + + if(target != GL_FRAMEBUFFER_OES) + { + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->bindFramebuffer(framebuffer); + } +} + +void BindRenderbufferOES(GLenum target, GLuint renderbuffer) +{ + TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); + + if(target != GL_RENDERBUFFER_OES) + { + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + if(renderbuffer != 0 && !context->getRenderbuffer(renderbuffer)) + { + // [OpenGL ES 2.0.25] Section 4.4.3 page 112 + // [OpenGL ES 3.0.2] Section 4.4.2 page 201 + // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of + // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated. + return error(GL_INVALID_OPERATION); + } + + context->bindRenderbuffer(renderbuffer); + } +} + +void BindTexture(GLenum target, GLuint texture) +{ + TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Texture *textureObject = context->getTexture(texture); + + if(textureObject && textureObject->getTarget() != target && texture != 0) + { + return error(GL_INVALID_OPERATION); + } + + switch(target) + { + case GL_TEXTURE_2D: + context->bindTexture2D(texture); + return; + case GL_TEXTURE_EXTERNAL_OES: + context->bindTextureExternal(texture); + return; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha); + +void BlendEquationOES(GLenum mode) +{ + BlendEquationSeparateOES(mode, mode); +} + +void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha) +{ + TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); + + switch(modeRGB) + { + case GL_FUNC_ADD_OES: + case GL_FUNC_SUBTRACT_OES: + case GL_FUNC_REVERSE_SUBTRACT_OES: + case GL_MIN_EXT: + case GL_MAX_EXT: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(modeAlpha) + { + case GL_FUNC_ADD_OES: + case GL_FUNC_SUBTRACT_OES: + case GL_FUNC_REVERSE_SUBTRACT_OES: + case GL_MIN_EXT: + case GL_MAX_EXT: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setBlendEquation(modeRGB, modeAlpha); + } +} + +void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + +void BlendFunc(GLenum sfactor, GLenum dfactor) +{ + BlendFuncSeparateOES(sfactor, dfactor, sfactor, dfactor); +} + +void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", + srcRGB, dstRGB, srcAlpha, dstAlpha); + + switch(srcRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(dstRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(srcAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(dstAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); + } +} + +void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +{ + size = static_cast<GLint>(size); // Work around issues with some 64-bit applications + + TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)", + target, size, data, usage); + + if(size < 0) + { + return error(GL_INVALID_VALUE); + } + + switch(usage) + { + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Buffer *buffer; + + switch(target) + { + case GL_ARRAY_BUFFER: + buffer = context->getArrayBuffer(); + break; + case GL_ELEMENT_ARRAY_BUFFER: + buffer = context->getElementArrayBuffer(); + break; + default: + return error(GL_INVALID_ENUM); + } + + if(!buffer) + { + return error(GL_INVALID_OPERATION); + } + + buffer->bufferData(data, size, usage); + } +} + +void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) +{ + size = static_cast<GLint>(size); // Work around issues with some 64-bit applications + offset = static_cast<GLint>(offset); + + TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)", + target, offset, size, data); + + if(size < 0 || offset < 0) + { + return error(GL_INVALID_VALUE); + } + + if(!data) + { + return; + } + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Buffer *buffer; + + switch(target) + { + case GL_ARRAY_BUFFER: + buffer = context->getArrayBuffer(); + break; + case GL_ELEMENT_ARRAY_BUFFER: + buffer = context->getElementArrayBuffer(); + break; + default: + return error(GL_INVALID_ENUM); + } + + if(!buffer) + { + return error(GL_INVALID_OPERATION); + } + + if((size_t)size + offset > buffer->size()) + { + return error(GL_INVALID_VALUE); + } + + buffer->bufferSubData(data, size, offset); + } +} + +GLenum CheckFramebufferStatusOES(GLenum target) +{ + TRACE("(GLenum target = 0x%X)", target); + + if(target != GL_FRAMEBUFFER_OES) + { + return error(GL_INVALID_ENUM, 0); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Framebuffer *framebuffer = context->getFramebuffer(); + + return framebuffer->completeness(); + } + + return 0; +} + +void Clear(GLbitfield mask) +{ + TRACE("(GLbitfield mask = %X)", mask); + + if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->clear(mask); + } +} + +void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", + red, green, blue, alpha); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setClearColor(red, green, blue, alpha); + } +} + +void ClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) +{ + ClearColor((float)red / 0x10000, (float)green / 0x10000, (float)blue / 0x10000, (float)alpha / 0x10000); +} + +void ClearDepthf(GLclampf depth) +{ + TRACE("(GLclampf depth = %f)", depth); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setClearDepth(depth); + } +} + +void ClearDepthx(GLclampx depth) +{ + ClearDepthf((float)depth / 0x10000); +} + +void ClearStencil(GLint s) +{ + TRACE("(GLint s = %d)", s); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setClearStencil(s); + } +} + +void ClientActiveTexture(GLenum texture) +{ + TRACE("(GLenum texture = 0x%X)", texture); + + switch(texture) + { + case GL_TEXTURE0: + case GL_TEXTURE1: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->clientActiveTexture(texture); + } +} + +void ClipPlanef(GLenum plane, const GLfloat *equation) +{ + TRACE("(GLenum plane = 0x%X, const GLfloat *equation)", plane); + + int index = plane - GL_CLIP_PLANE0; + + if(index < 0 || index >= MAX_CLIP_PLANES) + { + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setClipPlane(index, equation); + } +} + +void ClipPlanex(GLenum plane, const GLfixed *equation) +{ + GLfloat equationf[4] = + { + (float)equation[0] / 0x10000, + (float)equation[1] / 0x10000, + (float)equation[2] / 0x10000, + (float)equation[3] / 0x10000, + }; + + ClipPlanef(plane, equationf); +} + +void Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + TRACE("(GLfloat red = %f, GLfloat green = %f, GLfloat blue = %f, GLfloat alpha = %f)", red, green, blue, alpha); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setVertexAttrib(sw::Color0, red, green, blue, alpha); + } +} + +void Color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) +{ + Color4f((float)red / 0xFF, (float)green / 0xFF, (float)blue / 0xFF, (float)alpha / 0xFF); +} + +void Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +{ + Color4f((float)red / 0x10000, (float)green / 0x10000, (float)blue / 0x10000, (float)alpha / 0x10000); +} + +void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)", + red, green, blue, alpha); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); + } +} + +void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +{ + TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " + "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)", + index, size, type, normalized, stride, ptr); + + if(index >= es1::MAX_VERTEX_ATTRIBS) + { + return error(GL_INVALID_VALUE); + } + + if(size < 1 || size > 4) + { + return error(GL_INVALID_VALUE); + } + + switch(type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_FIXED: + case GL_FLOAT: + break; + default: + return error(GL_INVALID_ENUM); + } + + if(stride < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr); + } +} + +void ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer); + + if(size != 4) + { + return error(GL_INVALID_VALUE); + } + + VertexAttribPointer(sw::Color0, size, type, true, stride, pointer); +} + +void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid* data) +{ + TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)", + target, level, internalformat, width, height, border, imageSize, data); + + if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return error(GL_INVALID_VALUE); + } + + if(!validImageSize(level, width, height) || imageSize < 0) + { + return error(GL_INVALID_VALUE); + } + + switch(internalformat) + { + case GL_ETC1_RGB8_OES: + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if(!S3TC_SUPPORT) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_DEPTH_COMPONENT16_OES: + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH_STENCIL_OES: + case GL_DEPTH24_STENCIL8_OES: + return error(GL_INVALID_OPERATION); + default: + return error(GL_INVALID_ENUM); + } + + if(border != 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(target) + { + case GL_TEXTURE_2D: + if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) || + height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + if(imageSize != egl::ComputeCompressedSize(width, height, internalformat)) + { + return error(GL_INVALID_VALUE); + } + + if(target == GL_TEXTURE_2D) + { + es1::Texture2D *texture = context->getTexture2D(); + + if(!texture) + { + return error(GL_INVALID_OPERATION); + } + + texture->setCompressedImage(level, internalformat, width, height, imageSize, data); + } + else UNREACHABLE(target); + } +} + +void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, const GLvoid* data) +{ + TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, " + "GLsizei imageSize = %d, const GLvoid* data = %p)", + target, level, xoffset, yoffset, width, height, format, imageSize, data); + + if(!es1::IsTextureTarget(target)) + { + return error(GL_INVALID_ENUM); + } + + if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return error(GL_INVALID_VALUE); + } + + if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0) + { + return error(GL_INVALID_VALUE); + } + + switch(format) + { + case GL_ETC1_RGB8_OES: + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if(!S3TC_SUPPORT) + { + return error(GL_INVALID_ENUM); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + if(width == 0 || height == 0 || !data) + { + return; + } + + es1::Context *context = es1::getContext(); + + if(context) + { + if(imageSize != egl::ComputeCompressedSize(width, height, format)) + { + return error(GL_INVALID_VALUE); + } + + if(xoffset % 4 != 0 || yoffset % 4 != 0) + { + // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported + return error(GL_INVALID_OPERATION); + } + + if(target == GL_TEXTURE_2D) + { + es1::Texture2D *texture = context->getTexture2D(); + + if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture)) + { + texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); + } + } + else UNREACHABLE(target); + } +} + +void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " + "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", + target, level, internalformat, x, y, width, height, border); + + if(!validImageSize(level, width, height)) + { + return error(GL_INVALID_VALUE); + } + + if(border != 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(target) + { + case GL_TEXTURE_2D: + if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) || + height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Framebuffer *framebuffer = context->getFramebuffer(); + + if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE_OES) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES); + } + + if(context->getFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1) + { + return error(GL_INVALID_OPERATION); + } + + es1::Renderbuffer *source = framebuffer->getColorbuffer(); + GLenum colorbufferFormat = source->getFormat(); + + // [OpenGL ES 2.0.24] table 3.9 + switch(internalformat) + { + case GL_ALPHA: + if(colorbufferFormat != GL_ALPHA && + colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4_OES && + colorbufferFormat != GL_RGB5_A1_OES && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_LUMINANCE: + case GL_RGB: + if(colorbufferFormat != GL_RGB && + colorbufferFormat != GL_RGB565_OES && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4_OES && + colorbufferFormat != GL_RGB5_A1_OES && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + if(colorbufferFormat != GL_RGBA && + colorbufferFormat != GL_RGBA4_OES && + colorbufferFormat != GL_RGB5_A1_OES && + colorbufferFormat != GL_RGBA8_OES) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_ETC1_RGB8_OES: + return error(GL_INVALID_OPERATION); + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if(S3TC_SUPPORT) + { + return error(GL_INVALID_OPERATION); + } + else + { + return error(GL_INVALID_ENUM); + } + default: + return error(GL_INVALID_ENUM); + } + + if(target == GL_TEXTURE_2D) + { + es1::Texture2D *texture = context->getTexture2D(); + + if(!texture) + { + return error(GL_INVALID_OPERATION); + } + + texture->copyImage(level, internalformat, x, y, width, height, framebuffer); + } + else UNREACHABLE(target); + } +} + +void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, level, xoffset, yoffset, x, y, width, height); + + if(!es1::IsTextureTarget(target)) + { + return error(GL_INVALID_ENUM); + } + + if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return error(GL_INVALID_VALUE); + } + + if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) + { + return error(GL_INVALID_VALUE); + } + + if(width == 0 || height == 0) + { + return; + } + + es1::Context *context = es1::getContext(); + + if(context) + { + + es1::Framebuffer *framebuffer = context->getFramebuffer(); + + if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE_OES) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION_OES); + } + + es1::Renderbuffer *source = framebuffer->getColorbuffer(); + + if(context->getFramebufferName() != 0 && (!source || source->getSamples() > 1)) + { + return error(GL_INVALID_OPERATION); + } + + es1::Texture *texture = nullptr; + + if(target == GL_TEXTURE_2D) + { + texture = context->getTexture2D(); + } + else UNREACHABLE(target); + + if(!validateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE_OES, texture)) + { + return; + } + + texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer); + } +} + +void CullFace(GLenum mode) +{ + TRACE("(GLenum mode = 0x%X)", mode); + + switch(mode) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + { + es1::Context *context = es1::getContext(); + + if(context) + { + context->setCullMode(mode); + } + } + break; + default: + return error(GL_INVALID_ENUM); + } +} + +void DeleteBuffers(GLsizei n, const GLuint* buffers) +{ + TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers); + + if(n < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + for(int i = 0; i < n; i++) + { + context->deleteBuffer(buffers[i]); + } + } +} + +void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers) +{ + TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers); + + if(n < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + for(int i = 0; i < n; i++) + { + if(framebuffers[i] != 0) + { + context->deleteFramebuffer(framebuffers[i]); + } + } + } +} + +void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers) +{ + TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers); + + if(n < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + for(int i = 0; i < n; i++) + { + context->deleteRenderbuffer(renderbuffers[i]); + } + } +} + +void DeleteTextures(GLsizei n, const GLuint* textures) +{ + TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures); + + if(n < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + for(int i = 0; i < n; i++) + { + if(textures[i] != 0) + { + context->deleteTexture(textures[i]); + } + } + } +} + +void DepthFunc(GLenum func) +{ + TRACE("(GLenum func = 0x%X)", func); + + switch(func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_NOTEQUAL: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setDepthFunc(func); + } +} + +void DepthMask(GLboolean flag) +{ + TRACE("(GLboolean flag = %d)", flag); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setDepthMask(flag != GL_FALSE); + } +} + +void DepthRangef(GLclampf zNear, GLclampf zFar) +{ + TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setDepthRange(zNear, zFar); + } +} + +void DepthRangex(GLclampx zNear, GLclampx zFar) +{ + DepthRangef((float)zNear / 0x10000, (float)zFar / 0x10000); +} + +void Disable(GLenum cap) +{ + TRACE("(GLenum cap = 0x%X)", cap); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(cap) + { + case GL_CULL_FACE: context->setCullFaceEnabled(false); break; + case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break; + case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break; + case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break; + case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break; + case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break; + case GL_BLEND: context->setBlendEnabled(false); break; + case GL_DITHER: context->setDitherEnabled(false); break; + case GL_LIGHTING: context->setLightingEnabled(false); break; + case GL_LIGHT0: context->setLightEnabled(0, false); break; + case GL_LIGHT1: context->setLightEnabled(1, false); break; + case GL_LIGHT2: context->setLightEnabled(2, false); break; + case GL_LIGHT3: context->setLightEnabled(3, false); break; + case GL_LIGHT4: context->setLightEnabled(4, false); break; + case GL_LIGHT5: context->setLightEnabled(5, false); break; + case GL_LIGHT6: context->setLightEnabled(6, false); break; + case GL_LIGHT7: context->setLightEnabled(7, false); break; + case GL_FOG: context->setFogEnabled(false); break; + case GL_TEXTURE_2D: context->setTexture2Denabled(false); break; + case GL_TEXTURE_EXTERNAL_OES: context->setTextureExternalEnabled(false); break; + case GL_ALPHA_TEST: context->setAlphaTestEnabled(false); break; + case GL_COLOR_LOGIC_OP: context->setColorLogicOpEnabled(false); break; + case GL_POINT_SMOOTH: context->setPointSmoothEnabled(false); break; + case GL_LINE_SMOOTH: context->setLineSmoothEnabled(false); break; + case GL_COLOR_MATERIAL: context->setColorMaterialEnabled(false); break; + case GL_NORMALIZE: context->setNormalizeEnabled(false); break; + case GL_RESCALE_NORMAL: context->setRescaleNormalEnabled(false); break; + case GL_VERTEX_ARRAY: context->setVertexArrayEnabled(false); break; + case GL_NORMAL_ARRAY: context->setNormalArrayEnabled(false); break; + case GL_COLOR_ARRAY: context->setColorArrayEnabled(false); break; + case GL_POINT_SIZE_ARRAY_OES: context->setPointSizeArrayEnabled(false); break; + case GL_TEXTURE_COORD_ARRAY: context->setTextureCoordArrayEnabled(false); break; + case GL_MULTISAMPLE: context->setMultisampleEnabled(false); break; + case GL_SAMPLE_ALPHA_TO_ONE: context->setSampleAlphaToOneEnabled(false); break; + case GL_CLIP_PLANE0: context->setClipPlaneEnabled(0, false); break; + case GL_CLIP_PLANE1: context->setClipPlaneEnabled(1, false); break; + case GL_CLIP_PLANE2: context->setClipPlaneEnabled(2, false); break; + case GL_CLIP_PLANE3: context->setClipPlaneEnabled(3, false); break; + case GL_CLIP_PLANE4: context->setClipPlaneEnabled(4, false); break; + case GL_CLIP_PLANE5: context->setClipPlaneEnabled(5, false); break; + case GL_POINT_SPRITE_OES: context->setPointSpriteEnabled(false); break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void DisableClientState(GLenum array) +{ + TRACE("(GLenum array = 0x%X)", array); + + switch(array) + { + case GL_VERTEX_ARRAY: + case GL_NORMAL_ARRAY: + case GL_COLOR_ARRAY: + case GL_POINT_SIZE_ARRAY_OES: + case GL_TEXTURE_COORD_ARRAY: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + GLenum texture = context->getClientActiveTexture(); + + switch(array) + { + case GL_VERTEX_ARRAY: context->setVertexAttribArrayEnabled(sw::Position, false); break; + case GL_NORMAL_ARRAY: context->setVertexAttribArrayEnabled(sw::Normal, false); break; + case GL_COLOR_ARRAY: context->setVertexAttribArrayEnabled(sw::Color0, false); break; + case GL_POINT_SIZE_ARRAY_OES: context->setVertexAttribArrayEnabled(sw::PointSize, false); break; + case GL_TEXTURE_COORD_ARRAY: context->setVertexAttribArrayEnabled(sw::TexCoord0 + (texture - GL_TEXTURE0), false); break; + default: UNREACHABLE(array); + } + } +} + +void DrawArrays(GLenum mode, GLint first, GLsizei count) +{ + TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); + + if(count < 0 || first < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->drawArrays(mode, first, count); + } +} + +void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) +{ + TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)", + mode, count, type, indices); + + if(count < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + case GL_UNSIGNED_INT: + break; + default: + return error(GL_INVALID_ENUM); + } + + context->drawElements(mode, count, type, indices); + } +} + +void Enable(GLenum cap) +{ + TRACE("(GLenum cap = 0x%X)", cap); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(cap) + { + case GL_CULL_FACE: context->setCullFaceEnabled(true); break; + case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break; + case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break; + case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break; + case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break; + case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break; + case GL_BLEND: context->setBlendEnabled(true); break; + case GL_DITHER: context->setDitherEnabled(true); break; + case GL_LIGHTING: context->setLightingEnabled(true); break; + case GL_LIGHT0: context->setLightEnabled(0, true); break; + case GL_LIGHT1: context->setLightEnabled(1, true); break; + case GL_LIGHT2: context->setLightEnabled(2, true); break; + case GL_LIGHT3: context->setLightEnabled(3, true); break; + case GL_LIGHT4: context->setLightEnabled(4, true); break; + case GL_LIGHT5: context->setLightEnabled(5, true); break; + case GL_LIGHT6: context->setLightEnabled(6, true); break; + case GL_LIGHT7: context->setLightEnabled(7, true); break; + case GL_FOG: context->setFogEnabled(true); break; + case GL_TEXTURE_2D: context->setTexture2Denabled(true); break; + case GL_TEXTURE_EXTERNAL_OES: context->setTextureExternalEnabled(true); break; + case GL_ALPHA_TEST: context->setAlphaTestEnabled(true); break; + case GL_COLOR_LOGIC_OP: context->setColorLogicOpEnabled(true); break; + case GL_POINT_SMOOTH: context->setPointSmoothEnabled(true); break; + case GL_LINE_SMOOTH: context->setLineSmoothEnabled(true); break; + case GL_COLOR_MATERIAL: context->setColorMaterialEnabled(true); break; + case GL_NORMALIZE: context->setNormalizeEnabled(true); break; + case GL_RESCALE_NORMAL: context->setRescaleNormalEnabled(true); break; + case GL_VERTEX_ARRAY: context->setVertexArrayEnabled(true); break; + case GL_NORMAL_ARRAY: context->setNormalArrayEnabled(true); break; + case GL_COLOR_ARRAY: context->setColorArrayEnabled(true); break; + case GL_POINT_SIZE_ARRAY_OES: context->setPointSizeArrayEnabled(true); break; + case GL_TEXTURE_COORD_ARRAY: context->setTextureCoordArrayEnabled(true); break; + case GL_MULTISAMPLE: context->setMultisampleEnabled(true); break; + case GL_SAMPLE_ALPHA_TO_ONE: context->setSampleAlphaToOneEnabled(true); break; + case GL_CLIP_PLANE0: context->setClipPlaneEnabled(0, true); break; + case GL_CLIP_PLANE1: context->setClipPlaneEnabled(1, true); break; + case GL_CLIP_PLANE2: context->setClipPlaneEnabled(2, true); break; + case GL_CLIP_PLANE3: context->setClipPlaneEnabled(3, true); break; + case GL_CLIP_PLANE4: context->setClipPlaneEnabled(4, true); break; + case GL_CLIP_PLANE5: context->setClipPlaneEnabled(5, true); break; + case GL_POINT_SPRITE_OES: context->setPointSpriteEnabled(true); break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void EnableClientState(GLenum array) +{ + TRACE("(GLenum array = 0x%X)", array); + + switch(array) + { + case GL_VERTEX_ARRAY: + case GL_NORMAL_ARRAY: + case GL_COLOR_ARRAY: + case GL_POINT_SIZE_ARRAY_OES: + case GL_TEXTURE_COORD_ARRAY: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + GLenum texture = context->getClientActiveTexture(); + + switch(array) + { + case GL_VERTEX_ARRAY: context->setVertexAttribArrayEnabled(sw::Position, true); break; + case GL_NORMAL_ARRAY: context->setVertexAttribArrayEnabled(sw::Normal, true); break; + case GL_COLOR_ARRAY: context->setVertexAttribArrayEnabled(sw::Color0, true); break; + case GL_POINT_SIZE_ARRAY_OES: context->setVertexAttribArrayEnabled(sw::PointSize, true); break; + case GL_TEXTURE_COORD_ARRAY: context->setVertexAttribArrayEnabled(sw::TexCoord0 + (texture - GL_TEXTURE0), true); break; + default: UNREACHABLE(array); + } + } +} + +void Finish(void) +{ + TRACE("()"); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->finish(); + } +} + +void Flush(void) +{ + TRACE("()"); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->flush(); + } +} + +void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " + "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); + + if(target != GL_FRAMEBUFFER_OES || (renderbuffertarget != GL_RENDERBUFFER_OES && renderbuffer != 0)) + { + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Framebuffer *framebuffer = context->getFramebuffer(); + GLuint framebufferName = context->getFramebufferName(); + + if(!framebuffer || (framebufferName == 0 && renderbuffer != 0)) + { + return error(GL_INVALID_OPERATION); + } + + switch(attachment) + { + case GL_COLOR_ATTACHMENT0_OES: + framebuffer->setColorbuffer(GL_RENDERBUFFER_OES, renderbuffer); + break; + case GL_DEPTH_ATTACHMENT_OES: + framebuffer->setDepthbuffer(GL_RENDERBUFFER_OES, renderbuffer); + break; + case GL_STENCIL_ATTACHMENT_OES: + framebuffer->setStencilbuffer(GL_RENDERBUFFER_OES, renderbuffer); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " + "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); + + if(target != GL_FRAMEBUFFER_OES) + { + return error(GL_INVALID_ENUM); + } + + switch(attachment) + { + case GL_COLOR_ATTACHMENT0_OES: + case GL_DEPTH_ATTACHMENT_OES: + case GL_STENCIL_ATTACHMENT_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + if(texture == 0) + { + textarget = GL_NONE_OES; + } + else + { + es1::Texture *tex = context->getTexture(texture); + + if(!tex) + { + return error(GL_INVALID_OPERATION); + } + + if(tex->isCompressed(textarget, level)) + { + return error(GL_INVALID_OPERATION); + } + + switch(textarget) + { + case GL_TEXTURE_2D: + if(tex->getTarget() != GL_TEXTURE_2D) + { + return error(GL_INVALID_OPERATION); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + if(level != 0) + { + return error(GL_INVALID_VALUE); + } + } + + es1::Framebuffer *framebuffer = context->getFramebuffer(); + GLuint framebufferName = context->getFramebufferName(); + + if(framebufferName == 0 || !framebuffer) + { + return error(GL_INVALID_OPERATION); + } + + switch(attachment) + { + case GL_COLOR_ATTACHMENT0_OES: framebuffer->setColorbuffer(textarget, texture); break; + case GL_DEPTH_ATTACHMENT_OES: framebuffer->setDepthbuffer(textarget, texture); break; + case GL_STENCIL_ATTACHMENT_OES: framebuffer->setStencilbuffer(textarget, texture); break; + } + } +} + +void Fogf(GLenum pname, GLfloat param) +{ + TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_FOG_MODE: + switch((GLenum)param) + { + case GL_LINEAR: + case GL_EXP: + case GL_EXP2: + context->setFogMode((GLenum)param); + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_FOG_DENSITY: + if(param < 0) + { + return error(GL_INVALID_VALUE); + } + context->setFogDensity(param); + break; + case GL_FOG_START: + context->setFogStart(param); + break; + case GL_FOG_END: + context->setFogEnd(param); + break; + case GL_FOG_COLOR: + return error(GL_INVALID_ENUM); // Need four values, should call glFogfv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Fogfv(GLenum pname, const GLfloat *params) +{ + TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_FOG_MODE: + switch((GLenum)params[0]) + { + case GL_LINEAR: + case GL_EXP: + case GL_EXP2: + context->setFogMode((GLenum)params[0]); + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_FOG_DENSITY: + if(params[0] < 0) + { + return error(GL_INVALID_VALUE); + } + context->setFogDensity(params[0]); + break; + case GL_FOG_START: + context->setFogStart(params[0]); + break; + case GL_FOG_END: + context->setFogEnd(params[0]); + break; + case GL_FOG_COLOR: + context->setFogColor(params[0], params[1], params[2], params[3]); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Fogx(GLenum pname, GLfixed param) +{ + TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_FOG_MODE: + switch((GLenum)param) + { + case GL_LINEAR: + case GL_EXP: + case GL_EXP2: + context->setFogMode((GLenum)param); + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_FOG_DENSITY: + if(param < 0) + { + return error(GL_INVALID_VALUE); + } + context->setFogDensity((float)param / 0x10000); + break; + case GL_FOG_START: + context->setFogStart((float)param / 0x10000); + break; + case GL_FOG_END: + context->setFogEnd((float)param / 0x10000); + break; + case GL_FOG_COLOR: + return error(GL_INVALID_ENUM); // Need four values, should call glFogxv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Fogxv(GLenum pname, const GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void FrontFace(GLenum mode) +{ + TRACE("(GLenum mode = 0x%X)", mode); + + switch(mode) + { + case GL_CW: + case GL_CCW: + { + es1::Context *context = es1::getContext(); + + if(context) + { + context->setFrontFace(mode); + } + } + break; + default: + return error(GL_INVALID_ENUM); + } +} + +void Frustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + TRACE("(GLfloat left = %f, GLfloat right = %f, GLfloat bottom = %f, GLfloat top = %f, GLfloat zNear = %f, GLfloat zFar = %f)", left, right, bottom, top, zNear, zFar); + + if(zNear <= 0.0f || zFar <= 0.0f || left == right || bottom == top || zNear == zFar) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->frustum(left, right, bottom, top, zNear, zFar); + } +} + +void Frustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +{ + Frustumf((float)left / 0x10000, (float)right / 0x10000, (float)bottom / 0x10000, (float)top / 0x10000, (float)zNear / 0x10000, (float)zFar / 0x10000); +} + +void GenerateMipmapOES(GLenum target) +{ + TRACE("(GLenum target = 0x%X)", target); + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Texture *texture; + + switch(target) + { + case GL_TEXTURE_2D: + texture = context->getTexture2D(); + break; + default: + return error(GL_INVALID_ENUM); + } + + if(texture->isCompressed(target, 0) || texture->isDepth(target, 0)) + { + return error(GL_INVALID_OPERATION); + } + + texture->generateMipmaps(); + } +} + +void GenBuffers(GLsizei n, GLuint* buffers) +{ + TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers); + + if(n < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + for(int i = 0; i < n; i++) + { + buffers[i] = context->createBuffer(); + } + } +} + +void GenFramebuffersOES(GLsizei n, GLuint* framebuffers) +{ + TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers); + + if(n < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + for(int i = 0; i < n; i++) + { + framebuffers[i] = context->createFramebuffer(); + } + } +} + +void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers) +{ + TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers); + + if(n < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + for(int i = 0; i < n; i++) + { + renderbuffers[i] = context->createRenderbuffer(); + } + } +} + +void GenTextures(GLsizei n, GLuint* textures) +{ + TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures); + + if(n < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + for(int i = 0; i < n; i++) + { + textures[i] = context->createTexture(); + } + } +} + +void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + if(target != GL_RENDERBUFFER_OES) + { + return error(GL_INVALID_ENUM); + } + + if(context->getRenderbufferName() == 0) + { + return error(GL_INVALID_OPERATION); + } + + es1::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName()); + + switch(pname) + { + case GL_RENDERBUFFER_WIDTH_OES: *params = renderbuffer->getWidth(); break; + case GL_RENDERBUFFER_HEIGHT_OES: *params = renderbuffer->getHeight(); break; + case GL_RENDERBUFFER_INTERNAL_FORMAT_OES: *params = renderbuffer->getFormat(); break; + case GL_RENDERBUFFER_RED_SIZE_OES: *params = renderbuffer->getRedSize(); break; + case GL_RENDERBUFFER_GREEN_SIZE_OES: *params = renderbuffer->getGreenSize(); break; + case GL_RENDERBUFFER_BLUE_SIZE_OES: *params = renderbuffer->getBlueSize(); break; + case GL_RENDERBUFFER_ALPHA_SIZE_OES: *params = renderbuffer->getAlphaSize(); break; + case GL_RENDERBUFFER_DEPTH_SIZE_OES: *params = renderbuffer->getDepthSize(); break; + case GL_RENDERBUFFER_STENCIL_SIZE_OES: *params = renderbuffer->getStencilSize(); break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void GetBooleanv(GLenum pname, GLboolean* params) +{ + TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + if(!(context->getBooleanv(pname, params))) + { + int numParams = context->getQueryParameterNum(pname); + + if(numParams < 0) + { + return error(GL_INVALID_ENUM); + } + + if(numParams == 0) + { + return; + } + + if(context->isQueryParameterFloat(pname)) + { + GLfloat *floatParams = nullptr; + floatParams = new GLfloat[numParams]; + + context->getFloatv(pname, floatParams); + + for(int i = 0; i < numParams; ++i) + { + if(floatParams[i] == 0.0f) + params[i] = GL_FALSE; + else + params[i] = GL_TRUE; + } + + delete [] floatParams; + } + else if(context->isQueryParameterInt(pname)) + { + GLint *intParams = nullptr; + intParams = new GLint[numParams]; + + context->getIntegerv(pname, intParams); + + for(int i = 0; i < numParams; ++i) + { + if(intParams[i] == 0) + params[i] = GL_FALSE; + else + params[i] = GL_TRUE; + } + + delete [] intParams; + } + else UNREACHABLE(pname); + } + } +} + +void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Buffer *buffer; + + switch(target) + { + case GL_ARRAY_BUFFER: + buffer = context->getArrayBuffer(); + break; + case GL_ELEMENT_ARRAY_BUFFER: + buffer = context->getElementArrayBuffer(); + break; + default: + return error(GL_INVALID_ENUM); + } + + if(!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + return error(GL_INVALID_OPERATION); + } + + switch(pname) + { + case GL_BUFFER_USAGE: + *params = buffer->usage(); + break; + case GL_BUFFER_SIZE: + *params = buffer->size(); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void GetClipPlanef(GLenum pname, GLfloat eqn[4]) +{ + UNIMPLEMENTED(); +} + +void GetClipPlanex(GLenum pname, GLfixed eqn[4]) +{ + UNIMPLEMENTED(); +} + +GLenum GetError(void) +{ + TRACE("()"); + + es1::Context *context = es1::getContext(); + + if(context) + { + return context->getError(); + } + + return GL_NO_ERROR; +} + +void GetFixedv(GLenum pname, GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void GetFloatv(GLenum pname, GLfloat* params) +{ + TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + if(!(context->getFloatv(pname, params))) + { + int numParams = context->getQueryParameterNum(pname); + + if(numParams < 0) + { + return error(GL_INVALID_ENUM); + } + + if(numParams == 0) + { + return; + } + + if(context->isQueryParameterBool(pname)) + { + GLboolean *boolParams = nullptr; + boolParams = new GLboolean[numParams]; + + context->getBooleanv(pname, boolParams); + + for(int i = 0; i < numParams; ++i) + { + if(boolParams[i] == GL_FALSE) + params[i] = 0.0f; + else + params[i] = 1.0f; + } + + delete [] boolParams; + } + else if(context->isQueryParameterInt(pname)) + { + GLint *intParams = nullptr; + intParams = new GLint[numParams]; + + context->getIntegerv(pname, intParams); + + for(int i = 0; i < numParams; ++i) + { + params[i] = (GLfloat)intParams[i]; + } + + delete [] intParams; + } + else UNREACHABLE(pname); + } + } +} + +void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", + target, attachment, pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + if(target != GL_FRAMEBUFFER_OES) + { + return error(GL_INVALID_ENUM); + } + + if(context->getFramebufferName() == 0) + { + return error(GL_INVALID_OPERATION); + } + + es1::Framebuffer *framebuffer = context->getFramebuffer(); + + GLenum attachmentType; + GLuint attachmentHandle; + switch(attachment) + { + case GL_COLOR_ATTACHMENT0_OES: + attachmentType = framebuffer->getColorbufferType(); + attachmentHandle = framebuffer->getColorbufferName(); + break; + case GL_DEPTH_ATTACHMENT_OES: + attachmentType = framebuffer->getDepthbufferType(); + attachmentHandle = framebuffer->getDepthbufferName(); + break; + case GL_STENCIL_ATTACHMENT_OES: + attachmentType = framebuffer->getStencilbufferType(); + attachmentHandle = framebuffer->getStencilbufferName(); + break; + default: + return error(GL_INVALID_ENUM); + } + + GLenum attachmentObjectType; // Type category + if(attachmentType == GL_NONE_OES || attachmentType == GL_RENDERBUFFER_OES) + { + attachmentObjectType = attachmentType; + } + else if(es1::IsTextureTarget(attachmentType)) + { + attachmentObjectType = GL_TEXTURE; + } + else UNREACHABLE(attachmentType); + + switch(pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES: + *params = attachmentObjectType; + break; + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES: + if(attachmentObjectType == GL_RENDERBUFFER_OES || attachmentObjectType == GL_TEXTURE) + { + *params = attachmentHandle; + } + else + { + return error(GL_INVALID_ENUM); + } + break; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES: + if(attachmentObjectType == GL_TEXTURE) + { + *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0 + } + else + { + return error(GL_INVALID_ENUM); + } + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void GetIntegerv(GLenum pname, GLint* params) +{ + TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + if(!(context->getIntegerv(pname, params))) + { + int numParams = context->getQueryParameterNum(pname); + + if(numParams < 0) + { + return error(GL_INVALID_ENUM); + } + + if(numParams == 0) + { + return; + } + + if(context->isQueryParameterBool(pname)) + { + GLboolean *boolParams = nullptr; + boolParams = new GLboolean[numParams]; + + context->getBooleanv(pname, boolParams); + + for(int i = 0; i < numParams; ++i) + { + if(boolParams[i] == GL_FALSE) + params[i] = 0; + else + params[i] = 1; + } + + delete [] boolParams; + } + else if(context->isQueryParameterFloat(pname)) + { + GLfloat *floatParams = nullptr; + floatParams = new GLfloat[numParams]; + + context->getFloatv(pname, floatParams); + + for(int i = 0; i < numParams; ++i) + { + if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE) + { + params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f); + } + else + { + params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5)); + } + } + + delete [] floatParams; + } + else UNREACHABLE(pname); + } + } +} + +void GetLightfv(GLenum light, GLenum pname, GLfloat *params) +{ + UNIMPLEMENTED(); +} + +void GetLightxv(GLenum light, GLenum pname, GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void GetMaterialfv(GLenum face, GLenum pname, GLfloat *params) +{ + UNIMPLEMENTED(); +} + +void GetMaterialxv(GLenum face, GLenum pname, GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void GetPointerv(GLenum pname, GLvoid **params) +{ + TRACE("(GLenum pname = 0x%X, GLvoid **params = %p)", pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + if(!(context->getPointerv(pname, const_cast<const GLvoid**>(params)))) + { + return error(GL_INVALID_ENUM); + } + } +} + +const GLubyte* GetString(GLenum name) +{ + TRACE("(GLenum name = 0x%X)", name); + + switch(name) + { + case GL_VENDOR: + return (GLubyte*)"Google Inc."; + case GL_RENDERER: + return (GLubyte*)"Google SwiftShader"; + case GL_VERSION: + return (GLubyte*)"OpenGL ES 1.1 SwiftShader " VERSION_STRING; + case GL_EXTENSIONS: + // Keep list sorted in following order: + // OES extensions + // EXT extensions + // Vendor extensions + return (GLubyte*) + "GL_OES_blend_equation_separate " + "GL_OES_blend_func_separate " + "GL_OES_blend_subtract " + "GL_OES_compressed_ETC1_RGB8_texture " + "GL_OES_depth_texture " + "GL_OES_EGL_image " + "GL_OES_EGL_image_external " + "GL_OES_EGL_sync " + "GL_OES_element_index_uint " + "GL_OES_framebuffer_object " + "GL_OES_packed_depth_stencil " + "GL_OES_read_format " + "GL_OES_rgb8_rgba8 " + "GL_OES_stencil8 " + "GL_OES_stencil_wrap " + "GL_OES_texture_mirrored_repeat " + "GL_OES_texture_npot " + "GL_EXT_blend_minmax " + "GL_EXT_read_format_bgra " + #if (S3TC_SUPPORT) + "GL_EXT_texture_compression_dxt1 " + "GL_ANGLE_texture_compression_dxt3 " + "GL_ANGLE_texture_compression_dxt5 " + #endif + "GL_EXT_texture_filter_anisotropic " + "GL_EXT_texture_format_BGRA8888"; + default: + return error(GL_INVALID_ENUM, (GLubyte*)nullptr); + } +} + +void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Texture *texture; + + switch(target) + { + case GL_TEXTURE_2D: + texture = context->getTexture2D(); + break; + case GL_TEXTURE_EXTERNAL_OES: + texture = context->getTextureExternal(); + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = (GLfloat)texture->getMagFilter(); + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLfloat)texture->getMinFilter(); + break; + case GL_TEXTURE_WRAP_S: + *params = (GLfloat)texture->getWrapS(); + break; + case GL_TEXTURE_WRAP_T: + *params = (GLfloat)texture->getWrapT(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + *params = texture->getMaxAnisotropy(); + break; + case GL_GENERATE_MIPMAP: + *params = (GLfloat)texture->getGenerateMipmap(); + break; + case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: + *params = (GLfloat)1; + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params); + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Texture *texture; + + switch(target) + { + case GL_TEXTURE_2D: + texture = context->getTexture2D(); + break; + case GL_TEXTURE_EXTERNAL_OES: + texture = context->getTextureExternal(); + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = texture->getMagFilter(); + break; + case GL_TEXTURE_MIN_FILTER: + *params = texture->getMinFilter(); + break; + case GL_TEXTURE_WRAP_S: + *params = texture->getWrapS(); + break; + case GL_TEXTURE_WRAP_T: + *params = texture->getWrapT(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + *params = (GLint)texture->getMaxAnisotropy(); + break; + case GL_GENERATE_MIPMAP: + *params = (GLint)texture->getGenerateMipmap(); + break; + case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: + *params = 1; + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void GetTexEnvfv(GLenum env, GLenum pname, GLfloat *params) +{ + UNIMPLEMENTED(); +} + +void GetTexEnviv(GLenum env, GLenum pname, GLint *params) +{ + UNIMPLEMENTED(); +} + +void GetTexEnvxv(GLenum env, GLenum pname, GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void GetTexParameterxv(GLenum target, GLenum pname, GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void Hint(GLenum target, GLenum mode) +{ + TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); + + switch(mode) + { + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(target) + { + case GL_GENERATE_MIPMAP_HINT: + context->setGenerateMipmapHint(mode); + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + context->setPerspectiveCorrectionHint(mode); + break; + case GL_FOG_HINT: + context->setFogHint(mode); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +GLboolean IsBuffer(GLuint buffer) +{ + TRACE("(GLuint buffer = %d)", buffer); + + es1::Context *context = es1::getContext(); + + if(context && buffer) + { + es1::Buffer *bufferObject = context->getBuffer(buffer); + + if(bufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean IsEnabled(GLenum cap) +{ + TRACE("(GLenum cap = 0x%X)", cap); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(cap) + { + case GL_CULL_FACE: return context->isCullFaceEnabled(); break; + case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled(); break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled(); break; + case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled(); break; + case GL_SCISSOR_TEST: return context->isScissorTestEnabled(); break; + case GL_STENCIL_TEST: return context->isStencilTestEnabled(); break; + case GL_DEPTH_TEST: return context->isDepthTestEnabled(); break; + case GL_BLEND: return context->isBlendEnabled(); break; + case GL_DITHER: return context->isDitherEnabled(); break; + case GL_LIGHTING: return context->isLightingEnabled(); break; + case GL_LIGHT0: return context->isLightEnabled(0); break; + case GL_LIGHT1: return context->isLightEnabled(1); break; + case GL_LIGHT2: return context->isLightEnabled(2); break; + case GL_LIGHT3: return context->isLightEnabled(3); break; + case GL_LIGHT4: return context->isLightEnabled(4); break; + case GL_LIGHT5: return context->isLightEnabled(5); break; + case GL_LIGHT6: return context->isLightEnabled(6); break; + case GL_LIGHT7: return context->isLightEnabled(7); break; + case GL_FOG: return context->isFogEnabled(); break; + case GL_TEXTURE_2D: return context->isTexture2Denabled(); break; + case GL_TEXTURE_EXTERNAL_OES: return context->isTextureExternalEnabled(); break; + case GL_ALPHA_TEST: return context->isAlphaTestEnabled(); break; + case GL_COLOR_LOGIC_OP: return context->isColorLogicOpEnabled(); break; + case GL_POINT_SMOOTH: return context->isPointSmoothEnabled(); break; + case GL_LINE_SMOOTH: return context->isLineSmoothEnabled(); break; + case GL_COLOR_MATERIAL: return context->isColorMaterialEnabled(); break; + case GL_NORMALIZE: return context->isNormalizeEnabled(); break; + case GL_RESCALE_NORMAL: return context->isRescaleNormalEnabled(); break; + case GL_VERTEX_ARRAY: return context->isVertexArrayEnabled(); break; + case GL_NORMAL_ARRAY: return context->isNormalArrayEnabled(); break; + case GL_COLOR_ARRAY: return context->isColorArrayEnabled(); break; + case GL_POINT_SIZE_ARRAY_OES: return context->isPointSizeArrayEnabled(); break; + case GL_TEXTURE_COORD_ARRAY: return context->isTextureCoordArrayEnabled(); break; + case GL_MULTISAMPLE: return context->isMultisampleEnabled(); break; + case GL_SAMPLE_ALPHA_TO_ONE: return context->isSampleAlphaToOneEnabled(); break; + case GL_CLIP_PLANE0: return context->isClipPlaneEnabled(0); break; + case GL_CLIP_PLANE1: return context->isClipPlaneEnabled(1); break; + case GL_CLIP_PLANE2: return context->isClipPlaneEnabled(2); break; + case GL_CLIP_PLANE3: return context->isClipPlaneEnabled(3); break; + case GL_CLIP_PLANE4: return context->isClipPlaneEnabled(4); break; + case GL_CLIP_PLANE5: return context->isClipPlaneEnabled(5); break; + case GL_POINT_SPRITE_OES: return context->isPointSpriteEnabled(); break; + default: + return error(GL_INVALID_ENUM, GL_FALSE); + } + } + + return GL_FALSE; +} + +GLboolean IsFramebufferOES(GLuint framebuffer) +{ + TRACE("(GLuint framebuffer = %d)", framebuffer); + + es1::Context *context = es1::getContext(); + + if(context && framebuffer) + { + es1::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); + + if(framebufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean IsTexture(GLuint texture) +{ + TRACE("(GLuint texture = %d)", texture); + + es1::Context *context = es1::getContext(); + + if(context && texture) + { + es1::Texture *textureObject = context->getTexture(texture); + + if(textureObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean IsRenderbufferOES(GLuint renderbuffer) +{ + TRACE("(GLuint renderbuffer = %d)", renderbuffer); + + es1::Context *context = es1::getContext(); + + if(context && renderbuffer) + { + es1::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); + + if(renderbufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +void LightModelf(GLenum pname, GLfloat param) +{ + TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_LIGHT_MODEL_TWO_SIDE: + context->setLightModelTwoSide(param != 0.0f); + break; + case GL_LIGHT_MODEL_AMBIENT: + return error(GL_INVALID_ENUM); // Need four values, should call glLightModelfv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void LightModelfv(GLenum pname, const GLfloat *params) +{ + TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_LIGHT_MODEL_AMBIENT: + context->setGlobalAmbient(params[0], params[1], params[2], params[3]); + break; + case GL_LIGHT_MODEL_TWO_SIDE: + context->setLightModelTwoSide(params[0] != 0.0f); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void LightModelx(GLenum pname, GLfixed param) +{ + TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_LIGHT_MODEL_TWO_SIDE: + context->setLightModelTwoSide(param != 0); + break; + case GL_LIGHT_MODEL_AMBIENT: + return error(GL_INVALID_ENUM); // Need four values, should call glLightModelxv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void LightModelxv(GLenum pname, const GLfixed *params) +{ + TRACE("(GLenum pname = 0x%X, const GLfixed *params)", pname); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_LIGHT_MODEL_AMBIENT: + context->setGlobalAmbient((float)params[0] / 0x10000, (float)params[1] / 0x10000, (float)params[2] / 0x10000, (float)params[3] / 0x10000); + break; + case GL_LIGHT_MODEL_TWO_SIDE: + context->setLightModelTwoSide(params[0] != 0); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Lightf(GLenum light, GLenum pname, GLfloat param) +{ + TRACE("(GLenum light = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", light, pname, param); + + int index = light - GL_LIGHT0; + + if(index < 0 || index >= es1::MAX_LIGHTS) + { + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_SPOT_EXPONENT: + if(param < 0.0f || param > 128.0f) + { + return error(GL_INVALID_VALUE); + } + context->setSpotLightExponent(index, param); + break; + case GL_SPOT_CUTOFF: + if((param < 0.0f || param > 90.0f) && param != 180.0f) + { + return error(GL_INVALID_VALUE); + } + context->setSpotLightCutoff(index, param); + break; + case GL_CONSTANT_ATTENUATION: + if(param < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setLightAttenuationConstant(index, param); + break; + case GL_LINEAR_ATTENUATION: + if(param < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setLightAttenuationLinear(index, param); + break; + case GL_QUADRATIC_ATTENUATION: + if(param < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setLightAttenuationQuadratic(index, param); + break; + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_POSITION: + case GL_SPOT_DIRECTION: + return error(GL_INVALID_ENUM); // Need four values, should call glLightfv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Lightfv(GLenum light, GLenum pname, const GLfloat *params) +{ + TRACE("(GLenum light = 0x%X, GLenum pname = 0x%X, const GLint *params)", light, pname); + + es1::Context *context = es1::getContext(); + + if(context) + { + int index = light - GL_LIGHT0; + + if(index < 0 || index > es1::MAX_LIGHTS) + { + return error(GL_INVALID_ENUM); + } + + switch(pname) + { + case GL_AMBIENT: context->setLightAmbient(index, params[0], params[1], params[2], params[3]); break; + case GL_DIFFUSE: context->setLightDiffuse(index, params[0], params[1], params[2], params[3]); break; + case GL_SPECULAR: context->setLightSpecular(index, params[0], params[1], params[2], params[3]); break; + case GL_POSITION: context->setLightPosition(index, params[0], params[1], params[2], params[3]); break; + case GL_SPOT_DIRECTION: context->setLightDirection(index, params[0], params[1], params[2]); break; + case GL_SPOT_EXPONENT: + if(params[0] < 0.0f || params[0] > 128.0f) + { + return error(GL_INVALID_VALUE); + } + context->setSpotLightExponent(index, params[0]); + break; + case GL_SPOT_CUTOFF: + if((params[0] < 0.0f || params[0] > 90.0f) && params[0] != 180.0f) + { + return error(GL_INVALID_VALUE); + } + context->setSpotLightCutoff(index, params[0]); + break; + case GL_CONSTANT_ATTENUATION: + if(params[0] < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setLightAttenuationConstant(index, params[0]); + break; + case GL_LINEAR_ATTENUATION: + if(params[0] < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setLightAttenuationLinear(index, params[0]); + break; + case GL_QUADRATIC_ATTENUATION: + if(params[0] < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setLightAttenuationQuadratic(index, params[0]); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Lightx(GLenum light, GLenum pname, GLfixed param) +{ + UNIMPLEMENTED(); +} + +void Lightxv(GLenum light, GLenum pname, const GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void LineWidth(GLfloat width) +{ + TRACE("(GLfloat width = %f)", width); + + if(width <= 0.0f) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setLineWidth(width); + } +} + +void LineWidthx(GLfixed width) +{ + LineWidth((float)width / 0x10000); +} + +void LoadIdentity(void) +{ + TRACE("()"); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->loadIdentity(); + } +} + +void LoadMatrixf(const GLfloat *m) +{ + TRACE("(const GLfloat *m)"); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->load(m); + } +} + +void LoadMatrixx(const GLfixed *m) +{ + GLfloat matrix[16] = + { + (float)m[0] / 0x10000, (float)m[1] / 0x10000, (float)m[2] / 0x10000, (float)m[3] / 0x10000, + (float)m[4] / 0x10000, (float)m[5] / 0x10000, (float)m[6] / 0x10000, (float)m[7] / 0x10000, + (float)m[8] / 0x10000, (float)m[9] / 0x10000, (float)m[10] / 0x10000, (float)m[11] / 0x10000, + (float)m[12] / 0x10000, (float)m[13] / 0x10000, (float)m[14] / 0x10000, (float)m[15] / 0x10000 + }; + + LoadMatrixf(matrix); +} + +void LogicOp(GLenum opcode) +{ + TRACE("(GLenum opcode = 0x%X)", opcode); + + switch(opcode) + { + case GL_CLEAR: + case GL_SET: + case GL_COPY: + case GL_COPY_INVERTED: + case GL_NOOP: + case GL_INVERT: + case GL_AND: + case GL_NAND: + case GL_OR: + case GL_NOR: + case GL_XOR: + case GL_EQUIV: + case GL_AND_REVERSE: + case GL_AND_INVERTED: + case GL_OR_REVERSE: + case GL_OR_INVERTED: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setLogicalOperation(opcode); + } +} + +void Materialf(GLenum face, GLenum pname, GLfloat param) +{ + TRACE("(GLenum face = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", face, pname, param); + + if(face != GL_FRONT_AND_BACK) + { + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_SHININESS: + if(param < 0.0f || param > 128.0f) + { + return error(GL_INVALID_VALUE); + } + context->setMaterialShininess(param); + break; + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_AMBIENT_AND_DIFFUSE: + case GL_SPECULAR: + case GL_EMISSION: + return error(GL_INVALID_ENUM); // Need four values, should call glMaterialfv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Materialfv(GLenum face, GLenum pname, const GLfloat *params) +{ + TRACE("(GLenum face = 0x%X, GLenum pname = 0x%X, GLfloat params)", face, pname); + + if(face != GL_FRONT_AND_BACK) + { + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_AMBIENT: + context->setMaterialAmbient(params[0], params[1], params[2], params[3]); + break; + case GL_DIFFUSE: + context->setMaterialDiffuse(params[0], params[1], params[2], params[3]); + break; + case GL_AMBIENT_AND_DIFFUSE: + context->setMaterialAmbient(params[0], params[1], params[2], params[3]); + context->setMaterialDiffuse(params[0], params[1], params[2], params[3]); + break; + case GL_SPECULAR: + context->setMaterialSpecular(params[0], params[1], params[2], params[3]); + break; + case GL_EMISSION: + context->setMaterialEmission(params[0], params[1], params[2], params[3]); + break; + case GL_SHININESS: + context->setMaterialShininess(params[0]); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Materialx(GLenum face, GLenum pname, GLfixed param) +{ + UNIMPLEMENTED(); +} + +void Materialxv(GLenum face, GLenum pname, const GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void MatrixMode(GLenum mode) +{ + TRACE("(GLenum mode = 0x%X)", mode); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setMatrixMode(mode); + } +} + +void MultMatrixf(const GLfloat *m) +{ + TRACE("(const GLfloat *m)"); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->multiply(m); + } +} + +void MultMatrixx(const GLfixed *m) +{ + GLfloat matrix[16] = + { + (float)m[0] / 0x10000, (float)m[1] / 0x10000, (float)m[2] / 0x10000, (float)m[3] / 0x10000, + (float)m[4] / 0x10000, (float)m[5] / 0x10000, (float)m[6] / 0x10000, (float)m[7] / 0x10000, + (float)m[8] / 0x10000, (float)m[9] / 0x10000, (float)m[10] / 0x10000, (float)m[11] / 0x10000, + (float)m[12] / 0x10000, (float)m[13] / 0x10000, (float)m[14] / 0x10000, (float)m[15] / 0x10000 + }; + + MultMatrixf(matrix); +} + +void MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + TRACE("(GLenum target = 0x%X, GLfloat s = %f, GLfloat t = %f, GLfloat r = %f, GLfloat q = %f)", target, s, t, r, q); + + switch(target) + { + case GL_TEXTURE0: + case GL_TEXTURE1: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setVertexAttrib(sw::TexCoord0 + (target - GL_TEXTURE0), s, t, r, q); + } +} + +void MultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +{ + UNIMPLEMENTED(); +} + +void Normal3f(GLfloat nx, GLfloat ny, GLfloat nz) +{ + TRACE("(GLfloat nx, GLfloat ny, GLfloat nz)", nx, ny, nz); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setVertexAttrib(sw::Normal, nx, ny, nz, 0); + } +} + +void Normal3x(GLfixed nx, GLfixed ny, GLfixed nz) +{ + UNIMPLEMENTED(); +} + +void NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) +{ + TRACE("(GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", type, stride, pointer); + + VertexAttribPointer(sw::Normal, 3, type, true, stride, pointer); +} + +void Orthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + TRACE("(GLfloat left = %f, GLfloat right = %f, GLfloat bottom = %f, GLfloat top = %f, GLfloat zNear = %f, GLfloat zFar = %f)", left, right, bottom, top, zNear, zFar); + + if(left == right || bottom == top || zNear == zFar) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->ortho(left, right, bottom, top, zNear, zFar); + } +} + +void Orthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +{ + Orthof((float)left / 0x10000, (float)right / 0x10000, (float)bottom / 0x10000, (float)top / 0x10000, (float)zNear / 0x10000, (float)zFar / 0x10000); +} + +void PixelStorei(GLenum pname, GLint param) +{ + TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_UNPACK_ALIGNMENT: + if(param != 1 && param != 2 && param != 4 && param != 8) + { + return error(GL_INVALID_VALUE); + } + + context->setUnpackAlignment(param); + break; + case GL_PACK_ALIGNMENT: + if(param != 1 && param != 2 && param != 4 && param != 8) + { + return error(GL_INVALID_VALUE); + } + + context->setPackAlignment(param); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void PointParameterf(GLenum pname, GLfloat param) +{ + TRACE("(GLenum pname = 0x%X, GLfloat param = %f)", pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_POINT_SIZE_MIN: + if(param < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setPointSizeMin(param); + break; + case GL_POINT_SIZE_MAX: + if(param < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setPointSizeMax(param); + break; + case GL_POINT_FADE_THRESHOLD_SIZE: + if(param < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setPointFadeThresholdSize(param); + break; + case GL_POINT_DISTANCE_ATTENUATION: + return error(GL_INVALID_ENUM); // Needs three values, should call glPointParameterfv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void PointParameterfv(GLenum pname, const GLfloat *params) +{ + TRACE("(GLenum pname = 0x%X, const GLfloat *params)", pname); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_POINT_SIZE_MIN: + if(params[0] < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setPointSizeMin(params[0]); + break; + case GL_POINT_SIZE_MAX: + if(params[0] < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setPointSizeMax(params[0]); + break; + case GL_POINT_DISTANCE_ATTENUATION: + context->setPointDistanceAttenuation(params[0], params[1], params[2]); + break; + case GL_POINT_FADE_THRESHOLD_SIZE: + if(params[0] < 0.0f) + { + return error(GL_INVALID_VALUE); + } + context->setPointFadeThresholdSize(params[0]); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void PointParameterx(GLenum pname, GLfixed param) +{ + TRACE("(GLenum pname = 0x%X, GLfixed param = %d)", pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_POINT_SIZE_MIN: + if(param < 0) + { + return error(GL_INVALID_VALUE); + } + context->setPointSizeMin((float)param / 0x10000); + break; + case GL_POINT_SIZE_MAX: + if(param < 0) + { + return error(GL_INVALID_VALUE); + } + context->setPointSizeMax((float)param / 0x10000); + break; + case GL_POINT_FADE_THRESHOLD_SIZE: + if(param < 0) + { + return error(GL_INVALID_VALUE); + } + context->setPointFadeThresholdSize((float)param / 0x10000); + break; + case GL_POINT_DISTANCE_ATTENUATION: + return error(GL_INVALID_ENUM); // Needs three parameters, should call glPointParameterxv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void PointParameterxv(GLenum pname, const GLfixed *params) +{ + TRACE("(GLenum pname = 0x%X, const GLfixed *params)", pname); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(pname) + { + case GL_POINT_SIZE_MIN: + if(params[0] < 0) + { + return error(GL_INVALID_VALUE); + } + context->setPointSizeMin((float)params[0] / 0x10000); + break; + case GL_POINT_SIZE_MAX: + if(params[0] < 0) + { + return error(GL_INVALID_VALUE); + } + context->setPointSizeMax((float)params[0] / 0x10000); + break; + case GL_POINT_DISTANCE_ATTENUATION: + context->setPointDistanceAttenuation((float)params[0] / 0x10000, (float)params[1] / 0x10000, (float)params[2] / 0x10000); + break; + case GL_POINT_FADE_THRESHOLD_SIZE: + if(params[0] < 0) + { + return error(GL_INVALID_VALUE); + } + context->setPointFadeThresholdSize((float)params[0] / 0x10000); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void PointSize(GLfloat size) +{ + TRACE("(GLfloat size = %f)", size); + + if(size <= 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setVertexAttrib(sw::PointSize, size, size, size, size); + } +} + +void PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer) +{ + TRACE("(GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", type, stride, pointer); + + switch(type) + { + case GL_FIXED: + case GL_FLOAT: + break; + default: + return error(GL_INVALID_ENUM); + } + + VertexAttribPointer(sw::PointSize, 1, type, true, stride, pointer); +} + +void PointSizex(GLfixed size) +{ + PointSize((float)size / 0x10000); +} + +void PolygonOffset(GLfloat factor, GLfloat units) +{ + TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setPolygonOffsetParams(factor, units); + } +} + +void PolygonOffsetx(GLfixed factor, GLfixed units) +{ + PolygonOffset((float)factor / 0x10000, (float)units / 0x10000); +} + +void PopMatrix(void) +{ + TRACE("()"); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->popMatrix(); + } +} + +void PushMatrix(void) +{ + TRACE("()"); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->pushMatrix(); + } +} + +void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) +{ + TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)", + x, y, width, height, format, type, pixels); + + if(width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->readPixels(x, y, width, height, format, type, nullptr, pixels); + } +} + +void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + TRACE("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, internalformat, width, height); + + switch(target) + { + case GL_RENDERBUFFER_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + + if(!es1::IsColorRenderable(internalformat) && !es1::IsDepthRenderable(internalformat) && !es1::IsStencilRenderable(internalformat)) + { + return error(GL_INVALID_ENUM); + } + + if(width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + if(width > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE || + height > es1::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE) + { + return error(GL_INVALID_VALUE); + } + + GLuint handle = context->getRenderbufferName(); + if(handle == 0) + { + return error(GL_INVALID_OPERATION); + } + + switch(internalformat) + { + case GL_DEPTH_COMPONENT16_OES: + context->setRenderbufferStorage(new es1::Depthbuffer(width, height, 0)); + break; + case GL_RGBA4_OES: + case GL_RGB5_A1_OES: + case GL_RGB565_OES: + case GL_RGB8_OES: + case GL_RGBA8_OES: + context->setRenderbufferStorage(new es1::Colorbuffer(width, height, internalformat, 0)); + break; + case GL_STENCIL_INDEX8_OES: + context->setRenderbufferStorage(new es1::Stencilbuffer(width, height, 0)); + break; + case GL_DEPTH24_STENCIL8_OES: + context->setRenderbufferStorage(new es1::DepthStencilbuffer(width, height, 0)); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + TRACE("(GLfloat angle = %f, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", angle, x, y, z); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->rotate(angle, x, y, z); + } +} + +void Rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +{ + Rotatef((float)angle / 0x10000, (float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000); +} + +void SampleCoverage(GLclampf value, GLboolean invert) +{ + TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert); + + es1::Context* context = es1::getContext(); + + if(context) + { + context->setSampleCoverageParams(es1::clamp01(value), invert == GL_TRUE); + } +} + +void SampleCoveragex(GLclampx value, GLboolean invert) +{ + SampleCoverage((float)value / 0x10000, invert); +} + +void Scalef(GLfloat x, GLfloat y, GLfloat z) +{ + TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", x, y, z); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->scale(x, y, z); + } +} + +void Scalex(GLfixed x, GLfixed y, GLfixed z) +{ + Scalef((float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000); +} + +void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + if(width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context* context = es1::getContext(); + + if(context) + { + context->setScissorParams(x, y, width, height); + } +} + +void ShadeModel(GLenum mode) +{ + switch(mode) + { + case GL_FLAT: + case GL_SMOOTH: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setShadeModel(mode); + } +} + +void StencilFunc(GLenum func, GLint ref, GLuint mask) +{ + TRACE("(GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", func, ref, mask); + + switch(func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setStencilParams(func, ref, mask); + } +} + +void StencilMask(GLuint mask) +{ + TRACE("(GLuint mask = %d)", mask); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setStencilWritemask(mask); + } +} + +void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + TRACE("(GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", fail, zfail, zpass); + + switch(fail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP_OES: + case GL_DECR_WRAP_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(zfail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP_OES: + case GL_DECR_WRAP_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(zpass) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP_OES: + case GL_DECR_WRAP_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setStencilOperations(fail, zfail, zpass); + } +} + +void TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer); + + if(size < 2 || size > 4) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + GLenum texture = context->getClientActiveTexture(); + VertexAttribPointer(sw::TexCoord0 + (texture - GL_TEXTURE0), size, type, false, stride, pointer); + } +} + +void TexEnvi(GLenum target, GLenum pname, GLint param); + +void TexEnvf(GLenum target, GLenum pname, GLfloat param) +{ + TexEnvi(target, pname, (GLint)param); +} + +void TexEnvfv(GLenum target, GLenum pname, const GLfloat *params) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLfloat *params)", target, pname); + + es1::Context *context = es1::getContext(); + + if(context) + { + GLint iParam = (GLint)roundf(params[0]); + + switch(target) + { + case GL_POINT_SPRITE_OES: + UNIMPLEMENTED(); + break; + case GL_TEXTURE_ENV: + switch(pname) + { + case GL_TEXTURE_ENV_MODE: + switch(iParam) + { + case GL_REPLACE: + case GL_MODULATE: + case GL_DECAL: + case GL_BLEND: + case GL_ADD: + case GL_COMBINE: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setTextureEnvMode(iParam); + break; + case GL_TEXTURE_ENV_COLOR: + context->setTextureEnvColor(clamp01(params[0]), clamp01(params[1]), clamp01(params[2]), clamp01(params[3])); + break; + case GL_COMBINE_RGB: + switch(iParam) + { + case GL_REPLACE: + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_INTERPOLATE: + case GL_SUBTRACT: + case GL_DOT3_RGB: + case GL_DOT3_RGBA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setCombineRGB(iParam); + break; + case GL_COMBINE_ALPHA: + switch(iParam) + { + case GL_REPLACE: + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_INTERPOLATE: + case GL_SUBTRACT: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setCombineAlpha(iParam); + break; + case GL_RGB_SCALE: + if(iParam != 1 && iParam != 2 && iParam != 4) + { + return error(GL_INVALID_VALUE); + } + if(iParam != 1) UNIMPLEMENTED(); + break; + case GL_ALPHA_SCALE: + if(iParam != 1 && iParam != 2 && iParam != 4) + { + return error(GL_INVALID_VALUE); + } + if(iParam != 1) UNIMPLEMENTED(); + break; + case GL_OPERAND0_RGB: + switch(iParam) + { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand0RGB(iParam); + break; + case GL_OPERAND1_RGB: + switch(iParam) + { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand1RGB(iParam); + break; + case GL_OPERAND2_RGB: + switch(iParam) + { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand2RGB(iParam); + break; + case GL_OPERAND0_ALPHA: + switch(iParam) + { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand0Alpha(iParam); + break; + case GL_OPERAND1_ALPHA: + switch(iParam) + { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand1Alpha(iParam); + break; + case GL_OPERAND2_ALPHA: + switch(iParam) + { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand2Alpha(iParam); + break; + case GL_SRC0_RGB: + switch(iParam) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc0RGB(iParam); + break; + case GL_SRC1_RGB: + switch(iParam) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc1RGB(iParam); + break; + case GL_SRC2_RGB: + switch(iParam) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc2RGB(iParam); + break; + case GL_SRC0_ALPHA: + switch(iParam) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc0Alpha(iParam); + break; + case GL_SRC1_ALPHA: + switch(iParam) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc1Alpha(iParam); + break; + case GL_SRC2_ALPHA: + switch(iParam) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc2Alpha(iParam); + break; + default: + return error(GL_INVALID_ENUM); + } + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void TexEnvi(GLenum target, GLenum pname, GLint param) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(target) + { + case GL_POINT_SPRITE_OES: + UNIMPLEMENTED(); + break; + case GL_TEXTURE_ENV: + switch(pname) + { + case GL_TEXTURE_ENV_MODE: + switch((GLenum)param) + { + case GL_REPLACE: + case GL_MODULATE: + case GL_DECAL: + case GL_BLEND: + case GL_ADD: + case GL_COMBINE: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setTextureEnvMode((GLenum)param); + break; + case GL_TEXTURE_ENV_COLOR: + return error(GL_INVALID_ENUM); // Needs four values, should call glTexEnviv() instead + break; + case GL_COMBINE_RGB: + switch((GLenum)param) + { + case GL_REPLACE: + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_INTERPOLATE: + case GL_SUBTRACT: + case GL_DOT3_RGB: + case GL_DOT3_RGBA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setCombineRGB((GLenum)param); + break; + case GL_COMBINE_ALPHA: + switch((GLenum)param) + { + case GL_REPLACE: + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_INTERPOLATE: + case GL_SUBTRACT: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setCombineAlpha((GLenum)param); + break; + case GL_RGB_SCALE: + if(param != 1 && param != 2 && param != 4) + { + return error(GL_INVALID_VALUE); + } + if(param != 1) UNIMPLEMENTED(); + break; + case GL_ALPHA_SCALE: + if(param != 1 && param != 2 && param != 4) + { + return error(GL_INVALID_VALUE); + } + if(param != 1) UNIMPLEMENTED(); + break; + case GL_OPERAND0_RGB: + switch((GLenum)param) + { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand0RGB((GLenum)param); + break; + case GL_OPERAND1_RGB: + switch((GLenum)param) + { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand1RGB((GLenum)param); + break; + case GL_OPERAND2_RGB: + switch((GLenum)param) + { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand2RGB((GLenum)param); + break; + case GL_OPERAND0_ALPHA: + switch((GLenum)param) + { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand0Alpha((GLenum)param); + break; + case GL_OPERAND1_ALPHA: + switch((GLenum)param) + { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand1Alpha((GLenum)param); + break; + case GL_OPERAND2_ALPHA: + switch((GLenum)param) + { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setOperand2Alpha((GLenum)param); + break; + case GL_SRC0_RGB: + switch((GLenum)param) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc0RGB((GLenum)param); + break; + case GL_SRC1_RGB: + switch((GLenum)param) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc1RGB((GLenum)param); + break; + case GL_SRC2_RGB: + switch((GLenum)param) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc2RGB((GLenum)param); + break; + case GL_SRC0_ALPHA: + switch((GLenum)param) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc0Alpha((GLenum)param); + break; + case GL_SRC1_ALPHA: + switch((GLenum)param) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc1Alpha((GLenum)param); + break; + case GL_SRC2_ALPHA: + switch((GLenum)param) + { + case GL_TEXTURE: + case GL_CONSTANT: + case GL_PRIMARY_COLOR: + case GL_PREVIOUS: + break; + default: + error(GL_INVALID_ENUM); + } + + context->setSrc2Alpha((GLenum)param); + break; + default: + return error(GL_INVALID_ENUM); + } + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void TexEnvx(GLenum target, GLenum pname, GLfixed param) +{ + TexEnvi(target, pname, (GLint)param); +} + +void TexEnviv(GLenum target, GLenum pname, const GLint *params) +{ + UNIMPLEMENTED(); +} + +void TexEnvxv(GLenum target, GLenum pname, const GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " + "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = %p)", + target, level, internalformat, width, height, border, format, type, pixels); + + if(!validImageSize(level, width, height)) + { + return error(GL_INVALID_VALUE); + } + + if(internalformat != (GLint)format) + { + return error(GL_INVALID_OPERATION); + } + + switch(format) + { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + switch(type) + { + case GL_UNSIGNED_BYTE: + case GL_FLOAT: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_RGB: + switch(type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_FLOAT: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_RGBA: + switch(type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_FLOAT: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_BGRA_EXT: + switch(type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + case GL_ETC1_RGB8_OES: + return error(GL_INVALID_OPERATION); + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if(S3TC_SUPPORT) + { + return error(GL_INVALID_OPERATION); + } + else + { + return error(GL_INVALID_ENUM); + } + case GL_DEPTH_STENCIL_OES: + switch(type) + { + case GL_UNSIGNED_INT_24_8_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + break; + default: + return error(GL_INVALID_VALUE); + } + + if(border != 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + switch(target) + { + case GL_TEXTURE_2D: + if(width > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) || + height > (es1::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level)) + { + return error(GL_INVALID_VALUE); + } + break; + default: + return error(GL_INVALID_ENUM); + } + + if(target == GL_TEXTURE_2D) + { + es1::Texture2D *texture = context->getTexture2D(); + + if(!texture) + { + return error(GL_INVALID_OPERATION); + } + + texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels); + } + else UNREACHABLE(target); + } +} + +void TexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Texture *texture; + + switch(target) + { + case GL_TEXTURE_2D: + texture = context->getTexture2D(); + break; + case GL_TEXTURE_EXTERNAL_OES: + texture = context->getTextureExternal(); + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(pname) + { + case GL_TEXTURE_WRAP_S: + if(!texture->setWrapS((GLenum)param)) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_TEXTURE_WRAP_T: + if(!texture->setWrapT((GLenum)param)) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_TEXTURE_MIN_FILTER: + if(!texture->setMinFilter((GLenum)param)) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_TEXTURE_MAG_FILTER: + if(!texture->setMagFilter((GLenum)param)) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if(!texture->setMaxAnisotropy(param)) + { + return error(GL_INVALID_VALUE); + } + break; + case GL_GENERATE_MIPMAP: + texture->setGenerateMipmap((GLboolean)param); + break; + case GL_TEXTURE_CROP_RECT_OES: + return error(GL_INVALID_ENUM); // Needs four values, should call glTexParameterfv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) +{ + TexParameterf(target, pname, *params); +} + +void TexParameteri(GLenum target, GLenum pname, GLint param) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Texture *texture; + + switch(target) + { + case GL_TEXTURE_2D: + texture = context->getTexture2D(); + break; + case GL_TEXTURE_EXTERNAL_OES: + texture = context->getTextureExternal(); + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(pname) + { + case GL_TEXTURE_WRAP_S: + if(!texture->setWrapS((GLenum)param)) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_TEXTURE_WRAP_T: + if(!texture->setWrapT((GLenum)param)) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_TEXTURE_MIN_FILTER: + if(!texture->setMinFilter((GLenum)param)) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_TEXTURE_MAG_FILTER: + if(!texture->setMagFilter((GLenum)param)) + { + return error(GL_INVALID_ENUM); + } + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if(!texture->setMaxAnisotropy((GLfloat)param)) + { + return error(GL_INVALID_VALUE); + } + break; + case GL_GENERATE_MIPMAP: + texture->setGenerateMipmap((GLboolean)param); + break; + case GL_TEXTURE_CROP_RECT_OES: + return error(GL_INVALID_ENUM); // Needs four values, should call glTexParameteriv() instead + default: + return error(GL_INVALID_ENUM); + } + } +} + +void TexParameteriv(GLenum target, GLenum pname, const GLint* params) +{ + TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %p)", target, pname, params); + + switch(pname) + { + case GL_TEXTURE_CROP_RECT_OES: + break; + default: + return TexParameteri(target, pname, params[0]); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Texture *texture; + + switch(target) + { + case GL_TEXTURE_2D: + texture = context->getTexture2D(); + break; + default: + return error(GL_INVALID_ENUM); + } + + switch(pname) + { + case GL_TEXTURE_CROP_RECT_OES: + texture->setCropRect(params[0], params[1], params[2], params[3]); + break; + default: + return error(GL_INVALID_ENUM); + } + } +} + +void TexParameterx(GLenum target, GLenum pname, GLfixed param) +{ + TexParameteri(target, pname, (GLint)param); +} + +void TexParameterxv(GLenum target, GLenum pname, const GLfixed *params) +{ + UNIMPLEMENTED(); +} + +void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid* pixels) +{ + TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " + "const GLvoid* pixels = %p)", + target, level, xoffset, yoffset, width, height, format, type, pixels); + + if(!es1::IsTextureTarget(target)) + { + return error(GL_INVALID_ENUM); + } + + if(level < 0 || level >= es1::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + return error(GL_INVALID_VALUE); + } + + if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) + { + return error(GL_INVALID_VALUE); + } + + if(!es1::CheckTextureFormatType(format, type)) + { + return error(GL_INVALID_ENUM); + } + + if(width == 0 || height == 0 || !pixels) + { + return; + } + + es1::Context *context = es1::getContext(); + + if(context) + { + if(target == GL_TEXTURE_2D) + { + es1::Texture2D *texture = context->getTexture2D(); + + if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture)) + { + texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); + } + } + else UNREACHABLE(target); + } +} + +void Translatef(GLfloat x, GLfloat y, GLfloat z) +{ + TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", x, y, z); + + es1::Context *context = es1::getContext(); + + if(context) + { + context->translate(x, y, z); + } +} + +void Translatex(GLfixed x, GLfixed y, GLfixed z) +{ + Translatef((float)x / 0x10000, (float)y / 0x10000, (float)z / 0x10000); +} + +void VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + TRACE("(GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid *pointer = %p)", size, type, stride, pointer); + + if(size < 2 || size > 4) + { + return error(GL_INVALID_VALUE); + } + + VertexAttribPointer(sw::Position, size, type, false, stride, pointer); +} + +void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + if(width < 0 || height < 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->setViewportParams(x, y, width, height); + } +} + +void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image); + + switch(target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_EXTERNAL_OES: + break; + default: + return error(GL_INVALID_ENUM); + } + + if(!image) + { + return error(GL_INVALID_OPERATION); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + es1::Texture2D *texture = 0; + + switch(target) + { + case GL_TEXTURE_2D: texture = context->getTexture2D(); break; + case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break; + default: UNREACHABLE(target); + } + + if(!texture) + { + return error(GL_INVALID_OPERATION); + } + + egl::Image *glImage = static_cast<egl::Image*>(image); + + texture->setImage(glImage); + } +} + +void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image); + + UNIMPLEMENTED(); +} + +void DrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) +{ + UNIMPLEMENTED(); +} + +void DrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) +{ + TRACE("(GLint x = %d, GLint y = %d, GLint z = %d, GLint width = %d, GLint height = %d)", x, y, z, width, height); + + if(width <= 0 || height <= 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->drawTexture((GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)width, (GLfloat)height); + } +} + +void DrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) +{ + UNIMPLEMENTED(); +} + +void DrawTexsvOES(const GLshort *coords) +{ + UNIMPLEMENTED(); +} + +void DrawTexivOES(const GLint *coords) +{ + UNIMPLEMENTED(); +} + +void DrawTexxvOES(const GLfixed *coords) +{ + UNIMPLEMENTED(); +} + +void DrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) +{ + TRACE("(GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat width = %f, GLfloat height = %f)", x, y, z, width, height); + + if(width <= 0 || height <= 0) + { + return error(GL_INVALID_VALUE); + } + + es1::Context *context = es1::getContext(); + + if(context) + { + context->drawTexture(x, y, z, width, height); + } +} + +void DrawTexfvOES(const GLfloat *coords) +{ + UNIMPLEMENTED(); +} + +} + +extern "C" __eglMustCastToProperFunctionPointerType es1GetProcAddress(const char *procname) +{ + struct Extension + { + const char *name; + __eglMustCastToProperFunctionPointerType address; + }; + + static const Extension glExtensions[] = + { + #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name} + + EXTENSION(glEGLImageTargetTexture2DOES), + EXTENSION(glEGLImageTargetRenderbufferStorageOES), + EXTENSION(glIsRenderbufferOES), + EXTENSION(glBindRenderbufferOES), + EXTENSION(glDeleteRenderbuffersOES), + EXTENSION(glGenRenderbuffersOES), + EXTENSION(glRenderbufferStorageOES), + EXTENSION(glGetRenderbufferParameterivOES), + EXTENSION(glIsFramebufferOES), + EXTENSION(glBindFramebufferOES), + EXTENSION(glDeleteFramebuffersOES), + EXTENSION(glGenFramebuffersOES), + EXTENSION(glCheckFramebufferStatusOES), + EXTENSION(glFramebufferRenderbufferOES), + EXTENSION(glFramebufferTexture2DOES), + EXTENSION(glGetFramebufferAttachmentParameterivOES), + EXTENSION(glGenerateMipmapOES), + EXTENSION(glBlendEquationOES), + EXTENSION(glBlendEquationSeparateOES), + EXTENSION(glBlendFuncSeparateOES), + EXTENSION(glPointSizePointerOES), + + #undef EXTENSION + }; + + for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++) + { + if(strcmp(procname, glExtensions[ext].name) == 0) + { + return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address; + } + } + + return nullptr; +}
diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.hpp b/src/OpenGL/libGLES_CM/libGLES_CM.hpp index eddcd75..5c9657b 100644 --- a/src/OpenGL/libGLES_CM/libGLES_CM.hpp +++ b/src/OpenGL/libGLES_CM/libGLES_CM.hpp
@@ -1,3 +1,17 @@ +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #ifndef libGLES_CM_hpp #define libGLES_CM_hpp
diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.rc b/src/OpenGL/libGLES_CM/libGLES_CM.rc index cdbb35c..174d7b5 100644 --- a/src/OpenGL/libGLES_CM/libGLES_CM.rc +++ b/src/OpenGL/libGLES_CM/libGLES_CM.rc
@@ -28,18 +28,18 @@ // TEXTINCLUDE // -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN "resource.h\0" END -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "#include ""../common/version.h""\0" END -3 TEXTINCLUDE +3 TEXTINCLUDE BEGIN "\r\n" "\0" @@ -77,7 +77,7 @@ #endif VALUE "FileVersion", VERSION_STRING VALUE "InternalName", "libGLES_CM" - VALUE "LegalCopyright", "Copyright (C) 2012 TransGaming Inc." + VALUE "LegalCopyright", "Copyright (C) 2016 Google Inc." VALUE "OriginalFilename", "libGLES_CM.dll" VALUE "PrivateBuild", VERSION_STRING VALUE "ProductName", "SwiftShader libGLES_CM Dynamic Link Library"
diff --git a/src/OpenGL/libGLES_CM/main.cpp b/src/OpenGL/libGLES_CM/main.cpp index 8b91578..be2462a 100644 --- a/src/OpenGL/libGLES_CM/main.cpp +++ b/src/OpenGL/libGLES_CM/main.cpp
@@ -1,1606 +1,1609 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// main.cpp: DLL entry point and management of thread-local data. - -#include "main.h" - -#include "libGLES_CM.hpp" -#include "Framebuffer.h" -#include "libEGL/Surface.h" -#include "Common/Thread.hpp" -#include "Common/SharedLibrary.hpp" -#include "common/debug.h" - -#include <GLES/glext.h> - -#if !defined(_MSC_VER) -#define CONSTRUCTOR __attribute__((constructor)) -#define DESTRUCTOR __attribute__((destructor)) -#else -#define CONSTRUCTOR -#define DESTRUCTOR -#endif - -static void glAttachThread() -{ - TRACE("()"); -} - -static void glDetachThread() -{ - TRACE("()"); -} - -CONSTRUCTOR static void glAttachProcess() -{ - TRACE("()"); - - glAttachThread(); -} - -DESTRUCTOR static void glDetachProcess() -{ - TRACE("()"); - - glDetachThread(); -} - -#if defined(_WIN32) -extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -{ - switch(reason) - { - case DLL_PROCESS_ATTACH: - glAttachProcess(); - break; - case DLL_THREAD_ATTACH: - glAttachThread(); - break; - case DLL_THREAD_DETACH: - glDetachThread(); - break; - case DLL_PROCESS_DETACH: - glDetachProcess(); - break; - default: - break; - } - - return TRUE; -} -#endif - -namespace es1 -{ -es1::Context *getContext() -{ - egl::Context *context = libEGL->clientGetCurrentContext(); - - if(context && context->getClientVersion() == 1) - { - return static_cast<es1::Context*>(context); - } - - return 0; -} - -Device *getDevice() -{ - Context *context = getContext(); - - return context ? context->getDevice() : 0; -} - -// Records an error code -void error(GLenum errorCode) -{ - es1::Context *context = es1::getContext(); - - if(context) - { - switch(errorCode) - { - case GL_INVALID_ENUM: - context->recordInvalidEnum(); - TRACE("\t! Error generated: invalid enum\n"); - break; - case GL_INVALID_VALUE: - context->recordInvalidValue(); - TRACE("\t! Error generated: invalid value\n"); - break; - case GL_INVALID_OPERATION: - context->recordInvalidOperation(); - TRACE("\t! Error generated: invalid operation\n"); - break; - case GL_OUT_OF_MEMORY: - context->recordOutOfMemory(); - TRACE("\t! Error generated: out of memory\n"); - break; - case GL_INVALID_FRAMEBUFFER_OPERATION_OES: - context->recordInvalidFramebufferOperation(); - TRACE("\t! Error generated: invalid framebuffer operation\n"); - break; - case GL_STACK_OVERFLOW: - context->recordMatrixStackOverflow(); - TRACE("\t! Error generated: matrix stack overflow\n"); - break; - case GL_STACK_UNDERFLOW: - context->recordMatrixStackUnderflow(); - TRACE("\t! Error generated: matrix stack underflow\n"); - break; - default: UNREACHABLE(errorCode); - } - } -} -} - -namespace es1 -{ -void ActiveTexture(GLenum texture); -void AlphaFunc(GLenum func, GLclampf ref); -void AlphaFuncx(GLenum func, GLclampx ref); -void BindBuffer(GLenum target, GLuint buffer); -void BindFramebuffer(GLenum target, GLuint framebuffer); -void BindFramebufferOES(GLenum target, GLuint framebuffer); -void BindRenderbufferOES(GLenum target, GLuint renderbuffer); -void BindTexture(GLenum target, GLuint texture); -void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha); -void BlendEquationOES(GLenum mode); -void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha); -void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -void BlendFunc(GLenum sfactor, GLenum dfactor); -void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); -void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); -GLenum CheckFramebufferStatusOES(GLenum target); -void Clear(GLbitfield mask); -void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -void ClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha); -void ClearDepthf(GLclampf depth); -void ClearDepthx(GLclampx depth); -void ClearStencil(GLint s); -void ClientActiveTexture(GLenum texture); -void ClipPlanef(GLenum plane, const GLfloat *equation); -void ClipPlanex(GLenum plane, const GLfixed *equation); -void Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void Color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -void Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); -void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -void ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid* data); -void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const GLvoid* data); -void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -void CullFace(GLenum mode); -void DeleteBuffers(GLsizei n, const GLuint* buffers); -void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers); -void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers); -void DeleteTextures(GLsizei n, const GLuint* textures); -void DepthFunc(GLenum func); -void DepthMask(GLboolean flag); -void DepthRangex(GLclampx zNear, GLclampx zFar); -void DepthRangef(GLclampf zNear, GLclampf zFar); -void Disable(GLenum cap); -void DisableClientState(GLenum array); -void DrawArrays(GLenum mode, GLint first, GLsizei count); -void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); -void Enable(GLenum cap); -void EnableClientState(GLenum array); -void Finish(void); -void Flush(void); -void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -void Fogf(GLenum pname, GLfloat param); -void Fogfv(GLenum pname, const GLfloat *params); -void Fogx(GLenum pname, GLfixed param); -void Fogxv(GLenum pname, const GLfixed *params); -void FrontFace(GLenum mode); -void Frustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); -void Frustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); -void GenerateMipmapOES(GLenum target); -void GenBuffers(GLsizei n, GLuint* buffers); -void GenFramebuffersOES(GLsizei n, GLuint* framebuffers); -void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers); -void GenTextures(GLsizei n, GLuint* textures); -void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params); -void GetBooleanv(GLenum pname, GLboolean* params); -void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params); -void GetClipPlanef(GLenum pname, GLfloat eqn[4]); -void GetClipPlanex(GLenum pname, GLfixed eqn[4]); -GLenum GetError(void); -void GetFixedv(GLenum pname, GLfixed *params); -void GetFloatv(GLenum pname, GLfloat* params); -void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params); -void GetIntegerv(GLenum pname, GLint* params); -void GetLightfv(GLenum light, GLenum pname, GLfloat *params); -void GetLightxv(GLenum light, GLenum pname, GLfixed *params); -void GetMaterialfv(GLenum face, GLenum pname, GLfloat *params); -void GetMaterialxv(GLenum face, GLenum pname, GLfixed *params); -void GetPointerv(GLenum pname, GLvoid **params); -const GLubyte* GetString(GLenum name); -void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); -void GetTexParameteriv(GLenum target, GLenum pname, GLint* params); -void GetTexEnvfv(GLenum env, GLenum pname, GLfloat *params); -void GetTexEnviv(GLenum env, GLenum pname, GLint *params); -void GetTexEnvxv(GLenum env, GLenum pname, GLfixed *params); -void GetTexParameterxv(GLenum target, GLenum pname, GLfixed *params); -void Hint(GLenum target, GLenum mode); -GLboolean IsBuffer(GLuint buffer); -GLboolean IsEnabled(GLenum cap); -GLboolean IsFramebufferOES(GLuint framebuffer); -GLboolean IsTexture(GLuint texture); -GLboolean IsRenderbufferOES(GLuint renderbuffer); -void LightModelf(GLenum pname, GLfloat param); -void LightModelfv(GLenum pname, const GLfloat *params); -void LightModelx(GLenum pname, GLfixed param); -void LightModelxv(GLenum pname, const GLfixed *params); -void Lightf(GLenum light, GLenum pname, GLfloat param); -void Lightfv(GLenum light, GLenum pname, const GLfloat *params); -void Lightx(GLenum light, GLenum pname, GLfixed param); -void Lightxv(GLenum light, GLenum pname, const GLfixed *params); -void LineWidth(GLfloat width); -void LineWidthx(GLfixed width); -void LoadIdentity(void); -void LoadMatrixf(const GLfloat *m); -void LoadMatrixx(const GLfixed *m); -void LogicOp(GLenum opcode); -void Materialf(GLenum face, GLenum pname, GLfloat param); -void Materialfv(GLenum face, GLenum pname, const GLfloat *params); -void Materialx(GLenum face, GLenum pname, GLfixed param); -void Materialxv(GLenum face, GLenum pname, const GLfixed *params); -void MatrixMode(GLenum mode); -void MultMatrixf(const GLfloat *m); -void MultMatrixx(const GLfixed *m); -void MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -void MultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q); -void Normal3f(GLfloat nx, GLfloat ny, GLfloat nz); -void Normal3x(GLfixed nx, GLfixed ny, GLfixed nz); -void NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer); -void Orthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); -void Orthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); -void PixelStorei(GLenum pname, GLint param); -void PointParameterf(GLenum pname, GLfloat param); -void PointParameterfv(GLenum pname, const GLfloat *params); -void PointParameterx(GLenum pname, GLfixed param); -void PointParameterxv(GLenum pname, const GLfixed *params); -void PointSize(GLfloat size); -void PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer); -void PointSizex(GLfixed size); -void PolygonOffset(GLfloat factor, GLfloat units); -void PolygonOffsetx(GLfixed factor, GLfixed units); -void PopMatrix(void); -void PushMatrix(void); -void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); -void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -void Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -void Rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z); -void SampleCoverage(GLclampf value, GLboolean invert); -void SampleCoveragex(GLclampx value, GLboolean invert); -void Scalef(GLfloat x, GLfloat y, GLfloat z); -void Scalex(GLfixed x, GLfixed y, GLfixed z); -void Scissor(GLint x, GLint y, GLsizei width, GLsizei height); -void ShadeModel(GLenum mode); -void StencilFunc(GLenum func, GLint ref, GLuint mask); -void StencilMask(GLuint mask); -void StencilOp(GLenum fail, GLenum zfail, GLenum zpass); -void TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void TexEnvf(GLenum target, GLenum pname, GLfloat param); -void TexEnvfv(GLenum target, GLenum pname, const GLfloat *params); -void TexEnvi(GLenum target, GLenum pname, GLint param); -void TexEnvx(GLenum target, GLenum pname, GLfixed param); -void TexEnviv(GLenum target, GLenum pname, const GLint *params); -void TexEnvxv(GLenum target, GLenum pname, const GLfixed *params); -void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid* pixels); -void TexParameterf(GLenum target, GLenum pname, GLfloat param); -void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params); -void TexParameteri(GLenum target, GLenum pname, GLint param); -void TexParameteriv(GLenum target, GLenum pname, const GLint* params); -void TexParameterx(GLenum target, GLenum pname, GLfixed param); -void TexParameterxv(GLenum target, GLenum pname, const GLfixed *params); -void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid* pixels); -void Translatef(GLfloat x, GLfloat y, GLfloat z); -void Translatex(GLfixed x, GLfixed y, GLfixed z); -void VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void Viewport(GLint x, GLint y, GLsizei width, GLsizei height); -void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image); -void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image); -void DrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height); -void DrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height); -void DrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height); -void DrawTexsvOES(const GLshort *coords); -void DrawTexivOES(const GLint *coords); -void DrawTexxvOES(const GLfixed *coords); -void DrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); -void DrawTexfvOES(const GLfloat *coords); -} - -egl::Context *es1CreateContext(const egl::Config *config, const egl::Context *shareContext); -extern "C" __eglMustCastToProperFunctionPointerType es1GetProcAddress(const char *procname); -egl::Image *createBackBuffer(int width, int height, const egl::Config *config); -egl::Image *createDepthStencil(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard); -sw::FrameBuffer *createFrameBuffer(void *display, EGLNativeWindowType window, int width, int height); - -extern "C" -{ -EGLAPI EGLint EGLAPIENTRY eglGetError(void) -{ - return libEGL->eglGetError(); -} - -EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) -{ - return libEGL->eglGetDisplay(display_id); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) -{ - return libEGL->eglInitialize(dpy, major, minor); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) -{ - return libEGL->eglTerminate(dpy); -} - -EGLAPI const char *EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) -{ - return libEGL->eglQueryString(dpy, name); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) -{ - return libEGL->eglGetConfigs(dpy, configs, config_size, num_config); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) -{ - return libEGL->eglChooseConfig(dpy, attrib_list, configs, config_size, num_config); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) -{ - return libEGL->eglGetConfigAttrib(dpy, config, attribute, value); -} - -EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list) -{ - return libEGL->eglCreateWindowSurface(dpy, config, window, attrib_list); -} - -EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) -{ - return libEGL->eglCreatePbufferSurface(dpy, config, attrib_list); -} - -EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) -{ - return libEGL->eglCreatePixmapSurface(dpy, config, pixmap, attrib_list); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface) -{ - return libEGL->eglDestroySurface(dpy, surface); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) -{ - return libEGL->eglQuerySurface(dpy, surface, attribute, value); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) -{ - return libEGL->eglBindAPI(api); -} - -EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void) -{ - return libEGL->eglQueryAPI(); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void) -{ - return libEGL->eglWaitClient(); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) -{ - return libEGL->eglReleaseThread(); -} - -EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) -{ - return libEGL->eglCreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) -{ - return libEGL->eglSurfaceAttrib(dpy, surface, attribute, value); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) -{ - return libEGL->eglBindTexImage(dpy, surface, buffer); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) -{ - return libEGL->eglReleaseTexImage(dpy, surface, buffer); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) -{ - return libEGL->eglSwapInterval(dpy, interval); -} - -EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) -{ - return libEGL->eglCreateContext(dpy, config, share_context, attrib_list); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) -{ - return libEGL->eglDestroyContext(dpy, ctx); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) -{ - return libEGL->eglMakeCurrent(dpy, draw, read, ctx); -} - -EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) -{ - return libEGL->eglGetCurrentContext(); -} - -EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) -{ - return libEGL->eglGetCurrentSurface(readdraw); -} - -EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) -{ - return libEGL->eglGetCurrentDisplay(); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) -{ - return libEGL->eglQueryContext(dpy, ctx, attribute, value); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void) -{ - return libEGL->eglWaitGL(); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) -{ - return libEGL->eglWaitNative(engine); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) -{ - return libEGL->eglSwapBuffers(dpy, surface); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) -{ - return libEGL->eglCopyBuffers(dpy, surface, target); -} - -EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) -{ - return libEGL->eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) -{ - return libEGL->eglDestroyImageKHR(dpy, image); -} - -EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname) -{ - return libEGL->eglGetProcAddress(procname); -} - -EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) -{ - return libEGL->eglCreateSyncKHR(dpy, type, attrib_list); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) -{ - return libEGL->eglDestroySyncKHR(dpy, sync); -} - -EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) -{ - return libEGL->eglClientWaitSyncKHR(dpy, sync, flags, timeout); -} - -EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) -{ - return libEGL->eglGetSyncAttribKHR(dpy, sync, attribute, value); -} - -GL_API void GL_APIENTRY glActiveTexture(GLenum texture) -{ - return es1::ActiveTexture(texture); -} - -GL_API void GL_APIENTRY glAlphaFunc(GLenum func, GLclampf ref) -{ - return es1::AlphaFunc(func, ref); -} - -GL_API void GL_APIENTRY glAlphaFuncx(GLenum func, GLclampx ref) -{ - return es1::AlphaFuncx(func, ref); -} - -GL_API void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer) -{ - return es1::BindBuffer(target, buffer); -} - -GL_API void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer) -{ - return es1::BindFramebuffer(target, framebuffer); -} - -GL_API void GL_APIENTRY glBindFramebufferOES(GLenum target, GLuint framebuffer) -{ - return es1::BindFramebufferOES(target, framebuffer); -} - -GL_API void GL_APIENTRY glBindRenderbufferOES(GLenum target, GLuint renderbuffer) -{ - return es1::BindRenderbufferOES(target, renderbuffer); -} - -GL_API void GL_APIENTRY glBindTexture(GLenum target, GLuint texture) -{ - return es1::BindTexture(target, texture); -} - -GL_API void GL_APIENTRY glBlendEquationOES(GLenum mode) -{ - return es1::BlendEquationSeparateOES(mode, mode); -} - -GL_API void GL_APIENTRY glBlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha) -{ - return es1::BlendEquationSeparateOES(modeRGB, modeAlpha); -} - -GL_API void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) -{ - return es1::BlendFuncSeparateOES(sfactor, dfactor, sfactor, dfactor); -} - -GL_API void GL_APIENTRY glBlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) -{ - return es1::BlendFuncSeparateOES(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -GL_API void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) -{ - return es1::BufferData(target, size, data, usage); -} - -GL_API void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) -{ - return es1::BufferSubData(target, offset, size, data); -} - -GL_API GLenum GL_APIENTRY glCheckFramebufferStatusOES(GLenum target) -{ - return es1::CheckFramebufferStatusOES(target); -} - -GL_API void GL_APIENTRY glClear(GLbitfield mask) -{ - return es1::Clear(mask); -} - -GL_API void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) -{ - return es1::ClearColor(red, green, blue, alpha); -} - -GL_API void GL_APIENTRY glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) -{ - return es1::ClearColorx(red, green, blue, alpha); -} - -GL_API void GL_APIENTRY glClearDepthf(GLclampf depth) -{ - return es1::ClearDepthf(depth); -} - -GL_API void GL_APIENTRY glClearDepthx(GLclampx depth) -{ - return es1::ClearDepthx(depth); -} - -GL_API void GL_APIENTRY glClearStencil(GLint s) -{ - return es1::ClearStencil(s); -} - -GL_API void GL_APIENTRY glClientActiveTexture(GLenum texture) -{ - return es1::ClientActiveTexture(texture); -} - -GL_API void GL_APIENTRY glClipPlanef(GLenum plane, const GLfloat *equation) -{ - return es1::ClipPlanef(plane, equation); -} - -GL_API void GL_APIENTRY glClipPlanex(GLenum plane, const GLfixed *equation) -{ - return es1::ClipPlanex(plane, equation); -} - -GL_API void GL_APIENTRY glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) -{ - return es1::Color4f(red, green, blue, alpha); -} - -GL_API void GL_APIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) -{ - return es1::Color4ub(red, green, blue, alpha); -} - -GL_API void GL_APIENTRY glColor4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) -{ - return es1::Color4x(red, green, blue, alpha); -} - -GL_API void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) -{ - return es1::ColorMask(red, green, blue, alpha); -} - -GL_API void GL_APIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - return es1::ColorPointer(size, type, stride, pointer); -} - -GL_API void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid* data) -{ - return es1::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); -} - -GL_API void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const GLvoid* data) -{ - return es1::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); -} - -GL_API void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) -{ - return es1::CopyTexImage2D(target, level, internalformat, x, y, width, height, border); -} - -GL_API void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) -{ - return es1::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); -} - -GL_API void GL_APIENTRY glCullFace(GLenum mode) -{ - return es1::CullFace(mode); -} - -GL_API void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers) -{ - return es1::DeleteBuffers(n, buffers); -} - -GL_API void GL_APIENTRY glDeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers) -{ - return es1::DeleteFramebuffersOES(n, framebuffers); -} - -GL_API void GL_APIENTRY glDeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers) -{ - return es1::DeleteRenderbuffersOES(n, renderbuffers); -} - -GL_API void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures) -{ - return es1::DeleteTextures(n, textures); -} - -GL_API void GL_APIENTRY glDepthFunc(GLenum func) -{ - return es1::DepthFunc(func); -} - -GL_API void GL_APIENTRY glDepthMask(GLboolean flag) -{ - return es1::DepthMask(flag); -} - -GL_API void GL_APIENTRY glDepthRangex(GLclampx zNear, GLclampx zFar) -{ - return es1::DepthRangex(zNear, zFar); -} - -GL_API void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar) -{ - return es1::DepthRangef(zNear, zFar); -} - -GL_API void GL_APIENTRY glDisable(GLenum cap) -{ - return es1::Disable(cap); -} - -GL_API void GL_APIENTRY glDisableClientState(GLenum array) -{ - return es1::DisableClientState(array); -} - -GL_API void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) -{ - return es1::DrawArrays(mode, first, count); -} - -GL_API void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) -{ - return es1::DrawElements(mode, count, type, indices); -} - -GL_API void GL_APIENTRY glEnable(GLenum cap) -{ - return es1::Enable(cap); -} - -GL_API void GL_APIENTRY glEnableClientState(GLenum array) -{ - return es1::EnableClientState(array); -} - -GL_API void GL_APIENTRY glFinish(void) -{ - return es1::Finish(); -} - -GL_API void GL_APIENTRY glFlush(void) -{ - return es1::Flush(); -} - -GL_API void GL_APIENTRY glFramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) -{ - return es1::FramebufferRenderbufferOES(target, attachment, renderbuffertarget, renderbuffer); -} - -GL_API void GL_APIENTRY glFramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) -{ - return es1::FramebufferTexture2DOES(target, attachment, textarget, texture, level); -} - -GL_API void GL_APIENTRY glFogf(GLenum pname, GLfloat param) -{ - return es1::Fogf(pname, param); -} - -GL_API void GL_APIENTRY glFogfv(GLenum pname, const GLfloat *params) -{ - return es1::Fogfv(pname, params); -} - -GL_API void GL_APIENTRY glFogx(GLenum pname, GLfixed param) -{ - return es1::Fogx(pname, param); -} - -GL_API void GL_APIENTRY glFogxv(GLenum pname, const GLfixed *params) -{ - return es1::Fogxv(pname, params); -} - -GL_API void GL_APIENTRY glFrontFace(GLenum mode) -{ - return es1::FrontFace(mode); -} - -GL_API void GL_APIENTRY glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) -{ - return es1::Frustumf(left, right, bottom, top, zNear, zFar); -} - -GL_API void GL_APIENTRY glFrustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) -{ - return es1::Frustumx(left, right, bottom, top, zNear, zFar); -} - -GL_API void GL_APIENTRY glGenerateMipmapOES(GLenum target) -{ - return es1::GenerateMipmapOES(target); -} - -GL_API void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers) -{ - return es1::GenBuffers(n, buffers); -} - -GL_API void GL_APIENTRY glGenFramebuffersOES(GLsizei n, GLuint* framebuffers) -{ - return es1::GenFramebuffersOES(n, framebuffers); -} - -GL_API void GL_APIENTRY glGenRenderbuffersOES(GLsizei n, GLuint* renderbuffers) -{ - return es1::GenRenderbuffersOES(n, renderbuffers); -} - -GL_API void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures) -{ - return es1::GenTextures(n, textures); -} - -GL_API void GL_APIENTRY glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params) -{ - return es1::GetRenderbufferParameterivOES(target, pname, params); -} - -GL_API void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params) -{ - return es1::GetBooleanv(pname, params); -} - -GL_API void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) -{ - return es1::GetBufferParameteriv(target, pname, params); -} - -GL_API void GL_APIENTRY glGetClipPlanef(GLenum pname, GLfloat eqn[4]) -{ - return es1::GetClipPlanef(pname, eqn); -} - -GL_API void GL_APIENTRY glGetClipPlanex(GLenum pname, GLfixed eqn[4]) -{ - return es1::GetClipPlanex(pname, eqn); -} - -GL_API GLenum GL_APIENTRY glGetError(void) -{ - return es1::GetError(); -} - -GL_API void GL_APIENTRY glGetFixedv(GLenum pname, GLfixed *params) -{ - return es1::GetFixedv(pname, params); -} - -GL_API void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params) -{ - return es1::GetFloatv(pname, params); -} - -GL_API void GL_APIENTRY glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params) -{ - return es1::GetFramebufferAttachmentParameterivOES(target, attachment, pname, params); -} - -GL_API void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params) -{ - return es1::GetIntegerv(pname, params); -} - -GL_API void GL_APIENTRY glGetLightfv(GLenum light, GLenum pname, GLfloat *params) -{ - return es1::GetLightfv(light, pname, params); -} - -GL_API void GL_APIENTRY glGetLightxv(GLenum light, GLenum pname, GLfixed *params) -{ - return es1::GetLightxv(light, pname, params); -} - -GL_API void GL_APIENTRY glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) -{ - return es1::GetMaterialfv(face, pname, params); -} - -GL_API void GL_APIENTRY glGetMaterialxv(GLenum face, GLenum pname, GLfixed *params) -{ - return es1::GetMaterialxv(face, pname, params); -} - -GL_API void GL_APIENTRY glGetPointerv(GLenum pname, GLvoid **params) -{ - return es1::GetPointerv(pname, params); -} - -GL_API const GLubyte* GL_APIENTRY glGetString(GLenum name) -{ - return es1::GetString(name); -} - -GL_API void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) -{ - return es1::GetTexParameterfv(target, pname, params); -} - -GL_API void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) -{ - return es1::GetTexParameteriv(target, pname, params); -} - -GL_API void GL_APIENTRY glGetTexEnvfv(GLenum env, GLenum pname, GLfloat *params) -{ - return es1::GetTexEnvfv(env, pname, params); -} - -GL_API void GL_APIENTRY glGetTexEnviv(GLenum env, GLenum pname, GLint *params) -{ - return es1::GetTexEnviv(env, pname, params); -} - -GL_API void GL_APIENTRY glGetTexEnvxv(GLenum env, GLenum pname, GLfixed *params) -{ - return es1::GetTexEnvxv(env, pname, params); -} - -GL_API void GL_APIENTRY glGetTexParameterxv(GLenum target, GLenum pname, GLfixed *params) -{ - return es1::GetTexParameterxv(target, pname, params); -} - -GL_API void GL_APIENTRY glHint(GLenum target, GLenum mode) -{ - return es1::Hint(target, mode); -} - -GL_API GLboolean GL_APIENTRY glIsBuffer(GLuint buffer) -{ - return es1::IsBuffer(buffer); -} - -GL_API GLboolean GL_APIENTRY glIsEnabled(GLenum cap) -{ - return es1::IsEnabled(cap); -} - -GL_API GLboolean GL_APIENTRY glIsFramebufferOES(GLuint framebuffer) -{ - return es1::IsFramebufferOES(framebuffer); -} - -GL_API GLboolean GL_APIENTRY glIsTexture(GLuint texture) -{ - return es1::IsTexture(texture); -} - -GL_API GLboolean GL_APIENTRY glIsRenderbufferOES(GLuint renderbuffer) -{ - return es1::IsRenderbufferOES(renderbuffer); -} - -GL_API void GL_APIENTRY glLightModelf(GLenum pname, GLfloat param) -{ - return es1::LightModelf(pname, param); -} - -GL_API void GL_APIENTRY glLightModelfv(GLenum pname, const GLfloat *params) -{ - return es1::LightModelfv(pname, params); -} - -GL_API void GL_APIENTRY glLightModelx(GLenum pname, GLfixed param) -{ - return es1::LightModelx(pname, param); -} - -GL_API void GL_APIENTRY glLightModelxv(GLenum pname, const GLfixed *params) -{ - return es1::LightModelxv(pname, params); -} - -GL_API void GL_APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param) -{ - return es1::Lightf(light, pname, param); -} - -GL_API void GL_APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) -{ - return es1::Lightfv(light, pname, params); -} - -GL_API void GL_APIENTRY glLightx(GLenum light, GLenum pname, GLfixed param) -{ - return es1::Lightx(light, pname, param); -} - -GL_API void GL_APIENTRY glLightxv(GLenum light, GLenum pname, const GLfixed *params) -{ - return es1::Lightxv(light, pname, params); -} - -GL_API void GL_APIENTRY glLineWidth(GLfloat width) -{ - return es1::LineWidth(width); -} - -GL_API void GL_APIENTRY glLineWidthx(GLfixed width) -{ - return es1::LineWidthx(width); -} - -GL_API void GL_APIENTRY glLoadIdentity(void) -{ - return es1::LoadIdentity(); -} - -GL_API void GL_APIENTRY glLoadMatrixf(const GLfloat *m) -{ - return es1::LoadMatrixf(m); -} - -GL_API void GL_APIENTRY glLoadMatrixx(const GLfixed *m) -{ - return es1::LoadMatrixx(m); -} - -GL_API void GL_APIENTRY glLogicOp(GLenum opcode) -{ - return es1::LogicOp(opcode); -} - -GL_API void GL_APIENTRY glMaterialf(GLenum face, GLenum pname, GLfloat param) -{ - return es1::Materialf(face, pname, param); -} - -GL_API void GL_APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) -{ - return es1::Materialfv(face, pname, params); -} - -GL_API void GL_APIENTRY glMaterialx(GLenum face, GLenum pname, GLfixed param) -{ - return es1::Materialx(face, pname, param); -} - -GL_API void GL_APIENTRY glMaterialxv(GLenum face, GLenum pname, const GLfixed *params) -{ - return es1::Materialxv(face, pname, params); -} - -GL_API void GL_APIENTRY glMatrixMode(GLenum mode) -{ - return es1::MatrixMode(mode); -} - -GL_API void GL_APIENTRY glMultMatrixf(const GLfloat *m) -{ - return es1::MultMatrixf(m); -} - -GL_API void GL_APIENTRY glMultMatrixx(const GLfixed *m) -{ - return es1::MultMatrixx(m); -} - -GL_API void GL_APIENTRY glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) -{ - return es1::MultiTexCoord4f(target, s, t, r, q); -} - -GL_API void GL_APIENTRY glMultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) -{ - return es1::MultiTexCoord4x(target, s, t, r, q); -} - -GL_API void GL_APIENTRY glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) -{ - return es1::Normal3f(nx, ny, nz); -} - -GL_API void GL_APIENTRY glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz) -{ - return es1::Normal3x(nx, ny, nz); -} - -GL_API void GL_APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) -{ - return es1::NormalPointer(type, stride, pointer); -} - -GL_API void GL_APIENTRY glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) -{ - return es1::Orthof(left, right, bottom, top, zNear, zFar); -} - -GL_API void GL_APIENTRY glOrthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) -{ - return es1::Orthox(left, right, bottom, top, zNear, zFar); -} - -GL_API void GL_APIENTRY glPixelStorei(GLenum pname, GLint param) -{ - return es1::PixelStorei(pname, param); -} - -GL_API void GL_APIENTRY glPointParameterf(GLenum pname, GLfloat param) -{ - return es1::PointParameterf(pname, param); -} - -GL_API void GL_APIENTRY glPointParameterfv(GLenum pname, const GLfloat *params) -{ - return es1::PointParameterfv(pname, params); -} - -GL_API void GL_APIENTRY glPointParameterx(GLenum pname, GLfixed param) -{ - return es1::PointParameterx(pname, param); -} - -GL_API void GL_APIENTRY glPointParameterxv(GLenum pname, const GLfixed *params) -{ - return es1::PointParameterxv(pname, params); -} - -GL_API void GL_APIENTRY glPointSize(GLfloat size) -{ - return es1::PointSize(size); -} - -GL_API void GL_APIENTRY glPointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer) -{ - return es1::PointSizePointerOES(type, stride, pointer); -} - -GL_API void GL_APIENTRY glPointSizex(GLfixed size) -{ - return es1::PointSizex(size); -} - -GL_API void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units) -{ - return es1::PolygonOffset(factor, units); -} - -GL_API void GL_APIENTRY glPolygonOffsetx(GLfixed factor, GLfixed units) -{ - return es1::PolygonOffsetx(factor, units); -} - -GL_API void GL_APIENTRY glPopMatrix(void) -{ - return es1::PopMatrix(); -} - -GL_API void GL_APIENTRY glPushMatrix(void) -{ - return es1::PushMatrix(); -} - -GL_API void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) -{ - return es1::ReadPixels(x, y, width, height, format, type, pixels); -} - -GL_API void GL_APIENTRY glRenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) -{ - return es1::RenderbufferStorageOES(target, internalformat, width, height); -} - -GL_API void GL_APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) -{ - return es1::Rotatef(angle, x, y, z); -} - -GL_API void GL_APIENTRY glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) -{ - return es1::Rotatex(angle, x, y, z); -} - -GL_API void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert) -{ - return es1::SampleCoverage(value, invert); -} - -GL_API void GL_APIENTRY glSampleCoveragex(GLclampx value, GLboolean invert) -{ - return es1::SampleCoveragex(value, invert); -} - -GL_API void GL_APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) -{ - return es1::Scalef(x, y, z); -} - -GL_API void GL_APIENTRY glScalex(GLfixed x, GLfixed y, GLfixed z) -{ - return es1::Scalex(x, y, z); -} - -GL_API void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) -{ - return es1::Scissor(x, y, width, height); -} - -GL_API void GL_APIENTRY glShadeModel(GLenum mode) -{ - return es1::ShadeModel(mode); -} - -GL_API void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask) -{ - return es1::StencilFunc(func, ref, mask); -} - -GL_API void GL_APIENTRY glStencilMask(GLuint mask) -{ - return es1::StencilMask(mask); -} - -GL_API void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) -{ - return es1::StencilOp(fail, zfail, zpass); -} - -GL_API void GL_APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - return es1::TexCoordPointer(size, type, stride, pointer); -} - -GL_API void GL_APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param) -{ - return es1::TexEnvf(target, pname, param); -} - -GL_API void GL_APIENTRY glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) -{ - return es1::TexEnvfv(target, pname, params); -} - -GL_API void GL_APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) -{ - return es1::TexEnvi(target, pname, param); -} - -GL_API void GL_APIENTRY glTexEnvx(GLenum target, GLenum pname, GLfixed param) -{ - return es1::TexEnvx(target, pname, param); -} - -GL_API void GL_APIENTRY glTexEnviv(GLenum target, GLenum pname, const GLint *params) -{ - return es1::TexEnviv(target, pname, params); -} - -GL_API void GL_APIENTRY glTexEnvxv(GLenum target, GLenum pname, const GLfixed *params) -{ - return es1::TexEnvxv(target, pname, params); -} - -GL_API void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid* pixels) -{ - return es1::TexImage2D(target, level, internalformat, width, height, border, format, type, pixels); -} - -GL_API void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param) -{ - return es1::TexParameterf(target, pname, param); -} - -GL_API void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) -{ - return es1::TexParameterfv(target, pname, params); -} - -GL_API void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) -{ - return es1::TexParameteri(target, pname, param); -} - -GL_API void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params) -{ - return es1::TexParameteriv(target, pname, params); -} - -GL_API void GL_APIENTRY glTexParameterx(GLenum target, GLenum pname, GLfixed param) -{ - return es1::TexParameterx(target, pname, param); -} - -GL_API void GL_APIENTRY glTexParameterxv(GLenum target, GLenum pname, const GLfixed *params) -{ - return es1::TexParameterxv(target, pname, params); -} - -GL_API void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid* pixels) -{ - return es1::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); -} - -GL_API void GL_APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) -{ - return es1::Translatef(x, y, z); -} - -GL_API void GL_APIENTRY glTranslatex(GLfixed x, GLfixed y, GLfixed z) -{ - return es1::Translatex(x, y, z); -} - -GL_API void GL_APIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - return es1::VertexPointer(size, type, stride, pointer); -} - -GL_API void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) -{ - return es1::Viewport(x, y, width, height); -} - -GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) -{ - return es1::EGLImageTargetTexture2DOES(target, image); -} - -GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) -{ - return es1::EGLImageTargetRenderbufferStorageOES(target, image); -} - -GL_API void GL_APIENTRY glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) -{ - return es1::DrawTexsOES(x,y, z, width, height); -} - -GL_API void GL_APIENTRY glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) -{ - return es1::DrawTexiOES(x,y, z, width, height); -} - -GL_API void GL_APIENTRY glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) -{ - return es1::DrawTexxOES(x,y, z, width, height); -} - -GL_API void GL_APIENTRY glDrawTexsvOES(const GLshort *coords) -{ - return es1::DrawTexsvOES(coords); -} - -GL_API void GL_APIENTRY glDrawTexivOES(const GLint *coords) -{ - return es1::DrawTexivOES(coords); -} - -GL_API void GL_APIENTRY glDrawTexxvOES(const GLfixed *coords) -{ - return es1::DrawTexxvOES(coords); -} - -GL_API void GL_APIENTRY glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) -{ - return es1::DrawTexfOES(x, y, z, width, height); -} - -GL_API void GL_APIENTRY glDrawTexfvOES(const GLfloat *coords) -{ - return es1::DrawTexfvOES(coords); -} - -} - -LibGLES_CMexports::LibGLES_CMexports() -{ - this->glActiveTexture = es1::ActiveTexture; - this->glAlphaFunc = es1::AlphaFunc; - this->glAlphaFuncx = es1::AlphaFuncx; - this->glBindBuffer = es1::BindBuffer; - this->glBindFramebuffer = es1::BindFramebuffer; - this->glBindFramebufferOES = es1::BindFramebufferOES; - this->glBindRenderbufferOES = es1::BindRenderbufferOES; - this->glBindTexture = es1::BindTexture; - this->glBlendEquationSeparateOES = es1::BlendEquationSeparateOES; - this->glBlendEquationOES = es1::BlendEquationOES; - this->glBlendEquationSeparateOES = es1::BlendEquationSeparateOES; - this->glBlendFuncSeparateOES = es1::BlendFuncSeparateOES; - this->glBlendFunc = es1::BlendFunc; - this->glBlendFuncSeparateOES = es1::BlendFuncSeparateOES; - this->glBufferData = es1::BufferData; - this->glBufferSubData = es1::BufferSubData; - this->glCheckFramebufferStatusOES = es1::CheckFramebufferStatusOES; - this->glClear = es1::Clear; - this->glClearColor = es1::ClearColor; - this->glClearColorx = es1::ClearColorx; - this->glClearDepthf = es1::ClearDepthf; - this->glClearDepthx = es1::ClearDepthx; - this->glClearStencil = es1::ClearStencil; - this->glClientActiveTexture = es1::ClientActiveTexture; - this->glClipPlanef = es1::ClipPlanef; - this->glClipPlanex = es1::ClipPlanex; - this->glColor4f = es1::Color4f; - this->glColor4ub = es1::Color4ub; - this->glColor4x = es1::Color4x; - this->glColorMask = es1::ColorMask; - this->glColorPointer = es1::ColorPointer; - this->glCompressedTexImage2D = es1::CompressedTexImage2D; - this->glCompressedTexSubImage2D = es1::CompressedTexSubImage2D; - this->glCopyTexImage2D = es1::CopyTexImage2D; - this->glCopyTexSubImage2D = es1::CopyTexSubImage2D; - this->glCullFace = es1::CullFace; - this->glDeleteBuffers = es1::DeleteBuffers; - this->glDeleteFramebuffersOES = es1::DeleteFramebuffersOES; - this->glDeleteRenderbuffersOES = es1::DeleteRenderbuffersOES; - this->glDeleteTextures = es1::DeleteTextures; - this->glDepthFunc = es1::DepthFunc; - this->glDepthMask = es1::DepthMask; - this->glDepthRangex = es1::DepthRangex; - this->glDepthRangef = es1::DepthRangef; - this->glDisable = es1::Disable; - this->glDisableClientState = es1::DisableClientState; - this->glDrawArrays = es1::DrawArrays; - this->glDrawElements = es1::DrawElements; - this->glEnable = es1::Enable; - this->glEnableClientState = es1::EnableClientState; - this->glFinish = es1::Finish; - this->glFlush = es1::Flush; - this->glFramebufferRenderbufferOES = es1::FramebufferRenderbufferOES; - this->glFramebufferTexture2DOES = es1::FramebufferTexture2DOES; - this->glFogf = es1::Fogf; - this->glFogfv = es1::Fogfv; - this->glFogx = es1::Fogx; - this->glFogxv = es1::Fogxv; - this->glFrontFace = es1::FrontFace; - this->glFrustumf = es1::Frustumf; - this->glFrustumx = es1::Frustumx; - this->glGenerateMipmapOES = es1::GenerateMipmapOES; - this->glGenBuffers = es1::GenBuffers; - this->glGenFramebuffersOES = es1::GenFramebuffersOES; - this->glGenRenderbuffersOES = es1::GenRenderbuffersOES; - this->glGenTextures = es1::GenTextures; - this->glGetRenderbufferParameterivOES = es1::GetRenderbufferParameterivOES; - this->glGetBooleanv = es1::GetBooleanv; - this->glGetBufferParameteriv = es1::GetBufferParameteriv; - this->glGetClipPlanef = es1::GetClipPlanef; - this->glGetClipPlanex = es1::GetClipPlanex; - this->glGetError = es1::GetError; - this->glGetFixedv = es1::GetFixedv; - this->glGetFloatv = es1::GetFloatv; - this->glGetFramebufferAttachmentParameterivOES = es1::GetFramebufferAttachmentParameterivOES; - this->glGetIntegerv = es1::GetIntegerv; - this->glGetLightfv = es1::GetLightfv; - this->glGetLightxv = es1::GetLightxv; - this->glGetMaterialfv = es1::GetMaterialfv; - this->glGetMaterialxv = es1::GetMaterialxv; - this->glGetPointerv = es1::GetPointerv; - this->glGetString = es1::GetString; - this->glGetTexParameterfv = es1::GetTexParameterfv; - this->glGetTexParameteriv = es1::GetTexParameteriv; - this->glGetTexEnvfv = es1::GetTexEnvfv; - this->glGetTexEnviv = es1::GetTexEnviv; - this->glGetTexEnvxv = es1::GetTexEnvxv; - this->glGetTexParameterxv = es1::GetTexParameterxv; - this->glHint = es1::Hint; - this->glIsBuffer = es1::IsBuffer; - this->glIsEnabled = es1::IsEnabled; - this->glIsFramebufferOES = es1::IsFramebufferOES; - this->glIsTexture = es1::IsTexture; - this->glIsRenderbufferOES = es1::IsRenderbufferOES; - this->glLightModelf = es1::LightModelf; - this->glLightModelfv = es1::LightModelfv; - this->glLightModelx = es1::LightModelx; - this->glLightModelxv = es1::LightModelxv; - this->glLightf = es1::Lightf; - this->glLightfv = es1::Lightfv; - this->glLightx = es1::Lightx; - this->glLightxv = es1::Lightxv; - this->glLineWidth = es1::LineWidth; - this->glLineWidthx = es1::LineWidthx; - this->glLoadIdentity = es1::LoadIdentity; - this->glLoadMatrixf = es1::LoadMatrixf; - this->glLoadMatrixx = es1::LoadMatrixx; - this->glLogicOp = es1::LogicOp; - this->glMaterialf = es1::Materialf; - this->glMaterialfv = es1::Materialfv; - this->glMaterialx = es1::Materialx; - this->glMaterialxv = es1::Materialxv; - this->glMatrixMode = es1::MatrixMode; - this->glMultMatrixf = es1::MultMatrixf; - this->glMultMatrixx = es1::MultMatrixx; - this->glMultiTexCoord4f = es1::MultiTexCoord4f; - this->glMultiTexCoord4x = es1::MultiTexCoord4x; - this->glNormal3f = es1::Normal3f; - this->glNormal3x = es1::Normal3x; - this->glNormalPointer = es1::NormalPointer; - this->glOrthof = es1::Orthof; - this->glOrthox = es1::Orthox; - this->glPixelStorei = es1::PixelStorei; - this->glPointParameterf = es1::PointParameterf; - this->glPointParameterfv = es1::PointParameterfv; - this->glPointParameterx = es1::PointParameterx; - this->glPointParameterxv = es1::PointParameterxv; - this->glPointSize = es1::PointSize; - this->glPointSizePointerOES = es1::PointSizePointerOES; - this->glPointSizex = es1::PointSizex; - this->glPolygonOffset = es1::PolygonOffset; - this->glPolygonOffsetx = es1::PolygonOffsetx; - this->glPopMatrix = es1::PopMatrix; - this->glPushMatrix = es1::PushMatrix; - this->glReadPixels = es1::ReadPixels; - this->glRenderbufferStorageOES = es1::RenderbufferStorageOES; - this->glRotatef = es1::Rotatef; - this->glRotatex = es1::Rotatex; - this->glSampleCoverage = es1::SampleCoverage; - this->glSampleCoveragex = es1::SampleCoveragex; - this->glScalef = es1::Scalef; - this->glScalex = es1::Scalex; - this->glScissor = es1::Scissor; - this->glShadeModel = es1::ShadeModel; - this->glStencilFunc = es1::StencilFunc; - this->glStencilMask = es1::StencilMask; - this->glStencilOp = es1::StencilOp; - this->glTexCoordPointer = es1::TexCoordPointer; - this->glTexEnvf = es1::TexEnvf; - this->glTexEnvfv = es1::TexEnvfv; - this->glTexEnvi = es1::TexEnvi; - this->glTexEnvx = es1::TexEnvx; - this->glTexEnviv = es1::TexEnviv; - this->glTexEnvxv = es1::TexEnvxv; - this->glTexImage2D = es1::TexImage2D; - this->glTexParameterf = es1::TexParameterf; - this->glTexParameterfv = es1::TexParameterfv; - this->glTexParameteri = es1::TexParameteri; - this->glTexParameteriv = es1::TexParameteriv; - this->glTexParameterx = es1::TexParameterx; - this->glTexParameterxv = es1::TexParameterxv; - this->glTexSubImage2D = es1::TexSubImage2D; - this->glTranslatef = es1::Translatef; - this->glTranslatex = es1::Translatex; - this->glVertexPointer = es1::VertexPointer; - this->glViewport = es1::Viewport; - this->glEGLImageTargetTexture2DOES = es1::EGLImageTargetTexture2DOES; - this->glEGLImageTargetRenderbufferStorageOES = es1::EGLImageTargetRenderbufferStorageOES; - this->glDrawTexsOES = es1::DrawTexsOES; - this->glDrawTexiOES = es1::DrawTexiOES; - this->glDrawTexxOES = es1::DrawTexxOES; - this->glDrawTexsvOES = es1::DrawTexsvOES; - this->glDrawTexivOES = es1::DrawTexivOES; - this->glDrawTexxvOES = es1::DrawTexxvOES; - this->glDrawTexfOES = es1::DrawTexfOES; - this->glDrawTexfvOES = es1::DrawTexfvOES; - - this->es1CreateContext = ::es1CreateContext; - this->es1GetProcAddress = ::es1GetProcAddress; - this->createBackBuffer = ::createBackBuffer; - this->createDepthStencil = ::createDepthStencil; - this->createFrameBuffer = ::createFrameBuffer; -} - -extern "C" GL_API LibGLES_CMexports *libGLES_CM_swiftshader() -{ - static LibGLES_CMexports libGLES_CM; - return &libGLES_CM; -} - -LibEGL libEGL; +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// main.cpp: DLL entry point and management of thread-local data. + +#include "main.h" + +#include "libGLES_CM.hpp" +#include "Framebuffer.h" +#include "libEGL/Surface.h" +#include "Common/Thread.hpp" +#include "Common/SharedLibrary.hpp" +#include "common/debug.h" + +#include <GLES/glext.h> + +#if !defined(_MSC_VER) +#define CONSTRUCTOR __attribute__((constructor)) +#define DESTRUCTOR __attribute__((destructor)) +#else +#define CONSTRUCTOR +#define DESTRUCTOR +#endif + +static void glAttachThread() +{ + TRACE("()"); +} + +static void glDetachThread() +{ + TRACE("()"); +} + +CONSTRUCTOR static void glAttachProcess() +{ + TRACE("()"); + + glAttachThread(); +} + +DESTRUCTOR static void glDetachProcess() +{ + TRACE("()"); + + glDetachThread(); +} + +#if defined(_WIN32) +extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) +{ + switch(reason) + { + case DLL_PROCESS_ATTACH: + glAttachProcess(); + break; + case DLL_THREAD_ATTACH: + glAttachThread(); + break; + case DLL_THREAD_DETACH: + glDetachThread(); + break; + case DLL_PROCESS_DETACH: + glDetachProcess(); + break; + default: + break; + } + + return TRUE; +} +#endif + +namespace es1 +{ +es1::Context *getContext() +{ + egl::Context *context = libEGL->clientGetCurrentContext(); + + if(context && context->getClientVersion() == 1) + { + return static_cast<es1::Context*>(context); + } + + return 0; +} + +Device *getDevice() +{ + Context *context = getContext(); + + return context ? context->getDevice() : 0; +} + +// Records an error code +void error(GLenum errorCode) +{ + es1::Context *context = es1::getContext(); + + if(context) + { + switch(errorCode) + { + case GL_INVALID_ENUM: + context->recordInvalidEnum(); + TRACE("\t! Error generated: invalid enum\n"); + break; + case GL_INVALID_VALUE: + context->recordInvalidValue(); + TRACE("\t! Error generated: invalid value\n"); + break; + case GL_INVALID_OPERATION: + context->recordInvalidOperation(); + TRACE("\t! Error generated: invalid operation\n"); + break; + case GL_OUT_OF_MEMORY: + context->recordOutOfMemory(); + TRACE("\t! Error generated: out of memory\n"); + break; + case GL_INVALID_FRAMEBUFFER_OPERATION_OES: + context->recordInvalidFramebufferOperation(); + TRACE("\t! Error generated: invalid framebuffer operation\n"); + break; + case GL_STACK_OVERFLOW: + context->recordMatrixStackOverflow(); + TRACE("\t! Error generated: matrix stack overflow\n"); + break; + case GL_STACK_UNDERFLOW: + context->recordMatrixStackUnderflow(); + TRACE("\t! Error generated: matrix stack underflow\n"); + break; + default: UNREACHABLE(errorCode); + } + } +} +} + +namespace es1 +{ +void ActiveTexture(GLenum texture); +void AlphaFunc(GLenum func, GLclampf ref); +void AlphaFuncx(GLenum func, GLclampx ref); +void BindBuffer(GLenum target, GLuint buffer); +void BindFramebuffer(GLenum target, GLuint framebuffer); +void BindFramebufferOES(GLenum target, GLuint framebuffer); +void BindRenderbufferOES(GLenum target, GLuint renderbuffer); +void BindTexture(GLenum target, GLuint texture); +void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha); +void BlendEquationOES(GLenum mode); +void BlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha); +void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +void BlendFunc(GLenum sfactor, GLenum dfactor); +void BlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +GLenum CheckFramebufferStatusOES(GLenum target); +void Clear(GLbitfield mask); +void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +void ClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha); +void ClearDepthf(GLclampf depth); +void ClearDepthx(GLclampx depth); +void ClearStencil(GLint s); +void ClientActiveTexture(GLenum texture); +void ClipPlanef(GLenum plane, const GLfloat *equation); +void ClipPlanex(GLenum plane, const GLfixed *equation); +void Color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +void Color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +void Color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +void ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid* data); +void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, const GLvoid* data); +void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +void CullFace(GLenum mode); +void DeleteBuffers(GLsizei n, const GLuint* buffers); +void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers); +void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers); +void DeleteTextures(GLsizei n, const GLuint* textures); +void DepthFunc(GLenum func); +void DepthMask(GLboolean flag); +void DepthRangex(GLclampx zNear, GLclampx zFar); +void DepthRangef(GLclampf zNear, GLclampf zFar); +void Disable(GLenum cap); +void DisableClientState(GLenum array); +void DrawArrays(GLenum mode, GLint first, GLsizei count); +void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); +void Enable(GLenum cap); +void EnableClientState(GLenum array); +void Finish(void); +void Flush(void); +void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +void Fogf(GLenum pname, GLfloat param); +void Fogfv(GLenum pname, const GLfloat *params); +void Fogx(GLenum pname, GLfixed param); +void Fogxv(GLenum pname, const GLfixed *params); +void FrontFace(GLenum mode); +void Frustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +void Frustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +void GenerateMipmapOES(GLenum target); +void GenBuffers(GLsizei n, GLuint* buffers); +void GenFramebuffersOES(GLsizei n, GLuint* framebuffers); +void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers); +void GenTextures(GLsizei n, GLuint* textures); +void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params); +void GetBooleanv(GLenum pname, GLboolean* params); +void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params); +void GetClipPlanef(GLenum pname, GLfloat eqn[4]); +void GetClipPlanex(GLenum pname, GLfixed eqn[4]); +GLenum GetError(void); +void GetFixedv(GLenum pname, GLfixed *params); +void GetFloatv(GLenum pname, GLfloat* params); +void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params); +void GetIntegerv(GLenum pname, GLint* params); +void GetLightfv(GLenum light, GLenum pname, GLfloat *params); +void GetLightxv(GLenum light, GLenum pname, GLfixed *params); +void GetMaterialfv(GLenum face, GLenum pname, GLfloat *params); +void GetMaterialxv(GLenum face, GLenum pname, GLfixed *params); +void GetPointerv(GLenum pname, GLvoid **params); +const GLubyte* GetString(GLenum name); +void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); +void GetTexParameteriv(GLenum target, GLenum pname, GLint* params); +void GetTexEnvfv(GLenum env, GLenum pname, GLfloat *params); +void GetTexEnviv(GLenum env, GLenum pname, GLint *params); +void GetTexEnvxv(GLenum env, GLenum pname, GLfixed *params); +void GetTexParameterxv(GLenum target, GLenum pname, GLfixed *params); +void Hint(GLenum target, GLenum mode); +GLboolean IsBuffer(GLuint buffer); +GLboolean IsEnabled(GLenum cap); +GLboolean IsFramebufferOES(GLuint framebuffer); +GLboolean IsTexture(GLuint texture); +GLboolean IsRenderbufferOES(GLuint renderbuffer); +void LightModelf(GLenum pname, GLfloat param); +void LightModelfv(GLenum pname, const GLfloat *params); +void LightModelx(GLenum pname, GLfixed param); +void LightModelxv(GLenum pname, const GLfixed *params); +void Lightf(GLenum light, GLenum pname, GLfloat param); +void Lightfv(GLenum light, GLenum pname, const GLfloat *params); +void Lightx(GLenum light, GLenum pname, GLfixed param); +void Lightxv(GLenum light, GLenum pname, const GLfixed *params); +void LineWidth(GLfloat width); +void LineWidthx(GLfixed width); +void LoadIdentity(void); +void LoadMatrixf(const GLfloat *m); +void LoadMatrixx(const GLfixed *m); +void LogicOp(GLenum opcode); +void Materialf(GLenum face, GLenum pname, GLfloat param); +void Materialfv(GLenum face, GLenum pname, const GLfloat *params); +void Materialx(GLenum face, GLenum pname, GLfixed param); +void Materialxv(GLenum face, GLenum pname, const GLfixed *params); +void MatrixMode(GLenum mode); +void MultMatrixf(const GLfloat *m); +void MultMatrixx(const GLfixed *m); +void MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +void MultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q); +void Normal3f(GLfloat nx, GLfloat ny, GLfloat nz); +void Normal3x(GLfixed nx, GLfixed ny, GLfixed nz); +void NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer); +void Orthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +void Orthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +void PixelStorei(GLenum pname, GLint param); +void PointParameterf(GLenum pname, GLfloat param); +void PointParameterfv(GLenum pname, const GLfloat *params); +void PointParameterx(GLenum pname, GLfixed param); +void PointParameterxv(GLenum pname, const GLfixed *params); +void PointSize(GLfloat size); +void PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer); +void PointSizex(GLfixed size); +void PolygonOffset(GLfloat factor, GLfloat units); +void PolygonOffsetx(GLfixed factor, GLfixed units); +void PopMatrix(void); +void PushMatrix(void); +void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); +void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +void Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +void Rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z); +void SampleCoverage(GLclampf value, GLboolean invert); +void SampleCoveragex(GLclampx value, GLboolean invert); +void Scalef(GLfloat x, GLfloat y, GLfloat z); +void Scalex(GLfixed x, GLfixed y, GLfixed z); +void Scissor(GLint x, GLint y, GLsizei width, GLsizei height); +void ShadeModel(GLenum mode); +void StencilFunc(GLenum func, GLint ref, GLuint mask); +void StencilMask(GLuint mask); +void StencilOp(GLenum fail, GLenum zfail, GLenum zpass); +void TexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void TexEnvf(GLenum target, GLenum pname, GLfloat param); +void TexEnvfv(GLenum target, GLenum pname, const GLfloat *params); +void TexEnvi(GLenum target, GLenum pname, GLint param); +void TexEnvx(GLenum target, GLenum pname, GLfixed param); +void TexEnviv(GLenum target, GLenum pname, const GLint *params); +void TexEnvxv(GLenum target, GLenum pname, const GLfixed *params); +void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid* pixels); +void TexParameterf(GLenum target, GLenum pname, GLfloat param); +void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params); +void TexParameteri(GLenum target, GLenum pname, GLint param); +void TexParameteriv(GLenum target, GLenum pname, const GLint* params); +void TexParameterx(GLenum target, GLenum pname, GLfixed param); +void TexParameterxv(GLenum target, GLenum pname, const GLfixed *params); +void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid* pixels); +void Translatef(GLfloat x, GLfloat y, GLfloat z); +void Translatex(GLfixed x, GLfixed y, GLfixed z); +void VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +void Viewport(GLint x, GLint y, GLsizei width, GLsizei height); +void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image); +void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image); +void DrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height); +void DrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height); +void DrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height); +void DrawTexsvOES(const GLshort *coords); +void DrawTexivOES(const GLint *coords); +void DrawTexxvOES(const GLfixed *coords); +void DrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); +void DrawTexfvOES(const GLfloat *coords); +} + +egl::Context *es1CreateContext(const egl::Config *config, const egl::Context *shareContext); +extern "C" __eglMustCastToProperFunctionPointerType es1GetProcAddress(const char *procname); +egl::Image *createBackBuffer(int width, int height, const egl::Config *config); +egl::Image *createDepthStencil(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard); +sw::FrameBuffer *createFrameBuffer(void *display, EGLNativeWindowType window, int width, int height); + +extern "C" +{ +EGLAPI EGLint EGLAPIENTRY eglGetError(void) +{ + return libEGL->eglGetError(); +} + +EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) +{ + return libEGL->eglGetDisplay(display_id); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + return libEGL->eglInitialize(dpy, major, minor); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) +{ + return libEGL->eglTerminate(dpy); +} + +EGLAPI const char *EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) +{ + return libEGL->eglQueryString(dpy, name); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + return libEGL->eglGetConfigs(dpy, configs, config_size, num_config); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + return libEGL->eglChooseConfig(dpy, attrib_list, configs, config_size, num_config); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +{ + return libEGL->eglGetConfigAttrib(dpy, config, attribute, value); +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list) +{ + return libEGL->eglCreateWindowSurface(dpy, config, window, attrib_list); +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +{ + return libEGL->eglCreatePbufferSurface(dpy, config, attrib_list); +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) +{ + return libEGL->eglCreatePixmapSurface(dpy, config, pixmap, attrib_list); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +{ + return libEGL->eglDestroySurface(dpy, surface); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +{ + return libEGL->eglQuerySurface(dpy, surface, attribute, value); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) +{ + return libEGL->eglBindAPI(api); +} + +EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void) +{ + return libEGL->eglQueryAPI(); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void) +{ + return libEGL->eglWaitClient(); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) +{ + return libEGL->eglReleaseThread(); +} + +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) +{ + return libEGL->eglCreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +{ + return libEGL->eglSurfaceAttrib(dpy, surface, attribute, value); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + return libEGL->eglBindTexImage(dpy, surface, buffer); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + return libEGL->eglReleaseTexImage(dpy, surface, buffer); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) +{ + return libEGL->eglSwapInterval(dpy, interval); +} + +EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) +{ + return libEGL->eglCreateContext(dpy, config, share_context, attrib_list); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +{ + return libEGL->eglDestroyContext(dpy, ctx); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) +{ + return libEGL->eglMakeCurrent(dpy, draw, read, ctx); +} + +EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) +{ + return libEGL->eglGetCurrentContext(); +} + +EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) +{ + return libEGL->eglGetCurrentSurface(readdraw); +} + +EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) +{ + return libEGL->eglGetCurrentDisplay(); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +{ + return libEGL->eglQueryContext(dpy, ctx, attribute, value); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void) +{ + return libEGL->eglWaitGL(); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) +{ + return libEGL->eglWaitNative(engine); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) +{ + return libEGL->eglSwapBuffers(dpy, surface); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) +{ + return libEGL->eglCopyBuffers(dpy, surface, target); +} + +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) +{ + return libEGL->eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) +{ + return libEGL->eglDestroyImageKHR(dpy, image); +} + +EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname) +{ + return libEGL->eglGetProcAddress(procname); +} + +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) +{ + return libEGL->eglCreateSyncKHR(dpy, type, attrib_list); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) +{ + return libEGL->eglDestroySyncKHR(dpy, sync); +} + +EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) +{ + return libEGL->eglClientWaitSyncKHR(dpy, sync, flags, timeout); +} + +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) +{ + return libEGL->eglGetSyncAttribKHR(dpy, sync, attribute, value); +} + +GL_API void GL_APIENTRY glActiveTexture(GLenum texture) +{ + return es1::ActiveTexture(texture); +} + +GL_API void GL_APIENTRY glAlphaFunc(GLenum func, GLclampf ref) +{ + return es1::AlphaFunc(func, ref); +} + +GL_API void GL_APIENTRY glAlphaFuncx(GLenum func, GLclampx ref) +{ + return es1::AlphaFuncx(func, ref); +} + +GL_API void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer) +{ + return es1::BindBuffer(target, buffer); +} + +GL_API void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer) +{ + return es1::BindFramebuffer(target, framebuffer); +} + +GL_API void GL_APIENTRY glBindFramebufferOES(GLenum target, GLuint framebuffer) +{ + return es1::BindFramebufferOES(target, framebuffer); +} + +GL_API void GL_APIENTRY glBindRenderbufferOES(GLenum target, GLuint renderbuffer) +{ + return es1::BindRenderbufferOES(target, renderbuffer); +} + +GL_API void GL_APIENTRY glBindTexture(GLenum target, GLuint texture) +{ + return es1::BindTexture(target, texture); +} + +GL_API void GL_APIENTRY glBlendEquationOES(GLenum mode) +{ + return es1::BlendEquationSeparateOES(mode, mode); +} + +GL_API void GL_APIENTRY glBlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha) +{ + return es1::BlendEquationSeparateOES(modeRGB, modeAlpha); +} + +GL_API void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) +{ + return es1::BlendFuncSeparateOES(sfactor, dfactor, sfactor, dfactor); +} + +GL_API void GL_APIENTRY glBlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + return es1::BlendFuncSeparateOES(srcRGB, dstRGB, srcAlpha, dstAlpha); +} + +GL_API void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +{ + return es1::BufferData(target, size, data, usage); +} + +GL_API void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) +{ + return es1::BufferSubData(target, offset, size, data); +} + +GL_API GLenum GL_APIENTRY glCheckFramebufferStatusOES(GLenum target) +{ + return es1::CheckFramebufferStatusOES(target); +} + +GL_API void GL_APIENTRY glClear(GLbitfield mask) +{ + return es1::Clear(mask); +} + +GL_API void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + return es1::ClearColor(red, green, blue, alpha); +} + +GL_API void GL_APIENTRY glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) +{ + return es1::ClearColorx(red, green, blue, alpha); +} + +GL_API void GL_APIENTRY glClearDepthf(GLclampf depth) +{ + return es1::ClearDepthf(depth); +} + +GL_API void GL_APIENTRY glClearDepthx(GLclampx depth) +{ + return es1::ClearDepthx(depth); +} + +GL_API void GL_APIENTRY glClearStencil(GLint s) +{ + return es1::ClearStencil(s); +} + +GL_API void GL_APIENTRY glClientActiveTexture(GLenum texture) +{ + return es1::ClientActiveTexture(texture); +} + +GL_API void GL_APIENTRY glClipPlanef(GLenum plane, const GLfloat *equation) +{ + return es1::ClipPlanef(plane, equation); +} + +GL_API void GL_APIENTRY glClipPlanex(GLenum plane, const GLfixed *equation) +{ + return es1::ClipPlanex(plane, equation); +} + +GL_API void GL_APIENTRY glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + return es1::Color4f(red, green, blue, alpha); +} + +GL_API void GL_APIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) +{ + return es1::Color4ub(red, green, blue, alpha); +} + +GL_API void GL_APIENTRY glColor4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) +{ + return es1::Color4x(red, green, blue, alpha); +} + +GL_API void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + return es1::ColorMask(red, green, blue, alpha); +} + +GL_API void GL_APIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + return es1::ColorPointer(size, type, stride, pointer); +} + +GL_API void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid* data) +{ + return es1::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} + +GL_API void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, const GLvoid* data) +{ + return es1::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +GL_API void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + return es1::CopyTexImage2D(target, level, internalformat, x, y, width, height, border); +} + +GL_API void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + return es1::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + +GL_API void GL_APIENTRY glCullFace(GLenum mode) +{ + return es1::CullFace(mode); +} + +GL_API void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers) +{ + return es1::DeleteBuffers(n, buffers); +} + +GL_API void GL_APIENTRY glDeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers) +{ + return es1::DeleteFramebuffersOES(n, framebuffers); +} + +GL_API void GL_APIENTRY glDeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers) +{ + return es1::DeleteRenderbuffersOES(n, renderbuffers); +} + +GL_API void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures) +{ + return es1::DeleteTextures(n, textures); +} + +GL_API void GL_APIENTRY glDepthFunc(GLenum func) +{ + return es1::DepthFunc(func); +} + +GL_API void GL_APIENTRY glDepthMask(GLboolean flag) +{ + return es1::DepthMask(flag); +} + +GL_API void GL_APIENTRY glDepthRangex(GLclampx zNear, GLclampx zFar) +{ + return es1::DepthRangex(zNear, zFar); +} + +GL_API void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar) +{ + return es1::DepthRangef(zNear, zFar); +} + +GL_API void GL_APIENTRY glDisable(GLenum cap) +{ + return es1::Disable(cap); +} + +GL_API void GL_APIENTRY glDisableClientState(GLenum array) +{ + return es1::DisableClientState(array); +} + +GL_API void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) +{ + return es1::DrawArrays(mode, first, count); +} + +GL_API void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) +{ + return es1::DrawElements(mode, count, type, indices); +} + +GL_API void GL_APIENTRY glEnable(GLenum cap) +{ + return es1::Enable(cap); +} + +GL_API void GL_APIENTRY glEnableClientState(GLenum array) +{ + return es1::EnableClientState(array); +} + +GL_API void GL_APIENTRY glFinish(void) +{ + return es1::Finish(); +} + +GL_API void GL_APIENTRY glFlush(void) +{ + return es1::Flush(); +} + +GL_API void GL_APIENTRY glFramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + return es1::FramebufferRenderbufferOES(target, attachment, renderbuffertarget, renderbuffer); +} + +GL_API void GL_APIENTRY glFramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + return es1::FramebufferTexture2DOES(target, attachment, textarget, texture, level); +} + +GL_API void GL_APIENTRY glFogf(GLenum pname, GLfloat param) +{ + return es1::Fogf(pname, param); +} + +GL_API void GL_APIENTRY glFogfv(GLenum pname, const GLfloat *params) +{ + return es1::Fogfv(pname, params); +} + +GL_API void GL_APIENTRY glFogx(GLenum pname, GLfixed param) +{ + return es1::Fogx(pname, param); +} + +GL_API void GL_APIENTRY glFogxv(GLenum pname, const GLfixed *params) +{ + return es1::Fogxv(pname, params); +} + +GL_API void GL_APIENTRY glFrontFace(GLenum mode) +{ + return es1::FrontFace(mode); +} + +GL_API void GL_APIENTRY glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + return es1::Frustumf(left, right, bottom, top, zNear, zFar); +} + +GL_API void GL_APIENTRY glFrustumx(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +{ + return es1::Frustumx(left, right, bottom, top, zNear, zFar); +} + +GL_API void GL_APIENTRY glGenerateMipmapOES(GLenum target) +{ + return es1::GenerateMipmapOES(target); +} + +GL_API void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers) +{ + return es1::GenBuffers(n, buffers); +} + +GL_API void GL_APIENTRY glGenFramebuffersOES(GLsizei n, GLuint* framebuffers) +{ + return es1::GenFramebuffersOES(n, framebuffers); +} + +GL_API void GL_APIENTRY glGenRenderbuffersOES(GLsizei n, GLuint* renderbuffers) +{ + return es1::GenRenderbuffersOES(n, renderbuffers); +} + +GL_API void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures) +{ + return es1::GenTextures(n, textures); +} + +GL_API void GL_APIENTRY glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params) +{ + return es1::GetRenderbufferParameterivOES(target, pname, params); +} + +GL_API void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params) +{ + return es1::GetBooleanv(pname, params); +} + +GL_API void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + return es1::GetBufferParameteriv(target, pname, params); +} + +GL_API void GL_APIENTRY glGetClipPlanef(GLenum pname, GLfloat eqn[4]) +{ + return es1::GetClipPlanef(pname, eqn); +} + +GL_API void GL_APIENTRY glGetClipPlanex(GLenum pname, GLfixed eqn[4]) +{ + return es1::GetClipPlanex(pname, eqn); +} + +GL_API GLenum GL_APIENTRY glGetError(void) +{ + return es1::GetError(); +} + +GL_API void GL_APIENTRY glGetFixedv(GLenum pname, GLfixed *params) +{ + return es1::GetFixedv(pname, params); +} + +GL_API void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params) +{ + return es1::GetFloatv(pname, params); +} + +GL_API void GL_APIENTRY glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + return es1::GetFramebufferAttachmentParameterivOES(target, attachment, pname, params); +} + +GL_API void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params) +{ + return es1::GetIntegerv(pname, params); +} + +GL_API void GL_APIENTRY glGetLightfv(GLenum light, GLenum pname, GLfloat *params) +{ + return es1::GetLightfv(light, pname, params); +} + +GL_API void GL_APIENTRY glGetLightxv(GLenum light, GLenum pname, GLfixed *params) +{ + return es1::GetLightxv(light, pname, params); +} + +GL_API void GL_APIENTRY glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) +{ + return es1::GetMaterialfv(face, pname, params); +} + +GL_API void GL_APIENTRY glGetMaterialxv(GLenum face, GLenum pname, GLfixed *params) +{ + return es1::GetMaterialxv(face, pname, params); +} + +GL_API void GL_APIENTRY glGetPointerv(GLenum pname, GLvoid **params) +{ + return es1::GetPointerv(pname, params); +} + +GL_API const GLubyte* GL_APIENTRY glGetString(GLenum name) +{ + return es1::GetString(name); +} + +GL_API void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) +{ + return es1::GetTexParameterfv(target, pname, params); +} + +GL_API void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) +{ + return es1::GetTexParameteriv(target, pname, params); +} + +GL_API void GL_APIENTRY glGetTexEnvfv(GLenum env, GLenum pname, GLfloat *params) +{ + return es1::GetTexEnvfv(env, pname, params); +} + +GL_API void GL_APIENTRY glGetTexEnviv(GLenum env, GLenum pname, GLint *params) +{ + return es1::GetTexEnviv(env, pname, params); +} + +GL_API void GL_APIENTRY glGetTexEnvxv(GLenum env, GLenum pname, GLfixed *params) +{ + return es1::GetTexEnvxv(env, pname, params); +} + +GL_API void GL_APIENTRY glGetTexParameterxv(GLenum target, GLenum pname, GLfixed *params) +{ + return es1::GetTexParameterxv(target, pname, params); +} + +GL_API void GL_APIENTRY glHint(GLenum target, GLenum mode) +{ + return es1::Hint(target, mode); +} + +GL_API GLboolean GL_APIENTRY glIsBuffer(GLuint buffer) +{ + return es1::IsBuffer(buffer); +} + +GL_API GLboolean GL_APIENTRY glIsEnabled(GLenum cap) +{ + return es1::IsEnabled(cap); +} + +GL_API GLboolean GL_APIENTRY glIsFramebufferOES(GLuint framebuffer) +{ + return es1::IsFramebufferOES(framebuffer); +} + +GL_API GLboolean GL_APIENTRY glIsTexture(GLuint texture) +{ + return es1::IsTexture(texture); +} + +GL_API GLboolean GL_APIENTRY glIsRenderbufferOES(GLuint renderbuffer) +{ + return es1::IsRenderbufferOES(renderbuffer); +} + +GL_API void GL_APIENTRY glLightModelf(GLenum pname, GLfloat param) +{ + return es1::LightModelf(pname, param); +} + +GL_API void GL_APIENTRY glLightModelfv(GLenum pname, const GLfloat *params) +{ + return es1::LightModelfv(pname, params); +} + +GL_API void GL_APIENTRY glLightModelx(GLenum pname, GLfixed param) +{ + return es1::LightModelx(pname, param); +} + +GL_API void GL_APIENTRY glLightModelxv(GLenum pname, const GLfixed *params) +{ + return es1::LightModelxv(pname, params); +} + +GL_API void GL_APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param) +{ + return es1::Lightf(light, pname, param); +} + +GL_API void GL_APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) +{ + return es1::Lightfv(light, pname, params); +} + +GL_API void GL_APIENTRY glLightx(GLenum light, GLenum pname, GLfixed param) +{ + return es1::Lightx(light, pname, param); +} + +GL_API void GL_APIENTRY glLightxv(GLenum light, GLenum pname, const GLfixed *params) +{ + return es1::Lightxv(light, pname, params); +} + +GL_API void GL_APIENTRY glLineWidth(GLfloat width) +{ + return es1::LineWidth(width); +} + +GL_API void GL_APIENTRY glLineWidthx(GLfixed width) +{ + return es1::LineWidthx(width); +} + +GL_API void GL_APIENTRY glLoadIdentity(void) +{ + return es1::LoadIdentity(); +} + +GL_API void GL_APIENTRY glLoadMatrixf(const GLfloat *m) +{ + return es1::LoadMatrixf(m); +} + +GL_API void GL_APIENTRY glLoadMatrixx(const GLfixed *m) +{ + return es1::LoadMatrixx(m); +} + +GL_API void GL_APIENTRY glLogicOp(GLenum opcode) +{ + return es1::LogicOp(opcode); +} + +GL_API void GL_APIENTRY glMaterialf(GLenum face, GLenum pname, GLfloat param) +{ + return es1::Materialf(face, pname, param); +} + +GL_API void GL_APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) +{ + return es1::Materialfv(face, pname, params); +} + +GL_API void GL_APIENTRY glMaterialx(GLenum face, GLenum pname, GLfixed param) +{ + return es1::Materialx(face, pname, param); +} + +GL_API void GL_APIENTRY glMaterialxv(GLenum face, GLenum pname, const GLfixed *params) +{ + return es1::Materialxv(face, pname, params); +} + +GL_API void GL_APIENTRY glMatrixMode(GLenum mode) +{ + return es1::MatrixMode(mode); +} + +GL_API void GL_APIENTRY glMultMatrixf(const GLfloat *m) +{ + return es1::MultMatrixf(m); +} + +GL_API void GL_APIENTRY glMultMatrixx(const GLfixed *m) +{ + return es1::MultMatrixx(m); +} + +GL_API void GL_APIENTRY glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + return es1::MultiTexCoord4f(target, s, t, r, q); +} + +GL_API void GL_APIENTRY glMultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) +{ + return es1::MultiTexCoord4x(target, s, t, r, q); +} + +GL_API void GL_APIENTRY glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) +{ + return es1::Normal3f(nx, ny, nz); +} + +GL_API void GL_APIENTRY glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz) +{ + return es1::Normal3x(nx, ny, nz); +} + +GL_API void GL_APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) +{ + return es1::NormalPointer(type, stride, pointer); +} + +GL_API void GL_APIENTRY glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar) +{ + return es1::Orthof(left, right, bottom, top, zNear, zFar); +} + +GL_API void GL_APIENTRY glOrthox(GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar) +{ + return es1::Orthox(left, right, bottom, top, zNear, zFar); +} + +GL_API void GL_APIENTRY glPixelStorei(GLenum pname, GLint param) +{ + return es1::PixelStorei(pname, param); +} + +GL_API void GL_APIENTRY glPointParameterf(GLenum pname, GLfloat param) +{ + return es1::PointParameterf(pname, param); +} + +GL_API void GL_APIENTRY glPointParameterfv(GLenum pname, const GLfloat *params) +{ + return es1::PointParameterfv(pname, params); +} + +GL_API void GL_APIENTRY glPointParameterx(GLenum pname, GLfixed param) +{ + return es1::PointParameterx(pname, param); +} + +GL_API void GL_APIENTRY glPointParameterxv(GLenum pname, const GLfixed *params) +{ + return es1::PointParameterxv(pname, params); +} + +GL_API void GL_APIENTRY glPointSize(GLfloat size) +{ + return es1::PointSize(size); +} + +GL_API void GL_APIENTRY glPointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer) +{ + return es1::PointSizePointerOES(type, stride, pointer); +} + +GL_API void GL_APIENTRY glPointSizex(GLfixed size) +{ + return es1::PointSizex(size); +} + +GL_API void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units) +{ + return es1::PolygonOffset(factor, units); +} + +GL_API void GL_APIENTRY glPolygonOffsetx(GLfixed factor, GLfixed units) +{ + return es1::PolygonOffsetx(factor, units); +} + +GL_API void GL_APIENTRY glPopMatrix(void) +{ + return es1::PopMatrix(); +} + +GL_API void GL_APIENTRY glPushMatrix(void) +{ + return es1::PushMatrix(); +} + +GL_API void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) +{ + return es1::ReadPixels(x, y, width, height, format, type, pixels); +} + +GL_API void GL_APIENTRY glRenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + return es1::RenderbufferStorageOES(target, internalformat, width, height); +} + +GL_API void GL_APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + return es1::Rotatef(angle, x, y, z); +} + +GL_API void GL_APIENTRY glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) +{ + return es1::Rotatex(angle, x, y, z); +} + +GL_API void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert) +{ + return es1::SampleCoverage(value, invert); +} + +GL_API void GL_APIENTRY glSampleCoveragex(GLclampx value, GLboolean invert) +{ + return es1::SampleCoveragex(value, invert); +} + +GL_API void GL_APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) +{ + return es1::Scalef(x, y, z); +} + +GL_API void GL_APIENTRY glScalex(GLfixed x, GLfixed y, GLfixed z) +{ + return es1::Scalex(x, y, z); +} + +GL_API void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + return es1::Scissor(x, y, width, height); +} + +GL_API void GL_APIENTRY glShadeModel(GLenum mode) +{ + return es1::ShadeModel(mode); +} + +GL_API void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + return es1::StencilFunc(func, ref, mask); +} + +GL_API void GL_APIENTRY glStencilMask(GLuint mask) +{ + return es1::StencilMask(mask); +} + +GL_API void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + return es1::StencilOp(fail, zfail, zpass); +} + +GL_API void GL_APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + return es1::TexCoordPointer(size, type, stride, pointer); +} + +GL_API void GL_APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param) +{ + return es1::TexEnvf(target, pname, param); +} + +GL_API void GL_APIENTRY glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) +{ + return es1::TexEnvfv(target, pname, params); +} + +GL_API void GL_APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) +{ + return es1::TexEnvi(target, pname, param); +} + +GL_API void GL_APIENTRY glTexEnvx(GLenum target, GLenum pname, GLfixed param) +{ + return es1::TexEnvx(target, pname, param); +} + +GL_API void GL_APIENTRY glTexEnviv(GLenum target, GLenum pname, const GLint *params) +{ + return es1::TexEnviv(target, pname, params); +} + +GL_API void GL_APIENTRY glTexEnvxv(GLenum target, GLenum pname, const GLfixed *params) +{ + return es1::TexEnvxv(target, pname, params); +} + +GL_API void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + return es1::TexImage2D(target, level, internalformat, width, height, border, format, type, pixels); +} + +GL_API void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + return es1::TexParameterf(target, pname, param); +} + +GL_API void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) +{ + return es1::TexParameterfv(target, pname, params); +} + +GL_API void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) +{ + return es1::TexParameteri(target, pname, param); +} + +GL_API void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params) +{ + return es1::TexParameteriv(target, pname, params); +} + +GL_API void GL_APIENTRY glTexParameterx(GLenum target, GLenum pname, GLfixed param) +{ + return es1::TexParameterx(target, pname, param); +} + +GL_API void GL_APIENTRY glTexParameterxv(GLenum target, GLenum pname, const GLfixed *params) +{ + return es1::TexParameterxv(target, pname, params); +} + +GL_API void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid* pixels) +{ + return es1::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +GL_API void GL_APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) +{ + return es1::Translatef(x, y, z); +} + +GL_API void GL_APIENTRY glTranslatex(GLfixed x, GLfixed y, GLfixed z) +{ + return es1::Translatex(x, y, z); +} + +GL_API void GL_APIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + return es1::VertexPointer(size, type, stride, pointer); +} + +GL_API void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + return es1::Viewport(x, y, width, height); +} + +GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + return es1::EGLImageTargetTexture2DOES(target, image); +} + +GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + return es1::EGLImageTargetRenderbufferStorageOES(target, image); +} + +GL_API void GL_APIENTRY glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) +{ + return es1::DrawTexsOES(x,y, z, width, height); +} + +GL_API void GL_APIENTRY glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) +{ + return es1::DrawTexiOES(x,y, z, width, height); +} + +GL_API void GL_APIENTRY glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) +{ + return es1::DrawTexxOES(x,y, z, width, height); +} + +GL_API void GL_APIENTRY glDrawTexsvOES(const GLshort *coords) +{ + return es1::DrawTexsvOES(coords); +} + +GL_API void GL_APIENTRY glDrawTexivOES(const GLint *coords) +{ + return es1::DrawTexivOES(coords); +} + +GL_API void GL_APIENTRY glDrawTexxvOES(const GLfixed *coords) +{ + return es1::DrawTexxvOES(coords); +} + +GL_API void GL_APIENTRY glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) +{ + return es1::DrawTexfOES(x, y, z, width, height); +} + +GL_API void GL_APIENTRY glDrawTexfvOES(const GLfloat *coords) +{ + return es1::DrawTexfvOES(coords); +} + +} + +LibGLES_CMexports::LibGLES_CMexports() +{ + this->glActiveTexture = es1::ActiveTexture; + this->glAlphaFunc = es1::AlphaFunc; + this->glAlphaFuncx = es1::AlphaFuncx; + this->glBindBuffer = es1::BindBuffer; + this->glBindFramebuffer = es1::BindFramebuffer; + this->glBindFramebufferOES = es1::BindFramebufferOES; + this->glBindRenderbufferOES = es1::BindRenderbufferOES; + this->glBindTexture = es1::BindTexture; + this->glBlendEquationSeparateOES = es1::BlendEquationSeparateOES; + this->glBlendEquationOES = es1::BlendEquationOES; + this->glBlendEquationSeparateOES = es1::BlendEquationSeparateOES; + this->glBlendFuncSeparateOES = es1::BlendFuncSeparateOES; + this->glBlendFunc = es1::BlendFunc; + this->glBlendFuncSeparateOES = es1::BlendFuncSeparateOES; + this->glBufferData = es1::BufferData; + this->glBufferSubData = es1::BufferSubData; + this->glCheckFramebufferStatusOES = es1::CheckFramebufferStatusOES; + this->glClear = es1::Clear; + this->glClearColor = es1::ClearColor; + this->glClearColorx = es1::ClearColorx; + this->glClearDepthf = es1::ClearDepthf; + this->glClearDepthx = es1::ClearDepthx; + this->glClearStencil = es1::ClearStencil; + this->glClientActiveTexture = es1::ClientActiveTexture; + this->glClipPlanef = es1::ClipPlanef; + this->glClipPlanex = es1::ClipPlanex; + this->glColor4f = es1::Color4f; + this->glColor4ub = es1::Color4ub; + this->glColor4x = es1::Color4x; + this->glColorMask = es1::ColorMask; + this->glColorPointer = es1::ColorPointer; + this->glCompressedTexImage2D = es1::CompressedTexImage2D; + this->glCompressedTexSubImage2D = es1::CompressedTexSubImage2D; + this->glCopyTexImage2D = es1::CopyTexImage2D; + this->glCopyTexSubImage2D = es1::CopyTexSubImage2D; + this->glCullFace = es1::CullFace; + this->glDeleteBuffers = es1::DeleteBuffers; + this->glDeleteFramebuffersOES = es1::DeleteFramebuffersOES; + this->glDeleteRenderbuffersOES = es1::DeleteRenderbuffersOES; + this->glDeleteTextures = es1::DeleteTextures; + this->glDepthFunc = es1::DepthFunc; + this->glDepthMask = es1::DepthMask; + this->glDepthRangex = es1::DepthRangex; + this->glDepthRangef = es1::DepthRangef; + this->glDisable = es1::Disable; + this->glDisableClientState = es1::DisableClientState; + this->glDrawArrays = es1::DrawArrays; + this->glDrawElements = es1::DrawElements; + this->glEnable = es1::Enable; + this->glEnableClientState = es1::EnableClientState; + this->glFinish = es1::Finish; + this->glFlush = es1::Flush; + this->glFramebufferRenderbufferOES = es1::FramebufferRenderbufferOES; + this->glFramebufferTexture2DOES = es1::FramebufferTexture2DOES; + this->glFogf = es1::Fogf; + this->glFogfv = es1::Fogfv; + this->glFogx = es1::Fogx; + this->glFogxv = es1::Fogxv; + this->glFrontFace = es1::FrontFace; + this->glFrustumf = es1::Frustumf; + this->glFrustumx = es1::Frustumx; + this->glGenerateMipmapOES = es1::GenerateMipmapOES; + this->glGenBuffers = es1::GenBuffers; + this->glGenFramebuffersOES = es1::GenFramebuffersOES; + this->glGenRenderbuffersOES = es1::GenRenderbuffersOES; + this->glGenTextures = es1::GenTextures; + this->glGetRenderbufferParameterivOES = es1::GetRenderbufferParameterivOES; + this->glGetBooleanv = es1::GetBooleanv; + this->glGetBufferParameteriv = es1::GetBufferParameteriv; + this->glGetClipPlanef = es1::GetClipPlanef; + this->glGetClipPlanex = es1::GetClipPlanex; + this->glGetError = es1::GetError; + this->glGetFixedv = es1::GetFixedv; + this->glGetFloatv = es1::GetFloatv; + this->glGetFramebufferAttachmentParameterivOES = es1::GetFramebufferAttachmentParameterivOES; + this->glGetIntegerv = es1::GetIntegerv; + this->glGetLightfv = es1::GetLightfv; + this->glGetLightxv = es1::GetLightxv; + this->glGetMaterialfv = es1::GetMaterialfv; + this->glGetMaterialxv = es1::GetMaterialxv; + this->glGetPointerv = es1::GetPointerv; + this->glGetString = es1::GetString; + this->glGetTexParameterfv = es1::GetTexParameterfv; + this->glGetTexParameteriv = es1::GetTexParameteriv; + this->glGetTexEnvfv = es1::GetTexEnvfv; + this->glGetTexEnviv = es1::GetTexEnviv; + this->glGetTexEnvxv = es1::GetTexEnvxv; + this->glGetTexParameterxv = es1::GetTexParameterxv; + this->glHint = es1::Hint; + this->glIsBuffer = es1::IsBuffer; + this->glIsEnabled = es1::IsEnabled; + this->glIsFramebufferOES = es1::IsFramebufferOES; + this->glIsTexture = es1::IsTexture; + this->glIsRenderbufferOES = es1::IsRenderbufferOES; + this->glLightModelf = es1::LightModelf; + this->glLightModelfv = es1::LightModelfv; + this->glLightModelx = es1::LightModelx; + this->glLightModelxv = es1::LightModelxv; + this->glLightf = es1::Lightf; + this->glLightfv = es1::Lightfv; + this->glLightx = es1::Lightx; + this->glLightxv = es1::Lightxv; + this->glLineWidth = es1::LineWidth; + this->glLineWidthx = es1::LineWidthx; + this->glLoadIdentity = es1::LoadIdentity; + this->glLoadMatrixf = es1::LoadMatrixf; + this->glLoadMatrixx = es1::LoadMatrixx; + this->glLogicOp = es1::LogicOp; + this->glMaterialf = es1::Materialf; + this->glMaterialfv = es1::Materialfv; + this->glMaterialx = es1::Materialx; + this->glMaterialxv = es1::Materialxv; + this->glMatrixMode = es1::MatrixMode; + this->glMultMatrixf = es1::MultMatrixf; + this->glMultMatrixx = es1::MultMatrixx; + this->glMultiTexCoord4f = es1::MultiTexCoord4f; + this->glMultiTexCoord4x = es1::MultiTexCoord4x; + this->glNormal3f = es1::Normal3f; + this->glNormal3x = es1::Normal3x; + this->glNormalPointer = es1::NormalPointer; + this->glOrthof = es1::Orthof; + this->glOrthox = es1::Orthox; + this->glPixelStorei = es1::PixelStorei; + this->glPointParameterf = es1::PointParameterf; + this->glPointParameterfv = es1::PointParameterfv; + this->glPointParameterx = es1::PointParameterx; + this->glPointParameterxv = es1::PointParameterxv; + this->glPointSize = es1::PointSize; + this->glPointSizePointerOES = es1::PointSizePointerOES; + this->glPointSizex = es1::PointSizex; + this->glPolygonOffset = es1::PolygonOffset; + this->glPolygonOffsetx = es1::PolygonOffsetx; + this->glPopMatrix = es1::PopMatrix; + this->glPushMatrix = es1::PushMatrix; + this->glReadPixels = es1::ReadPixels; + this->glRenderbufferStorageOES = es1::RenderbufferStorageOES; + this->glRotatef = es1::Rotatef; + this->glRotatex = es1::Rotatex; + this->glSampleCoverage = es1::SampleCoverage; + this->glSampleCoveragex = es1::SampleCoveragex; + this->glScalef = es1::Scalef; + this->glScalex = es1::Scalex; + this->glScissor = es1::Scissor; + this->glShadeModel = es1::ShadeModel; + this->glStencilFunc = es1::StencilFunc; + this->glStencilMask = es1::StencilMask; + this->glStencilOp = es1::StencilOp; + this->glTexCoordPointer = es1::TexCoordPointer; + this->glTexEnvf = es1::TexEnvf; + this->glTexEnvfv = es1::TexEnvfv; + this->glTexEnvi = es1::TexEnvi; + this->glTexEnvx = es1::TexEnvx; + this->glTexEnviv = es1::TexEnviv; + this->glTexEnvxv = es1::TexEnvxv; + this->glTexImage2D = es1::TexImage2D; + this->glTexParameterf = es1::TexParameterf; + this->glTexParameterfv = es1::TexParameterfv; + this->glTexParameteri = es1::TexParameteri; + this->glTexParameteriv = es1::TexParameteriv; + this->glTexParameterx = es1::TexParameterx; + this->glTexParameterxv = es1::TexParameterxv; + this->glTexSubImage2D = es1::TexSubImage2D; + this->glTranslatef = es1::Translatef; + this->glTranslatex = es1::Translatex; + this->glVertexPointer = es1::VertexPointer; + this->glViewport = es1::Viewport; + this->glEGLImageTargetTexture2DOES = es1::EGLImageTargetTexture2DOES; + this->glEGLImageTargetRenderbufferStorageOES = es1::EGLImageTargetRenderbufferStorageOES; + this->glDrawTexsOES = es1::DrawTexsOES; + this->glDrawTexiOES = es1::DrawTexiOES; + this->glDrawTexxOES = es1::DrawTexxOES; + this->glDrawTexsvOES = es1::DrawTexsvOES; + this->glDrawTexivOES = es1::DrawTexivOES; + this->glDrawTexxvOES = es1::DrawTexxvOES; + this->glDrawTexfOES = es1::DrawTexfOES; + this->glDrawTexfvOES = es1::DrawTexfvOES; + + this->es1CreateContext = ::es1CreateContext; + this->es1GetProcAddress = ::es1GetProcAddress; + this->createBackBuffer = ::createBackBuffer; + this->createDepthStencil = ::createDepthStencil; + this->createFrameBuffer = ::createFrameBuffer; +} + +extern "C" GL_API LibGLES_CMexports *libGLES_CM_swiftshader() +{ + static LibGLES_CMexports libGLES_CM; + return &libGLES_CM; +} + +LibEGL libEGL;
diff --git a/src/OpenGL/libGLES_CM/main.h b/src/OpenGL/libGLES_CM/main.h index da8fed6..34092b0 100644 --- a/src/OpenGL/libGLES_CM/main.h +++ b/src/OpenGL/libGLES_CM/main.h
@@ -1,13 +1,16 @@ -// SwiftShader Software Renderer +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright(c) 2005-2012 TransGaming Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // main.h: Management of thread-local data.
diff --git a/src/OpenGL/libGLES_CM/mathutil.h b/src/OpenGL/libGLES_CM/mathutil.h index 89c2e54..7f62c5b 100644 --- a/src/OpenGL/libGLES_CM/mathutil.h +++ b/src/OpenGL/libGLES_CM/mathutil.h
@@ -1,13 +1,16 @@ -// SwiftShader Software Renderer +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // -// Copyright(c) 2005-2012 TransGaming Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // mathutil.h: Math and bit manipulation functions. @@ -21,27 +24,27 @@ { inline bool isPow2(int x) { - return (x & (x - 1)) == 0 && (x != 0); + return (x & (x - 1)) == 0 && (x != 0); } inline int log2(int x) { - int r = 0; - while((x >> r) > 1) r++; - return r; + int r = 0; + while((x >> r) > 1) r++; + return r; } inline unsigned int ceilPow2(unsigned int x) { - if(x != 0) x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x++; + if(x != 0) x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; - return x; + return x; } using sw::clamp; @@ -50,20 +53,20 @@ template<const int n> inline unsigned int unorm(float x) { - const unsigned int max = 0xFFFFFFFF >> (32 - n); + const unsigned int max = 0xFFFFFFFF >> (32 - n); - if(x > 1) - { - return max; - } - else if(x < 0) - { - return 0; - } - else - { - return (unsigned int)(max * x + 0.5f); - } + if(x > 1) + { + return max; + } + else if(x < 0) + { + return 0; + } + else + { + return (unsigned int)(max * x + 0.5f); + } } }
diff --git a/src/OpenGL/libGLES_CM/utilities.cpp b/src/OpenGL/libGLES_CM/utilities.cpp index 3dbedde..b03f15c 100644 --- a/src/OpenGL/libGLES_CM/utilities.cpp +++ b/src/OpenGL/libGLES_CM/utilities.cpp
@@ -1,720 +1,723 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// utilities.cpp: Conversion functions and other utility routines. - -#include "utilities.h" - -#include "mathutil.h" -#include "Context.h" -#include "common/debug.h" - -#include <limits> -#include <stdio.h> - -namespace es1 -{ - bool IsCompressed(GLenum format) - { - return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || - format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || - format == GL_ETC1_RGB8_OES; - } - - bool IsDepthTexture(GLenum format) - { - return format == GL_DEPTH_STENCIL_OES; - } - - bool IsStencilTexture(GLenum format) - { - return format == GL_DEPTH_STENCIL_OES; - } - - bool IsCubemapTextureTarget(GLenum target) - { - return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES); - } - - int CubeFaceIndex(GLenum cubeFace) - { - switch(cubeFace) - { - case GL_TEXTURE_CUBE_MAP_OES: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES: return 0; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES: return 1; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES: return 2; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES: return 3; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES: return 4; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES: return 5; - default: UNREACHABLE(cubeFace); return 0; - } - } - - bool IsTextureTarget(GLenum target) - { - return target == GL_TEXTURE_2D; - } - - // Verify that format/type are one of the combinations from table 3.4. - bool CheckTextureFormatType(GLenum format, GLenum type) - { - switch(type) - { - case GL_UNSIGNED_BYTE: - switch(format) - { - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - return true; - default: - return false; - } - case GL_FLOAT: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - return (format == GL_RGBA); - case GL_UNSIGNED_SHORT_5_6_5: - return (format == GL_RGB); - case GL_UNSIGNED_INT_24_8_OES: - return (format == GL_DEPTH_STENCIL_OES); - default: - return false; - } - } - - bool IsColorRenderable(GLenum internalformat) - { - switch(internalformat) - { - case GL_RGBA4_OES: - case GL_RGB5_A1_OES: - case GL_RGB565_OES: - case GL_RGB8_OES: - case GL_RGBA8_OES: - return true; - case GL_DEPTH_COMPONENT16_OES: - case GL_STENCIL_INDEX8_OES: - case GL_DEPTH24_STENCIL8_OES: - return false; - default: - UNIMPLEMENTED(); - } - - return false; - } - - bool IsDepthRenderable(GLenum internalformat) - { - switch(internalformat) - { - case GL_DEPTH_COMPONENT16_OES: - case GL_DEPTH24_STENCIL8_OES: - return true; - case GL_STENCIL_INDEX8_OES: - case GL_RGBA4_OES: - case GL_RGB5_A1_OES: - case GL_RGB565_OES: - case GL_RGB8_OES: - case GL_RGBA8_OES: - return false; - default: - UNIMPLEMENTED(); - } - - return false; - } - - bool IsStencilRenderable(GLenum internalformat) - { - switch(internalformat) - { - case GL_STENCIL_INDEX8_OES: - case GL_DEPTH24_STENCIL8_OES: - return true; - case GL_RGBA4_OES: - case GL_RGB5_A1_OES: - case GL_RGB565_OES: - case GL_RGB8_OES: - case GL_RGBA8_OES: - case GL_DEPTH_COMPONENT16_OES: - return false; - default: - UNIMPLEMENTED(); - } - - return false; - } - - bool IsAlpha(GLenum texFormat) - { - switch(texFormat) - { - case GL_ALPHA: - return true; - default: - return false; - } - } - - bool IsRGB(GLenum texFormat) - { - switch(texFormat) - { - case GL_LUMINANCE: - case GL_RGB: - case GL_RGB565_OES: // GL_OES_framebuffer_object - case GL_RGB8_OES: // GL_OES_rgb8_rgba8 - case SW_YV12_BT601: - case SW_YV12_BT709: - case SW_YV12_JFIF: - return true; - default: - return false; - } - } - - bool IsRGBA(GLenum texFormat) - { - switch(texFormat) - { - case GL_LUMINANCE_ALPHA: - case GL_RGBA: - case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888 - case GL_RGBA4_OES: // GL_OES_framebuffer_object - case GL_RGB5_A1_OES: // GL_OES_framebuffer_object - case GL_RGBA8_OES: // GL_OES_rgb8_rgba8 - return true; - default: - return false; - } - } -} - -namespace es2sw -{ - sw::DepthCompareMode ConvertDepthComparison(GLenum comparison) - { - switch(comparison) - { - case GL_NEVER: return sw::DEPTH_NEVER; - case GL_ALWAYS: return sw::DEPTH_ALWAYS; - case GL_LESS: return sw::DEPTH_LESS; - case GL_LEQUAL: return sw::DEPTH_LESSEQUAL; - case GL_EQUAL: return sw::DEPTH_EQUAL; - case GL_GREATER: return sw::DEPTH_GREATER; - case GL_GEQUAL: return sw::DEPTH_GREATEREQUAL; - case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL; - default: UNREACHABLE(comparison); - } - - return sw::DEPTH_ALWAYS; - } - - sw::StencilCompareMode ConvertStencilComparison(GLenum comparison) - { - switch(comparison) - { - case GL_NEVER: return sw::STENCIL_NEVER; - case GL_ALWAYS: return sw::STENCIL_ALWAYS; - case GL_LESS: return sw::STENCIL_LESS; - case GL_LEQUAL: return sw::STENCIL_LESSEQUAL; - case GL_EQUAL: return sw::STENCIL_EQUAL; - case GL_GREATER: return sw::STENCIL_GREATER; - case GL_GEQUAL: return sw::STENCIL_GREATEREQUAL; - case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL; - default: UNREACHABLE(comparison); - } - - return sw::STENCIL_ALWAYS; - } - - sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison) - { - switch(comparison) - { - case GL_NEVER: return sw::ALPHA_NEVER; - case GL_ALWAYS: return sw::ALPHA_ALWAYS; - case GL_LESS: return sw::ALPHA_LESS; - case GL_LEQUAL: return sw::ALPHA_LESSEQUAL; - case GL_EQUAL: return sw::ALPHA_EQUAL; - case GL_GREATER: return sw::ALPHA_GREATER; - case GL_GEQUAL: return sw::ALPHA_GREATEREQUAL; - case GL_NOTEQUAL: return sw::ALPHA_NOTEQUAL; - default: UNREACHABLE(comparison); - } - - return sw::ALPHA_ALWAYS; - } - - sw::Color<float> ConvertColor(es1::Color color) - { - return sw::Color<float>(color.red, color.green, color.blue, color.alpha); - } - - sw::BlendFactor ConvertBlendFunc(GLenum blend) - { - switch(blend) - { - case GL_ZERO: return sw::BLEND_ZERO; - case GL_ONE: return sw::BLEND_ONE; - case GL_SRC_COLOR: return sw::BLEND_SOURCE; - case GL_ONE_MINUS_SRC_COLOR: return sw::BLEND_INVSOURCE; - case GL_DST_COLOR: return sw::BLEND_DEST; - case GL_ONE_MINUS_DST_COLOR: return sw::BLEND_INVDEST; - case GL_SRC_ALPHA: return sw::BLEND_SOURCEALPHA; - case GL_ONE_MINUS_SRC_ALPHA: return sw::BLEND_INVSOURCEALPHA; - case GL_DST_ALPHA: return sw::BLEND_DESTALPHA; - case GL_ONE_MINUS_DST_ALPHA: return sw::BLEND_INVDESTALPHA; - case GL_SRC_ALPHA_SATURATE: return sw::BLEND_SRCALPHASAT; - default: UNREACHABLE(blend); - } - - return sw::BLEND_ZERO; - } - - sw::BlendOperation ConvertBlendOp(GLenum blendOp) - { - switch(blendOp) - { - case GL_FUNC_ADD_OES: return sw::BLENDOP_ADD; - case GL_FUNC_SUBTRACT_OES: return sw::BLENDOP_SUB; - case GL_FUNC_REVERSE_SUBTRACT_OES: return sw::BLENDOP_INVSUB; - case GL_MIN_EXT: return sw::BLENDOP_MIN; - case GL_MAX_EXT: return sw::BLENDOP_MAX; - default: UNREACHABLE(blendOp); - } - - return sw::BLENDOP_ADD; - } - - sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation) - { - switch(logicalOperation) - { - case GL_CLEAR: return sw::LOGICALOP_CLEAR; - case GL_SET: return sw::LOGICALOP_SET; - case GL_COPY: return sw::LOGICALOP_COPY; - case GL_COPY_INVERTED: return sw::LOGICALOP_COPY_INVERTED; - case GL_NOOP: return sw::LOGICALOP_NOOP; - case GL_INVERT: return sw::LOGICALOP_INVERT; - case GL_AND: return sw::LOGICALOP_AND; - case GL_NAND: return sw::LOGICALOP_NAND; - case GL_OR: return sw::LOGICALOP_OR; - case GL_NOR: return sw::LOGICALOP_NOR; - case GL_XOR: return sw::LOGICALOP_XOR; - case GL_EQUIV: return sw::LOGICALOP_EQUIV; - case GL_AND_REVERSE: return sw::LOGICALOP_AND_REVERSE; - case GL_AND_INVERTED: return sw::LOGICALOP_AND_INVERTED; - case GL_OR_REVERSE: return sw::LOGICALOP_OR_REVERSE; - case GL_OR_INVERTED: return sw::LOGICALOP_OR_INVERTED; - default: UNREACHABLE(logicalOperation); - } - - return sw::LOGICALOP_COPY; - } - - sw::StencilOperation ConvertStencilOp(GLenum stencilOp) - { - switch(stencilOp) - { - case GL_ZERO: return sw::OPERATION_ZERO; - case GL_KEEP: return sw::OPERATION_KEEP; - case GL_REPLACE: return sw::OPERATION_REPLACE; - case GL_INCR: return sw::OPERATION_INCRSAT; - case GL_DECR: return sw::OPERATION_DECRSAT; - case GL_INVERT: return sw::OPERATION_INVERT; - case GL_INCR_WRAP_OES: return sw::OPERATION_INCR; - case GL_DECR_WRAP_OES: return sw::OPERATION_DECR; - default: UNREACHABLE(stencilOp); - } - - return sw::OPERATION_KEEP; - } - - sw::AddressingMode ConvertTextureWrap(GLenum wrap) - { - switch(wrap) - { - case GL_REPEAT: return sw::ADDRESSING_WRAP; - case GL_CLAMP_TO_EDGE: return sw::ADDRESSING_CLAMP; - case GL_MIRRORED_REPEAT_OES: return sw::ADDRESSING_MIRROR; - default: UNREACHABLE(wrap); - } - - return sw::ADDRESSING_WRAP; - } - - sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace) - { - switch(cullFace) - { - case GL_FRONT: - return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE); - case GL_BACK: - return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE); - case GL_FRONT_AND_BACK: - return sw::CULL_NONE; // culling will be handled during draw - default: UNREACHABLE(cullFace); - } - - return sw::CULL_COUNTERCLOCKWISE; - } - - unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha) - { - return (red ? 0x00000001 : 0) | - (green ? 0x00000002 : 0) | - (blue ? 0x00000004 : 0) | - (alpha ? 0x00000008 : 0); - } - - sw::MipmapType ConvertMipMapFilter(GLenum minFilter) - { - switch(minFilter) - { - case GL_NEAREST: - case GL_LINEAR: - return sw::MIPMAP_NONE; - break; - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - return sw::MIPMAP_POINT; - break; - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return sw::MIPMAP_LINEAR; - break; - default: - UNREACHABLE(minFilter); - return sw::MIPMAP_NONE; - } - } - - sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) - { - if(maxAnisotropy > 1.0f) - { - return sw::FILTER_ANISOTROPIC; - } - - sw::FilterType magFilterType = sw::FILTER_POINT; - switch(magFilter) - { - case GL_NEAREST: magFilterType = sw::FILTER_POINT; break; - case GL_LINEAR: magFilterType = sw::FILTER_LINEAR; break; - default: UNREACHABLE(magFilter); - } - - switch(minFilter) - { - case GL_NEAREST: - case GL_NEAREST_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR; - case GL_LINEAR: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_LINEAR: - return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR; - default: - UNREACHABLE(minFilter); - return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR; - } - } - - bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType, sw::DrawType &drawType, int &primitiveCount) - { - switch(primitiveType) - { - case GL_POINTS: - drawType = sw::DRAW_POINTLIST; - primitiveCount = elementCount; - break; - case GL_LINES: - drawType = sw::DRAW_LINELIST; - primitiveCount = elementCount / 2; - break; - case GL_LINE_LOOP: - drawType = sw::DRAW_LINELOOP; - primitiveCount = elementCount; - break; - case GL_LINE_STRIP: - drawType = sw::DRAW_LINESTRIP; - primitiveCount = elementCount - 1; - break; - case GL_TRIANGLES: - drawType = sw::DRAW_TRIANGLELIST; - primitiveCount = elementCount / 3; - break; - case GL_TRIANGLE_STRIP: - drawType = sw::DRAW_TRIANGLESTRIP; - primitiveCount = elementCount - 2; - break; - case GL_TRIANGLE_FAN: - drawType = sw::DRAW_TRIANGLEFAN; - primitiveCount = elementCount - 2; - break; - default: - return false; - } - - sw::DrawType elementSize; - switch(elementType) - { - case GL_NONE: elementSize = sw::DRAW_NONINDEXED; break; - case GL_UNSIGNED_BYTE: elementSize = sw::DRAW_INDEXED8; break; - case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16; break; - case GL_UNSIGNED_INT: elementSize = sw::DRAW_INDEXED32; break; - default: return false; - } - - drawType = sw::DrawType(drawType | elementSize); - - return true; - } - - sw::Format ConvertRenderbufferFormat(GLenum format) - { - switch(format) - { - case GL_RGBA4_OES: - case GL_RGB5_A1_OES: - case GL_RGBA8_OES: return sw::FORMAT_A8B8G8R8; - case GL_RGB565_OES: return sw::FORMAT_R5G6B5; - case GL_RGB8_OES: return sw::FORMAT_X8B8G8R8; - case GL_DEPTH_COMPONENT16_OES: - case GL_STENCIL_INDEX8_OES: - case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8; - default: UNREACHABLE(format); return sw::FORMAT_A8B8G8R8; - } - } - - sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation) - { - switch(operation) - { - case GL_REPLACE: return sw::TextureStage::STAGE_SELECTARG1; - case GL_MODULATE: return sw::TextureStage::STAGE_MODULATE; - case GL_ADD: return sw::TextureStage::STAGE_ADD; - case GL_ADD_SIGNED: return sw::TextureStage::STAGE_ADDSIGNED; - case GL_INTERPOLATE: return sw::TextureStage::STAGE_LERP; - case GL_SUBTRACT: return sw::TextureStage::STAGE_SUBTRACT; - case GL_DOT3_RGB: return sw::TextureStage::STAGE_DOT3; - case GL_DOT3_RGBA: return sw::TextureStage::STAGE_DOT3; - default: UNREACHABLE(operation); return sw::TextureStage::STAGE_SELECTARG1; - } - } - - sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument) - { - switch(argument) - { - case GL_TEXTURE: return sw::TextureStage::SOURCE_TEXTURE; - case GL_CONSTANT: return sw::TextureStage::SOURCE_CONSTANT; - case GL_PRIMARY_COLOR: return sw::TextureStage::SOURCE_DIFFUSE; - case GL_PREVIOUS: return sw::TextureStage::SOURCE_CURRENT; - default: UNREACHABLE(argument); return sw::TextureStage::SOURCE_CURRENT; - } - } - - sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand) - { - switch(operand) - { - case GL_SRC_COLOR: return sw::TextureStage::MODIFIER_COLOR; - case GL_ONE_MINUS_SRC_COLOR: return sw::TextureStage::MODIFIER_INVCOLOR; - case GL_SRC_ALPHA: return sw::TextureStage::MODIFIER_ALPHA; - case GL_ONE_MINUS_SRC_ALPHA: return sw::TextureStage::MODIFIER_INVALPHA; - default: UNREACHABLE(operand); return sw::TextureStage::MODIFIER_COLOR; - } - } -} - -namespace sw2es -{ - unsigned int GetStencilSize(sw::Format stencilFormat) - { - switch(stencilFormat) - { - case sw::FORMAT_D24FS8: - case sw::FORMAT_D24S8: - case sw::FORMAT_D32FS8_TEXTURE: - return 8; - // case sw::FORMAT_D24X4S4: - // return 4; - // case sw::FORMAT_D15S1: - // return 1; - // case sw::FORMAT_D16_LOCKABLE: - case sw::FORMAT_D32: - case sw::FORMAT_D24X8: - case sw::FORMAT_D32F_LOCKABLE: - case sw::FORMAT_D16: - return 0; - // case sw::FORMAT_D32_LOCKABLE: return 0; - // case sw::FORMAT_S8_LOCKABLE: return 8; - default: - return 0; - } - } - - unsigned int GetAlphaSize(sw::Format colorFormat) - { - switch(colorFormat) - { - case sw::FORMAT_A16B16G16R16F: - return 16; - case sw::FORMAT_A32B32G32R32F: - return 32; - case sw::FORMAT_A2R10G10B10: - return 2; - case sw::FORMAT_A8R8G8B8: - case sw::FORMAT_A8B8G8R8: - return 8; - case sw::FORMAT_A1R5G5B5: - return 1; - case sw::FORMAT_X8R8G8B8: - case sw::FORMAT_X8B8G8R8: - case sw::FORMAT_R5G6B5: - return 0; - default: - return 0; - } - } - - unsigned int GetRedSize(sw::Format colorFormat) - { - switch(colorFormat) - { - case sw::FORMAT_A16B16G16R16F: - return 16; - case sw::FORMAT_A32B32G32R32F: - return 32; - case sw::FORMAT_A2R10G10B10: - return 10; - case sw::FORMAT_A8R8G8B8: - case sw::FORMAT_A8B8G8R8: - case sw::FORMAT_X8R8G8B8: - case sw::FORMAT_X8B8G8R8: - return 8; - case sw::FORMAT_A1R5G5B5: - case sw::FORMAT_R5G6B5: - return 5; - default: - return 0; - } - } - - unsigned int GetGreenSize(sw::Format colorFormat) - { - switch(colorFormat) - { - case sw::FORMAT_A16B16G16R16F: - return 16; - case sw::FORMAT_A32B32G32R32F: - return 32; - case sw::FORMAT_A2R10G10B10: - return 10; - case sw::FORMAT_A8R8G8B8: - case sw::FORMAT_A8B8G8R8: - case sw::FORMAT_X8R8G8B8: - case sw::FORMAT_X8B8G8R8: - return 8; - case sw::FORMAT_A1R5G5B5: - return 5; - case sw::FORMAT_R5G6B5: - return 6; - default: - return 0; - } - } - - unsigned int GetBlueSize(sw::Format colorFormat) - { - switch(colorFormat) - { - case sw::FORMAT_A16B16G16R16F: - return 16; - case sw::FORMAT_A32B32G32R32F: - return 32; - case sw::FORMAT_A2R10G10B10: - return 10; - case sw::FORMAT_A8R8G8B8: - case sw::FORMAT_A8B8G8R8: - case sw::FORMAT_X8R8G8B8: - case sw::FORMAT_X8B8G8R8: - return 8; - case sw::FORMAT_A1R5G5B5: - case sw::FORMAT_R5G6B5: - return 5; - default: - return 0; - } - } - - unsigned int GetDepthSize(sw::Format depthFormat) - { - switch(depthFormat) - { - // case sw::FORMAT_D16_LOCKABLE: return 16; - case sw::FORMAT_D32: return 32; - // case sw::FORMAT_D15S1: return 15; - case sw::FORMAT_D24S8: return 24; - case sw::FORMAT_D24X8: return 24; - // case sw::FORMAT_D24X4S4: return 24; - case sw::FORMAT_D16: return 16; - case sw::FORMAT_D32F_LOCKABLE: return 32; - case sw::FORMAT_D24FS8: return 24; - // case sw::FORMAT_D32_LOCKABLE: return 32; - // case sw::FORMAT_S8_LOCKABLE: return 0; - case sw::FORMAT_D32FS8_TEXTURE: return 32; - default: return 0; - } - } - - GLenum ConvertBackBufferFormat(sw::Format format) - { - switch(format) - { - case sw::FORMAT_A4R4G4B4: return GL_RGBA4_OES; - case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES; - case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES; - case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1_OES; - case sw::FORMAT_R5G6B5: return GL_RGB565_OES; - case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES; - case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES; - default: - UNREACHABLE(format); - } - - return GL_RGBA4_OES; - } - - GLenum ConvertDepthStencilFormat(sw::Format format) - { - switch(format) - { - case sw::FORMAT_D16: - case sw::FORMAT_D24X8: - case sw::FORMAT_D32: - return GL_DEPTH_COMPONENT16_OES; - case sw::FORMAT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(format); - } - - return GL_DEPTH24_STENCIL8_OES; - } -} +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// utilities.cpp: Conversion functions and other utility routines. + +#include "utilities.h" + +#include "mathutil.h" +#include "Context.h" +#include "common/debug.h" + +#include <limits> +#include <stdio.h> + +namespace es1 +{ + bool IsCompressed(GLenum format) + { + return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || + format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || + format == GL_ETC1_RGB8_OES; + } + + bool IsDepthTexture(GLenum format) + { + return format == GL_DEPTH_STENCIL_OES; + } + + bool IsStencilTexture(GLenum format) + { + return format == GL_DEPTH_STENCIL_OES; + } + + bool IsCubemapTextureTarget(GLenum target) + { + return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES); + } + + int CubeFaceIndex(GLenum cubeFace) + { + switch(cubeFace) + { + case GL_TEXTURE_CUBE_MAP_OES: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES: return 0; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES: return 1; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES: return 2; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES: return 3; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES: return 4; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES: return 5; + default: UNREACHABLE(cubeFace); return 0; + } + } + + bool IsTextureTarget(GLenum target) + { + return target == GL_TEXTURE_2D; + } + + // Verify that format/type are one of the combinations from table 3.4. + bool CheckTextureFormatType(GLenum format, GLenum type) + { + switch(type) + { + case GL_UNSIGNED_BYTE: + switch(format) + { + case GL_RGBA: + case GL_BGRA_EXT: + case GL_RGB: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + return true; + default: + return false; + } + case GL_FLOAT: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + return (format == GL_RGBA); + case GL_UNSIGNED_SHORT_5_6_5: + return (format == GL_RGB); + case GL_UNSIGNED_INT_24_8_OES: + return (format == GL_DEPTH_STENCIL_OES); + default: + return false; + } + } + + bool IsColorRenderable(GLenum internalformat) + { + switch(internalformat) + { + case GL_RGBA4_OES: + case GL_RGB5_A1_OES: + case GL_RGB565_OES: + case GL_RGB8_OES: + case GL_RGBA8_OES: + return true; + case GL_DEPTH_COMPONENT16_OES: + case GL_STENCIL_INDEX8_OES: + case GL_DEPTH24_STENCIL8_OES: + return false; + default: + UNIMPLEMENTED(); + } + + return false; + } + + bool IsDepthRenderable(GLenum internalformat) + { + switch(internalformat) + { + case GL_DEPTH_COMPONENT16_OES: + case GL_DEPTH24_STENCIL8_OES: + return true; + case GL_STENCIL_INDEX8_OES: + case GL_RGBA4_OES: + case GL_RGB5_A1_OES: + case GL_RGB565_OES: + case GL_RGB8_OES: + case GL_RGBA8_OES: + return false; + default: + UNIMPLEMENTED(); + } + + return false; + } + + bool IsStencilRenderable(GLenum internalformat) + { + switch(internalformat) + { + case GL_STENCIL_INDEX8_OES: + case GL_DEPTH24_STENCIL8_OES: + return true; + case GL_RGBA4_OES: + case GL_RGB5_A1_OES: + case GL_RGB565_OES: + case GL_RGB8_OES: + case GL_RGBA8_OES: + case GL_DEPTH_COMPONENT16_OES: + return false; + default: + UNIMPLEMENTED(); + } + + return false; + } + + bool IsAlpha(GLenum texFormat) + { + switch(texFormat) + { + case GL_ALPHA: + return true; + default: + return false; + } + } + + bool IsRGB(GLenum texFormat) + { + switch(texFormat) + { + case GL_LUMINANCE: + case GL_RGB: + case GL_RGB565_OES: // GL_OES_framebuffer_object + case GL_RGB8_OES: // GL_OES_rgb8_rgba8 + case SW_YV12_BT601: + case SW_YV12_BT709: + case SW_YV12_JFIF: + return true; + default: + return false; + } + } + + bool IsRGBA(GLenum texFormat) + { + switch(texFormat) + { + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888 + case GL_RGBA4_OES: // GL_OES_framebuffer_object + case GL_RGB5_A1_OES: // GL_OES_framebuffer_object + case GL_RGBA8_OES: // GL_OES_rgb8_rgba8 + return true; + default: + return false; + } + } +} + +namespace es2sw +{ + sw::DepthCompareMode ConvertDepthComparison(GLenum comparison) + { + switch(comparison) + { + case GL_NEVER: return sw::DEPTH_NEVER; + case GL_ALWAYS: return sw::DEPTH_ALWAYS; + case GL_LESS: return sw::DEPTH_LESS; + case GL_LEQUAL: return sw::DEPTH_LESSEQUAL; + case GL_EQUAL: return sw::DEPTH_EQUAL; + case GL_GREATER: return sw::DEPTH_GREATER; + case GL_GEQUAL: return sw::DEPTH_GREATEREQUAL; + case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL; + default: UNREACHABLE(comparison); + } + + return sw::DEPTH_ALWAYS; + } + + sw::StencilCompareMode ConvertStencilComparison(GLenum comparison) + { + switch(comparison) + { + case GL_NEVER: return sw::STENCIL_NEVER; + case GL_ALWAYS: return sw::STENCIL_ALWAYS; + case GL_LESS: return sw::STENCIL_LESS; + case GL_LEQUAL: return sw::STENCIL_LESSEQUAL; + case GL_EQUAL: return sw::STENCIL_EQUAL; + case GL_GREATER: return sw::STENCIL_GREATER; + case GL_GEQUAL: return sw::STENCIL_GREATEREQUAL; + case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL; + default: UNREACHABLE(comparison); + } + + return sw::STENCIL_ALWAYS; + } + + sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison) + { + switch(comparison) + { + case GL_NEVER: return sw::ALPHA_NEVER; + case GL_ALWAYS: return sw::ALPHA_ALWAYS; + case GL_LESS: return sw::ALPHA_LESS; + case GL_LEQUAL: return sw::ALPHA_LESSEQUAL; + case GL_EQUAL: return sw::ALPHA_EQUAL; + case GL_GREATER: return sw::ALPHA_GREATER; + case GL_GEQUAL: return sw::ALPHA_GREATEREQUAL; + case GL_NOTEQUAL: return sw::ALPHA_NOTEQUAL; + default: UNREACHABLE(comparison); + } + + return sw::ALPHA_ALWAYS; + } + + sw::Color<float> ConvertColor(es1::Color color) + { + return sw::Color<float>(color.red, color.green, color.blue, color.alpha); + } + + sw::BlendFactor ConvertBlendFunc(GLenum blend) + { + switch(blend) + { + case GL_ZERO: return sw::BLEND_ZERO; + case GL_ONE: return sw::BLEND_ONE; + case GL_SRC_COLOR: return sw::BLEND_SOURCE; + case GL_ONE_MINUS_SRC_COLOR: return sw::BLEND_INVSOURCE; + case GL_DST_COLOR: return sw::BLEND_DEST; + case GL_ONE_MINUS_DST_COLOR: return sw::BLEND_INVDEST; + case GL_SRC_ALPHA: return sw::BLEND_SOURCEALPHA; + case GL_ONE_MINUS_SRC_ALPHA: return sw::BLEND_INVSOURCEALPHA; + case GL_DST_ALPHA: return sw::BLEND_DESTALPHA; + case GL_ONE_MINUS_DST_ALPHA: return sw::BLEND_INVDESTALPHA; + case GL_SRC_ALPHA_SATURATE: return sw::BLEND_SRCALPHASAT; + default: UNREACHABLE(blend); + } + + return sw::BLEND_ZERO; + } + + sw::BlendOperation ConvertBlendOp(GLenum blendOp) + { + switch(blendOp) + { + case GL_FUNC_ADD_OES: return sw::BLENDOP_ADD; + case GL_FUNC_SUBTRACT_OES: return sw::BLENDOP_SUB; + case GL_FUNC_REVERSE_SUBTRACT_OES: return sw::BLENDOP_INVSUB; + case GL_MIN_EXT: return sw::BLENDOP_MIN; + case GL_MAX_EXT: return sw::BLENDOP_MAX; + default: UNREACHABLE(blendOp); + } + + return sw::BLENDOP_ADD; + } + + sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation) + { + switch(logicalOperation) + { + case GL_CLEAR: return sw::LOGICALOP_CLEAR; + case GL_SET: return sw::LOGICALOP_SET; + case GL_COPY: return sw::LOGICALOP_COPY; + case GL_COPY_INVERTED: return sw::LOGICALOP_COPY_INVERTED; + case GL_NOOP: return sw::LOGICALOP_NOOP; + case GL_INVERT: return sw::LOGICALOP_INVERT; + case GL_AND: return sw::LOGICALOP_AND; + case GL_NAND: return sw::LOGICALOP_NAND; + case GL_OR: return sw::LOGICALOP_OR; + case GL_NOR: return sw::LOGICALOP_NOR; + case GL_XOR: return sw::LOGICALOP_XOR; + case GL_EQUIV: return sw::LOGICALOP_EQUIV; + case GL_AND_REVERSE: return sw::LOGICALOP_AND_REVERSE; + case GL_AND_INVERTED: return sw::LOGICALOP_AND_INVERTED; + case GL_OR_REVERSE: return sw::LOGICALOP_OR_REVERSE; + case GL_OR_INVERTED: return sw::LOGICALOP_OR_INVERTED; + default: UNREACHABLE(logicalOperation); + } + + return sw::LOGICALOP_COPY; + } + + sw::StencilOperation ConvertStencilOp(GLenum stencilOp) + { + switch(stencilOp) + { + case GL_ZERO: return sw::OPERATION_ZERO; + case GL_KEEP: return sw::OPERATION_KEEP; + case GL_REPLACE: return sw::OPERATION_REPLACE; + case GL_INCR: return sw::OPERATION_INCRSAT; + case GL_DECR: return sw::OPERATION_DECRSAT; + case GL_INVERT: return sw::OPERATION_INVERT; + case GL_INCR_WRAP_OES: return sw::OPERATION_INCR; + case GL_DECR_WRAP_OES: return sw::OPERATION_DECR; + default: UNREACHABLE(stencilOp); + } + + return sw::OPERATION_KEEP; + } + + sw::AddressingMode ConvertTextureWrap(GLenum wrap) + { + switch(wrap) + { + case GL_REPEAT: return sw::ADDRESSING_WRAP; + case GL_CLAMP_TO_EDGE: return sw::ADDRESSING_CLAMP; + case GL_MIRRORED_REPEAT_OES: return sw::ADDRESSING_MIRROR; + default: UNREACHABLE(wrap); + } + + return sw::ADDRESSING_WRAP; + } + + sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace) + { + switch(cullFace) + { + case GL_FRONT: + return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE); + case GL_BACK: + return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE); + case GL_FRONT_AND_BACK: + return sw::CULL_NONE; // culling will be handled during draw + default: UNREACHABLE(cullFace); + } + + return sw::CULL_COUNTERCLOCKWISE; + } + + unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha) + { + return (red ? 0x00000001 : 0) | + (green ? 0x00000002 : 0) | + (blue ? 0x00000004 : 0) | + (alpha ? 0x00000008 : 0); + } + + sw::MipmapType ConvertMipMapFilter(GLenum minFilter) + { + switch(minFilter) + { + case GL_NEAREST: + case GL_LINEAR: + return sw::MIPMAP_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + return sw::MIPMAP_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return sw::MIPMAP_LINEAR; + break; + default: + UNREACHABLE(minFilter); + return sw::MIPMAP_NONE; + } + } + + sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) + { + if(maxAnisotropy > 1.0f) + { + return sw::FILTER_ANISOTROPIC; + } + + sw::FilterType magFilterType = sw::FILTER_POINT; + switch(magFilter) + { + case GL_NEAREST: magFilterType = sw::FILTER_POINT; break; + case GL_LINEAR: magFilterType = sw::FILTER_LINEAR; break; + default: UNREACHABLE(magFilter); + } + + switch(minFilter) + { + case GL_NEAREST: + case GL_NEAREST_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR; + case GL_LINEAR: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_LINEAR: + return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR; + default: + UNREACHABLE(minFilter); + return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR; + } + } + + bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType, sw::DrawType &drawType, int &primitiveCount) + { + switch(primitiveType) + { + case GL_POINTS: + drawType = sw::DRAW_POINTLIST; + primitiveCount = elementCount; + break; + case GL_LINES: + drawType = sw::DRAW_LINELIST; + primitiveCount = elementCount / 2; + break; + case GL_LINE_LOOP: + drawType = sw::DRAW_LINELOOP; + primitiveCount = elementCount; + break; + case GL_LINE_STRIP: + drawType = sw::DRAW_LINESTRIP; + primitiveCount = elementCount - 1; + break; + case GL_TRIANGLES: + drawType = sw::DRAW_TRIANGLELIST; + primitiveCount = elementCount / 3; + break; + case GL_TRIANGLE_STRIP: + drawType = sw::DRAW_TRIANGLESTRIP; + primitiveCount = elementCount - 2; + break; + case GL_TRIANGLE_FAN: + drawType = sw::DRAW_TRIANGLEFAN; + primitiveCount = elementCount - 2; + break; + default: + return false; + } + + sw::DrawType elementSize; + switch(elementType) + { + case GL_NONE: elementSize = sw::DRAW_NONINDEXED; break; + case GL_UNSIGNED_BYTE: elementSize = sw::DRAW_INDEXED8; break; + case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16; break; + case GL_UNSIGNED_INT: elementSize = sw::DRAW_INDEXED32; break; + default: return false; + } + + drawType = sw::DrawType(drawType | elementSize); + + return true; + } + + sw::Format ConvertRenderbufferFormat(GLenum format) + { + switch(format) + { + case GL_RGBA4_OES: + case GL_RGB5_A1_OES: + case GL_RGBA8_OES: return sw::FORMAT_A8B8G8R8; + case GL_RGB565_OES: return sw::FORMAT_R5G6B5; + case GL_RGB8_OES: return sw::FORMAT_X8B8G8R8; + case GL_DEPTH_COMPONENT16_OES: + case GL_STENCIL_INDEX8_OES: + case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8; + default: UNREACHABLE(format); return sw::FORMAT_A8B8G8R8; + } + } + + sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation) + { + switch(operation) + { + case GL_REPLACE: return sw::TextureStage::STAGE_SELECTARG1; + case GL_MODULATE: return sw::TextureStage::STAGE_MODULATE; + case GL_ADD: return sw::TextureStage::STAGE_ADD; + case GL_ADD_SIGNED: return sw::TextureStage::STAGE_ADDSIGNED; + case GL_INTERPOLATE: return sw::TextureStage::STAGE_LERP; + case GL_SUBTRACT: return sw::TextureStage::STAGE_SUBTRACT; + case GL_DOT3_RGB: return sw::TextureStage::STAGE_DOT3; + case GL_DOT3_RGBA: return sw::TextureStage::STAGE_DOT3; + default: UNREACHABLE(operation); return sw::TextureStage::STAGE_SELECTARG1; + } + } + + sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument) + { + switch(argument) + { + case GL_TEXTURE: return sw::TextureStage::SOURCE_TEXTURE; + case GL_CONSTANT: return sw::TextureStage::SOURCE_CONSTANT; + case GL_PRIMARY_COLOR: return sw::TextureStage::SOURCE_DIFFUSE; + case GL_PREVIOUS: return sw::TextureStage::SOURCE_CURRENT; + default: UNREACHABLE(argument); return sw::TextureStage::SOURCE_CURRENT; + } + } + + sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand) + { + switch(operand) + { + case GL_SRC_COLOR: return sw::TextureStage::MODIFIER_COLOR; + case GL_ONE_MINUS_SRC_COLOR: return sw::TextureStage::MODIFIER_INVCOLOR; + case GL_SRC_ALPHA: return sw::TextureStage::MODIFIER_ALPHA; + case GL_ONE_MINUS_SRC_ALPHA: return sw::TextureStage::MODIFIER_INVALPHA; + default: UNREACHABLE(operand); return sw::TextureStage::MODIFIER_COLOR; + } + } +} + +namespace sw2es +{ + unsigned int GetStencilSize(sw::Format stencilFormat) + { + switch(stencilFormat) + { + case sw::FORMAT_D24FS8: + case sw::FORMAT_D24S8: + case sw::FORMAT_D32FS8_TEXTURE: + return 8; + // case sw::FORMAT_D24X4S4: + // return 4; + // case sw::FORMAT_D15S1: + // return 1; + // case sw::FORMAT_D16_LOCKABLE: + case sw::FORMAT_D32: + case sw::FORMAT_D24X8: + case sw::FORMAT_D32F_LOCKABLE: + case sw::FORMAT_D16: + return 0; + // case sw::FORMAT_D32_LOCKABLE: return 0; + // case sw::FORMAT_S8_LOCKABLE: return 8; + default: + return 0; + } + } + + unsigned int GetAlphaSize(sw::Format colorFormat) + { + switch(colorFormat) + { + case sw::FORMAT_A16B16G16R16F: + return 16; + case sw::FORMAT_A32B32G32R32F: + return 32; + case sw::FORMAT_A2R10G10B10: + return 2; + case sw::FORMAT_A8R8G8B8: + case sw::FORMAT_A8B8G8R8: + return 8; + case sw::FORMAT_A1R5G5B5: + return 1; + case sw::FORMAT_X8R8G8B8: + case sw::FORMAT_X8B8G8R8: + case sw::FORMAT_R5G6B5: + return 0; + default: + return 0; + } + } + + unsigned int GetRedSize(sw::Format colorFormat) + { + switch(colorFormat) + { + case sw::FORMAT_A16B16G16R16F: + return 16; + case sw::FORMAT_A32B32G32R32F: + return 32; + case sw::FORMAT_A2R10G10B10: + return 10; + case sw::FORMAT_A8R8G8B8: + case sw::FORMAT_A8B8G8R8: + case sw::FORMAT_X8R8G8B8: + case sw::FORMAT_X8B8G8R8: + return 8; + case sw::FORMAT_A1R5G5B5: + case sw::FORMAT_R5G6B5: + return 5; + default: + return 0; + } + } + + unsigned int GetGreenSize(sw::Format colorFormat) + { + switch(colorFormat) + { + case sw::FORMAT_A16B16G16R16F: + return 16; + case sw::FORMAT_A32B32G32R32F: + return 32; + case sw::FORMAT_A2R10G10B10: + return 10; + case sw::FORMAT_A8R8G8B8: + case sw::FORMAT_A8B8G8R8: + case sw::FORMAT_X8R8G8B8: + case sw::FORMAT_X8B8G8R8: + return 8; + case sw::FORMAT_A1R5G5B5: + return 5; + case sw::FORMAT_R5G6B5: + return 6; + default: + return 0; + } + } + + unsigned int GetBlueSize(sw::Format colorFormat) + { + switch(colorFormat) + { + case sw::FORMAT_A16B16G16R16F: + return 16; + case sw::FORMAT_A32B32G32R32F: + return 32; + case sw::FORMAT_A2R10G10B10: + return 10; + case sw::FORMAT_A8R8G8B8: + case sw::FORMAT_A8B8G8R8: + case sw::FORMAT_X8R8G8B8: + case sw::FORMAT_X8B8G8R8: + return 8; + case sw::FORMAT_A1R5G5B5: + case sw::FORMAT_R5G6B5: + return 5; + default: + return 0; + } + } + + unsigned int GetDepthSize(sw::Format depthFormat) + { + switch(depthFormat) + { + // case sw::FORMAT_D16_LOCKABLE: return 16; + case sw::FORMAT_D32: return 32; + // case sw::FORMAT_D15S1: return 15; + case sw::FORMAT_D24S8: return 24; + case sw::FORMAT_D24X8: return 24; + // case sw::FORMAT_D24X4S4: return 24; + case sw::FORMAT_D16: return 16; + case sw::FORMAT_D32F_LOCKABLE: return 32; + case sw::FORMAT_D24FS8: return 24; + // case sw::FORMAT_D32_LOCKABLE: return 32; + // case sw::FORMAT_S8_LOCKABLE: return 0; + case sw::FORMAT_D32FS8_TEXTURE: return 32; + default: return 0; + } + } + + GLenum ConvertBackBufferFormat(sw::Format format) + { + switch(format) + { + case sw::FORMAT_A4R4G4B4: return GL_RGBA4_OES; + case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES; + case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES; + case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1_OES; + case sw::FORMAT_R5G6B5: return GL_RGB565_OES; + case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES; + case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES; + default: + UNREACHABLE(format); + } + + return GL_RGBA4_OES; + } + + GLenum ConvertDepthStencilFormat(sw::Format format) + { + switch(format) + { + case sw::FORMAT_D16: + case sw::FORMAT_D24X8: + case sw::FORMAT_D32: + return GL_DEPTH_COMPONENT16_OES; + case sw::FORMAT_D24S8: + return GL_DEPTH24_STENCIL8_OES; + default: + UNREACHABLE(format); + } + + return GL_DEPTH24_STENCIL8_OES; + } +}
diff --git a/src/OpenGL/libGLES_CM/utilities.h b/src/OpenGL/libGLES_CM/utilities.h index ef1d6ff..ec2a257 100644 --- a/src/OpenGL/libGLES_CM/utilities.h +++ b/src/OpenGL/libGLES_CM/utilities.h
@@ -1,82 +1,85 @@ -// SwiftShader Software Renderer -// -// Copyright(c) 2005-2013 TransGaming Inc. -// -// All rights reserved. No part of this software may be copied, distributed, transmitted, -// transcribed, stored in a retrieval system, translated into any human or computer -// language by any means, or disclosed to third parties without the explicit written -// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express -// or implied, including but not limited to any patent rights, are granted to you. -// - -// utilities.h: Conversion functions and other utility routines. - -#ifndef LIBGLES_CM_UTILITIES_H -#define LIBGLES_CM_UTILITIES_H - -#include "Device.hpp" -#include "common/Image.hpp" -#include "Texture.h" - -#include <GLES/gl.h> -#include <GLES/glext.h> - -#include <string> - -namespace es1 -{ - struct Color; - - bool IsCompressed(GLenum format); - bool IsDepthTexture(GLenum format); - bool IsStencilTexture(GLenum format); - bool IsCubemapTextureTarget(GLenum target); - int CubeFaceIndex(GLenum cubeTarget); - bool IsTextureTarget(GLenum target); - bool CheckTextureFormatType(GLenum format, GLenum type); - - bool IsColorRenderable(GLenum internalformat); - bool IsDepthRenderable(GLenum internalformat); - bool IsStencilRenderable(GLenum internalformat); - - bool IsAlpha(GLenum texFormat); - bool IsRGB(GLenum texFormat); - bool IsRGBA(GLenum texFormat); -} - -namespace es2sw -{ - sw::DepthCompareMode ConvertDepthComparison(GLenum comparison); - sw::StencilCompareMode ConvertStencilComparison(GLenum comparison); - sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison); - sw::Color<float> ConvertColor(es1::Color color); - sw::BlendFactor ConvertBlendFunc(GLenum blend); - sw::BlendOperation ConvertBlendOp(GLenum blendOp); - sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation); - sw::StencilOperation ConvertStencilOp(GLenum stencilOp); - sw::AddressingMode ConvertTextureWrap(GLenum wrap); - sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace); - unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha); - sw::MipmapType ConvertMipMapFilter(GLenum minFilter); - sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy); - bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType, sw::DrawType &swPrimitiveType, int &primitiveCount); - sw::Format ConvertRenderbufferFormat(GLenum format); - sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation); - sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument); - sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand); -} - -namespace sw2es -{ - GLuint GetAlphaSize(sw::Format colorFormat); - GLuint GetRedSize(sw::Format colorFormat); - GLuint GetGreenSize(sw::Format colorFormat); - GLuint GetBlueSize(sw::Format colorFormat); - GLuint GetDepthSize(sw::Format depthFormat); - GLuint GetStencilSize(sw::Format stencilFormat); - - GLenum ConvertBackBufferFormat(sw::Format format); - GLenum ConvertDepthStencilFormat(sw::Format format); -} - -#endif // LIBGLES_CM_UTILITIES_H +// Copyright 2016 The SwiftShader Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// utilities.h: Conversion functions and other utility routines. + +#ifndef LIBGLES_CM_UTILITIES_H +#define LIBGLES_CM_UTILITIES_H + +#include "Device.hpp" +#include "common/Image.hpp" +#include "Texture.h" + +#include <GLES/gl.h> +#include <GLES/glext.h> + +#include <string> + +namespace es1 +{ + struct Color; + + bool IsCompressed(GLenum format); + bool IsDepthTexture(GLenum format); + bool IsStencilTexture(GLenum format); + bool IsCubemapTextureTarget(GLenum target); + int CubeFaceIndex(GLenum cubeTarget); + bool IsTextureTarget(GLenum target); + bool CheckTextureFormatType(GLenum format, GLenum type); + + bool IsColorRenderable(GLenum internalformat); + bool IsDepthRenderable(GLenum internalformat); + bool IsStencilRenderable(GLenum internalformat); + + bool IsAlpha(GLenum texFormat); + bool IsRGB(GLenum texFormat); + bool IsRGBA(GLenum texFormat); +} + +namespace es2sw +{ + sw::DepthCompareMode ConvertDepthComparison(GLenum comparison); + sw::StencilCompareMode ConvertStencilComparison(GLenum comparison); + sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison); + sw::Color<float> ConvertColor(es1::Color color); + sw::BlendFactor ConvertBlendFunc(GLenum blend); + sw::BlendOperation ConvertBlendOp(GLenum blendOp); + sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation); + sw::StencilOperation ConvertStencilOp(GLenum stencilOp); + sw::AddressingMode ConvertTextureWrap(GLenum wrap); + sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace); + unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha); + sw::MipmapType ConvertMipMapFilter(GLenum minFilter); + sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy); + bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType, sw::DrawType &swPrimitiveType, int &primitiveCount); + sw::Format ConvertRenderbufferFormat(GLenum format); + sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation); + sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument); + sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand); +} + +namespace sw2es +{ + GLuint GetAlphaSize(sw::Format colorFormat); + GLuint GetRedSize(sw::Format colorFormat); + GLuint GetGreenSize(sw::Format colorFormat); + GLuint GetBlueSize(sw::Format colorFormat); + GLuint GetDepthSize(sw::Format depthFormat); + GLuint GetStencilSize(sw::Format stencilFormat); + + GLenum ConvertBackBufferFormat(sw::Format format); + GLenum ConvertDepthStencilFormat(sw::Format format); +} + +#endif // LIBGLES_CM_UTILITIES_H