diff options
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp')
-rw-r--r-- | Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp | 633 |
1 files changed, 448 insertions, 185 deletions
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp index 48ef8fc..9be59c4 100644 --- a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp +++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp @@ -19,15 +19,14 @@ #include "libGLESv2/Blit.h" #include "libGLESv2/ResourceManager.h" #include "libGLESv2/Buffer.h" +#include "libGLESv2/Fence.h" #include "libGLESv2/FrameBuffer.h" #include "libGLESv2/Program.h" #include "libGLESv2/RenderBuffer.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Texture.h" -#include "libGLESv2/geometry/backend.h" #include "libGLESv2/geometry/VertexDataManager.h" #include "libGLESv2/geometry/IndexDataManager.h" -#include "libGLESv2/geometry/dx9.h" #undef near #undef far @@ -83,6 +82,7 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) mState.scissorTest = false; mState.dither = true; mState.generateMipmapHint = GL_DONT_CARE; + mState.fragmentShaderDerivativeHint = GL_DONT_CARE; mState.lineWidth = 1.0f; @@ -120,11 +120,8 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) // 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); - mTextureCubeMapZero = new TextureCubeMap(0); - - mColorbufferZero = NULL; - mDepthStencilbufferZero = NULL; + mTexture2DZero.set(new Texture2D(0)); + mTextureCubeMapZero.set(new TextureCubeMap(0)); mState.activeSampler = 0; bindArrayBuffer(0); @@ -135,17 +132,11 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) bindDrawFramebuffer(0); bindRenderbuffer(0); - for (int type = 0; type < SAMPLER_TYPE_COUNT; type++) - { - mIncompleteTextures[type] = NULL; - } - mState.currentProgram = 0; mState.packAlignment = 4; mState.unpackAlignment = 4; - mBufferBackEnd = NULL; mVertexDataManager = NULL; mIndexDataManager = NULL; mBlit = NULL; @@ -158,6 +149,8 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext) mHasBeenCurrent = false; + mSupportsCompressedTextures = false; + mSupportsEventQueries = false; mMaxSupportedSamples = 0; mMaskedClearSavedState = NULL; markAllStateDirty(); @@ -180,6 +173,11 @@ Context::~Context() deleteFramebuffer(mFramebufferMap.begin()->first); } + while (!mFenceMap.empty()) + { + deleteFence(mFenceMap.begin()->first); + } + while (!mMultiSampleSupport.empty()) { delete [] mMultiSampleSupport.begin()->second; @@ -196,7 +194,7 @@ Context::~Context() for (int type = 0; type < SAMPLER_TYPE_COUNT; type++) { - delete mIncompleteTextures[type]; + mIncompleteTextures[type].set(NULL); } for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) @@ -206,14 +204,11 @@ Context::~Context() mState.arrayBuffer.set(NULL); mState.elementArrayBuffer.set(NULL); - mState.texture2D.set(NULL); - mState.textureCubeMap.set(NULL); mState.renderbuffer.set(NULL); - delete mTexture2DZero; - delete mTextureCubeMapZero; + mTexture2DZero.set(NULL); + mTextureCubeMapZero.set(NULL); - delete mBufferBackEnd; delete mVertexDataManager; delete mIndexDataManager; delete mBlit; @@ -234,11 +229,20 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) { mDeviceCaps = display->getDeviceCaps(); - mBufferBackEnd = new Dx9BackEnd(this, device); - mVertexDataManager = new VertexDataManager(this, mBufferBackEnd); - mIndexDataManager = new IndexDataManager(this, mBufferBackEnd); + mVertexDataManager = new VertexDataManager(this, device); + mIndexDataManager = new IndexDataManager(this, device); mBlit = new Blit(this); + mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0); + + mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight), + (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); + mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE); + mMaxRenderbufferDimension = mMaxTextureDimension; + mMaxTextureLevel = log2(mMaxTextureDimension) + 1; + TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d", + mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel); + const D3DFORMAT renderBufferFormats[] = { D3DFMT_A8R8G8B8, @@ -265,7 +269,14 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) mMaxSupportedSamples = max; + mSupportsEventQueries = display->getEventQuerySupport(); mSupportsCompressedTextures = display->getCompressedTextureSupport(); + mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures); + mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures); + mSupportsLuminanceTextures = display->getLuminanceTextureSupport(); + mSupportsLuminanceAlphaTextures = display->getLuminanceAlphaTextureSupport(); + + mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16); initExtensionString(); @@ -292,15 +303,16 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) setFramebufferZero(framebufferZero); - defaultRenderTarget->Release(); + if (defaultRenderTarget) + { + defaultRenderTarget->Release(); + } if (depthStencil) { depthStencil->Release(); } - mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0); - markAllStateDirty(); } @@ -309,6 +321,8 @@ void Context::markAllStateDirty() { mAppliedRenderTargetSerial = 0; mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; mAppliedProgram = 0; mClearStateDirty = true; @@ -322,11 +336,6 @@ void Context::markAllStateDirty() mSampleStateDirty = true; mDitherStateDirty = true; mFrontFaceDirty = true; - - if (mBufferBackEnd != NULL) - { - mBufferBackEnd->invalidate(); - } } void Context::setClearColor(float red, float green, float blue, float alpha) @@ -650,6 +659,14 @@ void Context::setGenerateMipmapHint(GLenum hint) mState.generateMipmapHint = hint; } +void Context::setFragmentShaderDerivativeHint(GLenum hint) +{ + mState.fragmentShaderDerivativeHint = hint; + // TODO: Propagate the hint to shader translator so we can write + // ddx, ddx_coarse, or ddx_fine depending on the hint. + // Ignore for now. It is valid for implementations to ignore hint. +} + void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) { mState.viewportX = x; @@ -718,12 +735,12 @@ GLuint Context::getArrayBufferHandle() const return mState.arrayBuffer.id(); } -void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled) +void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) { - mState.vertexAttribute[attribNum].mEnabled = enabled; + mState.vertexAttribute[attribNum].mArrayEnabled = enabled; } -const AttributeState &Context::getVertexAttribState(unsigned int attribNum) +const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) { return mState.vertexAttribute[attribNum]; } @@ -744,8 +761,7 @@ const void *Context::getVertexAttribPointer(unsigned int attribNum) const return mState.vertexAttribute[attribNum].mPointer; } -// returns entire set of attributes as a block -const AttributeState *Context::getVertexAttribBlock() +const VertexAttributeArray &Context::getVertexAttributes() { return mState.vertexAttribute; } @@ -810,6 +826,20 @@ GLuint Context::createFramebuffer() return handle; } +GLuint Context::createFence() +{ + unsigned int handle = 0; + + while (mFenceMap.find(handle) != mFenceMap.end()) + { + handle++; + } + + mFenceMap[handle] = new Fence; + + return handle; +} + void Context::deleteBuffer(GLuint buffer) { if (mResourceManager->getBuffer(buffer)) @@ -863,6 +893,17 @@ void Context::deleteFramebuffer(GLuint framebuffer) } } +void Context::deleteFence(GLuint fence) +{ + FenceMap::iterator fenceObject = mFenceMap.find(fence); + + if (fenceObject != mFenceMap.end()) + { + delete fenceObject->second; + mFenceMap.erase(fenceObject); + } +} + Buffer *Context::getBuffer(GLuint handle) { return mResourceManager->getBuffer(handle); @@ -916,18 +957,14 @@ void Context::bindTexture2D(GLuint texture) { mResourceManager->checkTextureAllocation(texture, SAMPLER_2D); - mState.texture2D.set(getTexture(texture)); - - mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(mState.texture2D.get()); + mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(getTexture(texture)); } void Context::bindTextureCubeMap(GLuint texture) { mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE); - mState.textureCubeMap.set(getTexture(texture)); - - mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(mState.textureCubeMap.get()); + mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(getTexture(texture)); } void Context::bindReadFramebuffer(GLuint framebuffer) @@ -1005,6 +1042,20 @@ Framebuffer *Context::getFramebuffer(unsigned int handle) } } +Fence *Context::getFence(unsigned int handle) +{ + FenceMap::iterator fence = mFenceMap.find(handle); + + if (fence == mFenceMap.end()) + { + return NULL; + } + else + { + return fence->second; + } +} + Buffer *Context::getArrayBuffer() { return mState.arrayBuffer.get(); @@ -1022,35 +1073,25 @@ Program *Context::getCurrentProgram() Texture2D *Context::getTexture2D() { - if (mState.texture2D.id() == 0) // Special case: 0 refers to different initial textures based on the target - { - return mTexture2DZero; - } - - return static_cast<Texture2D*>(mState.texture2D.get()); + return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, SAMPLER_2D)); } TextureCubeMap *Context::getTextureCubeMap() { - if (mState.textureCubeMap.id() == 0) // Special case: 0 refers to different initial textures based on the target - { - return mTextureCubeMapZero; - } - - return static_cast<TextureCubeMap*>(mState.textureCubeMap.get()); + return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, SAMPLER_CUBE)); } Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type) { GLuint texid = mState.samplerTexture[type][sampler].id(); - if (texid == 0) + if (texid == 0) // Special case: 0 refers to different initial textures based on the target { switch (type) { default: UNREACHABLE(); - case SAMPLER_2D: return mTexture2DZero; - case SAMPLER_CUBE: return mTextureCubeMapZero; + case SAMPLER_2D: return mTexture2DZero.get(); + case SAMPLER_CUBE: return mTextureCubeMapZero.get(); } } @@ -1070,15 +1111,15 @@ bool Context::getBooleanv(GLenum pname, GLboolean *params) params[2] = mState.colorMaskBlue; params[3] = mState.colorMaskAlpha; break; - case GL_CULL_FACE: *params = mState.cullFace; - case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; - case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; - case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; - case GL_SCISSOR_TEST: *params = mState.scissorTest; - case GL_STENCIL_TEST: *params = mState.stencilTest; - case GL_DEPTH_TEST: *params = mState.depthTest; - case GL_BLEND: *params = mState.blend; - case GL_DITHER: *params = mState.dither; + case GL_CULL_FACE: *params = mState.cullFace; break; + case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break; + case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; + case GL_SCISSOR_TEST: *params = mState.scissorTest; break; + case GL_STENCIL_TEST: *params = mState.stencilTest; break; + case GL_DEPTH_TEST: *params = mState.depthTest; break; + case GL_BLEND: *params = mState.blend; break; + case GL_DITHER: *params = mState.dither; break; default: return false; } @@ -1141,24 +1182,25 @@ bool Context::getIntegerv(GLenum pname, GLint *params) { case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break; - case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break; + case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break; case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break; case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break; case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break; - case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break; + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break; + case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break; case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break; case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break; case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break; case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break; - //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break; - case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break; + //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break; + case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break; case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break; case GL_CURRENT_PROGRAM: *params = mState.currentProgram; 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_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; 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; @@ -1183,8 +1225,8 @@ bool Context::getIntegerv(GLenum pname, GLint *params) case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break; case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; case GL_SUBPIXEL_BITS: *params = 4; break; - case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break; - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break; + case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break; case GL_NUM_COMPRESSED_TEXTURE_FORMATS: { if (supportsCompressedTextures()) @@ -1246,7 +1288,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params) case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break; case GL_MAX_VIEWPORT_DIMS: { - int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE); + int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension()); params[0] = maxDimension; params[1] = maxDimension; } @@ -1392,6 +1434,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_PACK_ALIGNMENT: case GL_UNPACK_ALIGNMENT: case GL_GENERATE_MIPMAP_HINT: + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: case GL_RED_BITS: case GL_GREEN_BITS: case GL_BLUE_BITS: @@ -1535,6 +1578,12 @@ bool Context::applyRenderTarget(bool ignoreViewport) } IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); + + if (!renderTarget) + { + return false; // Context must be lost + } + IDirect3DSurface9 *depthStencil = NULL; unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial(); @@ -1550,26 +1599,43 @@ bool Context::applyRenderTarget(bool ignoreViewport) if (framebufferObject->getDepthbufferType() != GL_NONE) { depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return false; + } + depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial(); } else if (framebufferObject->getStencilbufferType() != GL_NONE) { depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return false; + } + stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial(); } if (depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial) + stencilbufferSerial != mAppliedStencilbufferSerial || + !mDepthStencilInitialized) { device->SetDepthStencilSurface(depthStencil); mAppliedDepthbufferSerial = depthbufferSerial; mAppliedStencilbufferSerial = stencilbufferSerial; + mDepthStencilInitialized = true; } D3DVIEWPORT9 viewport; D3DSURFACE_DESC desc; renderTarget->GetDesc(&desc); + float zNear = clamp01(mState.zNear); + float zFar = clamp01(mState.zFar); + if (ignoreViewport) { viewport.X = 0; @@ -1585,8 +1651,8 @@ bool Context::applyRenderTarget(bool ignoreViewport) viewport.Y = std::max(mState.viewportY, 0); viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X); viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y); - viewport.MinZ = clamp01(mState.zNear); - viewport.MaxZ = clamp01(mState.zFar); + viewport.MinZ = zNear; + viewport.MaxZ = zFar; } if (viewport.Width <= 0 || viewport.Height <= 0) @@ -1623,27 +1689,21 @@ bool Context::applyRenderTarget(bool ignoreViewport) GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation(); GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height}; - programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy); + programObject->setUniform2fv(halfPixelSize, 1, xy); - GLint window = programObject->getDxViewportLocation(); + GLint viewport = programObject->getDxViewportLocation(); GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f, (float)mState.viewportX + mState.viewportWidth / 2.0f, (float)mState.viewportY + mState.viewportHeight / 2.0f}; - programObject->setUniform4fv(window, 1, (GLfloat*)&whxy); + programObject->setUniform4fv(viewport, 1, whxy); GLint depth = programObject->getDxDepthLocation(); - GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f}; - programObject->setUniform2fv(depth, 1, (GLfloat*)&dz); + GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f}; + programObject->setUniform2fv(depth, 1, dz); - GLint near = programObject->getDepthRangeNearLocation(); - programObject->setUniform1fv(near, 1, &mState.zNear); - - GLint far = programObject->getDepthRangeFarLocation(); - programObject->setUniform1fv(far, 1, &mState.zFar); - - GLint diff = programObject->getDepthRangeDiffLocation(); - GLfloat zDiff = mState.zFar - mState.zNear; - programObject->setUniform1fv(diff, 1, &zDiff); + GLint depthRange = programObject->getDxDepthRangeLocation(); + GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear}; + programObject->setUniform3fv(depthRange, 1, nearFarDiff); } return true; @@ -1830,39 +1890,46 @@ void Context::applyState(GLenum drawMode) mPolygonOffsetStateDirty = false; } - if (framebufferObject->isMultisample() && mSampleStateDirty) + if (mSampleStateDirty) { - if (mState.sampleAlphaToCoverage) + if (framebufferObject->isMultisample()) { - FIXME("Sample alpha to coverage is unimplemented."); - } + if (mState.sampleAlphaToCoverage) + { + FIXME("Sample alpha to coverage is unimplemented."); + } - if (mState.sampleCoverage) - { device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - unsigned int mask = 0; - if (mState.sampleCoverageValue != 0) + if (mState.sampleCoverage) { - float threshold = 0.5f; - - for (int i = 0; i < framebufferObject->getSamples(); ++i) + unsigned int mask = 0; + if (mState.sampleCoverageValue != 0) { - mask <<= 1; + float threshold = 0.5f; - if ((i + 1) * mState.sampleCoverageValue >= threshold) + for (int i = 0; i < framebufferObject->getSamples(); ++i) { - threshold += 1.0f; - mask |= 1; + mask <<= 1; + + if ((i + 1) * mState.sampleCoverageValue >= threshold) + { + threshold += 1.0f; + mask |= 1; + } } } + + if (mState.sampleCoverageInvert) + { + mask = ~mask; + } + + device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask); } - - if (mState.sampleCoverageInvert) + else { - mask = ~mask; + device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); } - - device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask); } else { @@ -1887,18 +1954,18 @@ void Context::lookupAttributeMapping(TranslatedAttribute *attributes) { for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { - if (attributes[i].enabled) + if (attributes[i].active) { attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i); } } } -GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo) +GLenum Context::applyVertexBuffer(GLint first, GLsizei count) { TranslatedAttribute translated[MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->preRenderValidate(first, count, translated); + GLenum err = mVertexDataManager->prepareVertexData(first, count, translated); if (err != GL_NO_ERROR) { return err; @@ -1906,53 +1973,20 @@ GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool lookupAttributeMapping(translated); - mBufferBackEnd->setupAttributesPreDraw(translated); - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].enabled && translated[i].nonArray) - { - err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo); - if (err != GL_NO_ERROR) - { - return err; - } + mVertexDataManager->setupAttributes(translated); - mBufferBackEnd->setupIndicesPreDraw(*indexInfo); - - *useIndexing = true; - return GL_NO_ERROR; - } - } - - *useIndexing = false; return GL_NO_ERROR; } -GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo) -{ - TranslatedAttribute translated[MAX_VERTEX_ATTRIBS]; - - GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated); - - if (err == GL_NO_ERROR) - { - lookupAttributeMapping(translated); - - mBufferBackEnd->setupAttributesPreDraw(translated); - } - - return err; -} - // Applies the indices and element array bindings to the Direct3D 9 device GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) { - GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, mState.elementArrayBuffer.get(), indices, indexInfo); + IDirect3DDevice9 *device = getDevice(); + GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo); if (err == GL_NO_ERROR) { - mBufferBackEnd->setupIndicesPreDraw(*indexInfo); + device->SetIndices(indexInfo->indexBuffer); } return err; @@ -2048,6 +2082,12 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum } IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget(); + + if (!renderTarget) + { + return; // Context must be lost, return silently + } + IDirect3DDevice9 *device = getDevice(); D3DSURFACE_DESC desc; @@ -2141,16 +2181,6 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum r = (rgb & 0xF800) * (1.0f / 0xF800); } break; - case D3DFMT_X1R5G5B5: - { - unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch); - - a = 1.0f; - b = (xrgb & 0x001F) * (1.0f / 0x001F); - g = (xrgb & 0x03E0) * (1.0f / 0x03E0); - r = (xrgb & 0x7C00) * (1.0f / 0x7C00); - } - break; case D3DFMT_A1R5G5B5: { unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch); @@ -2191,6 +2221,28 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); } break; + case D3DFMT_A32B32G32R32F: + { + // float formats in D3D are stored rgba, rather than the other way round + r = *((float*)(source + 16 * i + j * lock.Pitch) + 0); + g = *((float*)(source + 16 * i + j * lock.Pitch) + 1); + b = *((float*)(source + 16 * i + j * lock.Pitch) + 2); + a = *((float*)(source + 16 * i + j * lock.Pitch) + 3); + } + break; + case D3DFMT_A16B16G16R16F: + { + // float formats in D3D are stored rgba, rather than the other way round + float abgr[4]; + + D3DXFloat16To32Array(abgr, (D3DXFLOAT16*)(source + 8 * i + j * lock.Pitch), 4); + + a = abgr[3]; + b = abgr[2]; + g = abgr[1]; + r = abgr[0]; + } + break; default: UNIMPLEMENTED(); // FIXME UNREACHABLE(); @@ -2314,6 +2366,12 @@ void Context::clear(GLbitfield mask) if (framebufferObject->getStencilbufferType() != GL_NONE) { IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + return; + } + D3DSURFACE_DESC desc; depthStencil->GetDesc(&desc); @@ -2346,6 +2404,11 @@ void Context::clear(GLbitfield mask) IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget(); + if (!renderTarget) + { + return; // Context must be lost, return silently + } + D3DSURFACE_DESC desc; renderTarget->GetDesc(&desc); @@ -2381,7 +2444,7 @@ void Context::clear(GLbitfield mask) device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - device->SetStreamSourceFreq(0, 1); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); hr = device->EndStateBlock(&mMaskedClearSavedState); ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); @@ -2436,7 +2499,7 @@ void Context::clear(GLbitfield mask) device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - device->SetStreamSourceFreq(0, 1); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); struct Vertex { @@ -2517,9 +2580,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count) applyState(mode); - TranslatedIndexData indexInfo; - bool useIndexing; - GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo); + GLenum err = applyVertexBuffer(first, count); if (err != GL_NO_ERROR) { return error(err); @@ -2536,18 +2597,17 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count) if (!cullSkipsDraw(mode)) { display->startScene(); - if (useIndexing) - { - device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount); - } - else + + device->DrawPrimitive(primitiveType, 0, primitiveCount); + + if (mode == GL_LINE_LOOP) // Draw the last segment separately { - device->DrawPrimitive(primitiveType, 0, primitiveCount); + drawClosingLine(first, first + count - 1); } } } -void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) +void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) { if (!mState.currentProgram) { @@ -2586,7 +2646,8 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* return error(err); } - err = applyVertexBuffer(indexInfo); + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; + err = applyVertexBuffer(indexInfo.minIndex, vertexCount); if (err != GL_NO_ERROR) { return error(err); @@ -2603,7 +2664,13 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* if (!cullSkipsDraw(mode)) { display->startScene(); - device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount); + + device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount); + + if (mode == GL_LINE_LOOP) // Draw the last segment separately + { + drawClosingLine(count, type, indices); + } } } @@ -2631,7 +2698,6 @@ void Context::finish() ASSERT(SUCCEEDED(result)); // Render something outside the render target - device->SetStreamSourceFreq(0, 1); device->SetPixelShader(NULL); device->SetVertexShader(NULL); device->SetFVF(D3DFVF_XYZRHW); @@ -2687,6 +2753,93 @@ void Context::flush() } } +void Context::drawClosingLine(unsigned int first, unsigned int last) +{ + IDirect3DDevice9 *device = getDevice(); + IDirect3DIndexBuffer9 *indexBuffer = NULL; + HRESULT result = D3DERR_INVALIDCALL; + + if (supports32bitIndices()) + { + result = device->CreateIndexBuffer(8, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &indexBuffer, 0); + + if (SUCCEEDED(result)) + { + unsigned int *data; + result = indexBuffer->Lock(0, 0, (void**)&data, 0); + + if (SUCCEEDED(result)) + { + data[0] = last; + data[1] = first; + } + } + } + else + { + result = device->CreateIndexBuffer(4, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, 0); + + if (SUCCEEDED(result)) + { + unsigned short *data; + result = indexBuffer->Lock(0, 0, (void**)&data, 0); + + if (SUCCEEDED(result)) + { + data[0] = last; + data[1] = first; + } + } + } + + if (SUCCEEDED(result)) + { + indexBuffer->Unlock(); + device->SetIndices(indexBuffer); + + device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 2, 0, 1); + + indexBuffer->Release(); + } + else + { + ERR("Could not create an index buffer for closing a line loop."); + error(GL_OUT_OF_MEMORY); + } +} + +void Context::drawClosingLine(GLsizei count, GLenum type, const void *indices) +{ + unsigned int first = 0; + unsigned int last = 0; + + if (mState.elementArrayBuffer.get()) + { + Buffer *indexBuffer = mState.elementArrayBuffer.get(); + intptr_t offset = reinterpret_cast<intptr_t>(indices); + indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: + first = static_cast<const GLubyte*>(indices)[0]; + last = static_cast<const GLubyte*>(indices)[count - 1]; + break; + case GL_UNSIGNED_SHORT: + first = static_cast<const GLushort*>(indices)[0]; + last = static_cast<const GLushort*>(indices)[count - 1]; + break; + case GL_UNSIGNED_INT: + first = static_cast<const GLuint*>(indices)[0]; + last = static_cast<const GLuint*>(indices)[count - 1]; + break; + default: UNREACHABLE(); + } + + drawClosingLine(first, last); +} + void Context::recordInvalidEnum() { mInvalidEnum = true; @@ -2759,6 +2912,16 @@ bool Context::supportsShaderModel3() const return mSupportsShaderModel3; } +int Context::getMaximumVaryingVectors() const +{ + return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; +} + +int Context::getMaximumFragmentUniformVectors() const +{ + return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2; +} + int Context::getMaxSupportedSamples() const { return mMaxSupportedSamples; @@ -2788,11 +2951,81 @@ int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const return -1; } +bool Context::supportsEventQueries() const +{ + return mSupportsEventQueries; +} + bool Context::supportsCompressedTextures() const { return mSupportsCompressedTextures; } +bool Context::supportsFloatTextures() const +{ + return mSupportsFloatTextures; +} + +bool Context::supportsFloatLinearFilter() const +{ + return mSupportsFloatLinearFilter; +} + +bool Context::supportsFloatRenderableTextures() const +{ + return mSupportsFloatRenderableTextures; +} + +bool Context::supportsHalfFloatTextures() const +{ + return mSupportsHalfFloatTextures; +} + +bool Context::supportsHalfFloatLinearFilter() const +{ + return mSupportsHalfFloatLinearFilter; +} + +bool Context::supportsHalfFloatRenderableTextures() const +{ + return mSupportsHalfFloatRenderableTextures; +} + +int Context::getMaximumRenderbufferDimension() const +{ + return mMaxRenderbufferDimension; +} + +int Context::getMaximumTextureDimension() const +{ + return mMaxTextureDimension; +} + +int Context::getMaximumCubeTextureDimension() const +{ + return mMaxCubeTextureDimension; +} + +int Context::getMaximumTextureLevel() const +{ + return mMaxTextureLevel; +} + +bool Context::supportsLuminanceTextures() const +{ + return mSupportsLuminanceTextures; +} + +bool Context::supportsLuminanceAlphaTextures() const +{ + return mSupportsLuminanceAlphaTextures; +} + +bool Context::supports32bitIndices() const +{ + return mSupports32bitIndices; +} + void Context::detachBuffer(GLuint buffer) { // [OpenGL ES 2.0.24] section 2.9 page 22: @@ -2903,7 +3136,7 @@ void Context::detachRenderbuffer(GLuint renderbuffer) Texture *Context::getIncompleteTexture(SamplerType type) { - Texture *t = mIncompleteTextures[type]; + Texture *t = mIncompleteTextures[type].get(); if (t == NULL) { @@ -2939,7 +3172,7 @@ Texture *Context::getIncompleteTexture(SamplerType type) break; } - mIncompleteTextures[type] = t; + mIncompleteTextures[type].set(t); } return t; @@ -2978,7 +3211,7 @@ void Context::setVertexAttrib(GLuint index, const GLfloat *values) mState.vertexAttribute[index].mCurrentValue[2] = values[2]; mState.vertexAttribute[index].mCurrentValue[3] = values[3]; - mVertexDataManager->dirtyCurrentValues(); + mVertexDataManager->dirtyCurrentValue(index); } void Context::initExtensionString() @@ -2988,18 +3221,44 @@ void Context::initExtensionString() mExtensionString += "GL_EXT_read_format_bgra "; mExtensionString += "GL_ANGLE_framebuffer_blit "; mExtensionString += "GL_OES_rgb8_rgba8 "; + mExtensionString += "GL_OES_standard_derivatives "; + + if (supportsEventQueries()) + { + mExtensionString += "GL_NV_fence "; + } if (supportsCompressedTextures()) { mExtensionString += "GL_EXT_texture_compression_dxt1 "; } + if (supportsFloatTextures()) + { + mExtensionString += "GL_OES_texture_float "; + } + + if (supportsHalfFloatTextures()) + { + mExtensionString += "GL_OES_texture_half_float "; + } + + if (supportsFloatLinearFilter()) + { + mExtensionString += "GL_OES_texture_float_linear "; + } + + if (supportsHalfFloatLinearFilter()) + { + mExtensionString += "GL_OES_texture_half_float_linear "; + } + if (getMaxSupportedSamples() != 0) { mExtensionString += "GL_ANGLE_framebuffer_multisample "; } - if (mBufferBackEnd->supportIntIndices()) + if (supports32bitIndices()) { mExtensionString += "GL_OES_element_index_uint "; } @@ -3178,10 +3437,10 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 } bool partialBufferCopy = false; - if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readFramebuffer->getColorbuffer()->getHeight() || - sourceTrimmedRect.right - sourceTrimmedRect.left < readFramebuffer->getColorbuffer()->getWidth() || - destTrimmedRect.bottom - destTrimmedRect.top < drawFramebuffer->getColorbuffer()->getHeight() || - destTrimmedRect.right - destTrimmedRect.left < drawFramebuffer->getColorbuffer()->getWidth() || + if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight || + sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth || + destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight || + destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth || sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0) { partialBufferCopy = true; @@ -3189,7 +3448,11 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (mask & GL_COLOR_BUFFER_BIT) { - if (readFramebuffer->getColorbufferType() != drawFramebuffer->getColorbufferType() || + const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D || + readFramebuffer->getColorbufferType() == GL_RENDERBUFFER; + const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D || + drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER; + if (!validReadType || !validDrawType || readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat()) { ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation"); |