summaryrefslogtreecommitdiffstats
path: root/Source/ThirdParty/ANGLE/src/libGLESv2
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ThirdParty/ANGLE/src/libGLESv2')
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp57
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h4
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp65
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h14
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp1926
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Context.h217
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp26
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h8
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp108
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h11
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.cpp63
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.h45
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.cpp473
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.h149
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp1427
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Program.h95
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Query.cpp128
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Query.h48
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp440
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h176
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp46
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h34
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp177
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h45
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp2963
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h452
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.cpp782
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.h169
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp1828
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def19
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.rc102
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj258
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp43
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/main.h3
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h55
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/resource.h14
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp398
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h47
-rw-r--r--Source/ThirdParty/ANGLE/src/libGLESv2/vertexconversion.h208
39 files changed, 9161 insertions, 3962 deletions
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp
index 43ed8a0..a248d69 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.cpp
@@ -155,16 +155,23 @@ void Blit::initGeometry()
IDirect3DDevice9 *device = getDevice();
- HRESULT hr = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
+ HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
- if (FAILED(hr))
+ if (FAILED(result))
{
- ASSERT(hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ void *lockPtr = NULL;
+ result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
+
+ if (FAILED(result) || lockPtr == NULL)
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return error(GL_OUT_OF_MEMORY);
}
- void *lockPtr;
- mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
memcpy(lockPtr, quad, sizeof(quad));
mQuadVertexBuffer->Unlock();
@@ -174,10 +181,11 @@ void Blit::initGeometry()
D3DDECL_END()
};
- hr = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
- if (FAILED(hr))
+ result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
+
+ if (FAILED(result))
{
- ASSERT(hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
return error(GL_OUT_OF_MEMORY);
}
}
@@ -287,6 +295,34 @@ bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
return true;
}
+bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+{
+ IDirect3DDevice9 *device = getDevice();
+
+ D3DSURFACE_DESC sourceDesc;
+ D3DSURFACE_DESC destDesc;
+ source->GetDesc(&sourceDesc);
+ dest->GetDesc(&destDesc);
+
+ if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET) // Can use StretchRect
+ {
+ RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
+ HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY, false);
+ }
+ }
+ else
+ {
+ return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
+ }
+
+ return true;
+}
+
bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
{
IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
@@ -468,6 +504,11 @@ void Blit::setCommonBlitState()
RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
device->SetScissorRect(&scissorRect);
+
+ for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ device->SetStreamSourceFreq(i, 1);
+ }
}
void Blit::render()
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h
index a83aac3..8928ecd 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Blit.h
@@ -30,6 +30,10 @@ class Blit
// Copy from source surface to dest surface.
// sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+ bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+
+ // Copy from source surface to dest surface.
+ // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
// source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp
index 17cea6c..dd12e3c 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.cpp
@@ -11,8 +11,8 @@
#include "libGLESv2/Buffer.h"
#include "libGLESv2/main.h"
-#include "libGLESv2/geometry/VertexDataManager.h"
-#include "libGLESv2/geometry/IndexDataManager.h"
+#include "libGLESv2/VertexDataManager.h"
+#include "libGLESv2/IndexDataManager.h"
namespace gl
{
@@ -23,15 +23,16 @@ Buffer::Buffer(GLuint id) : RefCountObject(id)
mSize = 0;
mUsage = GL_DYNAMIC_DRAW;
- mVertexBuffer = NULL;
- mIndexBuffer = NULL;
+ mStaticVertexBuffer = NULL;
+ mStaticIndexBuffer = NULL;
+ mUnmodifiedDataUse = 0;
}
Buffer::~Buffer()
{
delete[] mContents;
- delete mVertexBuffer;
- delete mIndexBuffer;
+ delete mStaticVertexBuffer;
+ delete mStaticIndexBuffer;
}
void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
@@ -60,47 +61,57 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
if (usage == GL_STATIC_DRAW)
{
- mVertexBuffer = new StaticVertexBuffer(getDevice());
- mIndexBuffer = new StaticIndexBuffer(getDevice());
+ mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
+ mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
}
}
void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
memcpy(mContents + offset, data, size);
-
- if ((mVertexBuffer && mVertexBuffer->size() != 0) || (mIndexBuffer && mIndexBuffer->size() != 0))
+
+ if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0))
{
invalidateStaticData();
-
- if (mUsage == GL_STATIC_DRAW)
- {
- // If applications update the buffer data after it has already been used in a draw call,
- // it most likely isn't used as a static buffer so we should fall back to streaming usage
- // for best performance. So ignore the usage hint and don't create new static buffers.
- // mVertexBuffer = new StaticVertexBuffer(getDevice());
- // mIndexBuffer = new StaticIndexBuffer(getDevice());
- }
}
+
+ mUnmodifiedDataUse = 0;
}
-StaticVertexBuffer *Buffer::getVertexBuffer()
+StaticVertexBuffer *Buffer::getStaticVertexBuffer()
{
- return mVertexBuffer;
+ return mStaticVertexBuffer;
}
-StaticIndexBuffer *Buffer::getIndexBuffer()
+StaticIndexBuffer *Buffer::getStaticIndexBuffer()
{
- return mIndexBuffer;
+ return mStaticIndexBuffer;
}
void Buffer::invalidateStaticData()
{
- delete mVertexBuffer;
- mVertexBuffer = NULL;
+ delete mStaticVertexBuffer;
+ mStaticVertexBuffer = NULL;
+
+ delete mStaticIndexBuffer;
+ mStaticIndexBuffer = NULL;
+
+ mUnmodifiedDataUse = 0;
+}
+
+// Creates static buffers if sufficient used data has been left unmodified
+void Buffer::promoteStaticUsage(int dataSize)
+{
+ if (!mStaticVertexBuffer && !mStaticIndexBuffer)
+ {
+ mUnmodifiedDataUse += dataSize;
- delete mIndexBuffer;
- mIndexBuffer = NULL;
+ if (mUnmodifiedDataUse > 3 * mSize)
+ {
+ mStaticVertexBuffer = new StaticVertexBuffer(getDevice());
+ mStaticIndexBuffer = new StaticIndexBuffer(getDevice());
+ }
+ }
}
}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h
index c2ed60f..7019c4e 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Buffer.h
@@ -18,7 +18,7 @@
#include <GLES2/gl2.h>
#include "common/angleutils.h"
-#include "libGLESv2/RefCountObject.h"
+#include "common/RefCountObject.h"
namespace gl
{
@@ -39,19 +39,21 @@ class Buffer : public RefCountObject
size_t size() const { return mSize; }
GLenum usage() const { return mUsage; }
- StaticVertexBuffer *getVertexBuffer();
- StaticIndexBuffer *getIndexBuffer();
+ StaticVertexBuffer *getStaticVertexBuffer();
+ StaticIndexBuffer *getStaticIndexBuffer();
void invalidateStaticData();
+ void promoteStaticUsage(int dataSize);
private:
DISALLOW_COPY_AND_ASSIGN(Buffer);
GLubyte *mContents;
- size_t mSize;
+ GLsizeiptr mSize;
GLenum mUsage;
- StaticVertexBuffer *mVertexBuffer;
- StaticIndexBuffer *mIndexBuffer;
+ StaticVertexBuffer *mStaticVertexBuffer;
+ StaticIndexBuffer *mStaticIndexBuffer;
+ GLsizeiptr mUnmodifiedDataUse;
};
}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp
index 9be59c4..66cd5c0 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -22,20 +22,27 @@
#include "libGLESv2/Fence.h"
#include "libGLESv2/FrameBuffer.h"
#include "libGLESv2/Program.h"
+#include "libGLESv2/Query.h"
#include "libGLESv2/RenderBuffer.h"
#include "libGLESv2/Shader.h"
#include "libGLESv2/Texture.h"
-#include "libGLESv2/geometry/VertexDataManager.h"
-#include "libGLESv2/geometry/IndexDataManager.h"
+#include "libGLESv2/VertexDataManager.h"
+#include "libGLESv2/IndexDataManager.h"
#undef near
#undef far
namespace gl
{
-Context::Context(const egl::Config *config, const gl::Context *shareContext)
- : mConfig(config)
+Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config)
{
+ ASSERT(robustAccess == false); // Unimplemented
+
+ mDisplay = NULL;
+ mDevice = NULL;
+
+ mFenceHandleAllocator.setBaseHandle(0);
+
setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mState.depthClearValue = 1.0f;
@@ -136,10 +143,12 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext)
mState.packAlignment = 4;
mState.unpackAlignment = 4;
+ mState.packReverseRowOrder = false;
mVertexDataManager = NULL;
mIndexDataManager = NULL;
mBlit = NULL;
+ mLineLoopIB = NULL;
mInvalidEnum = false;
mInvalidValue = false;
@@ -148,9 +157,17 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext)
mInvalidFramebufferOperation = false;
mHasBeenCurrent = false;
-
- mSupportsCompressedTextures = false;
+ mContextLost = false;
+ mResetStatus = GL_NO_ERROR;
+ mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
+ mRobustAccess = robustAccess;
+
+ mSupportsDXT1Textures = false;
+ mSupportsDXT3Textures = false;
+ mSupportsDXT5Textures = false;
mSupportsEventQueries = false;
+ mSupportsOcclusionQueries = false;
+ mNumCompressedTextureFormats = 0;
mMaxSupportedSamples = 0;
mMaskedClearSavedState = NULL;
markAllStateDirty();
@@ -178,21 +195,26 @@ Context::~Context()
deleteFence(mFenceMap.begin()->first);
}
+ while (!mQueryMap.empty())
+ {
+ deleteQuery(mQueryMap.begin()->first);
+ }
+
while (!mMultiSampleSupport.empty())
{
delete [] mMultiSampleSupport.begin()->second;
mMultiSampleSupport.erase(mMultiSampleSupport.begin());
}
- for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
+ for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
{
- for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+ for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
{
mState.samplerTexture[type][sampler].set(NULL);
}
}
- for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
+ for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
{
mIncompleteTextures[type].set(NULL);
}
@@ -202,6 +224,11 @@ Context::~Context()
mState.vertexAttribute[i].mBoundBuffer.set(NULL);
}
+ for (int i = 0; i < QUERY_TYPE_COUNT; i++)
+ {
+ mState.activeQuery[i].set(NULL);
+ }
+
mState.arrayBuffer.set(NULL);
mState.elementArrayBuffer.set(NULL);
mState.renderbuffer.set(NULL);
@@ -212,6 +239,7 @@ Context::~Context()
delete mVertexDataManager;
delete mIndexDataManager;
delete mBlit;
+ delete mLineLoopIB;
if (mMaskedClearSavedState)
{
@@ -223,17 +251,21 @@ Context::~Context()
void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
{
- IDirect3DDevice9 *device = display->getDevice();
+ mDisplay = display;
+ mDevice = mDisplay->getDevice();
if (!mHasBeenCurrent)
{
- mDeviceCaps = display->getDeviceCaps();
+ mDeviceCaps = mDisplay->getDeviceCaps();
- mVertexDataManager = new VertexDataManager(this, device);
- mIndexDataManager = new IndexDataManager(this, device);
+ mVertexDataManager = new VertexDataManager(this, mDevice);
+ mIndexDataManager = new IndexDataManager(this, mDevice);
mBlit = new Blit(this);
- mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
+ mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+ mSupportsVertexTexture = mDisplay->getVertexTextureSupport();
+ mSupportsNonPower2Texture = mDisplay->getNonPower2TextureSupport();
+ mSupportsInstancing = mDisplay->getInstancingSupport();
mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight),
(int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
@@ -255,7 +287,7 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
for (int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i)
{
bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
- display->getMultiSampleSupport(renderBufferFormats[i], multisampleArray);
+ mDisplay->getMultiSampleSupport(renderBufferFormats[i], multisampleArray);
mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray;
for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
@@ -269,16 +301,34 @@ 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();
+ mSupportsEventQueries = mDisplay->getEventQuerySupport();
+ mSupportsOcclusionQueries = mDisplay->getOcclusionQuerySupport();
+ mSupportsDXT1Textures = mDisplay->getDXT1TextureSupport();
+ mSupportsDXT3Textures = mDisplay->getDXT3TextureSupport();
+ mSupportsDXT5Textures = mDisplay->getDXT5TextureSupport();
+ mSupportsFloat32Textures = mDisplay->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures);
+ mSupportsFloat16Textures = mDisplay->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures);
+ mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport();
+ mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport();
mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
+ mNumCompressedTextureFormats = 0;
+ if (supportsDXT1Textures())
+ {
+ mNumCompressedTextureFormats += 2;
+ }
+ if (supportsDXT3Textures())
+ {
+ mNumCompressedTextureFormats += 1;
+ }
+ if (supportsDXT5Textures())
+ {
+ mNumCompressedTextureFormats += 1;
+ }
+
initExtensionString();
+ initRendererString();
mState.viewportX = 0;
mState.viewportY = 0;
@@ -319,11 +369,26 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
void Context::markAllStateDirty()
{
+ for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++)
+ {
+ mAppliedTextureSerialPS[t] = 0;
+ }
+
+ for (int t = 0; t < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; t++)
+ {
+ mAppliedTextureSerialVS[t] = 0;
+ }
+
+ mAppliedProgramSerial = 0;
mAppliedRenderTargetSerial = 0;
mAppliedDepthbufferSerial = 0;
mAppliedStencilbufferSerial = 0;
+ mAppliedIBSerial = 0;
mDepthStencilInitialized = false;
- mAppliedProgram = 0;
+ mViewportInitialized = false;
+ mRenderTargetDescInitialized = false;
+
+ mVertexDeclarationCache.markStateDirty();
mClearStateDirty = true;
mCullStateDirty = true;
@@ -336,6 +401,20 @@ void Context::markAllStateDirty()
mSampleStateDirty = true;
mDitherStateDirty = true;
mFrontFaceDirty = true;
+ mDxUniformsDirty = true;
+ mCachedCurrentProgram = NULL;
+}
+
+void Context::markContextLost()
+{
+ if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
+ mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
+ mContextLost = true;
+}
+
+bool Context::isContextLost()
+{
+ return mContextLost;
}
void Context::setClearColor(float red, float green, float blue, float alpha)
@@ -710,7 +789,7 @@ void Context::setDepthMask(bool mask)
}
}
-void Context::setActiveSampler(int active)
+void Context::setActiveSampler(unsigned int active)
{
mState.activeSampler = active;
}
@@ -735,6 +814,32 @@ GLuint Context::getArrayBufferHandle() const
return mState.arrayBuffer.id();
}
+GLuint Context::getActiveQuery(GLenum target) const
+{
+ Query *queryObject = NULL;
+
+ switch (target)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
+ break;
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
+ break;
+ default:
+ ASSERT(false);
+ }
+
+ if (queryObject)
+ {
+ return queryObject->id();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
{
mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
@@ -786,6 +891,16 @@ GLint Context::getUnpackAlignment() const
return mState.unpackAlignment;
}
+void Context::setPackReverseRowOrder(bool reverseRowOrder)
+{
+ mState.packReverseRowOrder = reverseRowOrder;
+}
+
+bool Context::getPackReverseRowOrder() const
+{
+ return mState.packReverseRowOrder;
+}
+
GLuint Context::createBuffer()
{
return mResourceManager->createBuffer();
@@ -814,12 +929,7 @@ GLuint Context::createRenderbuffer()
// Returns an unused framebuffer name
GLuint Context::createFramebuffer()
{
- unsigned int handle = 1;
-
- while (mFramebufferMap.find(handle) != mFramebufferMap.end())
- {
- handle++;
- }
+ GLuint handle = mFramebufferHandleAllocator.allocate();
mFramebufferMap[handle] = NULL;
@@ -828,14 +938,19 @@ GLuint Context::createFramebuffer()
GLuint Context::createFence()
{
- unsigned int handle = 0;
+ GLuint handle = mFenceHandleAllocator.allocate();
- while (mFenceMap.find(handle) != mFenceMap.end())
- {
- handle++;
- }
+ mFenceMap[handle] = new Fence(mDisplay);
- mFenceMap[handle] = new Fence;
+ return handle;
+}
+
+// Returns an unused query name
+GLuint Context::createQuery()
+{
+ GLuint handle = mQueryHandleAllocator.allocate();
+
+ mQueryMap[handle] = NULL;
return handle;
}
@@ -858,6 +973,7 @@ void Context::deleteShader(GLuint shader)
void Context::deleteProgram(GLuint program)
{
mResourceManager->deleteProgram(program);
+ mCachedCurrentProgram = NULL;
}
void Context::deleteTexture(GLuint texture)
@@ -888,6 +1004,7 @@ void Context::deleteFramebuffer(GLuint framebuffer)
{
detachFramebuffer(framebuffer);
+ mFramebufferHandleAllocator.release(framebufferObject->first);
delete framebufferObject->second;
mFramebufferMap.erase(framebufferObject);
}
@@ -899,11 +1016,26 @@ void Context::deleteFence(GLuint fence)
if (fenceObject != mFenceMap.end())
{
+ mFenceHandleAllocator.release(fenceObject->first);
delete fenceObject->second;
mFenceMap.erase(fenceObject);
}
}
+void Context::deleteQuery(GLuint query)
+{
+ QueryMap::iterator queryObject = mQueryMap.find(query);
+ if (queryObject != mQueryMap.end())
+ {
+ mQueryHandleAllocator.release(queryObject->first);
+ if (queryObject->second)
+ {
+ queryObject->second->release();
+ }
+ mQueryMap.erase(queryObject);
+ }
+}
+
Buffer *Context::getBuffer(GLuint handle)
{
return mResourceManager->getBuffer(handle);
@@ -936,7 +1068,7 @@ Framebuffer *Context::getReadFramebuffer()
Framebuffer *Context::getDrawFramebuffer()
{
- return getFramebuffer(mState.drawFramebuffer);
+ return mBoundDrawFramebuffer;
}
void Context::bindArrayBuffer(unsigned int buffer)
@@ -955,16 +1087,16 @@ void Context::bindElementArrayBuffer(unsigned int buffer)
void Context::bindTexture2D(GLuint texture)
{
- mResourceManager->checkTextureAllocation(texture, SAMPLER_2D);
+ mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
- mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(getTexture(texture));
+ mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
}
void Context::bindTextureCubeMap(GLuint texture)
{
- mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE);
+ mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
- mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(getTexture(texture));
+ mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
}
void Context::bindReadFramebuffer(GLuint framebuffer)
@@ -985,6 +1117,8 @@ void Context::bindDrawFramebuffer(GLuint framebuffer)
}
mState.drawFramebuffer = framebuffer;
+
+ mBoundDrawFramebuffer = getFramebuffer(framebuffer);
}
void Context::bindRenderbuffer(GLuint renderbuffer)
@@ -1003,6 +1137,8 @@ void Context::useProgram(GLuint program)
{
Program *newProgram = mResourceManager->getProgram(program);
Program *oldProgram = mResourceManager->getProgram(priorProgram);
+ mCachedCurrentProgram = NULL;
+ mDxUniformsDirty = true;
if (newProgram)
{
@@ -1016,10 +1152,103 @@ void Context::useProgram(GLuint program)
}
}
+void Context::beginQuery(GLenum target, GLuint query)
+{
+ // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
+ // of zero, if the active query object name for <target> is non-zero (for the
+ // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
+ // the active query for either target is non-zero), if <id> is the name of an
+ // existing query object whose type does not match <target>, or if <id> is the
+ // active query object name for any query type, the error INVALID_OPERATION is
+ // generated.
+
+ // Ensure no other queries are active
+ // NOTE: If other queries than occlusion are supported, we will need to check
+ // separately that:
+ // a) The query ID passed is not the current active query for any target/type
+ // b) There are no active queries for the requested target (and in the case
+ // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
+ // no query may be active for either if glBeginQuery targets either.
+ for (int i = 0; i < QUERY_TYPE_COUNT; i++)
+ {
+ if (mState.activeQuery[i].get() != NULL)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+
+ QueryType qType;
+ switch (target)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ qType = QUERY_ANY_SAMPLES_PASSED;
+ break;
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
+ break;
+ default:
+ ASSERT(false);
+ return;
+ }
+
+ Query *queryObject = getQuery(query, true, target);
+
+ // check that name was obtained with glGenQueries
+ if (!queryObject)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ // check for type mismatch
+ if (queryObject->getType() != target)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ // set query as active for specified target
+ mState.activeQuery[qType].set(queryObject);
+
+ // begin query
+ queryObject->begin();
+}
+
+void Context::endQuery(GLenum target)
+{
+ QueryType qType;
+
+ switch (target)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ qType = QUERY_ANY_SAMPLES_PASSED;
+ break;
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
+ break;
+ default:
+ ASSERT(false);
+ return;
+ }
+
+ Query *queryObject = mState.activeQuery[qType].get();
+
+ if (queryObject == NULL)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ queryObject->end();
+
+ mState.activeQuery[qType].set(NULL);
+}
+
void Context::setFramebufferZero(Framebuffer *buffer)
{
delete mFramebufferMap[0];
mFramebufferMap[0] = buffer;
+ if (mState.drawFramebuffer == 0)
+ {
+ mBoundDrawFramebuffer = buffer;
+ }
}
void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
@@ -1056,6 +1285,25 @@ Fence *Context::getFence(unsigned int handle)
}
}
+Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
+{
+ QueryMap::iterator query = mQueryMap.find(handle);
+
+ if (query == mQueryMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ if (!query->second && create)
+ {
+ query->second = new Query(handle, type);
+ query->second->addRef();
+ }
+ return query->second;
+ }
+}
+
Buffer *Context::getArrayBuffer()
{
return mState.arrayBuffer.get();
@@ -1068,20 +1316,24 @@ Buffer *Context::getElementArrayBuffer()
Program *Context::getCurrentProgram()
{
- return mResourceManager->getProgram(mState.currentProgram);
+ if (!mCachedCurrentProgram)
+ {
+ mCachedCurrentProgram = mResourceManager->getProgram(mState.currentProgram);
+ }
+ return mCachedCurrentProgram;
}
Texture2D *Context::getTexture2D()
{
- return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, SAMPLER_2D));
+ return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
}
TextureCubeMap *Context::getTextureCubeMap()
{
- return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, SAMPLER_CUBE));
+ return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
}
-Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
+Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
{
GLuint texid = mState.samplerTexture[type][sampler].id();
@@ -1090,8 +1342,8 @@ Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
switch (type)
{
default: UNREACHABLE();
- case SAMPLER_2D: return mTexture2DZero.get();
- case SAMPLER_CUBE: return mTextureCubeMapZero.get();
+ case TEXTURE_2D: return mTexture2DZero.get();
+ case TEXTURE_CUBE: return mTextureCubeMapZero.get();
}
}
@@ -1102,24 +1354,25 @@ bool Context::getBooleanv(GLenum pname, GLboolean *params)
{
switch (pname)
{
- case GL_SHADER_COMPILER: *params = GL_TRUE; break;
- case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
- case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
+ case GL_SHADER_COMPILER: *params = GL_TRUE; break;
+ 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.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;
+ 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;
+ case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
default:
return false;
}
@@ -1183,8 +1436,8 @@ 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 = 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_COMBINED_TEXTURE_IMAGE_UNITS: *params = getMaximumCombinedTextureImageUnits(); break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = getMaximumVertexTextureImageUnits(); break;
case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break;
case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break;
@@ -1198,6 +1451,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
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_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mState.packReverseRowOrder; 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;
@@ -1228,18 +1482,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
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())
- {
- // at current, only GL_COMPRESSED_RGB_S3TC_DXT1_EXT and
- // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT are supported
- *params = 2;
- }
- else
- {
- *params = 0;
- }
- }
+ params[0] = mNumCompressedTextureFormats;
break;
case GL_MAX_SAMPLES_ANGLE:
{
@@ -1295,10 +1538,18 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
break;
case GL_COMPRESSED_TEXTURE_FORMATS:
{
- if (supportsCompressedTextures())
+ if (supportsDXT1Textures())
+ {
+ *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ }
+ if (supportsDXT3Textures())
+ {
+ *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ }
+ if (supportsDXT5Textures())
{
- params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
- params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
}
}
break;
@@ -1322,7 +1573,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
case GL_ALPHA_BITS:
{
gl::Framebuffer *framebuffer = getDrawFramebuffer();
- gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
+ gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
if (colorbuffer)
{
@@ -1343,7 +1594,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
case GL_DEPTH_BITS:
{
gl::Framebuffer *framebuffer = getDrawFramebuffer();
- gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
+ gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
if (depthbuffer)
{
@@ -1358,7 +1609,7 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
case GL_STENCIL_BITS:
{
gl::Framebuffer *framebuffer = getDrawFramebuffer();
- gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
+ gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
if (stencilbuffer)
{
@@ -1372,26 +1623,29 @@ bool Context::getIntegerv(GLenum pname, GLint *params)
break;
case GL_TEXTURE_BINDING_2D:
{
- if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+ if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
{
error(GL_INVALID_OPERATION);
return false;
}
- *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler].id();
+ *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
}
break;
case GL_TEXTURE_BINDING_CUBE_MAP:
{
- if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+ if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
{
error(GL_INVALID_OPERATION);
return false;
}
- *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].id();
+ *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
}
break;
+ case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+ *params = mResetStrategy;
+ break;
default:
return false;
}
@@ -1410,7 +1664,12 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
// application.
switch (pname)
{
- case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
+ case GL_COMPRESSED_TEXTURE_FORMATS:
+ {
+ *type = GL_INT;
+ *numParams = mNumCompressedTextureFormats;
+ }
+ break;
case GL_SHADER_BINARY_FORMATS:
{
*type = GL_INT;
@@ -1432,6 +1691,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_RENDERBUFFER_BINDING:
case GL_CURRENT_PROGRAM:
case GL_PACK_ALIGNMENT:
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
case GL_UNPACK_ALIGNMENT:
case GL_GENERATE_MIPMAP_HINT:
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
@@ -1476,6 +1736,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
case GL_TEXTURE_BINDING_2D:
case GL_TEXTURE_BINDING_CUBE_MAP:
+ case GL_RESET_NOTIFICATION_STRATEGY_EXT:
{
*type = GL_INT;
*numParams = 1;
@@ -1519,6 +1780,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
case GL_DEPTH_TEST:
case GL_BLEND:
case GL_DITHER:
+ case GL_CONTEXT_ROBUST_ACCESS_EXT:
{
*type = GL_BOOL;
*numParams = 1;
@@ -1566,34 +1828,30 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
// scissor rectangle to the Direct3D 9 device
bool Context::applyRenderTarget(bool ignoreViewport)
{
- IDirect3DDevice9 *device = getDevice();
-
Framebuffer *framebufferObject = getDrawFramebuffer();
if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
- error(GL_INVALID_FRAMEBUFFER_OPERATION);
-
- return false;
+ return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
}
- IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
-
- if (!renderTarget)
- {
- return false; // Context must be lost
- }
-
- IDirect3DSurface9 *depthStencil = NULL;
-
+ bool renderTargetChanged = false;
unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
if (renderTargetSerial != mAppliedRenderTargetSerial)
{
- device->SetRenderTarget(0, renderTarget);
+ IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
+ if (!renderTarget)
+ {
+ return false; // Context must be lost
+ }
+ mDevice->SetRenderTarget(0, renderTarget);
mAppliedRenderTargetSerial = renderTargetSerial;
mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets.
+ renderTargetChanged = true;
+ renderTarget->Release();
}
+ IDirect3DSurface9 *depthStencil = NULL;
unsigned int depthbufferSerial = 0;
unsigned int stencilbufferSerial = 0;
if (framebufferObject->getDepthbufferType() != GL_NONE)
@@ -1623,15 +1881,25 @@ bool Context::applyRenderTarget(bool ignoreViewport)
stencilbufferSerial != mAppliedStencilbufferSerial ||
!mDepthStencilInitialized)
{
- device->SetDepthStencilSurface(depthStencil);
+ mDevice->SetDepthStencilSurface(depthStencil);
mAppliedDepthbufferSerial = depthbufferSerial;
mAppliedStencilbufferSerial = stencilbufferSerial;
mDepthStencilInitialized = true;
}
+ if (!mRenderTargetDescInitialized || renderTargetChanged)
+ {
+ IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
+ if (!renderTarget)
+ {
+ return false; // Context must be lost
+ }
+ renderTarget->GetDesc(&mRenderTargetDesc);
+ mRenderTargetDescInitialized = true;
+ renderTarget->Release();
+ }
+
D3DVIEWPORT9 viewport;
- D3DSURFACE_DESC desc;
- renderTarget->GetDesc(&desc);
float zNear = clamp01(mState.zNear);
float zFar = clamp01(mState.zFar);
@@ -1640,17 +1908,18 @@ bool Context::applyRenderTarget(bool ignoreViewport)
{
viewport.X = 0;
viewport.Y = 0;
- viewport.Width = desc.Width;
- viewport.Height = desc.Height;
+ viewport.Width = mRenderTargetDesc.Width;
+ viewport.Height = mRenderTargetDesc.Height;
viewport.MinZ = 0.0f;
viewport.MaxZ = 1.0f;
}
else
{
- viewport.X = std::max(mState.viewportX, 0);
- 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);
+ RECT rect = transformPixelRect(mState.viewportX, mState.viewportY, mState.viewportWidth, mState.viewportHeight, mRenderTargetDesc.Height);
+ viewport.X = clamp(rect.left, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
+ viewport.Y = clamp(rect.top, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
+ viewport.Width = clamp(rect.right - rect.left, 0L, static_cast<LONG>(mRenderTargetDesc.Width) - static_cast<LONG>(viewport.X));
+ viewport.Height = clamp(rect.bottom - rect.top, 0L, static_cast<LONG>(mRenderTargetDesc.Height) - static_cast<LONG>(viewport.Y));
viewport.MinZ = zNear;
viewport.MaxZ = zFar;
}
@@ -1660,42 +1929,49 @@ bool Context::applyRenderTarget(bool ignoreViewport)
return false; // Nothing to render
}
- device->SetViewport(&viewport);
+ if (renderTargetChanged || !mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0)
+ {
+ mDevice->SetViewport(&viewport);
+ mSetViewport = viewport;
+ mViewportInitialized = true;
+ mDxUniformsDirty = true;
+ }
if (mScissorStateDirty)
{
if (mState.scissorTest)
{
- RECT rect = {mState.scissorX,
- mState.scissorY,
- mState.scissorX + mState.scissorWidth,
- mState.scissorY + mState.scissorHeight};
- rect.right = std::min(static_cast<UINT>(rect.right), desc.Width);
- rect.bottom = std::min(static_cast<UINT>(rect.bottom), desc.Height);
- device->SetScissorRect(&rect);
- device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+ RECT rect = transformPixelRect(mState.scissorX, mState.scissorY, mState.scissorWidth, mState.scissorHeight, mRenderTargetDesc.Height);
+ rect.left = clamp(rect.left, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
+ rect.top = clamp(rect.top, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
+ rect.right = clamp(rect.right, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
+ rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
+ mDevice->SetScissorRect(&rect);
+ mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
}
else
{
- device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
}
mScissorStateDirty = false;
}
- if (mState.currentProgram)
+ if (mState.currentProgram && mDxUniformsDirty)
{
Program *programObject = getCurrentProgram();
GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
- GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
+ GLfloat xy[2] = {1.0f / viewport.Width, -1.0f / viewport.Height};
programObject->setUniform2fv(halfPixelSize, 1, xy);
- GLint viewport = programObject->getDxViewportLocation();
- GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
+ // These values are used for computing gl_FragCoord in Program::linkVaryings(). The approach depends on Shader Model 3.0 support.
+ GLint coord = programObject->getDxCoordLocation();
+ float h = mSupportsShaderModel3 ? mRenderTargetDesc.Height : mState.viewportHeight / 2.0f;
+ GLfloat whxy[4] = {mState.viewportWidth / 2.0f, h,
(float)mState.viewportX + mState.viewportWidth / 2.0f,
(float)mState.viewportY + mState.viewportHeight / 2.0f};
- programObject->setUniform4fv(viewport, 1, whxy);
+ programObject->setUniform4fv(coord, 1, whxy);
GLint depth = programObject->getDxDepthLocation();
GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
@@ -1704,6 +1980,7 @@ bool Context::applyRenderTarget(bool ignoreViewport)
GLint depthRange = programObject->getDxDepthRangeLocation();
GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
programObject->setUniform3fv(depthRange, 1, nearFarDiff);
+ mDxUniformsDirty = false;
}
return true;
@@ -1712,28 +1989,37 @@ bool Context::applyRenderTarget(bool ignoreViewport)
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
void Context::applyState(GLenum drawMode)
{
- IDirect3DDevice9 *device = getDevice();
Program *programObject = getCurrentProgram();
+ Framebuffer *framebufferObject = getDrawFramebuffer();
+
+ GLenum adjustedFrontFace = adjustWinding(mState.frontFace);
+
GLint frontCCW = programObject->getDxFrontCCWLocation();
- GLint ccw = (mState.frontFace == GL_CCW);
+ GLint ccw = (adjustedFrontFace == GL_CCW);
programObject->setUniform1iv(frontCCW, 1, &ccw);
GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
GLint alwaysFront = !isTriangleMode(drawMode);
programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
- Framebuffer *framebufferObject = getDrawFramebuffer();
+ D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier();
+ bool zeroColorMaskAllowed = identifier->VendorId != 0x1002;
+ // Apparently some ATI cards have a bug where a draw with a zero color
+ // write mask can cause later draws to have incorrect results. Instead,
+ // set a nonzero color write mask but modify the blend state so that no
+ // drawing is done.
+ // http://code.google.com/p/angleproject/issues/detail?id=169
if (mCullStateDirty || mFrontFaceDirty)
{
if (mState.cullFace)
{
- device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
+ mDevice->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, adjustedFrontFace));
}
else
{
- device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}
mCullStateDirty = false;
@@ -1741,61 +2027,66 @@ void Context::applyState(GLenum drawMode)
if (mDepthStateDirty)
{
- if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
+ if (mState.depthTest)
{
- device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
- device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
+ mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+ mDevice->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
}
else
{
- device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
}
mDepthStateDirty = false;
}
+ if (!zeroColorMaskAllowed && (mMaskStateDirty || mBlendStateDirty))
+ {
+ mBlendStateDirty = true;
+ mMaskStateDirty = true;
+ }
+
if (mBlendStateDirty)
{
if (mState.blend)
{
- device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
{
- device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
+ mDevice->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
}
else
{
- device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
+ mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
unorm<8>(mState.blendColor.alpha),
unorm<8>(mState.blendColor.alpha),
unorm<8>(mState.blendColor.alpha)));
}
- device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
- device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
- device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
+ mDevice->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
+ mDevice->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
+ mDevice->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
mState.destBlendRGB != mState.destBlendAlpha ||
mState.blendEquationRGB != mState.blendEquationAlpha)
{
- device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
-
- device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
- device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
- device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
+ mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
+ mDevice->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
}
else
{
- device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
}
}
else
{
- device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
mBlendStateDirty = false;
@@ -1805,8 +2096,8 @@ void Context::applyState(GLenum drawMode)
{
if (mState.stencilTest && framebufferObject->hasStencil())
{
- device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
- device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
// FIXME: Unsupported by D3D9
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
@@ -1821,50 +2112,65 @@ void Context::applyState(GLenum drawMode)
}
// get the maximum size of the stencil ref
- gl::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
+ gl::Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
- device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
- device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
+ mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
es2dx::ConvertComparison(mState.stencilFunc));
- device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
- device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
+ mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
+ mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
- device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
es2dx::ConvertStencilOp(mState.stencilFail));
- device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
- device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
- device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
- device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
+ mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
es2dx::ConvertComparison(mState.stencilBackFunc));
- device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
- device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
+ mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
+ mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
- device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
es2dx::ConvertStencilOp(mState.stencilBackFail));
- device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
- device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
}
else
{
- device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
}
mStencilStateDirty = false;
+ mFrontFaceDirty = false;
}
if (mMaskStateDirty)
{
- device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
- mState.colorMaskBlue, mState.colorMaskAlpha));
- device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
+ int colorMask = es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
+ mState.colorMaskBlue, mState.colorMaskAlpha);
+ if (colorMask == 0 && !zeroColorMaskAllowed)
+ {
+ // Enable green channel, but set blending so nothing will be drawn.
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+ mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+ mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+ mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
+ }
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
mMaskStateDirty = false;
}
@@ -1873,18 +2179,18 @@ void Context::applyState(GLenum drawMode)
{
if (mState.polygonOffsetFill)
{
- gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
+ gl::Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer();
if (depthbuffer)
{
- device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
+ mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
- device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
+ mDevice->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
}
}
else
{
- device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
- device->SetRenderState(D3DRS_DEPTHBIAS, 0);
+ mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
+ mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
}
mPolygonOffsetStateDirty = false;
@@ -1892,48 +2198,41 @@ void Context::applyState(GLenum drawMode)
if (mSampleStateDirty)
{
- if (framebufferObject->isMultisample())
+ if (mState.sampleAlphaToCoverage)
{
- if (mState.sampleAlphaToCoverage)
- {
- FIXME("Sample alpha to coverage is unimplemented.");
- }
+ FIXME("Sample alpha to coverage is unimplemented.");
+ }
- device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
- if (mState.sampleCoverage)
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
+ if (mState.sampleCoverage)
+ {
+ unsigned int mask = 0;
+ if (mState.sampleCoverageValue != 0)
{
- unsigned int mask = 0;
- if (mState.sampleCoverageValue != 0)
+ float threshold = 0.5f;
+
+ for (int i = 0; i < framebufferObject->getSamples(); ++i)
{
- float threshold = 0.5f;
+ mask <<= 1;
- for (int i = 0; i < framebufferObject->getSamples(); ++i)
+ if ((i + 1) * mState.sampleCoverageValue >= threshold)
{
- mask <<= 1;
-
- if ((i + 1) * mState.sampleCoverageValue >= threshold)
- {
- threshold += 1.0f;
- mask |= 1;
- }
+ threshold += 1.0f;
+ mask |= 1;
}
}
-
- if (mState.sampleCoverageInvert)
- {
- mask = ~mask;
- }
-
- device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
}
- else
+
+ if (mState.sampleCoverageInvert)
{
- device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+ mask = ~mask;
}
+
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
}
else
{
- device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
}
mSampleStateDirty = false;
@@ -1941,52 +2240,37 @@ void Context::applyState(GLenum drawMode)
if (mDitherStateDirty)
{
- device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
+ mDevice->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
mDitherStateDirty = false;
}
-
- mFrontFaceDirty = false;
}
-// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
-void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
+GLenum Context::applyVertexBuffer(GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw)
{
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- if (attributes[i].active)
- {
- attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
- }
- }
-}
+ TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
-GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
-{
- TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
-
- GLenum err = mVertexDataManager->prepareVertexData(first, count, translated);
+ GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes, instances);
if (err != GL_NO_ERROR)
{
return err;
}
- lookupAttributeMapping(translated);
-
- mVertexDataManager->setupAttributes(translated);
-
- return GL_NO_ERROR;
+ return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, getCurrentProgram(), instances, repeatDraw);
}
// 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 Context::applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
{
- IDirect3DDevice9 *device = getDevice();
GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
if (err == GL_NO_ERROR)
{
- device->SetIndices(indexInfo->indexBuffer);
+ if (indexInfo->serial != mAppliedIBSerial)
+ {
+ mDevice->SetIndices(indexInfo->indexBuffer);
+ mAppliedIBSerial = indexInfo->serial;
+ }
}
return err;
@@ -1995,19 +2279,16 @@ GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode
// Applies the shaders and shader constants to the Direct3D 9 device
void Context::applyShaders()
{
- IDirect3DDevice9 *device = getDevice();
Program *programObject = getCurrentProgram();
- IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
- IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
-
- device->SetVertexShader(vertexShader);
- device->SetPixelShader(pixelShader);
-
- if (programObject->getSerial() != mAppliedProgram)
+ if (programObject->getSerial() != mAppliedProgramSerial)
{
+ IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
+ IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
+
+ mDevice->SetPixelShader(pixelShader);
+ mDevice->SetVertexShader(vertexShader);
programObject->dirtyAllUniforms();
- programObject->dirtyAllSamplers();
- mAppliedProgram = programObject->getSerial();
+ mAppliedProgramSerial = programObject->getSerial();
}
programObject->applyUniforms();
@@ -2016,58 +2297,96 @@ void Context::applyShaders()
// Applies the textures and sampler states to the Direct3D 9 device
void Context::applyTextures()
{
- IDirect3DDevice9 *device = getDevice();
+ applyTextures(SAMPLER_PIXEL);
+
+ if (mSupportsVertexTexture)
+ {
+ applyTextures(SAMPLER_VERTEX);
+ }
+}
+
+// For each Direct3D 9 sampler of either the pixel or vertex stage,
+// looks up the corresponding OpenGL texture image unit and texture type,
+// and sets the texture and its addressing/filtering state (or NULL when inactive).
+void Context::applyTextures(SamplerType type)
+{
Program *programObject = getCurrentProgram();
- for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+ int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; // Range of Direct3D 9 samplers of given sampler type
+ unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS;
+ int d3dSamplerOffset = (type == SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+ int samplerRange = programObject->getUsedSamplerRange(type);
+
+ for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
{
- int textureUnit = programObject->getSamplerMapping(sampler);
+ int textureUnit = programObject->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index
+ int d3dSampler = samplerIndex + d3dSamplerOffset;
+
if (textureUnit != -1)
{
- SamplerType textureType = programObject->getSamplerType(sampler);
+ TextureType textureType = programObject->getSamplerTextureType(type, samplerIndex);
Texture *texture = getSamplerTexture(textureUnit, textureType);
- if (programObject->isSamplerDirty(sampler) || texture->isDirty())
+ if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyParameters() || texture->hasDirtyImages())
{
- if (texture->isComplete())
- {
- GLenum wrapS = texture->getWrapS();
- GLenum wrapT = texture->getWrapT();
- GLenum minFilter = texture->getMinFilter();
- GLenum magFilter = texture->getMagFilter();
-
- device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
- device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
+ IDirect3DBaseTexture9 *d3dTexture = texture->getTexture();
- device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
- D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
- es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
- device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
- device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+ if (d3dTexture)
+ {
+ if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyParameters())
+ {
+ GLenum wrapS = texture->getWrapS();
+ GLenum wrapT = texture->getWrapT();
+ GLenum minFilter = texture->getMinFilter();
+ GLenum magFilter = texture->getMagFilter();
+
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
+
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
+ D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
+ es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+ }
- device->SetTexture(sampler, texture->getTexture());
+ if (appliedTextureSerial[samplerIndex] != texture->getTextureSerial() || texture->hasDirtyImages())
+ {
+ mDevice->SetTexture(d3dSampler, d3dTexture);
+ }
}
else
{
- device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
+ mDevice->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture());
}
- }
- programObject->setSamplerDirty(sampler, false);
+ appliedTextureSerial[samplerIndex] = texture->getTextureSerial();
+ texture->resetDirty();
+ }
}
else
{
- if (programObject->isSamplerDirty(sampler))
+ if (appliedTextureSerial[samplerIndex] != 0)
{
- device->SetTexture(sampler, NULL);
- programObject->setSamplerDirty(sampler, false);
+ mDevice->SetTexture(d3dSampler, NULL);
+ appliedTextureSerial[samplerIndex] = 0;
}
- }
+ }
+ }
+
+ for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+ {
+ if (appliedTextureSerial[samplerIndex] != 0)
+ {
+ mDevice->SetTexture(samplerIndex + d3dSamplerOffset, NULL);
+ appliedTextureSerial[samplerIndex] = 0;
+ }
}
}
-void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
+void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
{
Framebuffer *framebuffer = getReadFramebuffer();
@@ -2081,55 +2400,93 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
return error(GL_INVALID_OPERATION);
}
- IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
+ GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
+ // sized query sanity check
+ if (bufSize)
+ {
+ int requiredSize = outputPitch * height;
+ if (requiredSize > *bufSize)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
if (!renderTarget)
{
return; // Context must be lost, return silently
}
- IDirect3DDevice9 *device = getDevice();
-
D3DSURFACE_DESC desc;
renderTarget->GetDesc(&desc);
- IDirect3DSurface9 *systemSurface;
- HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
-
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
{
+ UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
+ renderTarget->Release();
return error(GL_OUT_OF_MEMORY);
}
- ASSERT(SUCCEEDED(result));
+ HRESULT result;
+ IDirect3DSurface9 *systemSurface = NULL;
+ bool directToPixels = getPackReverseRowOrder() && getPackAlignment() <= 4 && mDisplay->isD3d9ExDevice() &&
+ x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
+ desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
+ if (directToPixels)
+ {
+ // Use the pixels ptr as a shared handle to write directly into client's memory
+ result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
+ if (FAILED(result))
+ {
+ // Try again without the shared handle
+ directToPixels = false;
+ }
+ }
- if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+ if (!directToPixels)
{
- UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
+ result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return error(GL_OUT_OF_MEMORY);
+ }
}
- result = device->GetRenderTargetData(renderTarget, systemSurface);
+ result = mDevice->GetRenderTargetData(renderTarget, systemSurface);
+ renderTarget->Release();
+ renderTarget = NULL;
if (FAILED(result))
{
systemSurface->Release();
- switch (result)
+ // It turns out that D3D will sometimes produce more error
+ // codes than those documented.
+ if (checkDeviceLost(result))
+ return error(GL_OUT_OF_MEMORY);
+ else
{
- case D3DERR_DRIVERINTERNALERROR:
- case D3DERR_DEVICELOST:
- return error(GL_OUT_OF_MEMORY);
- default:
- UNREACHABLE();
- return; // No sensible error to generate
+ UNREACHABLE();
+ return;
}
+
+ }
+
+ if (directToPixels)
+ {
+ systemSurface->Release();
+ return;
}
D3DLOCKED_RECT lock;
- RECT rect = {std::max(x, 0),
- std::max(y, 0),
- std::min(x + width, (int)desc.Width),
- std::min(y + height, (int)desc.Height)};
+ RECT rect = transformPixelRect(x, y, width, height, desc.Height);
+ rect.left = clamp(rect.left, 0L, static_cast<LONG>(desc.Width));
+ rect.top = clamp(rect.top, 0L, static_cast<LONG>(desc.Height));
+ rect.right = clamp(rect.right, 0L, static_cast<LONG>(desc.Width));
+ rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(desc.Height));
result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
@@ -2141,11 +2498,21 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
return; // No sensible error to generate
}
- unsigned char *source = (unsigned char*)lock.pBits;
unsigned char *dest = (unsigned char*)pixels;
unsigned short *dest16 = (unsigned short*)pixels;
- GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
+ unsigned char *source;
+ int inputPitch;
+ if (getPackReverseRowOrder())
+ {
+ source = (unsigned char*)lock.pBits;
+ inputPitch = lock.Pitch;
+ }
+ else
+ {
+ source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
+ inputPitch = -lock.Pitch;
+ }
for (int j = 0; j < rect.bottom - rect.top; j++)
{
@@ -2157,7 +2524,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
// an RGBA source buffer. Note that buffers with no
// alpha go through the slow path below.
memcpy(dest + j * outputPitch,
- source + j * lock.Pitch,
+ source + j * inputPitch,
(rect.right - rect.left) * 4);
continue;
}
@@ -2173,7 +2540,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
{
case D3DFMT_R5G6B5:
{
- unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
+ unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
a = 1.0f;
b = (rgb & 0x001F) * (1.0f / 0x001F);
@@ -2183,7 +2550,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
break;
case D3DFMT_A1R5G5B5:
{
- unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
+ unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
a = (argb & 0x8000) ? 1.0f : 0.0f;
b = (argb & 0x001F) * (1.0f / 0x001F);
@@ -2193,7 +2560,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
break;
case D3DFMT_A8R8G8B8:
{
- unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+ unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
@@ -2203,7 +2570,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
break;
case D3DFMT_X8R8G8B8:
{
- unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+ unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
a = 1.0f;
b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
@@ -2213,7 +2580,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
break;
case D3DFMT_A2R10G10B10:
{
- unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
+ unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
@@ -2224,10 +2591,10 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
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);
+ r = *((float*)(source + 16 * i + j * inputPitch) + 0);
+ g = *((float*)(source + 16 * i + j * inputPitch) + 1);
+ b = *((float*)(source + 16 * i + j * inputPitch) + 2);
+ a = *((float*)(source + 16 * i + j * inputPitch) + 3);
}
break;
case D3DFMT_A16B16G16R16F:
@@ -2235,7 +2602,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
// 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);
+ D3DXFloat16To32Array(abgr, (D3DXFLOAT16*)(source + 8 * i + j * inputPitch), 4);
a = abgr[3];
b = abgr[2];
@@ -2246,6 +2613,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
default:
UNIMPLEMENTED(); // FIXME
UNREACHABLE();
+ return;
}
switch (format)
@@ -2330,13 +2698,9 @@ void Context::clear(GLbitfield mask)
if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
- error(GL_INVALID_FRAMEBUFFER_OPERATION);
-
- return;
+ return error(GL_INVALID_FRAMEBUFFER_OPERATION);
}
- egl::Display *display = getDisplay();
- IDirect3DDevice9 *device = getDevice();
DWORD flags = 0;
if (mask & GL_COLOR_BUFFER_BIT)
@@ -2375,7 +2739,7 @@ void Context::clear(GLbitfield mask)
D3DSURFACE_DESC desc;
depthStencil->GetDesc(&desc);
- unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
+ unsigned int stencilSize = dx2es::GetStencilSize(desc.Format);
stencilUnmasked = (0x1 << stencilSize) - 1;
if (stencilUnmasked != 0x0)
@@ -2396,23 +2760,13 @@ void Context::clear(GLbitfield mask)
}
D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
- unorm<8>(mState.colorClearValue.red),
- unorm<8>(mState.colorClearValue.green),
- unorm<8>(mState.colorClearValue.blue));
+ unorm<8>(mState.colorClearValue.red),
+ unorm<8>(mState.colorClearValue.green),
+ unorm<8>(mState.colorClearValue.blue));
float depth = clamp01(mState.depthClearValue);
int stencil = mState.stencilClearValue & 0x000000FF;
- IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
-
- if (!renderTarget)
- {
- return; // Context must be lost, return silently
- }
-
- D3DSURFACE_DESC desc;
- renderTarget->GetDesc(&desc);
-
- bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
+ bool alphaUnmasked = (dx2es::GetAlphaSize(mRenderTargetDesc.Format) == 0) || mState.colorMaskAlpha;
const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
(mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
@@ -2428,25 +2782,37 @@ void Context::clear(GLbitfield mask)
HRESULT hr;
if (mMaskedClearSavedState == NULL)
{
- hr = device->BeginStateBlock();
+ hr = mDevice->BeginStateBlock();
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
- device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
- device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
- device->SetRenderState(D3DRS_ZENABLE, FALSE);
- device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
- device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
- device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
- device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
- device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
- device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
- device->SetPixelShader(NULL);
- device->SetVertexShader(NULL);
- device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
- device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
-
- hr = device->EndStateBlock(&mMaskedClearSavedState);
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ mDevice->SetPixelShader(NULL);
+ mDevice->SetVertexShader(NULL);
+ mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+ mDevice->SetStreamSource(0, NULL, 0, 0);
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+ mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+ mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+ for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ mDevice->SetStreamSourceFreq(i, 1);
+ }
+
+ hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
}
@@ -2458,88 +2824,86 @@ void Context::clear(GLbitfield mask)
ASSERT(SUCCEEDED(hr));
}
- device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
- device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
- device->SetRenderState(D3DRS_ZENABLE, FALSE);
- device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
- device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
- device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
- device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
if (flags & D3DCLEAR_TARGET)
{
- device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
- (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
- (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
- (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));
}
else
{
- device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
}
if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
{
- device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
- device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
- device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
- device->SetRenderState(D3DRS_STENCILREF, stencil);
- device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
- device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
- device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
- device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
+ mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
+ mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
+ mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
+ mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
+ mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
mStencilStateDirty = true;
}
else
{
- device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
}
- device->SetPixelShader(NULL);
- device->SetVertexShader(NULL);
- device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
- device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
-
- struct Vertex
+ mDevice->SetPixelShader(NULL);
+ mDevice->SetVertexShader(NULL);
+ mDevice->SetFVF(D3DFVF_XYZRHW);
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+ mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+ mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+ for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
{
- float x, y, z, w;
- D3DCOLOR diffuse;
- };
+ mDevice->SetStreamSourceFreq(i, 1);
+ }
+
+ float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
+ quad[0][0] = -0.5f;
+ quad[0][1] = mRenderTargetDesc.Height - 0.5f;
+ quad[0][2] = 0.0f;
+ quad[0][3] = 1.0f;
+
+ quad[1][0] = mRenderTargetDesc.Width - 0.5f;
+ quad[1][1] = mRenderTargetDesc.Height - 0.5f;
+ quad[1][2] = 0.0f;
+ quad[1][3] = 1.0f;
+
+ quad[2][0] = -0.5f;
+ quad[2][1] = -0.5f;
+ quad[2][2] = 0.0f;
+ quad[2][3] = 1.0f;
- Vertex quad[4];
- quad[0].x = 0.0f;
- quad[0].y = (float)desc.Height;
- quad[0].z = 0.0f;
- quad[0].w = 1.0f;
- quad[0].diffuse = color;
-
- quad[1].x = (float)desc.Width;
- quad[1].y = (float)desc.Height;
- quad[1].z = 0.0f;
- quad[1].w = 1.0f;
- quad[1].diffuse = color;
-
- quad[2].x = 0.0f;
- quad[2].y = 0.0f;
- quad[2].z = 0.0f;
- quad[2].w = 1.0f;
- quad[2].diffuse = color;
-
- quad[3].x = (float)desc.Width;
- quad[3].y = 0.0f;
- quad[3].z = 0.0f;
- quad[3].w = 1.0f;
- quad[3].diffuse = color;
-
- display->startScene();
- device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
+ quad[3][0] = mRenderTargetDesc.Width - 0.5f;
+ quad[3][1] = -0.5f;
+ quad[3][2] = 0.0f;
+ quad[3][3] = 1.0f;
+
+ mDisplay->startScene();
+ mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
if (flags & D3DCLEAR_ZBUFFER)
{
- device->SetRenderState(D3DRS_ZENABLE, TRUE);
- device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
- device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
+ mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
+ mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
}
if (mMaskedClearSavedState != NULL)
@@ -2549,19 +2913,17 @@ void Context::clear(GLbitfield mask)
}
else if (flags)
{
- device->Clear(0, NULL, flags, color, depth, stencil);
+ mDevice->Clear(0, NULL, flags, color, depth, stencil);
}
}
-void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
+void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
{
if (!mState.currentProgram)
{
return error(GL_INVALID_OPERATION);
}
- egl::Display *display = getDisplay();
- IDirect3DDevice9 *device = getDevice();
D3DPRIMITIVETYPE primitiveType;
int primitiveCount;
@@ -2580,7 +2942,8 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
applyState(mode);
- GLenum err = applyVertexBuffer(first, count);
+ GLsizei repeatDraw = 1;
+ GLenum err = applyVertexBuffer(first, count, instances, &repeatDraw);
if (err != GL_NO_ERROR)
{
return error(err);
@@ -2589,25 +2952,49 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
applyShaders();
applyTextures();
- if (!getCurrentProgram()->validateSamplers())
+ if (!getCurrentProgram()->validateSamplers(false))
{
return error(GL_INVALID_OPERATION);
}
if (!cullSkipsDraw(mode))
{
- display->startScene();
+ mDisplay->startScene();
- device->DrawPrimitive(primitiveType, 0, primitiveCount);
+ if (mode == GL_LINE_LOOP)
+ {
+ drawLineLoop(count, GL_NONE, NULL, 0);
+ }
+ else if (instances > 0)
+ {
+ StaticIndexBuffer *countingIB = mIndexDataManager->getCountingIndices(count);
+ if (countingIB)
+ {
+ if (mAppliedIBSerial != countingIB->getSerial())
+ {
+ mDevice->SetIndices(countingIB->getBuffer());
+ mAppliedIBSerial = countingIB->getSerial();
+ }
- if (mode == GL_LINE_LOOP) // Draw the last segment separately
+ for (int i = 0; i < repeatDraw; i++)
+ {
+ mDevice->DrawIndexedPrimitive(primitiveType, 0, 0, count, 0, primitiveCount);
+ }
+ }
+ else
+ {
+ ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
+ return error(GL_OUT_OF_MEMORY);
+ }
+ }
+ else // Regular case
{
- drawClosingLine(first, first + count - 1);
+ mDevice->DrawPrimitive(primitiveType, 0, primitiveCount);
}
}
}
-void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
+void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances)
{
if (!mState.currentProgram)
{
@@ -2619,8 +3006,6 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
return error(GL_INVALID_OPERATION);
}
- egl::Display *display = getDisplay();
- IDirect3DDevice9 *device = getDevice();
D3DPRIMITIVETYPE primitiveType;
int primitiveCount;
@@ -2647,7 +3032,8 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
}
GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
- err = applyVertexBuffer(indexInfo.minIndex, vertexCount);
+ GLsizei repeatDraw = 1;
+ err = applyVertexBuffer(indexInfo.minIndex, vertexCount, instances, &repeatDraw);
if (err != GL_NO_ERROR)
{
return error(err);
@@ -2656,188 +3042,178 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *
applyShaders();
applyTextures();
- if (!getCurrentProgram()->validateSamplers())
+ if (!getCurrentProgram()->validateSamplers(false))
{
return error(GL_INVALID_OPERATION);
}
if (!cullSkipsDraw(mode))
{
- display->startScene();
-
- 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);
- }
- }
-}
-
-void Context::finish()
-{
- egl::Display *display = getDisplay();
- IDirect3DDevice9 *device = getDevice();
- IDirect3DQuery9 *occlusionQuery = NULL;
-
- HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
-
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
- {
- return error(GL_OUT_OF_MEMORY);
- }
-
- ASSERT(SUCCEEDED(result));
-
- if (occlusionQuery)
- {
- IDirect3DStateBlock9 *savedState = NULL;
- device->CreateStateBlock(D3DSBT_ALL, &savedState);
-
- HRESULT result = occlusionQuery->Issue(D3DISSUE_BEGIN);
- ASSERT(SUCCEEDED(result));
-
- // Render something outside the render target
- device->SetPixelShader(NULL);
- device->SetVertexShader(NULL);
- device->SetFVF(D3DFVF_XYZRHW);
- float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
- display->startScene();
- device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
-
- result = occlusionQuery->Issue(D3DISSUE_END);
- ASSERT(SUCCEEDED(result));
+ mDisplay->startScene();
- while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
+ if (mode == GL_LINE_LOOP)
{
- // Keep polling, but allow other threads to do something useful first
- Sleep(0);
+ drawLineLoop(count, type, indices, indexInfo.minIndex);
}
-
- occlusionQuery->Release();
-
- if (savedState)
+ else
{
- savedState->Apply();
- savedState->Release();
+ for (int i = 0; i < repeatDraw; i++)
+ {
+ mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
+ }
}
}
}
-void Context::flush()
+// Implements glFlush when block is false, glFinish when block is true
+void Context::sync(bool block)
{
- IDirect3DDevice9 *device = getDevice();
- IDirect3DQuery9 *eventQuery = NULL;
-
- HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
+ mDisplay->sync(block);
+}
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+void Context::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex)
+{
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && mState.elementArrayBuffer.get())
{
- return error(GL_OUT_OF_MEMORY);
+ Buffer *indexBuffer = mState.elementArrayBuffer.get();
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
}
- ASSERT(SUCCEEDED(result));
+ UINT startIndex = 0;
+ bool succeeded = false;
- if (eventQuery)
+ if (supports32bitIndices())
{
- HRESULT result = eventQuery->Issue(D3DISSUE_END);
- ASSERT(SUCCEEDED(result));
+ const int spaceNeeded = (count + 1) * sizeof(unsigned int);
- result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
- eventQuery->Release();
-
- if (result == D3DERR_DEVICELOST)
+ if (!mLineLoopIB)
{
- error(GL_OUT_OF_MEMORY);
+ mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
}
- }
-}
-
-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))
+ if (mLineLoopIB)
{
- unsigned int *data;
- result = indexBuffer->Lock(0, 0, (void**)&data, 0);
+ mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
- if (SUCCEEDED(result))
+ UINT offset = 0;
+ unsigned int *data = static_cast<unsigned int*>(mLineLoopIB->map(spaceNeeded, &offset));
+ startIndex = offset / 4;
+
+ if (data)
{
- data[0] = last;
- data[1] = first;
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+
+ mLineLoopIB->unmap();
+ succeeded = true;
}
}
}
else
{
- result = device->CreateIndexBuffer(4, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, 0);
+ const int spaceNeeded = (count + 1) * sizeof(unsigned short);
- if (SUCCEEDED(result))
+ if (!mLineLoopIB)
{
- unsigned short *data;
- result = indexBuffer->Lock(0, 0, (void**)&data, 0);
+ mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
+ }
- if (SUCCEEDED(result))
+ if (mLineLoopIB)
+ {
+ mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+ UINT offset = 0;
+ unsigned short *data = static_cast<unsigned short*>(mLineLoopIB->map(spaceNeeded, &offset));
+ startIndex = offset / 2;
+
+ if (data)
{
- data[0] = last;
- data[1] = first;
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+
+ mLineLoopIB->unmap();
+ succeeded = true;
}
}
}
- if (SUCCEEDED(result))
+ if (succeeded)
{
- indexBuffer->Unlock();
- device->SetIndices(indexBuffer);
-
- device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 2, 0, 1);
+ if (mAppliedIBSerial != mLineLoopIB->getSerial())
+ {
+ mDevice->SetIndices(mLineLoopIB->getBuffer());
+ mAppliedIBSerial = mLineLoopIB->getSerial();
+ }
- indexBuffer->Release();
+ mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
}
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();
+ ERR("Could not create a looping index buffer for GL_LINE_LOOP.");
+ return error(GL_OUT_OF_MEMORY);
}
-
- drawClosingLine(first, last);
}
void Context::recordInvalidEnum()
@@ -2907,6 +3283,36 @@ GLenum Context::getError()
return GL_NO_ERROR;
}
+GLenum Context::getResetStatus()
+{
+ if (mResetStatus == GL_NO_ERROR)
+ {
+ bool lost = mDisplay->testDeviceLost();
+
+ if (lost)
+ {
+ mDisplay->notifyDeviceLost(); // Sets mResetStatus
+ }
+ }
+
+ GLenum status = mResetStatus;
+
+ if (mResetStatus != GL_NO_ERROR)
+ {
+ if (mDisplay->testDeviceResettable())
+ {
+ mResetStatus = GL_NO_ERROR;
+ }
+ }
+
+ return status;
+}
+
+bool Context::isResetNotificationEnabled()
+{
+ return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
bool Context::supportsShaderModel3() const
{
return mSupportsShaderModel3;
@@ -2917,6 +3323,16 @@ int Context::getMaximumVaryingVectors() const
return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
}
+unsigned int Context::getMaximumVertexTextureImageUnits() const
+{
+ return mSupportsVertexTexture ? MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF : 0;
+}
+
+unsigned int Context::getMaximumCombinedTextureImageUnits() const
+{
+ return MAX_TEXTURE_IMAGE_UNITS + getMaximumVertexTextureImageUnits();
+}
+
int Context::getMaximumFragmentUniformVectors() const
{
return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2;
@@ -2956,39 +3372,54 @@ bool Context::supportsEventQueries() const
return mSupportsEventQueries;
}
-bool Context::supportsCompressedTextures() const
+bool Context::supportsOcclusionQueries() const
+{
+ return mSupportsOcclusionQueries;
+}
+
+bool Context::supportsDXT1Textures() const
+{
+ return mSupportsDXT1Textures;
+}
+
+bool Context::supportsDXT3Textures() const
+{
+ return mSupportsDXT3Textures;
+}
+
+bool Context::supportsDXT5Textures() const
{
- return mSupportsCompressedTextures;
+ return mSupportsDXT5Textures;
}
-bool Context::supportsFloatTextures() const
+bool Context::supportsFloat32Textures() const
{
- return mSupportsFloatTextures;
+ return mSupportsFloat32Textures;
}
-bool Context::supportsFloatLinearFilter() const
+bool Context::supportsFloat32LinearFilter() const
{
- return mSupportsFloatLinearFilter;
+ return mSupportsFloat32LinearFilter;
}
-bool Context::supportsFloatRenderableTextures() const
+bool Context::supportsFloat32RenderableTextures() const
{
- return mSupportsFloatRenderableTextures;
+ return mSupportsFloat32RenderableTextures;
}
-bool Context::supportsHalfFloatTextures() const
+bool Context::supportsFloat16Textures() const
{
- return mSupportsHalfFloatTextures;
+ return mSupportsFloat16Textures;
}
-bool Context::supportsHalfFloatLinearFilter() const
+bool Context::supportsFloat16LinearFilter() const
{
- return mSupportsHalfFloatLinearFilter;
+ return mSupportsFloat16LinearFilter;
}
-bool Context::supportsHalfFloatRenderableTextures() const
+bool Context::supportsFloat16RenderableTextures() const
{
- return mSupportsHalfFloatRenderableTextures;
+ return mSupportsFloat16RenderableTextures;
}
int Context::getMaximumRenderbufferDimension() const
@@ -3026,6 +3457,16 @@ bool Context::supports32bitIndices() const
return mSupports32bitIndices;
}
+bool Context::supportsNonPower2Texture() const
+{
+ return mSupportsNonPower2Texture;
+}
+
+bool Context::supportsInstancing() const
+{
+ return mSupportsInstancing;
+}
+
void Context::detachBuffer(GLuint buffer)
{
// [OpenGL ES 2.0.24] section 2.9 page 22:
@@ -3057,9 +3498,9 @@ void Context::detachTexture(GLuint texture)
// 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 < SAMPLER_TYPE_COUNT; type++)
+ for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
{
- for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+ for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
{
if (mState.samplerTexture[type][sampler].id() == texture)
{
@@ -3134,7 +3575,7 @@ void Context::detachRenderbuffer(GLuint renderbuffer)
}
}
-Texture *Context::getIncompleteTexture(SamplerType type)
+Texture *Context::getIncompleteTexture(TextureType type)
{
Texture *t = mIncompleteTextures[type].get();
@@ -3146,26 +3587,26 @@ Texture *Context::getIncompleteTexture(SamplerType type)
{
default:
UNREACHABLE();
- // default falls through to SAMPLER_2D
+ // default falls through to TEXTURE_2D
- case SAMPLER_2D:
+ case TEXTURE_2D:
{
Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
- incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
t = incomplete2d;
}
break;
- case SAMPLER_CUBE:
+ case TEXTURE_CUBE:
{
TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
- incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
- incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
+ incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
t = incompleteCube;
}
@@ -3214,53 +3655,100 @@ void Context::setVertexAttrib(GLuint index, const GLfloat *values)
mVertexDataManager->dirtyCurrentValue(index);
}
+void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
+
+ mState.vertexAttribute[index].mDivisor = divisor;
+}
+
+// keep list sorted in following order
+// OES extensions
+// EXT extensions
+// Vendor extensions
void Context::initExtensionString()
{
+ mExtensionString = "";
+
+ // OES extensions
+ if (supports32bitIndices())
+ {
+ mExtensionString += "GL_OES_element_index_uint ";
+ }
+
mExtensionString += "GL_OES_packed_depth_stencil ";
- mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
- mExtensionString += "GL_EXT_read_format_bgra ";
- mExtensionString += "GL_ANGLE_framebuffer_blit ";
mExtensionString += "GL_OES_rgb8_rgba8 ";
mExtensionString += "GL_OES_standard_derivatives ";
- if (supportsEventQueries())
+ if (supportsFloat16Textures())
{
- mExtensionString += "GL_NV_fence ";
+ mExtensionString += "GL_OES_texture_half_float ";
}
-
- if (supportsCompressedTextures())
+ if (supportsFloat16LinearFilter())
{
- mExtensionString += "GL_EXT_texture_compression_dxt1 ";
+ mExtensionString += "GL_OES_texture_half_float_linear ";
}
-
- if (supportsFloatTextures())
+ if (supportsFloat32Textures())
{
mExtensionString += "GL_OES_texture_float ";
}
+ if (supportsFloat32LinearFilter())
+ {
+ mExtensionString += "GL_OES_texture_float_linear ";
+ }
- if (supportsHalfFloatTextures())
+ if (supportsNonPower2Texture())
{
- mExtensionString += "GL_OES_texture_half_float ";
+ mExtensionString += "GL_OES_texture_npot ";
}
- if (supportsFloatLinearFilter())
+ // Multi-vendor (EXT) extensions
+ if (supportsOcclusionQueries())
{
- mExtensionString += "GL_OES_texture_float_linear ";
+ mExtensionString += "GL_EXT_occlusion_query_boolean ";
}
- if (supportsHalfFloatLinearFilter())
+ mExtensionString += "GL_EXT_read_format_bgra ";
+ mExtensionString += "GL_EXT_robustness ";
+
+ if (supportsDXT1Textures())
{
- mExtensionString += "GL_OES_texture_half_float_linear ";
+ mExtensionString += "GL_EXT_texture_compression_dxt1 ";
}
+ mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
+ mExtensionString += "GL_EXT_texture_storage ";
+
+ // ANGLE-specific extensions
+ mExtensionString += "GL_ANGLE_framebuffer_blit ";
if (getMaxSupportedSamples() != 0)
{
mExtensionString += "GL_ANGLE_framebuffer_multisample ";
}
- if (supports32bitIndices())
+ if (supportsInstancing())
{
- mExtensionString += "GL_OES_element_index_uint ";
+ mExtensionString += "GL_ANGLE_instanced_arrays ";
+ }
+
+ mExtensionString += "GL_ANGLE_pack_reverse_row_order ";
+
+ if (supportsDXT3Textures())
+ {
+ mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
+ }
+ if (supportsDXT5Textures())
+ {
+ mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
+ }
+
+ mExtensionString += "GL_ANGLE_texture_usage ";
+ mExtensionString += "GL_ANGLE_translated_shader_source ";
+
+ // Other vendor-specific extensions
+ if (supportsEventQueries())
+ {
+ mExtensionString += "GL_NV_fence ";
}
std::string::size_type end = mExtensionString.find_last_not_of(' ');
@@ -3275,12 +3763,24 @@ const char *Context::getExtensionString() const
return mExtensionString.c_str();
}
+void Context::initRendererString()
+{
+ D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier();
+
+ mRendererString = "ANGLE (";
+ mRendererString += identifier->Description;
+ mRendererString += ")";
+}
+
+const char *Context::getRendererString() const
+{
+ return mRendererString.c_str();
+}
+
void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask)
{
- IDirect3DDevice9 *device = getDevice();
-
Framebuffer *readFramebuffer = getReadFramebuffer();
Framebuffer *drawFramebuffer = getDrawFramebuffer();
@@ -3295,6 +3795,11 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
return error(GL_INVALID_OPERATION);
}
+ int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
+ int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
+ int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
+ int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
+
RECT sourceRect;
RECT destRect;
@@ -3313,21 +3818,19 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
destRect.right = dstX0;
}
- // Arguments to StretchRect must be in D3D-style (0-top) coordinates, so we must
- // flip our Y-values here
if (srcY0 < srcY1)
{
- sourceRect.bottom = srcY1;
- destRect.bottom = dstY1;
- sourceRect.top = srcY0;
- destRect.top = dstY0;
+ sourceRect.top = readBufferHeight - srcY1;
+ destRect.top = drawBufferHeight - dstY1;
+ sourceRect.bottom = readBufferHeight - srcY0;
+ destRect.bottom = drawBufferHeight - dstY0;
}
else
{
- sourceRect.bottom = srcY0;
- destRect.bottom = dstY0;
- sourceRect.top = srcY1;
- destRect.top = dstY1;
+ sourceRect.top = readBufferHeight - srcY0;
+ destRect.top = drawBufferHeight - dstY0;
+ sourceRect.bottom = readBufferHeight - srcY1;
+ destRect.bottom = drawBufferHeight - dstY1;
}
RECT sourceScissoredRect = sourceRect;
@@ -3382,11 +3885,6 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
destTrimmedRect.left += xDiff;
}
- int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
- int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
- int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
- int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
-
if (sourceTrimmedRect.right > readBufferWidth)
{
int xDiff = sourceTrimmedRect.right - readBufferWidth;
@@ -3470,8 +3968,8 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
{
- DepthStencilbuffer *readDSBuffer = NULL;
- DepthStencilbuffer *drawDSBuffer = NULL;
+ Renderbuffer *readDSBuffer = NULL;
+ Renderbuffer *drawDSBuffer = NULL;
// We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
// both a depth and stencil buffer, it will be the same buffer.
@@ -3523,13 +4021,18 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
if (blitRenderTarget || blitDepthStencil)
{
- egl::Display *display = getDisplay();
- display->endScene();
+ mDisplay->endScene();
if (blitRenderTarget)
{
- HRESULT result = device->StretchRect(readFramebuffer->getRenderTarget(), &sourceTrimmedRect,
- drawFramebuffer->getRenderTarget(), &destTrimmedRect, D3DTEXF_NONE);
+ IDirect3DSurface9* readRenderTarget = readFramebuffer->getRenderTarget();
+ IDirect3DSurface9* drawRenderTarget = drawFramebuffer->getRenderTarget();
+
+ HRESULT result = mDevice->StretchRect(readRenderTarget, &sourceTrimmedRect,
+ drawRenderTarget, &destTrimmedRect, D3DTEXF_NONE);
+
+ readRenderTarget->Release();
+ drawRenderTarget->Release();
if (FAILED(result))
{
@@ -3540,7 +4043,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
if (blitDepthStencil)
{
- HRESULT result = device->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE);
+ HRESULT result = mDevice->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE);
if (FAILED(result))
{
@@ -3551,13 +4054,204 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
}
}
+VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
+{
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ mVertexDeclCache[i].vertexDeclaration = NULL;
+ mVertexDeclCache[i].lruCount = 0;
+ }
+}
+
+VertexDeclarationCache::~VertexDeclarationCache()
+{
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ if (mVertexDeclCache[i].vertexDeclaration)
+ {
+ mVertexDeclCache[i].vertexDeclaration->Release();
+ }
+ }
+}
+
+GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program, GLsizei instances, GLsizei *repeatDraw)
+{
+ *repeatDraw = 1;
+
+ int indexedAttribute = MAX_VERTEX_ATTRIBS;
+ int instancedAttribute = MAX_VERTEX_ATTRIBS;
+
+ if (instances > 0)
+ {
+ // Find an indexed attribute to be mapped to D3D stream 0
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].active)
+ {
+ if (indexedAttribute == MAX_VERTEX_ATTRIBS)
+ {
+ if (attributes[i].divisor == 0)
+ {
+ indexedAttribute = i;
+ }
+ }
+ else if (instancedAttribute == MAX_VERTEX_ATTRIBS)
+ {
+ if (attributes[i].divisor != 0)
+ {
+ instancedAttribute = i;
+ }
+ }
+ else break; // Found both an indexed and instanced attribute
+ }
+ }
+
+ if (indexedAttribute == MAX_VERTEX_ATTRIBS)
+ {
+ return GL_INVALID_OPERATION;
+ }
+ }
+
+ D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1];
+ D3DVERTEXELEMENT9 *element = &elements[0];
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].active)
+ {
+ int stream = i;
+
+ if (instances > 0)
+ {
+ // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
+ if (instancedAttribute == MAX_VERTEX_ATTRIBS)
+ {
+ *repeatDraw = instances;
+ }
+ else
+ {
+ if (i == indexedAttribute)
+ {
+ stream = 0;
+ }
+ else if (i == 0)
+ {
+ stream = indexedAttribute;
+ }
+
+ UINT frequency = 1;
+
+ if (attributes[i].divisor == 0)
+ {
+ frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
+ }
+ else
+ {
+ frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
+ }
+
+ device->SetStreamSourceFreq(stream, frequency);
+ mInstancingEnabled = true;
+ }
+ }
+
+ if (mAppliedVBs[stream].serial != attributes[i].serial ||
+ mAppliedVBs[stream].stride != attributes[i].stride ||
+ mAppliedVBs[stream].offset != attributes[i].offset)
+ {
+ device->SetStreamSource(stream, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride);
+ mAppliedVBs[stream].serial = attributes[i].serial;
+ mAppliedVBs[stream].stride = attributes[i].stride;
+ mAppliedVBs[stream].offset = attributes[i].offset;
+ }
+
+ element->Stream = stream;
+ element->Offset = 0;
+ element->Type = attributes[i].type;
+ element->Method = D3DDECLMETHOD_DEFAULT;
+ element->Usage = D3DDECLUSAGE_TEXCOORD;
+ element->UsageIndex = program->getSemanticIndex(i);
+ element++;
+ }
+ }
+
+ if (instances == 0 || instancedAttribute == MAX_VERTEX_ATTRIBS)
+ {
+ if (mInstancingEnabled)
+ {
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ device->SetStreamSourceFreq(i, 1);
+ }
+
+ mInstancingEnabled = false;
+ }
+ }
+
+ static const D3DVERTEXELEMENT9 end = D3DDECL_END();
+ *(element++) = end;
+
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
+ if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
+ {
+ entry->lruCount = ++mMaxLru;
+ if(entry->vertexDeclaration != mLastSetVDecl)
+ {
+ device->SetVertexDeclaration(entry->vertexDeclaration);
+ mLastSetVDecl = entry->vertexDeclaration;
+ }
+
+ return GL_NO_ERROR;
+ }
+ }
+
+ VertexDeclCacheEntry *lastCache = mVertexDeclCache;
+
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
+ {
+ lastCache = &mVertexDeclCache[i];
+ }
+ }
+
+ if (lastCache->vertexDeclaration != NULL)
+ {
+ lastCache->vertexDeclaration->Release();
+ lastCache->vertexDeclaration = NULL;
+ // mLastSetVDecl is set to the replacement, so we don't have to worry
+ // about it.
+ }
+
+ memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
+ device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
+ device->SetVertexDeclaration(lastCache->vertexDeclaration);
+ mLastSetVDecl = lastCache->vertexDeclaration;
+ lastCache->lruCount = ++mMaxLru;
+
+ return GL_NO_ERROR;
+}
+
+void VertexDeclarationCache::markStateDirty()
+{
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAppliedVBs[i].serial = 0;
+ }
+
+ mLastSetVDecl = NULL;
+ mInstancingEnabled = true; // Forces it to be disabled when not used
+}
+
}
extern "C"
{
-gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
{
- return new gl::Context(config, shareContext);
+ return new gl::Context(config, shareContext, notifyResets, robustAccess);
}
void glDestroyContext(gl::Context *context)
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h
index 2906664..8dccf0f 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Context.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -18,10 +18,12 @@
#include <d3d9.h>
#include <map>
+#include <hash_map>
#include "common/angleutils.h"
+#include "common/RefCountObject.h"
#include "libGLESv2/ResourceManager.h"
-#include "libGLESv2/RefCountObject.h"
+#include "libGLESv2/HandleAllocator.h"
namespace egl
{
@@ -46,23 +48,29 @@ class Renderbuffer;
class RenderbufferStorage;
class Colorbuffer;
class Depthbuffer;
+class StreamingIndexBuffer;
class Stencilbuffer;
class DepthStencilbuffer;
class VertexDataManager;
class IndexDataManager;
class Blit;
class Fence;
+class Query;
enum
{
+ D3D9_MAX_FLOAT_CONSTANTS = 256,
+ D3D9_MAX_BOOL_CONSTANTS = 16,
+ D3D9_MAX_INT_CONSTANTS = 16,
+
MAX_VERTEX_ATTRIBS = 16,
- MAX_VERTEX_UNIFORM_VECTORS = 256 - 2, // 256 is the minimum for SM2, and in practice the maximum for DX9. Reserve space for dx_HalfPixelSize and dx_DepthRange.
+ MAX_VERTEX_UNIFORM_VECTORS = D3D9_MAX_FLOAT_CONSTANTS - 2, // Reserve space for dx_HalfPixelSize and dx_DepthRange.
MAX_VARYING_VECTORS_SM2 = 8,
MAX_VARYING_VECTORS_SM3 = 10,
- MAX_COMBINED_TEXTURE_IMAGE_UNITS = 16,
- MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0,
MAX_TEXTURE_IMAGE_UNITS = 16,
- MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3, // Reserve space for dx_Viewport, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers.
+ MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF = 4, // For devices supporting vertex texture fetch
+ MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF,
+ MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3, // Reserve space for dx_Coord, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers.
MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3,
MAX_DRAW_BUFFERS = 1,
@@ -70,6 +78,14 @@ enum
IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5
};
+enum QueryType
+{
+ QUERY_ANY_SAMPLES_PASSED,
+ QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE,
+
+ QUERY_TYPE_COUNT
+};
+
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 = 1.0f;
@@ -88,7 +104,7 @@ struct Color
class VertexAttribute
{
public:
- VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false)
+ VertexAttribute() : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0)
{
mCurrentValue[0] = 0.0f;
mCurrentValue[1] = 0.0f;
@@ -131,6 +147,7 @@ class VertexAttribute
bool mArrayEnabled; // From glEnable/DisableVertexAttribArray
float mCurrentValue[4]; // From glVertexAttrib
+ unsigned int mDivisor;
};
typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS];
@@ -203,7 +220,7 @@ struct State
bool colorMaskAlpha;
bool depthMask;
- int activeSampler; // Active texture unit selector - GL_TEXTURE0
+ unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0
BindingPointer<Buffer> arrayBuffer;
BindingPointer<Buffer> elementArrayBuffer;
GLuint readFramebuffer;
@@ -212,16 +229,53 @@ struct State
GLuint currentProgram;
VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS];
- BindingPointer<Texture> samplerTexture[SAMPLER_TYPE_COUNT][MAX_TEXTURE_IMAGE_UNITS];
+ BindingPointer<Texture> samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
+ BindingPointer<Query> activeQuery[QUERY_TYPE_COUNT];
GLint unpackAlignment;
GLint packAlignment;
+ bool packReverseRowOrder;
+};
+
+// Helper class to construct and cache vertex declarations
+class VertexDeclarationCache
+{
+ public:
+ VertexDeclarationCache();
+ ~VertexDeclarationCache();
+
+ GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], Program *program, GLsizei instances, GLsizei *repeatDraw);
+
+ void markStateDirty();
+
+ private:
+ UINT mMaxLru;
+
+ enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 16 };
+
+ struct VBData
+ {
+ unsigned int serial;
+ unsigned int stride;
+ unsigned int offset;
+ };
+
+ VBData mAppliedVBs[MAX_VERTEX_ATTRIBS];
+ IDirect3DVertexDeclaration9 *mLastSetVDecl;
+ bool mInstancingEnabled;
+
+ struct VertexDeclCacheEntry
+ {
+ D3DVERTEXELEMENT9 cachedElements[MAX_VERTEX_ATTRIBS + 1];
+ UINT lruCount;
+ IDirect3DVertexDeclaration9 *vertexDeclaration;
+ } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
};
class Context
{
public:
- Context(const egl::Config *config, const gl::Context *shareContext);
+ Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
~Context();
@@ -229,6 +283,9 @@ class Context
void markAllStateDirty();
+ virtual void markContextLost();
+ bool isContextLost();
+
// State manipulation
void setClearColor(float red, float green, float blue, float alpha);
@@ -298,7 +355,7 @@ class Context
void setColorMask(bool red, bool green, bool blue, bool alpha);
void setDepthMask(bool mask);
- void setActiveSampler(int active);
+ void setActiveSampler(unsigned int active);
GLuint getReadFramebufferHandle() const;
GLuint getDrawFramebufferHandle() const;
@@ -306,6 +363,8 @@ class Context
GLuint getArrayBufferHandle() const;
+ GLuint getActiveQuery(GLenum target) const;
+
void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
const VertexAttribute &getVertexAttribState(unsigned int attribNum);
void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
@@ -320,6 +379,9 @@ class Context
void setPackAlignment(GLint alignment);
GLint getPackAlignment() const;
+ void setPackReverseRowOrder(bool reverseRowOrder);
+ bool getPackReverseRowOrder() const;
+
// These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types
GLuint createBuffer();
@@ -341,6 +403,10 @@ class Context
// Fences are owned by the Context.
GLuint createFence();
void deleteFence(GLuint fence);
+
+ // Queries are owned by the Context;
+ GLuint createQuery();
+ void deleteQuery(GLuint query);
void bindArrayBuffer(GLuint buffer);
void bindElementArrayBuffer(GLuint buffer);
@@ -351,11 +417,15 @@ class Context
void bindRenderbuffer(GLuint renderbuffer);
void useProgram(GLuint program);
+ void beginQuery(GLenum target, GLuint query);
+ void endQuery(GLenum target);
+
void setFramebufferZero(Framebuffer *framebuffer);
void setRenderbufferStorage(RenderbufferStorage *renderbuffer);
void setVertexAttrib(GLuint index, const GLfloat *values);
+ void setVertexAttribDivisor(GLuint index, GLuint divisor);
Buffer *getBuffer(GLuint handle);
Fence *getFence(GLuint handle);
@@ -364,13 +434,14 @@ class Context
Texture *getTexture(GLuint handle);
Framebuffer *getFramebuffer(GLuint handle);
Renderbuffer *getRenderbuffer(GLuint handle);
+ Query *getQuery(GLuint handle, bool create, GLenum type);
Buffer *getArrayBuffer();
Buffer *getElementArrayBuffer();
Program *getCurrentProgram();
Texture2D *getTexture2D();
TextureCubeMap *getTextureCubeMap();
- Texture *getSamplerTexture(unsigned int sampler, SamplerType type);
+ Texture *getSamplerTexture(unsigned int sampler, TextureType type);
Framebuffer *getReadFramebuffer();
Framebuffer *getDrawFramebuffer();
@@ -380,23 +451,13 @@ class Context
bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
- bool applyRenderTarget(bool ignoreViewport);
- void applyState(GLenum drawMode);
- GLenum applyVertexBuffer(GLint first, GLsizei count);
- GLenum applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
- void applyShaders();
- void applyTextures();
-
- void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+ 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 finish();
- void flush();
+ void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
+ void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances);
+ void sync(bool block); // flush/finish
- // Draw the last segment of a line loop
- void drawClosingLine(unsigned int first, unsigned int last);
- void drawClosingLine(GLsizei count, GLenum type, const void *indices);
+ void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex);
void recordInvalidEnum();
void recordInvalidValue();
@@ -405,9 +466,13 @@ class Context
void recordInvalidFramebufferOperation();
GLenum getError();
+ GLenum getResetStatus();
+ virtual bool isResetNotificationEnabled();
bool supportsShaderModel3() const;
int getMaximumVaryingVectors() const;
+ unsigned int getMaximumVertexTextureImageUnits() const;
+ unsigned int getMaximumCombinedTextureImageUnits() const;
int getMaximumFragmentUniformVectors() const;
int getMaximumRenderbufferDimension() const;
int getMaximumTextureDimension() const;
@@ -416,17 +481,23 @@ class Context
GLsizei getMaxSupportedSamples() const;
int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
const char *getExtensionString() const;
+ const char *getRendererString() const;
bool supportsEventQueries() const;
- bool supportsCompressedTextures() const;
- bool supportsFloatTextures() const;
- bool supportsFloatLinearFilter() const;
- bool supportsFloatRenderableTextures() const;
- bool supportsHalfFloatTextures() const;
- bool supportsHalfFloatLinearFilter() const;
- bool supportsHalfFloatRenderableTextures() const;
+ bool supportsOcclusionQueries() const;
+ bool supportsDXT1Textures() const;
+ bool supportsDXT3Textures() const;
+ bool supportsDXT5Textures() const;
+ bool supportsFloat32Textures() const;
+ bool supportsFloat32LinearFilter() const;
+ bool supportsFloat32RenderableTextures() const;
+ bool supportsFloat16Textures() const;
+ bool supportsFloat16LinearFilter() const;
+ bool supportsFloat16RenderableTextures() const;
bool supportsLuminanceTextures() const;
bool supportsLuminanceAlphaTextures() const;
bool supports32bitIndices() const;
+ bool supportsNonPower2Texture() const;
+ bool supportsInstancing() const;
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
@@ -439,40 +510,59 @@ class Context
private:
DISALLOW_COPY_AND_ASSIGN(Context);
- void lookupAttributeMapping(TranslatedAttribute *attributes);
+ bool applyRenderTarget(bool ignoreViewport);
+ void applyState(GLenum drawMode);
+ GLenum applyVertexBuffer(GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw);
+ GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
+ void applyShaders();
+ void applyTextures();
+ void applyTextures(SamplerType type);
void detachBuffer(GLuint buffer);
void detachTexture(GLuint texture);
void detachFramebuffer(GLuint framebuffer);
void detachRenderbuffer(GLuint renderbuffer);
- Texture *getIncompleteTexture(SamplerType type);
+ Texture *getIncompleteTexture(TextureType type);
bool cullSkipsDraw(GLenum drawMode);
bool isTriangleMode(GLenum drawMode);
+ void initExtensionString();
+ void initRendererString();
+
const egl::Config *const mConfig;
+ egl::Display *mDisplay;
+ IDirect3DDevice9 *mDevice;
- State mState;
+ State mState;
BindingPointer<Texture2D> mTexture2DZero;
BindingPointer<TextureCubeMap> mTextureCubeMapZero;
- typedef std::map<GLuint, Framebuffer*> FramebufferMap;
+ typedef stdext::hash_map<GLuint, Framebuffer*> FramebufferMap;
FramebufferMap mFramebufferMap;
+ HandleAllocator mFramebufferHandleAllocator;
- typedef std::map<GLuint, Fence*> FenceMap;
+ typedef stdext::hash_map<GLuint, Fence*> FenceMap;
FenceMap mFenceMap;
+ HandleAllocator mFenceHandleAllocator;
+
+ typedef stdext::hash_map<GLuint, Query*> QueryMap;
+ QueryMap mQueryMap;
+ HandleAllocator mQueryHandleAllocator;
- void initExtensionString();
std::string mExtensionString;
+ std::string mRendererString;
VertexDataManager *mVertexDataManager;
IndexDataManager *mIndexDataManager;
Blit *mBlit;
+
+ StreamingIndexBuffer *mLineLoopIB;
- BindingPointer<Texture> mIncompleteTextures[SAMPLER_TYPE_COUNT];
+ BindingPointer<Texture> mIncompleteTextures[TEXTURE_TYPE_COUNT];
// Recorded errors
bool mInvalidEnum;
@@ -481,15 +571,33 @@ class Context
bool mOutOfMemory;
bool mInvalidFramebufferOperation;
+ // Current/lost context flags
bool mHasBeenCurrent;
-
- unsigned int mAppliedProgram;
+ bool mContextLost;
+ GLenum mResetStatus;
+ GLenum mResetStrategy;
+ bool mRobustAccess;
+
+ unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS];
+ unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
+ unsigned int mAppliedProgramSerial;
unsigned int mAppliedRenderTargetSerial;
unsigned int mAppliedDepthbufferSerial;
unsigned int mAppliedStencilbufferSerial;
+ unsigned int mAppliedIBSerial;
bool mDepthStencilInitialized;
+ bool mViewportInitialized;
+ D3DVIEWPORT9 mSetViewport;
+ bool mRenderTargetDescInitialized;
+ D3DSURFACE_DESC mRenderTargetDesc;
+ bool mDxUniformsDirty;
+ Program *mCachedCurrentProgram;
+ Framebuffer *mBoundDrawFramebuffer;
bool mSupportsShaderModel3;
+ bool mSupportsVertexTexture;
+ bool mSupportsNonPower2Texture;
+ bool mSupportsInstancing;
int mMaxRenderbufferDimension;
int mMaxTextureDimension;
int mMaxCubeTextureDimension;
@@ -497,16 +605,20 @@ class Context
std::map<D3DFORMAT, bool *> mMultiSampleSupport;
GLsizei mMaxSupportedSamples;
bool mSupportsEventQueries;
- bool mSupportsCompressedTextures;
- bool mSupportsFloatTextures;
- bool mSupportsFloatLinearFilter;
- bool mSupportsFloatRenderableTextures;
- bool mSupportsHalfFloatTextures;
- bool mSupportsHalfFloatLinearFilter;
- bool mSupportsHalfFloatRenderableTextures;
+ bool mSupportsOcclusionQueries;
+ bool mSupportsDXT1Textures;
+ bool mSupportsDXT3Textures;
+ bool mSupportsDXT5Textures;
+ bool mSupportsFloat32Textures;
+ bool mSupportsFloat32LinearFilter;
+ bool mSupportsFloat32RenderableTextures;
+ bool mSupportsFloat16Textures;
+ bool mSupportsFloat16LinearFilter;
+ bool mSupportsFloat16RenderableTextures;
bool mSupportsLuminanceTextures;
bool mSupportsLuminanceAlphaTextures;
bool mSupports32bitIndices;
+ int mNumCompressedTextureFormats;
// state caching flags
bool mClearStateDirty;
@@ -527,17 +639,20 @@ class Context
D3DCAPS9 mDeviceCaps;
ResourceManager *mResourceManager;
+
+ VertexDeclarationCache mVertexDeclarationCache;
};
}
extern "C"
{
// Exported functions for use by EGL
-gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext);
+gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
void glDestroyContext(gl::Context *context);
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
gl::Context *glGetCurrentContext();
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
+bool __stdcall glBindTexImage(egl::Surface *surface);
}
#endif // INCLUDE_CONTEXT_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp
index 7fbcb6a..14d1239 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.cpp
@@ -13,8 +13,9 @@
namespace gl
{
-Fence::Fence()
-{
+Fence::Fence(egl::Display* display)
+{
+ mDisplay = display;
mQuery = NULL;
mCondition = GL_NONE;
mStatus = GL_FALSE;
@@ -24,8 +25,7 @@ Fence::~Fence()
{
if (mQuery != NULL)
{
- mQuery->Release();
- mQuery = NULL;
+ mDisplay->freeEventQuery(mQuery);
}
}
@@ -38,15 +38,13 @@ GLboolean Fence::isFence()
void Fence::setFence(GLenum condition)
{
- if (mQuery != NULL)
+ if (!mQuery)
{
- mQuery->Release();
- mQuery = NULL;
- }
-
- if (FAILED(getDevice()->CreateQuery(D3DQUERYTYPE_EVENT, &mQuery)))
- {
- return error(GL_OUT_OF_MEMORY);
+ mQuery = mDisplay->allocateEventQuery();
+ if (!mQuery)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
}
HRESULT result = mQuery->Issue(D3DISSUE_END);
@@ -65,7 +63,7 @@ GLboolean Fence::testFence()
HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
- if (result == D3DERR_DEVICELOST)
+ if (checkDeviceLost(result))
{
return error(GL_OUT_OF_MEMORY, GL_TRUE);
}
@@ -110,7 +108,7 @@ void Fence::getFenceiv(GLenum pname, GLint *params)
HRESULT result = mQuery->GetData(NULL, 0, 0);
- if (result == D3DERR_DEVICELOST)
+ if (checkDeviceLost(result))
{
params[0] = GL_TRUE;
return error(GL_OUT_OF_MEMORY);
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h
index 17bad78..9626cb0 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Fence.h
@@ -15,13 +15,18 @@
#include "common/angleutils.h"
+namespace egl
+{
+class Display;
+}
+
namespace gl
{
class Fence
{
public:
- Fence();
+ explicit Fence(egl::Display* display);
virtual ~Fence();
GLboolean isFence();
@@ -33,6 +38,7 @@ class Fence
private:
DISALLOW_COPY_AND_ASSIGN(Fence);
+ egl::Display* mDisplay;
IDirect3DQuery9* mQuery;
GLenum mCondition;
GLboolean mStatus;
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp
index 5fe01e0..730fffc 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.cpp
@@ -44,9 +44,9 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
{
buffer = context->getRenderbuffer(handle);
}
- else if (IsTextureTarget(type))
+ else if (IsInternalTextureTarget(type))
{
- buffer = context->getTexture(handle)->getColorbuffer(type);
+ buffer = context->getTexture(handle)->getRenderbuffer(type);
}
else
{
@@ -58,37 +58,37 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
{
- mColorbufferType = type;
+ mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
}
void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
{
- mDepthbufferType = type;
+ mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
}
void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
{
- mStencilbufferType = type;
+ mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
}
void Framebuffer::detachTexture(GLuint texture)
{
- if (mColorbufferPointer.id() == texture && IsTextureTarget(mColorbufferType))
+ if (mColorbufferPointer.id() == texture && IsInternalTextureTarget(mColorbufferType))
{
mColorbufferType = GL_NONE;
mColorbufferPointer.set(NULL);
}
- if (mDepthbufferPointer.id() == texture && IsTextureTarget(mDepthbufferType))
+ if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
{
mDepthbufferType = GL_NONE;
mDepthbufferPointer.set(NULL);
}
- if (mStencilbufferPointer.id() == texture && IsTextureTarget(mStencilbufferType))
+ if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
{
mStencilbufferType = GL_NONE;
mStencilbufferPointer.set(NULL);
@@ -181,46 +181,19 @@ unsigned int Framebuffer::getStencilbufferSerial()
return 0;
}
-Colorbuffer *Framebuffer::getColorbuffer()
+Renderbuffer *Framebuffer::getColorbuffer()
{
- Renderbuffer *rb = mColorbufferPointer.get();
-
- if (rb != NULL && rb->isColorbuffer())
- {
- return static_cast<Colorbuffer*>(rb->getStorage());
- }
- else
- {
- return NULL;
- }
+ return mColorbufferPointer.get();
}
-DepthStencilbuffer *Framebuffer::getDepthbuffer()
+Renderbuffer *Framebuffer::getDepthbuffer()
{
- Renderbuffer *rb = mDepthbufferPointer.get();
-
- if (rb != NULL && rb->isDepthbuffer())
- {
- return static_cast<DepthStencilbuffer*>(rb->getStorage());
- }
- else
- {
- return NULL;
- }
+ return mDepthbufferPointer.get();
}
-DepthStencilbuffer *Framebuffer::getStencilbuffer()
+Renderbuffer *Framebuffer::getStencilbuffer()
{
- Renderbuffer *rb = mStencilbufferPointer.get();
-
- if (rb != NULL && rb->isStencilbuffer())
- {
- return static_cast<DepthStencilbuffer*>(rb->getStorage());
- }
- else
- {
- return NULL;
- }
+ return mStencilbufferPointer.get();
}
GLenum Framebuffer::getColorbufferType()
@@ -257,7 +230,7 @@ bool Framebuffer::hasStencil()
{
if (mStencilbufferType != GL_NONE)
{
- DepthStencilbuffer *stencilbufferObject = getStencilbuffer();
+ Renderbuffer *stencilbufferObject = getStencilbuffer();
if (stencilbufferObject)
{
@@ -268,23 +241,6 @@ bool Framebuffer::hasStencil()
return false;
}
-bool Framebuffer::isMultisample()
-{
- // If the framebuffer is not complete, attachment samples may be mismatched, and it
- // cannot be used as a multisample framebuffer. If it is complete, it is required to
- // have a color attachment, and all its attachments must have the same number of samples,
- // so the number of samples for the colorbuffer will indicate whether the framebuffer is
- // multisampled.
- if (completeness() == GL_FRAMEBUFFER_COMPLETE && getColorbuffer()->getSamples() > 0)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
GLenum Framebuffer::completeness()
{
int width = 0;
@@ -293,7 +249,7 @@ GLenum Framebuffer::completeness()
if (mColorbufferType != GL_NONE)
{
- Colorbuffer *colorbuffer = getColorbuffer();
+ Renderbuffer *colorbuffer = getColorbuffer();
if (!colorbuffer)
{
@@ -307,25 +263,25 @@ GLenum Framebuffer::completeness()
if (mColorbufferType == GL_RENDERBUFFER)
{
- if (!gl::IsColorRenderable(colorbuffer->getFormat()))
+ if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
- else if (IsTextureTarget(mColorbufferType))
+ else if (IsInternalTextureTarget(mColorbufferType))
{
- if (IsCompressed(colorbuffer->getFormat()))
+ if (IsCompressed(colorbuffer->getInternalFormat()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
- if (colorbuffer->isFloatingPoint() && (!getContext()->supportsFloatRenderableTextures() ||
- !getContext()->supportsHalfFloatRenderableTextures()))
+ if ((dx2es::IsFloat32Format(colorbuffer->getD3DFormat()) && !getContext()->supportsFloat32RenderableTextures()) ||
+ (dx2es::IsFloat16Format(colorbuffer->getD3DFormat()) && !getContext()->supportsFloat16RenderableTextures()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
- if (colorbuffer->getFormat() == GL_LUMINANCE || colorbuffer->getFormat() == GL_LUMINANCE_ALPHA)
+ if (colorbuffer->getInternalFormat() == GL_LUMINANCE || colorbuffer->getInternalFormat() == GL_LUMINANCE_ALPHA)
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
@@ -341,8 +297,8 @@ GLenum Framebuffer::completeness()
return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
}
- DepthStencilbuffer *depthbuffer = NULL;
- DepthStencilbuffer *stencilbuffer = NULL;
+ Renderbuffer *depthbuffer = NULL;
+ Renderbuffer *stencilbuffer = NULL;
if (mDepthbufferType != GL_NONE)
{
@@ -424,8 +380,8 @@ GLenum Framebuffer::completeness()
if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER)
{
- if (depthbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
- stencilbuffer->getFormat() != GL_DEPTH24_STENCIL8_OES ||
+ if (depthbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
+ stencilbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
depthbuffer->getSerial() != stencilbuffer->getSerial())
{
return GL_FRAMEBUFFER_UNSUPPORTED;
@@ -435,17 +391,17 @@ GLenum Framebuffer::completeness()
return GL_FRAMEBUFFER_COMPLETE;
}
-DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil)
+DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
{
- mColorbufferType = GL_RENDERBUFFER;
- mDepthbufferType = (depthStencil->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
- mStencilbufferType = (depthStencil->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
-
- mColorbufferPointer.set(new Renderbuffer(0, color));
+ mColorbufferPointer.set(new Renderbuffer(0, colorbuffer));
Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
mDepthbufferPointer.set(depthStencilRenderbuffer);
mStencilbufferPointer.set(depthStencilRenderbuffer);
+
+ mColorbufferType = GL_RENDERBUFFER;
+ mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+ mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
}
int Framebuffer::getSamples()
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h
index 0995145..b73f9a0 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Framebuffer.h
@@ -15,7 +15,7 @@
#include <d3d9.h>
#include "common/angleutils.h"
-#include "libGLESv2/RefCountObject.h"
+#include "common/RefCountObject.h"
namespace gl
{
@@ -46,9 +46,9 @@ class Framebuffer
unsigned int getDepthbufferSerial();
unsigned int getStencilbufferSerial();
- Colorbuffer *getColorbuffer();
- DepthStencilbuffer *getDepthbuffer();
- DepthStencilbuffer *getStencilbuffer();
+ Renderbuffer *getColorbuffer();
+ Renderbuffer *getDepthbuffer();
+ Renderbuffer *getStencilbuffer();
GLenum getColorbufferType();
GLenum getDepthbufferType();
@@ -59,7 +59,6 @@ class Framebuffer
GLuint getStencilbufferHandle();
bool hasStencil();
- bool isMultisample();
int getSamples();
virtual GLenum completeness();
@@ -83,7 +82,7 @@ class Framebuffer
class DefaultFramebuffer : public Framebuffer
{
public:
- DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil);
+ DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil);
virtual GLenum completeness();
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.cpp
new file mode 100644
index 0000000..c498f8a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.cpp
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
+// to allocate GL handles.
+
+#include "libGLESv2/HandleAllocator.h"
+
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+
+HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1)
+{
+}
+
+HandleAllocator::~HandleAllocator()
+{
+}
+
+void HandleAllocator::setBaseHandle(GLuint value)
+{
+ ASSERT(mBaseValue == mNextValue);
+ mBaseValue = value;
+ mNextValue = value;
+}
+
+GLuint HandleAllocator::allocate()
+{
+ if (mFreeValues.size())
+ {
+ GLuint handle = mFreeValues.back();
+ mFreeValues.pop_back();
+ return handle;
+ }
+ return mNextValue++;
+}
+
+void HandleAllocator::release(GLuint handle)
+{
+ if (handle == mNextValue - 1)
+ {
+ // Don't drop below base value
+ if(mNextValue > mBaseValue)
+ {
+ mNextValue--;
+ }
+ }
+ else
+ {
+ // Only free handles that we own - don't drop below the base value
+ if (handle >= mBaseValue)
+ {
+ mFreeValues.push_back(handle);
+ }
+ }
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.h b/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.h
new file mode 100644
index 0000000..a92e168
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/HandleAllocator.h
@@ -0,0 +1,45 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to
+// allocate GL handles.
+
+#ifndef LIBGLESV2_HANDLEALLOCATOR_H_
+#define LIBGLESV2_HANDLEALLOCATOR_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include <vector>
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+
+class HandleAllocator
+{
+ public:
+ HandleAllocator();
+ virtual ~HandleAllocator();
+
+ void setBaseHandle(GLuint value);
+
+ GLuint allocate();
+ void release(GLuint handle);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HandleAllocator);
+
+ GLuint mBaseValue;
+ GLuint mNextValue;
+ typedef std::vector<GLuint> HandleList;
+ HandleList mFreeValues;
+};
+
+}
+
+#endif // LIBGLESV2_HANDLEALLOCATOR_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.cpp
new file mode 100644
index 0000000..3dc0aef
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.cpp
@@ -0,0 +1,473 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexDataManager.cpp: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#include "libGLESv2/IndexDataManager.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+unsigned int IndexBuffer::mCurrentSerial = 1;
+
+IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device)
+{
+ mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
+
+ if (context->supports32bitIndices())
+ {
+ mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
+
+ if (!mStreamingBufferInt)
+ {
+ // Don't leave it in a half-initialized state
+ delete mStreamingBufferShort;
+ mStreamingBufferShort = NULL;
+ }
+ }
+ else
+ {
+ mStreamingBufferInt = NULL;
+ }
+
+ if (!mStreamingBufferShort)
+ {
+ ERR("Failed to allocate the streaming index buffer(s).");
+ }
+
+ mCountingBuffer = NULL;
+}
+
+IndexDataManager::~IndexDataManager()
+{
+ delete mStreamingBufferShort;
+ delete mStreamingBufferInt;
+ delete mCountingBuffer;
+}
+
+void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
+{
+ if (type == GL_UNSIGNED_BYTE)
+ {
+ const GLubyte *in = static_cast<const GLubyte*>(input);
+ GLushort *out = static_cast<GLushort*>(output);
+
+ for (GLsizei i = 0; i < count; i++)
+ {
+ out[i] = in[i];
+ }
+ }
+ else if (type == GL_UNSIGNED_INT)
+ {
+ memcpy(output, input, count * sizeof(GLuint));
+ }
+ else if (type == GL_UNSIGNED_SHORT)
+ {
+ memcpy(output, input, count * sizeof(GLushort));
+ }
+ else UNREACHABLE();
+}
+
+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 GLvoid *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_INT)
+ {
+ computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
+ }
+ else if (type == GL_UNSIGNED_SHORT)
+ {
+ computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
+ }
+ else UNREACHABLE();
+}
+
+GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
+{
+ if (!mStreamingBufferShort)
+ {
+ return GL_OUT_OF_MEMORY;
+ }
+
+ D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ bool alignedOffset = false;
+
+ if (buffer != NULL)
+ {
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break;
+ case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
+ case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break;
+ default: UNREACHABLE(); alignedOffset = false;
+ }
+
+ 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 = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
+
+ StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
+ IndexBuffer *indexBuffer = streamingBuffer;
+ UINT streamOffset = 0;
+
+ if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
+ {
+ indexBuffer = staticBuffer;
+ streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
+
+ if (streamOffset == -1)
+ {
+ streamOffset = (offset / typeSize(type)) * indexSize(format);
+ computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+ staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+ }
+ }
+ else
+ {
+ int convertCount = count;
+
+ if (staticBuffer)
+ {
+ if (staticBuffer->size() == 0 && alignedOffset)
+ {
+ indexBuffer = staticBuffer;
+ convertCount = buffer->size() / typeSize(type);
+ }
+ else
+ {
+ buffer->invalidateStaticData();
+ staticBuffer = NULL;
+ }
+ }
+
+ void *output = NULL;
+
+ if (indexBuffer)
+ {
+ indexBuffer->reserveSpace(convertCount * indexSize(format), type);
+ output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
+ }
+
+ if (output == NULL)
+ {
+ ERR("Failed to map index buffer.");
+ return GL_OUT_OF_MEMORY;
+ }
+
+ convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
+ indexBuffer->unmap();
+
+ computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
+
+ if (staticBuffer)
+ {
+ streamOffset = (offset / typeSize(type)) * indexSize(format);
+ staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
+ }
+ }
+
+ translated->indexBuffer = indexBuffer->getBuffer();
+ translated->serial = indexBuffer->getSerial();
+ translated->startIndex = streamOffset / indexSize(format);
+
+ if (buffer)
+ {
+ buffer->promoteStaticUsage(count * typeSize(type));
+ }
+
+ return GL_NO_ERROR;
+}
+
+std::size_t IndexDataManager::indexSize(D3DFORMAT format) const
+{
+ return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short);
+}
+
+std::size_t IndexDataManager::typeSize(GLenum type) const
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT: return sizeof(GLuint);
+ case GL_UNSIGNED_SHORT: return sizeof(GLushort);
+ case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
+ default: UNREACHABLE(); return sizeof(GLushort);
+ }
+}
+
+StaticIndexBuffer *IndexDataManager::getCountingIndices(GLsizei count)
+{
+ if (count <= 65536) // 16-bit indices
+ {
+ const unsigned int spaceNeeded = count * sizeof(unsigned short);
+
+ if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
+ {
+ delete mCountingBuffer;
+ mCountingBuffer = new StaticIndexBuffer(mDevice);
+ mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+
+ UINT offset;
+ unsigned short *data = static_cast<unsigned short*>(mCountingBuffer->map(spaceNeeded, &offset));
+
+ if (data)
+ {
+ for(int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+
+ mCountingBuffer->unmap();
+ }
+ }
+ }
+ else if (mStreamingBufferInt) // 32-bit indices supported
+ {
+ const unsigned int spaceNeeded = count * sizeof(unsigned int);
+
+ if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
+ {
+ delete mCountingBuffer;
+ mCountingBuffer = new StaticIndexBuffer(mDevice);
+ mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
+
+ UINT offset;
+ unsigned int *data = static_cast<unsigned int*>(mCountingBuffer->map(spaceNeeded, &offset));
+
+ if (data)
+ {
+ for(int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+
+ mCountingBuffer->unmap();
+ }
+ }
+ }
+ else return NULL;
+
+ return mCountingBuffer;
+}
+
+IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL)
+{
+ if (size > 0)
+ {
+ D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+ HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL);
+ mSerial = issueSerial();
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating an index buffer of size %lu.", size);
+ }
+ }
+}
+
+IndexBuffer::~IndexBuffer()
+{
+ if (mIndexBuffer)
+ {
+ mIndexBuffer->Release();
+ }
+}
+
+IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const
+{
+ return mIndexBuffer;
+}
+
+unsigned int IndexBuffer::getSerial() const
+{
+ return mSerial;
+}
+
+unsigned int IndexBuffer::issueSerial()
+{
+ return mCurrentSerial++;
+}
+
+void IndexBuffer::unmap()
+{
+ if (mIndexBuffer)
+ {
+ mIndexBuffer->Unlock();
+ }
+}
+
+StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format)
+{
+ mWritePosition = 0;
+}
+
+StreamingIndexBuffer::~StreamingIndexBuffer()
+{
+}
+
+void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset)
+{
+ void *mapPtr = NULL;
+
+ if (mIndexBuffer)
+ {
+ HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
+
+ if (FAILED(result))
+ {
+ ERR(" Lock failed with error 0x%08x", result);
+ return NULL;
+ }
+
+ *offset = mWritePosition;
+ mWritePosition += requiredSpace;
+ }
+
+ return mapPtr;
+}
+
+void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
+{
+ if (requiredSpace > mBufferSize)
+ {
+ if (mIndexBuffer)
+ {
+ mIndexBuffer->Release();
+ mIndexBuffer = NULL;
+ }
+
+ mBufferSize = std::max(requiredSpace, 2 * mBufferSize);
+
+ D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+ HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
+ mSerial = issueSerial();
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+ }
+
+ mWritePosition = 0;
+ }
+ else if (mWritePosition + requiredSpace > mBufferSize) // Recycle
+ {
+ void *dummy;
+ mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ mIndexBuffer->Unlock();
+
+ mWritePosition = 0;
+ }
+}
+
+StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN)
+{
+ mCacheType = GL_NONE;
+}
+
+StaticIndexBuffer::~StaticIndexBuffer()
+{
+}
+
+void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset)
+{
+ void *mapPtr = NULL;
+
+ if (mIndexBuffer)
+ {
+ HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
+
+ if (FAILED(result))
+ {
+ ERR(" Lock failed with error 0x%08x", result);
+ return NULL;
+ }
+
+ *offset = 0;
+ }
+
+ return mapPtr;
+}
+
+void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
+{
+ if (!mIndexBuffer && mBufferSize == 0)
+ {
+ D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY);
+ HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL);
+ mSerial = issueSerial();
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+ }
+
+ mBufferSize = requiredSpace;
+ mCacheType = type;
+ }
+ else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
+ {
+ // Already allocated
+ }
+ else UNREACHABLE(); // Static index buffers can't be resized
+}
+
+bool StaticIndexBuffer::lookupType(GLenum type)
+{
+ return mCacheType == type;
+}
+
+UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
+{
+ IndexRange range = {offset, count};
+
+ std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
+
+ if (res == mCache.end())
+ {
+ return -1;
+ }
+
+ *minIndex = res->second.minIndex;
+ *maxIndex = res->second.maxIndex;
+ return res->second.streamOffset;
+}
+
+void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset)
+{
+ IndexRange indexRange = {offset, count};
+ IndexResult indexResult = {minIndex, maxIndex, streamOffset};
+ mCache[indexRange] = indexResult;
+}
+
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.h
new file mode 100644
index 0000000..c1d4168
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/IndexDataManager.h
@@ -0,0 +1,149 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexDataManager.h: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#ifndef LIBGLESV2_INDEXDATAMANAGER_H_
+#define LIBGLESV2_INDEXDATAMANAGER_H_
+
+#include <vector>
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace
+{
+ enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
+}
+
+namespace gl
+{
+
+struct TranslatedIndexData
+{
+ UINT minIndex;
+ UINT maxIndex;
+ UINT startIndex;
+
+ IDirect3DIndexBuffer9 *indexBuffer;
+ unsigned int serial;
+};
+
+class IndexBuffer
+{
+ public:
+ IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format);
+ virtual ~IndexBuffer();
+
+ UINT size() const { return mBufferSize; }
+ virtual void *map(UINT requiredSpace, UINT *offset) = 0;
+ void unmap();
+ virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0;
+
+ IDirect3DIndexBuffer9 *getBuffer() const;
+ unsigned int getSerial() const;
+
+ protected:
+ IDirect3DDevice9 *const mDevice;
+
+ IDirect3DIndexBuffer9 *mIndexBuffer;
+ UINT mBufferSize;
+
+ unsigned int mSerial;
+ static unsigned int issueSerial();
+ static unsigned int mCurrentSerial;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
+};
+
+class StreamingIndexBuffer : public IndexBuffer
+{
+ public:
+ StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format);
+ ~StreamingIndexBuffer();
+
+ virtual void *map(UINT requiredSpace, UINT *offset);
+ virtual void reserveSpace(UINT requiredSpace, GLenum type);
+
+ private:
+ UINT mWritePosition;
+};
+
+class StaticIndexBuffer : public IndexBuffer
+{
+ public:
+ explicit StaticIndexBuffer(IDirect3DDevice9 *device);
+ ~StaticIndexBuffer();
+
+ virtual void *map(UINT requiredSpace, UINT *offset);
+ virtual void reserveSpace(UINT requiredSpace, GLenum type);
+
+ bool lookupType(GLenum type);
+ UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex); // Returns the offset into the index buffer, or -1 if not found
+ void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset);
+
+ private:
+ GLenum mCacheType;
+
+ struct IndexRange
+ {
+ intptr_t offset;
+ GLsizei count;
+
+ bool operator<(const IndexRange& rhs) const
+ {
+ if (offset != rhs.offset)
+ {
+ return offset < rhs.offset;
+ }
+ if (count != rhs.count)
+ {
+ return count < rhs.count;
+ }
+ return false;
+ }
+ };
+
+ struct IndexResult
+ {
+ UINT minIndex;
+ UINT maxIndex;
+ UINT streamOffset;
+ };
+
+ std::map<IndexRange, IndexResult> mCache;
+};
+
+class IndexDataManager
+{
+ public:
+ IndexDataManager(Context *context, IDirect3DDevice9 *evice);
+ virtual ~IndexDataManager();
+
+ GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
+ StaticIndexBuffer *getCountingIndices(GLsizei count);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
+
+ std::size_t typeSize(GLenum type) const;
+ std::size_t indexSize(D3DFORMAT format) const;
+
+ IDirect3DDevice9 *const mDevice;
+
+ StreamingIndexBuffer *mStreamingBufferShort;
+ StreamingIndexBuffer *mStreamingBufferInt;
+ StaticIndexBuffer *mCountingBuffer;
+};
+
+}
+
+#endif // LIBGLESV2_INDEXDATAMANAGER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp
index 780c3e3..a5e38bf 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -15,9 +15,16 @@
#include "libGLESv2/Shader.h"
#include "libGLESv2/utilities.h"
+#include <string>
+
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
+#endif
+
namespace gl
{
unsigned int Program::mCurrentSerial = 1;
+const char *fakepath = "C:\\fakepath";
std::string str(int i)
{
@@ -26,13 +33,13 @@ std::string str(int i)
return buffer;
}
-Uniform::Uniform(GLenum type, const std::string &name, unsigned int arraySize) : type(type), name(name), arraySize(arraySize)
+Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize)
+ : type(type), _name(_name), name(Program::undecorateUniform(_name)), arraySize(arraySize)
{
- int bytes = UniformTypeSize(type) * arraySize;
+ int bytes = UniformInternalSize(type) * arraySize;
data = new unsigned char[bytes];
memset(data, 0, bytes);
dirty = true;
- handlesSet = false;
}
Uniform::~Uniform()
@@ -40,13 +47,19 @@ Uniform::~Uniform()
delete[] data;
}
-UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index)
- : name(name), element(element), index(index)
+bool Uniform::isArray()
+{
+ return _name.compare(0, 3, "ar_") == 0;
+}
+
+UniformLocation::UniformLocation(const std::string &_name, unsigned int element, unsigned int index)
+ : name(Program::undecorateUniform(_name)), element(element), index(index)
{
}
Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial())
{
+ mDevice = getDevice();
mFragmentShader = NULL;
mVertexShader = NULL;
@@ -131,8 +144,6 @@ bool Program::detachShader(Shader *shader)
}
else UNREACHABLE();
- unlink();
-
return true;
}
@@ -182,28 +193,54 @@ GLuint Program::getAttributeLocation(const char *name)
int Program::getSemanticIndex(int attributeIndex)
{
- if (attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS)
+ ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
+
+ return mSemanticIndex[attributeIndex];
+}
+
+// Returns one more than the highest sampler index used.
+GLint Program::getUsedSamplerRange(SamplerType type)
+{
+ switch (type)
{
- return mSemanticIndex[attributeIndex];
+ case SAMPLER_PIXEL:
+ return mUsedPixelSamplerRange;
+ case SAMPLER_VERTEX:
+ return mUsedVertexSamplerRange;
+ default:
+ UNREACHABLE();
+ return 0;
}
-
- return -1;
}
-// Returns the index of the texture unit corresponding to a Direct3D 9 sampler
-// index referenced in the compiled HLSL shader
-GLint Program::getSamplerMapping(unsigned int samplerIndex)
+// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
+// index (0-15 for the pixel shader and 0-3 for the vertex shader).
+GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
{
- assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
-
GLint logicalTextureUnit = -1;
- if (mSamplers[samplerIndex].active)
+ switch (type)
{
- logicalTextureUnit = mSamplers[samplerIndex].logicalTextureUnit;
+ case SAMPLER_PIXEL:
+ ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
+
+ if (mSamplersPS[samplerIndex].active)
+ {
+ logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
+ }
+ break;
+ case SAMPLER_VERTEX:
+ ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
+
+ if (mSamplersVS[samplerIndex].active)
+ {
+ logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
+ }
+ break;
+ default: UNREACHABLE();
}
- if (logicalTextureUnit >= 0 && logicalTextureUnit < MAX_TEXTURE_IMAGE_UNITS)
+ if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)getContext()->getMaximumCombinedTextureImageUnits())
{
return logicalTextureUnit;
}
@@ -211,52 +248,43 @@ GLint Program::getSamplerMapping(unsigned int samplerIndex)
return -1;
}
-SamplerType Program::getSamplerType(unsigned int samplerIndex)
+// Returns the texture type for a given Direct3D 9 sampler type and
+// index (0-15 for the pixel shader and 0-3 for the vertex shader).
+TextureType Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
{
- assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
- assert(mSamplers[samplerIndex].active);
-
- return mSamplers[samplerIndex].type;
-}
-
-bool Program::isSamplerDirty(unsigned int samplerIndex) const
-{
- if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
+ switch (type)
{
- return mSamplers[samplerIndex].dirty;
+ case SAMPLER_PIXEL:
+ ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
+ ASSERT(mSamplersPS[samplerIndex].active);
+ return mSamplersPS[samplerIndex].textureType;
+ case SAMPLER_VERTEX:
+ ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
+ ASSERT(mSamplersVS[samplerIndex].active);
+ return mSamplersVS[samplerIndex].textureType;
+ default: UNREACHABLE();
}
- else UNREACHABLE();
-
- return false;
-}
-void Program::setSamplerDirty(unsigned int samplerIndex, bool dirty)
-{
- if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
- {
- mSamplers[samplerIndex].dirty = dirty;
- }
- else UNREACHABLE();
+ return TEXTURE_2D;
}
-GLint Program::getUniformLocation(const char *name, bool decorated)
+GLint Program::getUniformLocation(std::string name)
{
- std::string _name = decorated ? name : decorate(name);
- int subscript = 0;
+ unsigned int subscript = 0;
// Strip any trailing array operator and retrieve the subscript
- size_t open = _name.find_last_of('[');
- size_t close = _name.find_last_of(']');
- if (open != std::string::npos && close == _name.length() - 1)
+ size_t open = name.find_last_of('[');
+ size_t close = name.find_last_of(']');
+ if (open != std::string::npos && close == name.length() - 1)
{
- subscript = atoi(_name.substr(open + 1).c_str());
- _name.erase(open);
+ subscript = atoi(name.substr(open + 1).c_str());
+ name.erase(open);
}
unsigned int numUniforms = mUniformIndex.size();
for (unsigned int location = 0; location < numUniforms; location++)
{
- if (mUniformIndex[location].name == _name &&
+ if (mUniformIndex[location].name == name &&
mUniformIndex[location].element == subscript)
{
return location;
@@ -285,8 +313,17 @@ bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat),
- v, sizeof(GLfloat) * count);
+ GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+ for (int i = 0; i < count; i++)
+ {
+ target[0] = v[0];
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ target += 4;
+ v += 1;
+ }
}
else if (targetUniform->type == GL_BOOL)
{
@@ -296,7 +333,7 @@ bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- GLboolean *boolParams = new GLboolean[count];
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element;
for (int i = 0; i < count; ++i)
{
@@ -309,11 +346,6 @@ bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
boolParams[i] = GL_TRUE;
}
}
-
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
- boolParams, sizeof(GLboolean) * count);
-
- delete [] boolParams;
}
else
{
@@ -342,8 +374,17 @@ bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 2,
- v, 2 * sizeof(GLfloat) * count);
+ GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+ for (int i = 0; i < count; i++)
+ {
+ target[0] = v[0];
+ target[1] = v[1];
+ target[2] = 0;
+ target[3] = 0;
+ target += 4;
+ v += 2;
+ }
}
else if (targetUniform->type == GL_BOOL_VEC2)
{
@@ -354,7 +395,7 @@ bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- GLboolean *boolParams = new GLboolean[count * 2];
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2;
for (int i = 0; i < count * 2; ++i)
{
@@ -367,11 +408,6 @@ bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
boolParams[i] = GL_TRUE;
}
}
-
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
- boolParams, 2 * sizeof(GLboolean) * count);
-
- delete [] boolParams;
}
else
{
@@ -400,8 +436,17 @@ bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 3,
- v, 3 * sizeof(GLfloat) * count);
+ GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
+
+ for (int i = 0; i < count; i++)
+ {
+ target[0] = v[0];
+ target[1] = v[1];
+ target[2] = v[2];
+ target[3] = 0;
+ target += 4;
+ v += 3;
+ }
}
else if (targetUniform->type == GL_BOOL_VEC3)
{
@@ -411,7 +456,7 @@ bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- GLboolean *boolParams = new GLboolean[count * 3];
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3;
for (int i = 0; i < count * 3; ++i)
{
@@ -424,11 +469,6 @@ bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
boolParams[i] = GL_TRUE;
}
}
-
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
- boolParams, 3 * sizeof(GLboolean) * count);
-
- delete [] boolParams;
}
else
{
@@ -468,7 +508,7 @@ bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- GLboolean *boolParams = new GLboolean[count * 4];
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4;
for (int i = 0; i < count * 4; ++i)
{
@@ -481,11 +521,6 @@ bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
boolParams[i] = GL_TRUE;
}
}
-
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
- boolParams, 4 * sizeof(GLboolean) * count);
-
- delete [] boolParams;
}
else
{
@@ -495,6 +530,37 @@ bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
return true;
}
+template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight>
+void transposeMatrix(T *target, const GLfloat *value)
+{
+ int copyWidth = std::min(targetWidth, srcWidth);
+ int copyHeight = std::min(targetHeight, srcHeight);
+
+ for (int x = 0; x < copyWidth; x++)
+ {
+ for (int y = 0; y < copyHeight; y++)
+ {
+ target[x * targetWidth + y] = (T)value[y * srcWidth + x];
+ }
+ }
+ // clear unfilled right side
+ for (int y = 0; y < copyHeight; y++)
+ {
+ for (int x = srcWidth; x < targetWidth; x++)
+ {
+ target[y * targetWidth + x] = (T)0;
+ }
+ }
+ // clear unfilled bottom.
+ for (int y = srcHeight; y < targetHeight; y++)
+ {
+ for (int x = 0; x < targetWidth; x++)
+ {
+ target[y * targetWidth + x] = (T)0;
+ }
+ }
+}
+
bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
{
if (location < 0 || location >= (int)mUniformIndex.size())
@@ -517,8 +583,13 @@ bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
- value, 4 * sizeof(GLfloat) * count);
+ GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8;
+ for (int i = 0; i < count; i++)
+ {
+ transposeMatrix<GLfloat,4,2,2,2>(target, value);
+ target += 8;
+ value += 4;
+ }
return true;
}
@@ -545,12 +616,18 @@ bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 9,
- value, 9 * sizeof(GLfloat) * count);
+ GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12;
+ for (int i = 0; i < count; i++)
+ {
+ transposeMatrix<GLfloat,4,3,3,3>(target, value);
+ target += 12;
+ value += 9;
+ }
return true;
}
+
bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
{
if (location < 0 || location >= (int)mUniformIndex.size())
@@ -573,8 +650,13 @@ bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16,
- value, 16 * sizeof(GLfloat) * count);
+ GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16);
+ for (int i = 0; i < count; i++)
+ {
+ transposeMatrix<GLfloat,4,4,4,4>(target, value);
+ target += 16;
+ value += 16;
+ }
return true;
}
@@ -611,7 +693,7 @@ bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- GLboolean *boolParams = new GLboolean[count];
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element;
for (int i = 0; i < count; ++i)
{
@@ -624,11 +706,6 @@ bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
boolParams[i] = GL_TRUE;
}
}
-
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
- boolParams, sizeof(GLboolean) * count);
-
- delete [] boolParams;
}
else
{
@@ -668,7 +745,7 @@ bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- GLboolean *boolParams = new GLboolean[count * 2];
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2;
for (int i = 0; i < count * 2; ++i)
{
@@ -681,11 +758,6 @@ bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
boolParams[i] = GL_TRUE;
}
}
-
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
- boolParams, 2 * sizeof(GLboolean) * count);
-
- delete [] boolParams;
}
else
{
@@ -725,7 +797,7 @@ bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- GLboolean *boolParams = new GLboolean[count * 3];
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3;
for (int i = 0; i < count * 3; ++i)
{
@@ -738,11 +810,6 @@ bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
boolParams[i] = GL_TRUE;
}
}
-
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
- boolParams, 3 * sizeof(GLboolean) * count);
-
- delete [] boolParams;
}
else
{
@@ -782,7 +849,7 @@ bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
count = std::min(arraySize - (int)mUniformIndex[location].element, count);
- GLboolean *boolParams = new GLboolean[count * 4];
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4;
for (int i = 0; i < count * 4; ++i)
{
@@ -795,11 +862,6 @@ bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
boolParams[i] = GL_TRUE;
}
}
-
- memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
- boolParams, 4 * sizeof(GLboolean) * count);
-
- delete [] boolParams;
}
else
{
@@ -809,7 +871,7 @@ bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
return true;
}
-bool Program::getUniformfv(GLint location, GLfloat *params)
+bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
{
if (location < 0 || location >= (int)mUniformIndex.size())
{
@@ -818,41 +880,67 @@ bool Program::getUniformfv(GLint location, GLfloat *params)
Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- unsigned int count = UniformComponentCount(targetUniform->type);
-
- switch (UniformComponentType(targetUniform->type))
+ // sized queries -- ensure the provided buffer is large enough
+ if (bufSize)
{
- case GL_BOOL:
+ int requiredBytes = UniformExternalSize(targetUniform->type);
+ if (*bufSize < requiredBytes)
{
- GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * count;
-
- for (unsigned int i = 0; i < count; ++i)
- {
- params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
- }
+ return false;
}
+ }
+
+ switch (targetUniform->type)
+ {
+ case GL_FLOAT_MAT2:
+ transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
+ break;
+ case GL_FLOAT_MAT3:
+ transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
break;
- case GL_FLOAT:
- memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLfloat),
- count * sizeof(GLfloat));
+ case GL_FLOAT_MAT4:
+ transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
break;
- case GL_INT:
+ default:
{
- GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * count;
+ unsigned int count = UniformExternalComponentCount(targetUniform->type);
+ unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
- for (unsigned int i = 0; i < count; ++i)
+ switch (UniformComponentType(targetUniform->type))
{
- params[i] = (float)intParams[i];
+ case GL_BOOL:
+ {
+ GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
+ }
+ }
+ break;
+ case GL_FLOAT:
+ memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLfloat),
+ count * sizeof(GLfloat));
+ break;
+ case GL_INT:
+ {
+ GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ params[i] = (float)intParams[i];
+ }
+ }
+ break;
+ default: UNREACHABLE();
}
}
- break;
- default: UNREACHABLE();
}
return true;
}
-bool Program::getUniformiv(GLint location, GLint *params)
+bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
{
if (location < 0 || location >= (int)mUniformIndex.size())
{
@@ -861,35 +949,67 @@ bool Program::getUniformiv(GLint location, GLint *params)
Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
- unsigned int count = UniformComponentCount(targetUniform->type);
-
- switch (UniformComponentType(targetUniform->type))
+ // sized queries -- ensure the provided buffer is large enough
+ if (bufSize)
{
- case GL_BOOL:
+ int requiredBytes = UniformExternalSize(targetUniform->type);
+ if (*bufSize < requiredBytes)
{
- GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * count;
+ return false;
+ }
+ }
- for (unsigned int i = 0; i < count; ++i)
- {
- params[i] = (GLint)boolParams[i];
- }
+ switch (targetUniform->type)
+ {
+ case GL_FLOAT_MAT2:
+ {
+ transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
+ }
+ break;
+ case GL_FLOAT_MAT3:
+ {
+ transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
}
break;
- case GL_FLOAT:
+ case GL_FLOAT_MAT4:
+ {
+ transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
+ }
+ break;
+ default:
{
- GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * count;
+ unsigned int count = UniformExternalComponentCount(targetUniform->type);
+ unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
- for (unsigned int i = 0; i < count; ++i)
+ switch (UniformComponentType(targetUniform->type))
{
- params[i] = (GLint)floatParams[i];
+ case GL_BOOL:
+ {
+ GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * internalCount;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ params[i] = (GLint)boolParams[i];
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * internalCount;
+
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ params[i] = (GLint)floatParams[i];
+ }
+ }
+ break;
+ case GL_INT:
+ memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLint),
+ count * sizeof(GLint));
+ break;
+ default: UNREACHABLE();
}
}
- break;
- case GL_INT:
- memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLint),
- count * sizeof(GLint));
- break;
- default: UNREACHABLE();
}
return true;
@@ -904,26 +1024,11 @@ void Program::dirtyAllUniforms()
}
}
-void Program::dirtyAllSamplers()
-{
- for (unsigned int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; ++index)
- {
- mSamplers[index].dirty = true;
- }
-}
-
// Applies all the uniforms set for this program object to the Direct3D 9 device
void Program::applyUniforms()
{
- unsigned int numUniforms = mUniformIndex.size();
- for (unsigned int location = 0; location < numUniforms; location++)
- {
- if (mUniformIndex[location].element != 0)
- {
- continue;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+ for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) {
+ Uniform *targetUniform = *ub;
if (targetUniform->dirty)
{
@@ -934,23 +1039,23 @@ void Program::applyUniforms()
switch (targetUniform->type)
{
- case GL_BOOL: applyUniform1bv(location, arraySize, b); break;
- case GL_BOOL_VEC2: applyUniform2bv(location, arraySize, b); break;
- case GL_BOOL_VEC3: applyUniform3bv(location, arraySize, b); break;
- case GL_BOOL_VEC4: applyUniform4bv(location, arraySize, b); break;
- case GL_FLOAT: applyUniform1fv(location, arraySize, f); break;
- case GL_FLOAT_VEC2: applyUniform2fv(location, arraySize, f); break;
- case GL_FLOAT_VEC3: applyUniform3fv(location, arraySize, f); break;
- case GL_FLOAT_VEC4: applyUniform4fv(location, arraySize, f); break;
- case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, arraySize, f); break;
- case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, arraySize, f); break;
- case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, arraySize, f); break;
+ case GL_BOOL: applyUniformnbv(targetUniform, arraySize, 1, b); break;
+ case GL_BOOL_VEC2: applyUniformnbv(targetUniform, arraySize, 2, b); break;
+ case GL_BOOL_VEC3: applyUniformnbv(targetUniform, arraySize, 3, b); break;
+ case GL_BOOL_VEC4: applyUniformnbv(targetUniform, arraySize, 4, b); break;
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT4: applyUniformnfv(targetUniform, f); break;
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
- case GL_INT: applyUniform1iv(location, arraySize, i); break;
- case GL_INT_VEC2: applyUniform2iv(location, arraySize, i); break;
- case GL_INT_VEC3: applyUniform3iv(location, arraySize, i); break;
- case GL_INT_VEC4: applyUniform4iv(location, arraySize, i); break;
+ case GL_INT: applyUniform1iv(targetUniform, arraySize, i); break;
+ case GL_INT_VEC2: applyUniform2iv(targetUniform, arraySize, i); break;
+ case GL_INT_VEC3: applyUniform3iv(targetUniform, arraySize, i); break;
+ case GL_INT_VEC4: applyUniform4iv(targetUniform, arraySize, i); break;
default:
UNREACHABLE();
}
@@ -961,38 +1066,76 @@ void Program::applyUniforms()
}
// Compiles the HLSL code of the attached shaders into executable binaries
-ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
+ID3D10Blob *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
{
if (!hlsl)
{
return NULL;
}
- ID3DXBuffer *binary = NULL;
- ID3DXBuffer *errorMessage = NULL;
-
- HRESULT result = D3DXCompileShader(hlsl, (UINT)strlen(hlsl), NULL, NULL, "main", profile, 0, &binary, &errorMessage, constantTable);
-
- if (SUCCEEDED(result))
+ DWORD result;
+ UINT flags = 0;
+ std::string sourceText;
+ if (perfActive())
{
- return binary;
- }
+ flags |= D3DCOMPILE_DEBUG;
+#ifdef NDEBUG
+ flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
+#else
+ flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ std::string sourcePath = getTempPath();
+ sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
+ writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
+ }
+ else
{
- return error(GL_OUT_OF_MEMORY, (ID3DXBuffer*)NULL);
+ flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
+ sourceText = hlsl;
}
+ ID3D10Blob *binary = NULL;
+ ID3D10Blob *errorMessage = NULL;
+ result = D3DCompile(hlsl, strlen(hlsl), fakepath, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage);
+
if (errorMessage)
{
const char *message = (const char*)errorMessage->GetBufferPointer();
- appendToInfoLog("%s\n", message);
+ appendToInfoLogSanitized(message);
TRACE("\n%s", hlsl);
TRACE("\n%s", message);
+
+ errorMessage->Release();
+ errorMessage = NULL;
+ }
+
+ if (FAILED(result))
+ {
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ error(GL_OUT_OF_MEMORY);
+ }
+
+ return NULL;
+ }
+
+ result = D3DXGetShaderConstantTable(static_cast<const DWORD*>(binary->GetBufferPointer()), constantTable);
+
+ if (FAILED(result))
+ {
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ error(GL_OUT_OF_MEMORY);
+ }
+
+ binary->Release();
+
+ return NULL;
}
- return NULL;
+ return binary;
}
// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
@@ -1002,7 +1145,7 @@ int Program::packVaryings(const Varying *packing[][4])
Context *context = getContext();
const int maxVaryingVectors = context->getMaximumVaryingVectors();
- for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
+ for (VaryingList::iterator varying = mFragmentShader->mVaryings.begin(); varying != mFragmentShader->mVaryings.end(); varying++)
{
int n = VariableRowCount(varying->type) * varying->size;
int m = VariableColumnCount(varying->type);
@@ -1093,13 +1236,13 @@ int Program::packVaryings(const Varying *packing[][4])
for (int x = 0; x < 4; x++)
{
- if (space[x] > n && space[x] < space[column])
+ if (space[x] >= n && space[x] < space[column])
{
column = x;
}
}
- if (space[column] > n)
+ if (space[column] >= n)
{
for (int r = 0; r < maxVaryingVectors; r++)
{
@@ -1152,6 +1295,20 @@ bool Program::linkVaryings()
return false;
}
+ // Reset the varying register assignments
+ for (VaryingList::iterator fragVar = mFragmentShader->mVaryings.begin(); fragVar != mFragmentShader->mVaryings.end(); fragVar++)
+ {
+ fragVar->reg = -1;
+ fragVar->col = -1;
+ }
+
+ for (VaryingList::iterator vtxVar = mVertexShader->mVaryings.begin(); vtxVar != mVertexShader->mVaryings.end(); vtxVar++)
+ {
+ vtxVar->reg = -1;
+ vtxVar->col = -1;
+ }
+
+ // Map the varyings to the register file
const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
int registers = packVaryings(packing);
@@ -1160,6 +1317,7 @@ bool Program::linkVaryings()
return false;
}
+ // Write the HLSL input/output declarations
Context *context = getContext();
const bool sm3 = context->supportsShaderModel3();
const int maxVaryingVectors = context->getMaximumVaryingVectors();
@@ -1171,11 +1329,11 @@ bool Program::linkVaryings()
return false;
}
- for (VaryingList::iterator input = mFragmentShader->varyings.begin(); input != mFragmentShader->varyings.end(); input++)
+ for (VaryingList::iterator input = mFragmentShader->mVaryings.begin(); input != mFragmentShader->mVaryings.end(); input++)
{
bool matched = false;
- for (VaryingList::iterator output = mVertexShader->varyings.begin(); output != mVertexShader->varyings.end(); output++)
+ for (VaryingList::iterator output = mVertexShader->mVaryings.begin(); output != mVertexShader->mVaryings.end(); output++)
{
if (output->name == input->name)
{
@@ -1196,7 +1354,7 @@ bool Program::linkVaryings()
if (!matched)
{
- appendToInfoLog("Fragment varying varying %s does not match any vertex varying", input->name.c_str());
+ appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
return false;
}
@@ -1222,7 +1380,7 @@ bool Program::linkVaryings()
default: UNREACHABLE();
}
- mVertexHLSL += decorate(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
+ mVertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
semanticIndex += VariableRowCount(attribute->type);
}
@@ -1257,14 +1415,14 @@ bool Program::linkVaryings()
for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
{
- mVertexHLSL += " " + decorate(attribute->name) + " = ";
+ mVertexHLSL += " " + decorateAttribute(attribute->name) + " = ";
if (VariableRowCount(attribute->type) > 1) // Matrix
{
mVertexHLSL += "transpose";
}
- mVertexHLSL += "(input." + decorate(attribute->name) + ");\n";
+ mVertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
}
mVertexHLSL += "\n"
@@ -1272,7 +1430,7 @@ bool Program::linkVaryings()
"\n"
" VS_OUTPUT output;\n"
" output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
- " output.gl_Position.y = -(gl_Position.y - dx_HalfPixelSize.y * gl_Position.w);\n"
+ " output.gl_Position.y = gl_Position.y - dx_HalfPixelSize.y * gl_Position.w;\n"
" output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.gl_Position.w = gl_Position.w;\n";
@@ -1286,7 +1444,7 @@ bool Program::linkVaryings()
mVertexHLSL += " output.gl_FragCoord = gl_Position;\n";
}
- for (VaryingList::iterator varying = mVertexShader->varyings.begin(); varying != mVertexShader->varyings.end(); varying++)
+ for (VaryingList::iterator varying = mVertexShader->mVaryings.begin(); varying != mVertexShader->mVaryings.end(); varying++)
{
if (varying->reg >= 0)
{
@@ -1354,7 +1512,7 @@ bool Program::linkVaryings()
mPixelHLSL += "struct PS_INPUT\n"
"{\n";
- for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
+ for (VaryingList::iterator varying = mFragmentShader->mVaryings.begin(); varying != mFragmentShader->mVaryings.end(); varying++)
{
if (varying->reg >= 0)
{
@@ -1402,20 +1560,27 @@ bool Program::linkVaryings()
if (mFragmentShader->mUsesFragCoord)
{
mPixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
- if (sm3) {
- mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n"
- " gl_FragCoord.y = input.dx_VPos.y;\n";
- } else {
- mPixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Viewport.x + dx_Viewport.z;\n"
- " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Viewport.y + dx_Viewport.w;\n";
+
+ if (sm3)
+ {
+ // dx_Coord.y contains the render target height. See Context::applyRenderTarget()
+ mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
+ " gl_FragCoord.y = dx_Coord.y - input.dx_VPos.y - 0.5;\n";
}
+ else
+ {
+ // dx_Coord contains the viewport width/2, height/2, center.x and center.y. See Context::applyRenderTarget()
+ mPixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Coord.x + dx_Coord.z;\n"
+ " gl_FragCoord.y = -(input.gl_FragCoord.y * rhw) * dx_Coord.y + dx_Coord.w;\n";
+ }
+
mPixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
" gl_FragCoord.w = rhw;\n";
}
if (mFragmentShader->mUsesPointCoord && sm3)
{
- mPixelHLSL += " gl_PointCoord = float2(input.gl_PointCoord.x, 1.0 - input.gl_PointCoord.y);\n";
+ mPixelHLSL += " gl_PointCoord = input.gl_PointCoord;\n";
}
if (mFragmentShader->mUsesFrontFacing)
@@ -1423,7 +1588,7 @@ bool Program::linkVaryings()
mPixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
}
- for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
+ for (VaryingList::iterator varying = mFragmentShader->mVaryings.begin(); varying != mFragmentShader->mVaryings.end(); varying++)
{
if (varying->reg >= 0)
{
@@ -1461,9 +1626,6 @@ bool Program::linkVaryings()
" return output;\n"
"}\n";
- TRACE("\n%s", mPixelHLSL.c_str());
- TRACE("\n%s", mVertexHLSL.c_str());
-
return true;
}
@@ -1496,14 +1658,13 @@ void Program::link()
const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
- ID3DXBuffer *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
- ID3DXBuffer *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
+ ID3D10Blob *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
+ ID3D10Blob *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
if (vertexBinary && pixelBinary)
{
- IDirect3DDevice9 *device = getDevice();
- HRESULT vertexResult = device->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
- HRESULT pixelResult = device->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
+ HRESULT vertexResult = mDevice->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
+ HRESULT pixelResult = mDevice->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
{
@@ -1536,12 +1697,12 @@ void Program::link()
// these uniforms are searched as already-decorated because gl_ and dx_
// are reserved prefixes, and do not receive additional decoration
- mDxDepthRangeLocation = getUniformLocation("dx_DepthRange", true);
- mDxDepthLocation = getUniformLocation("dx_Depth", true);
- mDxViewportLocation = getUniformLocation("dx_Viewport", true);
- mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize", true);
- mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW", true);
- mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines", true);
+ mDxDepthRangeLocation = getUniformLocation("dx_DepthRange");
+ mDxDepthLocation = getUniformLocation("dx_Depth");
+ mDxCoordLocation = getUniformLocation("dx_Coord");
+ mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize");
+ mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW");
+ mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines");
mLinked = true; // Success
}
@@ -1642,7 +1803,8 @@ bool Program::linkUniforms(ID3DXConstantTable *constantTable)
for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
{
D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
- constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
+ HRESULT result = constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
+ ASSERT(SUCCEEDED(result));
if (!defineUniform(constantHandle, constantDescription))
{
@@ -1659,14 +1821,46 @@ bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT
{
if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
{
- for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++)
+ for (unsigned int i = 0; i < constantDescription.RegisterCount; i++)
{
- ASSERT(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
+ D3DXHANDLE psConstant = mConstantTablePS->GetConstantByName(NULL, constantDescription.Name);
+ D3DXHANDLE vsConstant = mConstantTableVS->GetConstantByName(NULL, constantDescription.Name);
- mSamplers[samplerIndex].active = true;
- mSamplers[samplerIndex].type = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? SAMPLER_CUBE : SAMPLER_2D;
- mSamplers[samplerIndex].logicalTextureUnit = 0;
- mSamplers[samplerIndex].dirty = true;
+ if (psConstant)
+ {
+ unsigned int samplerIndex = mConstantTablePS->GetSamplerIndex(psConstant) + i;
+
+ if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+ {
+ mSamplersPS[samplerIndex].active = true;
+ mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
+ mSamplersPS[samplerIndex].logicalTextureUnit = 0;
+ mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
+ }
+ else
+ {
+ appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
+ return false;
+ }
+ }
+
+ if (vsConstant)
+ {
+ unsigned int samplerIndex = mConstantTableVS->GetSamplerIndex(vsConstant) + i;
+
+ if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
+ {
+ mSamplersVS[samplerIndex].active = true;
+ mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
+ mSamplersVS[samplerIndex].logicalTextureUnit = 0;
+ mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
+ }
+ else
+ {
+ appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
+ return false;
+ }
+ }
}
}
@@ -1683,7 +1877,8 @@ bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT
D3DXCONSTANT_DESC fieldDescription;
UINT descriptionCount = 1;
- mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
+ HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
+ ASSERT(SUCCEEDED(result));
std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
@@ -1707,9 +1902,9 @@ bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT
}
}
-bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
+bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, const std::string &_name)
{
- Uniform *uniform = createUniform(constantDescription, name);
+ Uniform *uniform = createUniform(constantDescription, _name);
if(!uniform)
{
@@ -1717,7 +1912,7 @@ bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::s
}
// Check if already defined
- GLint location = getUniformLocation(name.c_str(), true);
+ GLint location = getUniformLocation(uniform->name);
GLenum type = uniform->type;
if (location >= 0)
@@ -1734,18 +1929,21 @@ bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::s
}
}
+ initializeConstantHandles(uniform, &uniform->ps, mConstantTablePS);
+ initializeConstantHandles(uniform, &uniform->vs, mConstantTableVS);
+
mUniforms.push_back(uniform);
unsigned int uniformIndex = mUniforms.size() - 1;
for (unsigned int i = 0; i < uniform->arraySize; ++i)
{
- mUniformIndex.push_back(UniformLocation(name, i, uniformIndex));
+ mUniformIndex.push_back(UniformLocation(_name, i, uniformIndex));
}
return true;
}
-Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
+Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, const std::string &_name)
{
if (constantDescription.Rows == 1) // Vectors and scalars
{
@@ -1754,44 +1952,44 @@ Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, st
case D3DXPT_SAMPLER2D:
switch (constantDescription.Columns)
{
- case 1: return new Uniform(GL_SAMPLER_2D, name, constantDescription.Elements);
+ case 1: return new Uniform(GL_SAMPLER_2D, _name, constantDescription.Elements);
default: UNREACHABLE();
}
break;
case D3DXPT_SAMPLERCUBE:
switch (constantDescription.Columns)
{
- case 1: return new Uniform(GL_SAMPLER_CUBE, name, constantDescription.Elements);
+ case 1: return new Uniform(GL_SAMPLER_CUBE, _name, constantDescription.Elements);
default: UNREACHABLE();
}
break;
case D3DXPT_BOOL:
switch (constantDescription.Columns)
{
- case 1: return new Uniform(GL_BOOL, name, constantDescription.Elements);
- case 2: return new Uniform(GL_BOOL_VEC2, name, constantDescription.Elements);
- case 3: return new Uniform(GL_BOOL_VEC3, name, constantDescription.Elements);
- case 4: return new Uniform(GL_BOOL_VEC4, name, constantDescription.Elements);
+ case 1: return new Uniform(GL_BOOL, _name, constantDescription.Elements);
+ case 2: return new Uniform(GL_BOOL_VEC2, _name, constantDescription.Elements);
+ case 3: return new Uniform(GL_BOOL_VEC3, _name, constantDescription.Elements);
+ case 4: return new Uniform(GL_BOOL_VEC4, _name, constantDescription.Elements);
default: UNREACHABLE();
}
break;
case D3DXPT_INT:
switch (constantDescription.Columns)
{
- case 1: return new Uniform(GL_INT, name, constantDescription.Elements);
- case 2: return new Uniform(GL_INT_VEC2, name, constantDescription.Elements);
- case 3: return new Uniform(GL_INT_VEC3, name, constantDescription.Elements);
- case 4: return new Uniform(GL_INT_VEC4, name, constantDescription.Elements);
+ case 1: return new Uniform(GL_INT, _name, constantDescription.Elements);
+ case 2: return new Uniform(GL_INT_VEC2, _name, constantDescription.Elements);
+ case 3: return new Uniform(GL_INT_VEC3, _name, constantDescription.Elements);
+ case 4: return new Uniform(GL_INT_VEC4, _name, constantDescription.Elements);
default: UNREACHABLE();
}
break;
case D3DXPT_FLOAT:
switch (constantDescription.Columns)
{
- case 1: return new Uniform(GL_FLOAT, name, constantDescription.Elements);
- case 2: return new Uniform(GL_FLOAT_VEC2, name, constantDescription.Elements);
- case 3: return new Uniform(GL_FLOAT_VEC3, name, constantDescription.Elements);
- case 4: return new Uniform(GL_FLOAT_VEC4, name, constantDescription.Elements);
+ case 1: return new Uniform(GL_FLOAT, _name, constantDescription.Elements);
+ case 2: return new Uniform(GL_FLOAT_VEC2, _name, constantDescription.Elements);
+ case 3: return new Uniform(GL_FLOAT_VEC3, _name, constantDescription.Elements);
+ case 4: return new Uniform(GL_FLOAT_VEC4, _name, constantDescription.Elements);
default: UNREACHABLE();
}
break;
@@ -1806,9 +2004,9 @@ Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, st
case D3DXPT_FLOAT:
switch (constantDescription.Rows)
{
- case 2: return new Uniform(GL_FLOAT_MAT2, name, constantDescription.Elements);
- case 3: return new Uniform(GL_FLOAT_MAT3, name, constantDescription.Elements);
- case 4: return new Uniform(GL_FLOAT_MAT4, name, constantDescription.Elements);
+ case 2: return new Uniform(GL_FLOAT_MAT2, _name, constantDescription.Elements);
+ case 3: return new Uniform(GL_FLOAT_MAT3, _name, constantDescription.Elements);
+ case 4: return new Uniform(GL_FLOAT_MAT4, _name, constantDescription.Elements);
default: UNREACHABLE();
}
break;
@@ -1821,410 +2019,125 @@ Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, st
}
// This method needs to match OutputHLSL::decorate
-std::string Program::decorate(const std::string &string)
-{
- if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
- {
- return "_" + string;
- }
- else
- {
- return string;
- }
-}
-
-std::string Program::undecorate(const std::string &string)
+std::string Program::decorateAttribute(const std::string &name)
{
- if (string.substr(0, 1) == "_")
+ if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
{
- return string.substr(1);
+ return "_" + name;
}
- else
- {
- return string;
- }
-}
-
-bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)
-{
- BOOL *vector = new BOOL[count];
- for (int i = 0; i < count; i++)
- {
- if (v[i] == GL_FALSE)
- vector[i] = 0;
- else
- vector[i] = 1;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
-
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetBoolArray(device, constantPS, vector, count);
- }
-
- if (constantVS)
- {
- mConstantTableVS->SetBoolArray(device, constantVS, vector, count);
- }
-
- delete [] vector;
-
- return true;
-}
-
-bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)
-{
- D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
-
- for (int i = 0; i < count; i++)
- {
- vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
- (v[1] == GL_FALSE ? 0.0f : 1.0f), 0, 0);
-
- v += 2;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
- }
-
- if (constantVS)
- {
- mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
- }
-
- delete[] vector;
-
- return true;
-}
-
-bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)
-{
- D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
-
- for (int i = 0; i < count; i++)
- {
- vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
- (v[1] == GL_FALSE ? 0.0f : 1.0f),
- (v[2] == GL_FALSE ? 0.0f : 1.0f), 0);
-
- v += 3;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
- }
-
- if (constantVS)
- {
- mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
- }
-
- delete[] vector;
-
- return true;
-}
-
-bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)
-{
- D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
-
- for (int i = 0; i < count; i++)
- {
- vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
- (v[1] == GL_FALSE ? 0.0f : 1.0f),
- (v[2] == GL_FALSE ? 0.0f : 1.0f),
- (v[3] == GL_FALSE ? 0.0f : 1.0f));
-
- v += 3;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
- }
-
- if (constantVS)
- {
- mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
- }
-
- delete [] vector;
-
- return true;
-}
-
-bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
-{
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetFloatArray(device, constantPS, v, count);
- }
-
- if (constantVS)
- {
- mConstantTableVS->SetFloatArray(device, constantVS, v, count);
- }
-
- return true;
+
+ return name;
}
-bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+std::string Program::undecorateUniform(const std::string &_name)
{
- D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
-
- for (int i = 0; i < count; i++)
+ if (_name[0] == '_')
{
- vector[i] = D3DXVECTOR4(v[0], v[1], 0, 0);
-
- v += 2;
+ return _name.substr(1);
}
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
- }
-
- if (constantVS)
+ else if (_name.compare(0, 3, "ar_") == 0)
{
- mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ return _name.substr(3);
}
-
- delete[] vector;
-
- return true;
+
+ return _name;
}
-bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+void Program::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v)
{
- D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+ float vector[D3D9_MAX_FLOAT_CONSTANTS * 4];
+ BOOL boolVector[D3D9_MAX_BOOL_CONSTANTS];
- for (int i = 0; i < count; i++)
+ if (targetUniform->ps.registerCount && targetUniform->ps.registerSet == D3DXRS_FLOAT4 ||
+ targetUniform->vs.registerCount && targetUniform->vs.registerSet == D3DXRS_FLOAT4)
{
- vector[i] = D3DXVECTOR4(v[0], v[1], v[2], 0);
-
- v += 3;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+ for (int i = 0; i < count; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ if (j < width)
+ {
+ vector[i * 4 + j] = (v[i * width + j] == GL_FALSE) ? 0.0f : 1.0f;
+ }
+ else
+ {
+ vector[i * 4 + j] = 0.0f;
+ }
+ }
+ }
}
- if (constantVS)
+ if (targetUniform->ps.registerCount && targetUniform->ps.registerSet == D3DXRS_BOOL ||
+ targetUniform->vs.registerCount && targetUniform->vs.registerSet == D3DXRS_BOOL)
{
- mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ int psCount = targetUniform->ps.registerSet == D3DXRS_BOOL ? targetUniform->ps.registerCount : 0;
+ int vsCount = targetUniform->vs.registerSet == D3DXRS_BOOL ? targetUniform->vs.registerCount : 0;
+ int copyCount = std::min(count * width, std::max(psCount, vsCount));
+ ASSERT(copyCount <= D3D9_MAX_BOOL_CONSTANTS);
+ for (int i = 0; i < copyCount; i++)
+ {
+ boolVector[i] = v[i] != GL_FALSE;
+ }
}
- delete[] vector;
-
- return true;
-}
-
-bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
-{
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
+ if (targetUniform->ps.registerCount)
{
- mConstantTablePS->SetVectorArray(device, constantPS, (D3DXVECTOR4*)v, count);
+ if (targetUniform->ps.registerSet == D3DXRS_FLOAT4)
+ {
+ mDevice->SetPixelShaderConstantF(targetUniform->ps.registerIndex, vector, targetUniform->ps.registerCount);
+ }
+ else if (targetUniform->ps.registerSet == D3DXRS_BOOL)
+ {
+ mDevice->SetPixelShaderConstantB(targetUniform->ps.registerIndex, boolVector, targetUniform->ps.registerCount);
+ }
+ else UNREACHABLE();
}
- if (constantVS)
+ if (targetUniform->vs.registerCount)
{
- mConstantTableVS->SetVectorArray(device, constantVS, (D3DXVECTOR4*)v, count);
+ if (targetUniform->vs.registerSet == D3DXRS_FLOAT4)
+ {
+ mDevice->SetVertexShaderConstantF(targetUniform->vs.registerIndex, vector, targetUniform->vs.registerCount);
+ }
+ else if (targetUniform->vs.registerSet == D3DXRS_BOOL)
+ {
+ mDevice->SetVertexShaderConstantB(targetUniform->vs.registerIndex, boolVector, targetUniform->vs.registerCount);
+ }
+ else UNREACHABLE();
}
-
- return true;
}
-bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
+bool Program::applyUniformnfv(Uniform *targetUniform, const GLfloat *v)
{
- D3DXMATRIX *matrix = new D3DXMATRIX[count];
-
- for (int i = 0; i < count; i++)
+ if (targetUniform->ps.registerCount)
{
- matrix[i] = D3DXMATRIX(value[0], value[2], 0, 0,
- value[1], value[3], 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1);
-
- value += 4;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
+ mDevice->SetPixelShaderConstantF(targetUniform->ps.registerIndex, v, targetUniform->ps.registerCount);
}
- if (constantVS)
+ if (targetUniform->vs.registerCount)
{
- mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
+ mDevice->SetVertexShaderConstantF(targetUniform->vs.registerIndex, v, targetUniform->vs.registerCount);
}
- delete[] matrix;
-
return true;
}
-bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
+bool Program::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v)
{
- D3DXMATRIX *matrix = new D3DXMATRIX[count];
+ ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+ D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
for (int i = 0; i < count; i++)
{
- matrix[i] = D3DXMATRIX(value[0], value[3], value[6], 0,
- value[1], value[4], value[7], 0,
- value[2], value[5], value[8], 0,
- 0, 0, 0, 1);
-
- value += 9;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
+ vector[i] = D3DXVECTOR4((float)v[i], 0, 0, 0);
}
- if (constantVS)
+ if (targetUniform->ps.registerCount)
{
- mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
- }
-
- delete[] matrix;
-
- return true;
-}
-
-bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
-{
- D3DXMATRIX *matrix = new D3DXMATRIX[count];
-
- for (int i = 0; i < count; i++)
- {
- matrix[i] = D3DXMATRIX(value[0], value[4], value[8], value[12],
- value[1], value[5], value[9], value[13],
- value[2], value[6], value[10], value[14],
- value[3], value[7], value[11], value[15]);
-
- value += 16;
- }
-
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
- }
-
- if (constantVS)
- {
- mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
- }
-
- delete[] matrix;
-
- return true;
-}
-
-bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
-{
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- D3DXCONSTANT_DESC constantDescription;
- UINT descriptionCount = 1;
- HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
-
- if (FAILED(result))
- {
- return false;
- }
-
- if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
+ if (targetUniform->ps.registerSet == D3DXRS_SAMPLER)
{
- unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS);
+ unsigned int firstIndex = targetUniform->ps.registerIndex;
for (int i = 0; i < count; i++)
{
@@ -2232,32 +2145,49 @@ bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
{
- ASSERT(mSamplers[samplerIndex].active);
- mSamplers[samplerIndex].logicalTextureUnit = v[i];
- mSamplers[samplerIndex].dirty = true;
+ ASSERT(mSamplersPS[samplerIndex].active);
+ mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
}
}
-
- return true;
+ }
+ else
+ {
+ ASSERT(targetUniform->ps.registerSet == D3DXRS_FLOAT4);
+ mDevice->SetPixelShaderConstantF(targetUniform->ps.registerIndex, (const float*)vector, targetUniform->ps.registerCount);
}
}
- if (constantPS)
+ if (targetUniform->vs.registerCount)
{
- mConstantTablePS->SetIntArray(device, constantPS, v, count);
- }
+ if (targetUniform->vs.registerSet == D3DXRS_SAMPLER)
+ {
+ unsigned int firstIndex = targetUniform->vs.registerIndex;
- if (constantVS)
- {
- mConstantTableVS->SetIntArray(device, constantVS, v, count);
+ for (int i = 0; i < count; i++)
+ {
+ unsigned int samplerIndex = firstIndex + i;
+
+ if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
+ {
+ ASSERT(mSamplersVS[samplerIndex].active);
+ mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
+ }
+ }
+ }
+ else
+ {
+ ASSERT(targetUniform->vs.registerSet == D3DXRS_FLOAT4);
+ mDevice->SetVertexShaderConstantF(targetUniform->vs.registerIndex, (const float *)vector, targetUniform->vs.registerCount);
+ }
}
return true;
}
-bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
+bool Program::applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v)
{
- D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+ ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+ D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
for (int i = 0; i < count; i++)
{
@@ -2266,31 +2196,15 @@ bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
v += 2;
}
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
- }
-
- if (constantVS)
- {
- mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
- }
-
- delete[] vector;
+ applyUniformniv(targetUniform, count, vector);
return true;
}
-bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
+bool Program::applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v)
{
- D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+ ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+ D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
for (int i = 0; i < count; i++)
{
@@ -2299,31 +2213,15 @@ bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
v += 3;
}
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
-
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
-
- if (constantPS)
- {
- mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
- }
-
- if (constantVS)
- {
- mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
- }
-
- delete[] vector;
+ applyUniformniv(targetUniform, count, vector);
return true;
}
-bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
+bool Program::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v)
{
- D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
+ ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
+ D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
for (int i = 0; i < count; i++)
{
@@ -2332,26 +2230,45 @@ bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
v += 4;
}
- Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
+ applyUniformniv(targetUniform, count, vector);
- D3DXHANDLE constantPS;
- D3DXHANDLE constantVS;
- getConstantHandles(targetUniform, &constantPS, &constantVS);
- IDirect3DDevice9 *device = getDevice();
+ return true;
+}
- if (constantPS)
+void Program::applyUniformniv(Uniform *targetUniform, GLsizei count, const D3DXVECTOR4 *vector)
+{
+ if (targetUniform->ps.registerCount)
{
- mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
+ ASSERT(targetUniform->ps.registerSet == D3DXRS_FLOAT4);
+ mDevice->SetPixelShaderConstantF(targetUniform->ps.registerIndex, (const float *)vector, targetUniform->ps.registerCount);
}
- if (constantVS)
+ if (targetUniform->vs.registerCount)
{
- mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
+ ASSERT(targetUniform->vs.registerSet == D3DXRS_FLOAT4);
+ mDevice->SetVertexShaderConstantF(targetUniform->vs.registerIndex, (const float *)vector, targetUniform->vs.registerCount);
}
+}
- delete [] vector;
+// append a santized message to the program info log.
+// The D3D compiler includes a fake file path in some of the warning or error
+// messages, so lets remove all occurrences of this fake file path from the log.
+void Program::appendToInfoLogSanitized(const char *message)
+{
+ std::string msg(message);
- return true;
+ size_t found;
+ do
+ {
+ found = msg.find(fakepath);
+ if (found != std::string::npos)
+ {
+ msg.erase(found, strlen(fakepath));
+ }
+ }
+ while (found != std::string::npos);
+
+ appendToInfoLog("%s\n", msg.c_str());
}
void Program::appendToInfoLog(const char *format, ...)
@@ -2396,7 +2313,7 @@ void Program::resetInfoLog()
}
}
-// Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
+// Returns the program object to an unlinked state, before re-linking, or at destruction
void Program::unlink(bool destroy)
{
if (destroy) // Object being destructed
@@ -2446,10 +2363,17 @@ void Program::unlink(bool destroy)
for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
{
- mSamplers[index].active = false;
- mSamplers[index].dirty = true;
+ mSamplersPS[index].active = false;
}
+ for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
+ {
+ mSamplersVS[index].active = false;
+ }
+
+ mUsedVertexSamplerRange = 0;
+ mUsedPixelSamplerRange = 0;
+
while (!mUniforms.empty())
{
delete mUniforms.back();
@@ -2458,7 +2382,7 @@ void Program::unlink(bool destroy)
mDxDepthRangeLocation = -1;
mDxDepthLocation = -1;
- mDxViewportLocation = -1;
+ mDxCoordLocation = -1;
mDxHalfPixelSizeLocation = -1;
mDxFrontCCWLocation = -1;
mDxPointsOrLinesLocation = -1;
@@ -2532,11 +2456,8 @@ void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
if (mInfoLog)
{
- while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
- {
- infoLog[index] = mInfoLog[index];
- index++;
- }
+ index = std::min(bufSize - 1, (int)strlen(mInfoLog));
+ memcpy(infoLog, mInfoLog, index);
}
if (bufSize)
@@ -2655,7 +2576,7 @@ void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, G
unsigned int uniform;
for (uniform = 0; uniform < mUniforms.size(); uniform++)
{
- if (mUniforms[uniform]->name.substr(0, 3) == "dx_")
+ if (mUniforms[uniform]->name.compare(0, 3, "dx_") == 0)
{
continue;
}
@@ -2672,9 +2593,9 @@ void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, G
if (bufsize > 0)
{
- std::string string = undecorate(mUniforms[uniform]->name);
+ std::string string = mUniforms[uniform]->name;
- if (mUniforms[uniform]->arraySize != 1)
+ if (mUniforms[uniform]->isArray())
{
string += "[0]";
}
@@ -2700,7 +2621,7 @@ GLint Program::getActiveUniformCount()
unsigned int numUniforms = mUniforms.size();
for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
{
- if (mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
+ if (mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
{
count++;
}
@@ -2716,9 +2637,14 @@ GLint Program::getActiveUniformMaxLength()
unsigned int numUniforms = mUniforms.size();
for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
{
- if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
+ if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
{
- maxLength = std::max((int)(undecorate(mUniforms[uniformIndex]->name).length() + 1), maxLength);
+ int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
+ if (mUniforms[uniformIndex]->isArray())
+ {
+ length += 3; // Counting in "[0]".
+ }
+ maxLength = std::max(length, maxLength);
}
}
@@ -2747,9 +2673,8 @@ void Program::validate()
else
{
applyUniforms();
- if (!validateSamplers())
+ if (!validateSamplers(true))
{
- appendToInfoLog("Samplers of conflicting types refer to the same texture image unit.");
mValidated = false;
}
else
@@ -2759,24 +2684,86 @@ void Program::validate()
}
}
-bool Program::validateSamplers() const
+bool Program::validateSamplers(bool logErrors)
{
// if any two active samplers in a program are of different types, but refer to the same
// texture image unit, and this is the current program, then ValidateProgram will fail, and
// DrawArrays and DrawElements will issue the INVALID_OPERATION error.
- std::map<int, SamplerType> samplerMap;
- for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
+
+ const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
+ TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
+
+ for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
+ {
+ textureUnitType[i] = TEXTURE_UNKNOWN;
+ }
+
+ for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
{
- if (mSamplers[i].active)
+ if (mSamplersPS[i].active)
{
- if (samplerMap.find(mSamplers[i].logicalTextureUnit) != samplerMap.end())
+ unsigned int unit = mSamplersPS[i].logicalTextureUnit;
+
+ if (unit >= maxCombinedTextureImageUnits)
{
- if (mSamplers[i].type != samplerMap[mSamplers[i].logicalTextureUnit])
+ if (logErrors)
+ {
+ appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
+ }
+
+ return false;
+ }
+
+ if (textureUnitType[unit] != TEXTURE_UNKNOWN)
+ {
+ if (mSamplersPS[i].textureType != textureUnitType[unit])
+ {
+ if (logErrors)
+ {
+ appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
+ }
+
return false;
+ }
}
else
{
- samplerMap[mSamplers[i].logicalTextureUnit] = mSamplers[i].type;
+ textureUnitType[unit] = mSamplersPS[i].textureType;
+ }
+ }
+ }
+
+ for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
+ {
+ if (mSamplersVS[i].active)
+ {
+ unsigned int unit = mSamplersVS[i].logicalTextureUnit;
+
+ if (unit >= maxCombinedTextureImageUnits)
+ {
+ if (logErrors)
+ {
+ appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
+ }
+
+ return false;
+ }
+
+ if (textureUnitType[unit] != TEXTURE_UNKNOWN)
+ {
+ if (mSamplersVS[i].textureType != textureUnitType[unit])
+ {
+ if (logErrors)
+ {
+ appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
+ }
+
+ return false;
+ }
+ }
+ else
+ {
+ textureUnitType[unit] = mSamplersVS[i].textureType;
}
}
}
@@ -2784,17 +2771,23 @@ bool Program::validateSamplers() const
return true;
}
-void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS)
+void Program::initializeConstantHandles(Uniform *targetUniform, Uniform::RegisterInfo *ri, ID3DXConstantTable *constantTable)
{
- if (!targetUniform->handlesSet)
+ D3DXHANDLE handle = constantTable->GetConstantByName(0, targetUniform->_name.c_str());
+ if (handle)
+ {
+ UINT descriptionCount = 1;
+ D3DXCONSTANT_DESC constantDescription;
+ HRESULT result = constantTable->GetConstantDesc(handle, &constantDescription, &descriptionCount);
+ ASSERT(SUCCEEDED(result));
+ ri->registerIndex = constantDescription.RegisterIndex;
+ ri->registerCount = constantDescription.RegisterCount;
+ ri->registerSet = constantDescription.RegisterSet;
+ }
+ else
{
- targetUniform->psHandle = mConstantTablePS->GetConstantByName(0, targetUniform->name.c_str());
- targetUniform->vsHandle = mConstantTableVS->GetConstantByName(0, targetUniform->name.c_str());
- targetUniform->handlesSet = true;
+ ri->registerCount = 0;
}
-
- *constantPS = targetUniform->psHandle;
- *constantVS = targetUniform->vsHandle;
}
GLint Program::getDxDepthRangeLocation() const
@@ -2807,9 +2800,9 @@ GLint Program::getDxDepthLocation() const
return mDxDepthLocation;
}
-GLint Program::getDxViewportLocation() const
+GLint Program::getDxCoordLocation() const
{
- return mDxViewportLocation;
+ return mDxCoordLocation;
}
GLint Program::getDxHalfPixelSizeLocation() const
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h
index e9c149e..61830c6 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Program.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -11,6 +11,7 @@
#define LIBGLESV2_PROGRAM_H_
#include <d3dx9.h>
+#include <d3dcompiler.h>
#include <string>
#include <vector>
#include <set>
@@ -27,26 +28,35 @@ class VertexShader;
// Helper struct representing a single shader uniform
struct Uniform
{
- Uniform(GLenum type, const std::string &name, unsigned int arraySize);
+ Uniform(GLenum type, const std::string &_name, unsigned int arraySize);
~Uniform();
+ bool isArray();
+
const GLenum type;
- const std::string name;
+ const std::string _name; // Decorated name
+ const std::string name; // Undecorated name
const unsigned int arraySize;
unsigned char *data;
bool dirty;
- D3DXHANDLE vsHandle;
- D3DXHANDLE psHandle;
- bool handlesSet;
+ struct RegisterInfo
+ {
+ int registerSet;
+ int registerIndex;
+ int registerCount;
+ };
+
+ RegisterInfo ps;
+ RegisterInfo vs;
};
// Struct used for correlating uniforms/elements of uniform arrays to handles
struct UniformLocation
{
- UniformLocation(const std::string &name, unsigned int element, unsigned int index);
+ UniformLocation(const std::string &_name, unsigned int element, unsigned int index);
std::string name;
unsigned int element;
@@ -71,14 +81,11 @@ class Program
GLuint getAttributeLocation(const char *name);
int getSemanticIndex(int attributeIndex);
- void dirtyAllSamplers();
+ GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex);
+ TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
+ GLint getUsedSamplerRange(SamplerType type);
- GLint getSamplerMapping(unsigned int samplerIndex);
- SamplerType getSamplerType(unsigned int samplerIndex);
- bool isSamplerDirty(unsigned int samplerIndex) const;
- void setSamplerDirty(unsigned int samplerIndex, bool dirty);
-
- GLint getUniformLocation(const char *name, bool decorated);
+ GLint getUniformLocation(std::string name);
bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
@@ -91,12 +98,12 @@ class Program
bool setUniform3iv(GLint location, GLsizei count, const GLint *v);
bool setUniform4iv(GLint location, GLsizei count, const GLint *v);
- bool getUniformfv(GLint location, GLfloat *params);
- bool getUniformiv(GLint location, GLint *params);
+ bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params);
+ bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params);
GLint getDxDepthRangeLocation() const;
GLint getDxDepthLocation() const;
- GLint getDxViewportLocation() const;
+ GLint getDxCoordLocation() const;
GLint getDxHalfPixelSizeLocation() const;
GLint getDxFrontCCWLocation() const;
GLint getDxPointsOrLinesLocation() const;
@@ -125,15 +132,18 @@ class Program
bool isFlaggedForDeletion() const;
void validate();
- bool validateSamplers() const;
+ bool validateSamplers(bool logErrors);
bool isValidated() const;
unsigned int getSerial() const;
+ static std::string decorateAttribute(const std::string &name); // Prepend an underscore
+ static std::string undecorateUniform(const std::string &_name); // Remove leading underscore
+
private:
DISALLOW_COPY_AND_ASSIGN(Program);
- ID3DXBuffer *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable);
+ ID3D10Blob *compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable);
void unlink(bool destroy = false);
int packVaryings(const Varying *packing[][4]);
@@ -144,34 +154,25 @@ class Program
bool linkUniforms(ID3DXConstantTable *constantTable);
bool defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name = "");
- bool defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
- Uniform *createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
- bool applyUniform1bv(GLint location, GLsizei count, const GLboolean *v);
- bool applyUniform2bv(GLint location, GLsizei count, const GLboolean *v);
- bool applyUniform3bv(GLint location, GLsizei count, const GLboolean *v);
- bool applyUniform4bv(GLint location, GLsizei count, const GLboolean *v);
- bool applyUniform1fv(GLint location, GLsizei count, const GLfloat *v);
- bool applyUniform2fv(GLint location, GLsizei count, const GLfloat *v);
- bool applyUniform3fv(GLint location, GLsizei count, const GLfloat *v);
- bool applyUniform4fv(GLint location, GLsizei count, const GLfloat *v);
- bool applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value);
- bool applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value);
- bool applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value);
- bool applyUniform1iv(GLint location, GLsizei count, const GLint *v);
- bool applyUniform2iv(GLint location, GLsizei count, const GLint *v);
- bool applyUniform3iv(GLint location, GLsizei count, const GLint *v);
- bool applyUniform4iv(GLint location, GLsizei count, const GLint *v);
-
- void getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS);
-
+ bool defineUniform(const D3DXCONSTANT_DESC &constantDescription, const std::string &name);
+ Uniform *createUniform(const D3DXCONSTANT_DESC &constantDescription, const std::string &name);
+ bool applyUniformnfv(Uniform *targetUniform, const GLfloat *v);
+ bool applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+ bool applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+ bool applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+ bool applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v);
+ void applyUniformniv(Uniform *targetUniform, GLsizei count, const D3DXVECTOR4 *vector);
+ void applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v);
+
+ void initializeConstantHandles(Uniform *targetUniform, Uniform::RegisterInfo *rs, ID3DXConstantTable *constantTable);
+
+ void appendToInfoLogSanitized(const char *message);
void appendToInfoLog(const char *info, ...);
void resetInfoLog();
- static std::string decorate(const std::string &string); // Prepend an underscore
- static std::string undecorate(const std::string &string); // Remove leading underscore
-
static unsigned int issueSerial();
+ IDirect3DDevice9 *mDevice;
FragmentShader *mFragmentShader;
VertexShader *mVertexShader;
@@ -191,11 +192,13 @@ class Program
{
bool active;
GLint logicalTextureUnit;
- SamplerType type;
- bool dirty;
+ TextureType textureType;
};
- Sampler mSamplers[MAX_TEXTURE_IMAGE_UNITS];
+ Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
+ Sampler mSamplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF];
+ GLuint mUsedVertexSamplerRange;
+ GLuint mUsedPixelSamplerRange;
typedef std::vector<Uniform*> UniformArray;
UniformArray mUniforms;
@@ -204,7 +207,7 @@ class Program
GLint mDxDepthRangeLocation;
GLint mDxDepthLocation;
- GLint mDxViewportLocation;
+ GLint mDxCoordLocation;
GLint mDxHalfPixelSizeLocation;
GLint mDxFrontCCWLocation;
GLint mDxPointsOrLinesLocation;
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Query.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Query.cpp
new file mode 100644
index 0000000..10edda5
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Query.cpp
@@ -0,0 +1,128 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query.cpp: Implements the gl::Query class
+
+#include "libGLESv2/Query.h"
+
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+
+Query::Query(GLuint id, GLenum type) : RefCountObject(id)
+{
+ mQuery = NULL;
+ mStatus = GL_FALSE;
+ mResult = GL_FALSE;
+ mType = type;
+}
+
+Query::~Query()
+{
+ if (mQuery != NULL)
+ {
+ mQuery->Release();
+ mQuery = NULL;
+ }
+}
+
+void Query::begin()
+{
+ if (mQuery == NULL)
+ {
+ if (FAILED(getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery)))
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
+ ASSERT(SUCCEEDED(result));
+}
+
+void Query::end()
+{
+ if (mQuery == NULL)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ HRESULT result = mQuery->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+
+ mStatus = GL_FALSE;
+ mResult = GL_FALSE;
+}
+
+GLuint Query::getResult()
+{
+ if (mQuery != NULL)
+ {
+ while (!testQuery())
+ {
+ Sleep(0);
+ // explicitly check for device loss
+ // some drivers seem to return S_FALSE even if the device is lost
+ // instead of D3DERR_DEVICELOST like they should
+ if (gl::getDisplay()->testDeviceLost())
+ {
+ gl::getDisplay()->notifyDeviceLost();
+ return error(GL_OUT_OF_MEMORY, 0);
+ }
+ }
+ }
+
+ return (GLuint)mResult;
+}
+
+GLboolean Query::isResultAvailable()
+{
+ if (mQuery != NULL)
+ {
+ testQuery();
+ }
+
+ return mStatus;
+}
+
+GLenum Query::getType() const
+{
+ return mType;
+}
+
+GLboolean Query::testQuery()
+{
+ if (mQuery != NULL && mStatus != GL_TRUE)
+ {
+ DWORD numPixels = 0;
+
+ HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH);
+ if (hres == S_OK)
+ {
+ mStatus = GL_TRUE;
+
+ switch (mType)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ ASSERT(false);
+ }
+ }
+ else if (checkDeviceLost(hres))
+ {
+ return error(GL_OUT_OF_MEMORY, GL_TRUE);
+ }
+
+ return mStatus;
+ }
+
+ return GL_TRUE; // prevent blocking when query is null
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Query.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Query.h
new file mode 100644
index 0000000..79357a0
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Query.h
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query.h: Defines the gl::Query class
+
+#ifndef LIBGLESV2_QUERY_H_
+#define LIBGLESV2_QUERY_H_
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+#include <d3d9.h>
+
+#include "common/angleutils.h"
+#include "common/RefCountObject.h"
+
+namespace gl
+{
+
+class Query : public RefCountObject
+{
+ public:
+ Query(GLuint id, GLenum type);
+ virtual ~Query();
+
+ void begin();
+ void end();
+ GLuint getResult();
+ GLboolean isResultAvailable();
+
+ GLenum getType() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Query);
+
+ GLboolean testQuery();
+
+ IDirect3DQuery9* mQuery;
+ GLenum mType;
+ GLboolean mStatus;
+ GLint mResult;
+};
+
+}
+
+#endif // LIBGLESV2_QUERY_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp
index 6e4494b..6004255 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.cpp
@@ -18,137 +18,254 @@ namespace gl
{
unsigned int RenderbufferStorage::mCurrentSerial = 1;
-Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *storage) : RefCountObject(id)
+RenderbufferInterface::RenderbufferInterface()
{
- ASSERT(storage != NULL);
- mStorage = storage;
}
-Renderbuffer::~Renderbuffer()
+// 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.
+void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy)
+{
+}
+
+void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy)
+{
+}
+
+GLuint RenderbufferInterface::getRedSize() const
+{
+ return dx2es::GetRedSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getGreenSize() const
+{
+ return dx2es::GetGreenSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getBlueSize() const
+{
+ return dx2es::GetBlueSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getAlphaSize() const
+{
+ return dx2es::GetAlphaSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getDepthSize() const
+{
+ return dx2es::GetDepthSize(getD3DFormat());
+}
+
+GLuint RenderbufferInterface::getStencilSize() const
+{
+ return dx2es::GetStencilSize(getD3DFormat());
+}
+
+RenderbufferTexture::RenderbufferTexture(Texture *texture, GLenum target) : mTarget(target)
+{
+ mTexture.set(texture);
+}
+
+RenderbufferTexture::~RenderbufferTexture()
+{
+ mTexture.set(NULL);
+}
+
+// Textures need to maintain their own reference count for references via
+// Renderbuffers acting as proxies. Here, we notify the texture of a reference.
+void RenderbufferTexture::addProxyRef(const Renderbuffer *proxy)
+{
+ mTexture->addProxyRef(proxy);
+}
+
+void RenderbufferTexture::releaseProxy(const Renderbuffer *proxy)
+{
+ mTexture->releaseProxy(proxy);
+}
+
+IDirect3DSurface9 *RenderbufferTexture::getRenderTarget()
+{
+ return mTexture->getRenderTarget(mTarget);
+}
+
+IDirect3DSurface9 *RenderbufferTexture::getDepthStencil()
+{
+ return NULL;
+}
+
+GLsizei RenderbufferTexture::getWidth() const
+{
+ return mTexture->getWidth(0);
+}
+
+GLsizei RenderbufferTexture::getHeight() const
+{
+ return mTexture->getHeight(0);
+}
+
+GLenum RenderbufferTexture::getInternalFormat() const
+{
+ return mTexture->getInternalFormat();
+}
+
+D3DFORMAT RenderbufferTexture::getD3DFormat() const
+{
+ return mTexture->getD3DFormat();
+}
+
+GLsizei RenderbufferTexture::getSamples() const
+{
+ return 0;
+}
+
+unsigned int RenderbufferTexture::getSerial() const
+{
+ return mTexture->getRenderTargetSerial(mTarget);
+}
+
+Renderbuffer::Renderbuffer(GLuint id, RenderbufferInterface *instance) : RefCountObject(id)
{
- delete mStorage;
+ ASSERT(instance != NULL);
+ mInstance = instance;
}
-bool Renderbuffer::isColorbuffer() const
+Renderbuffer::~Renderbuffer()
{
- return mStorage->isColorbuffer();
+ delete mInstance;
}
-bool Renderbuffer::isDepthbuffer() const
+// The RenderbufferInterface contained in this Renderbuffer may need to maintain
+// its own reference count, so we pass it on here.
+void Renderbuffer::addRef() const
{
- return mStorage->isDepthbuffer();
+ mInstance->addProxyRef(this);
+
+ RefCountObject::addRef();
}
-bool Renderbuffer::isStencilbuffer() const
+void Renderbuffer::release() const
{
- return mStorage->isStencilbuffer();
+ mInstance->releaseProxy(this);
+
+ RefCountObject::release();
}
IDirect3DSurface9 *Renderbuffer::getRenderTarget()
{
- return mStorage->getRenderTarget();
+ return mInstance->getRenderTarget();
}
IDirect3DSurface9 *Renderbuffer::getDepthStencil()
{
- return mStorage->getDepthStencil();
+ return mInstance->getDepthStencil();
}
-int Renderbuffer::getWidth() const
+GLsizei Renderbuffer::getWidth() const
{
- return mStorage->getWidth();
+ return mInstance->getWidth();
}
-int Renderbuffer::getHeight() const
+GLsizei Renderbuffer::getHeight() const
{
- return mStorage->getHeight();
+ return mInstance->getHeight();
}
-GLenum Renderbuffer::getFormat() const
+GLenum Renderbuffer::getInternalFormat() const
{
- return mStorage->getFormat();
+ return mInstance->getInternalFormat();
}
D3DFORMAT Renderbuffer::getD3DFormat() const
{
- return mStorage->getD3DFormat();
+ return mInstance->getD3DFormat();
}
-unsigned int Renderbuffer::getSerial() const
+GLuint Renderbuffer::getRedSize() const
{
- return mStorage->getSerial();
+ return mInstance->getRedSize();
}
-void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
+GLuint Renderbuffer::getGreenSize() const
{
- ASSERT(newStorage != NULL);
+ return mInstance->getGreenSize();
+}
- delete mStorage;
- mStorage = newStorage;
+GLuint Renderbuffer::getBlueSize() const
+{
+ return mInstance->getBlueSize();
}
-RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial())
+GLuint Renderbuffer::getAlphaSize() const
{
- mWidth = 0;
- mHeight = 0;
- mFormat = GL_RGBA4;
- mD3DFormat = D3DFMT_A8R8G8B8;
- mSamples = 0;
+ return mInstance->getAlphaSize();
}
-RenderbufferStorage::~RenderbufferStorage()
+GLuint Renderbuffer::getDepthSize() const
{
+ return mInstance->getDepthSize();
}
-bool RenderbufferStorage::isColorbuffer() const
+GLuint Renderbuffer::getStencilSize() const
{
- return false;
+ return mInstance->getStencilSize();
}
-bool RenderbufferStorage::isDepthbuffer() const
+GLsizei Renderbuffer::getSamples() const
{
- return false;
+ return mInstance->getSamples();
}
-bool RenderbufferStorage::isStencilbuffer() const
+unsigned int Renderbuffer::getSerial() const
{
- return false;
+ return mInstance->getSerial();
}
-IDirect3DSurface9 *RenderbufferStorage::getRenderTarget()
+void Renderbuffer::setStorage(RenderbufferStorage *newStorage)
{
- return NULL;
+ ASSERT(newStorage != NULL);
+
+ delete mInstance;
+ mInstance = newStorage;
}
-IDirect3DSurface9 *RenderbufferStorage::getDepthStencil()
+RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial())
{
- return NULL;
+ mWidth = 0;
+ mHeight = 0;
+ mInternalFormat = GL_RGBA4;
+ mD3DFormat = D3DFMT_A8R8G8B8;
+ mSamples = 0;
}
-int RenderbufferStorage::getWidth() const
+RenderbufferStorage::~RenderbufferStorage()
{
- return mWidth;
}
-int RenderbufferStorage::getHeight() const
+IDirect3DSurface9 *RenderbufferStorage::getRenderTarget()
{
- return mHeight;
+ return NULL;
}
-void RenderbufferStorage::setSize(int width, int height)
+IDirect3DSurface9 *RenderbufferStorage::getDepthStencil()
{
- mWidth = width;
- mHeight = height;
+ return NULL;
}
-GLenum RenderbufferStorage::getFormat() const
+GLsizei RenderbufferStorage::getWidth() const
{
- return mFormat;
+ return mWidth;
}
-bool RenderbufferStorage::isFloatingPoint() const
+GLsizei RenderbufferStorage::getHeight() const
{
- return false; // no floating point renderbuffers
+ return mHeight;
+}
+
+GLenum RenderbufferStorage::getInternalFormat() const
+{
+ return mInternalFormat;
}
D3DFORMAT RenderbufferStorage::getD3DFormat() const
@@ -171,6 +288,13 @@ unsigned int RenderbufferStorage::issueSerial()
return mCurrentSerial++;
}
+unsigned int RenderbufferStorage::issueCubeSerials()
+{
+ unsigned int firstSerial = mCurrentSerial;
+ mCurrentSerial += 6;
+ return firstSerial;
+}
+
Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget)
{
if (renderTarget)
@@ -180,25 +304,18 @@ Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(render
D3DSURFACE_DESC description;
renderTarget->GetDesc(&description);
- setSize(description.Width, description.Height);
- mFormat = dx2es::ConvertBackBufferFormat(description.Format);
+ mWidth = description.Width;
+ mHeight = description.Height;
+ mInternalFormat = dx2es::ConvertBackBufferFormat(description.Format);
mD3DFormat = description.Format;
- mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
+ mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType);
}
}
-Colorbuffer::Colorbuffer(const Texture* texture) : mRenderTarget(NULL)
-{
- setSize(texture->getWidth(), texture->getHeight());
- mD3DFormat = texture->getD3DFormat();
- mSamples = 0;
-}
-
-Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
+Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL)
{
IDirect3DDevice9 *device = getDevice();
- mRenderTarget = NULL;
D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format);
int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples);
@@ -224,13 +341,11 @@ Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples)
ASSERT(SUCCEEDED(result));
}
- if (mRenderTarget)
- {
- setSize(width, height);
- mFormat = format;
- mD3DFormat = requestedFormat;
- mSamples = supportedSamples;
- }
+ mWidth = width;
+ mHeight = height;
+ mInternalFormat = format;
+ mD3DFormat = requestedFormat;
+ mSamples = supportedSamples;
}
Colorbuffer::~Colorbuffer()
@@ -241,65 +356,13 @@ Colorbuffer::~Colorbuffer()
}
}
-bool Colorbuffer::isColorbuffer() const
-{
- return true;
-}
-
-GLuint Colorbuffer::getRedSize() const
-{
- if (mRenderTarget)
- {
- D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
-
- return es2dx::GetRedSize(description.Format);
- }
-
- return 0;
-}
-
-GLuint Colorbuffer::getGreenSize() const
-{
- if (mRenderTarget)
- {
- D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
-
- return es2dx::GetGreenSize(description.Format);
- }
-
- return 0;
-}
-
-GLuint Colorbuffer::getBlueSize() const
-{
- if (mRenderTarget)
- {
- D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
-
- return es2dx::GetBlueSize(description.Format);
- }
-
- return 0;
-}
-
-GLuint Colorbuffer::getAlphaSize() const
+IDirect3DSurface9 *Colorbuffer::getRenderTarget()
{
if (mRenderTarget)
{
- D3DSURFACE_DESC description;
- mRenderTarget->GetDesc(&description);
-
- return es2dx::GetAlphaSize(description.Format);
+ mRenderTarget->AddRef();
}
- return 0;
-}
-
-IDirect3DSurface9 *Colorbuffer::getRenderTarget()
-{
return mRenderTarget;
}
@@ -312,9 +375,10 @@ DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepth
D3DSURFACE_DESC description;
depthStencil->GetDesc(&description);
- setSize(description.Width, description.Height);
- mFormat = dx2es::ConvertDepthStencilFormat(description.Format);
- mSamples = es2dx::GetSamplesFromMultisampleType(description.MultiSampleType);
+ mWidth = description.Width;
+ mHeight = description.Height;
+ mInternalFormat = dx2es::ConvertDepthStencilFormat(description.Format);
+ mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType);
mD3DFormat = description.Format;
}
}
@@ -334,25 +398,26 @@ DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples)
return;
}
- HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
- 0, FALSE, &mDepthStencil, 0);
-
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ if (width > 0 && height > 0)
{
- error(GL_OUT_OF_MEMORY);
+ HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples),
+ 0, FALSE, &mDepthStencil, 0);
- return;
- }
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ error(GL_OUT_OF_MEMORY);
- ASSERT(SUCCEEDED(result));
+ return;
+ }
- if (mDepthStencil)
- {
- setSize(width, height);
- mFormat = GL_DEPTH24_STENCIL8_OES;
- mD3DFormat = D3DFMT_D24S8;
- mSamples = supportedSamples;
+ ASSERT(SUCCEEDED(result));
}
+
+ mWidth = width;
+ mHeight = height;
+ mInternalFormat = GL_DEPTH24_STENCIL8_OES;
+ mD3DFormat = D3DFMT_D24S8;
+ mSamples = supportedSamples;
}
DepthStencilbuffer::~DepthStencilbuffer()
@@ -363,42 +428,6 @@ DepthStencilbuffer::~DepthStencilbuffer()
}
}
-bool DepthStencilbuffer::isDepthbuffer() const
-{
- return true;
-}
-
-bool DepthStencilbuffer::isStencilbuffer() const
-{
- return true;
-}
-
-GLuint DepthStencilbuffer::getDepthSize() const
-{
- if (mDepthStencil)
- {
- D3DSURFACE_DESC description;
- mDepthStencil->GetDesc(&description);
-
- return es2dx::GetDepthSize(description.Format);
- }
-
- return 0;
-}
-
-GLuint DepthStencilbuffer::getStencilSize() const
-{
- if (mDepthStencil)
- {
- D3DSURFACE_DESC description;
- mDepthStencil->GetDesc(&description);
-
- return es2dx::GetStencilSize(description.Format);
- }
-
- return 0;
-}
-
IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil()
{
return mDepthStencil;
@@ -408,19 +437,19 @@ Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(d
{
if (depthStencil)
{
- mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
- // will expect one of the valid renderbuffer formats for use in
- // glRenderbufferStorage
+ mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
+ // will expect one of the valid renderbuffer formats for use in
+ // glRenderbufferStorage
}
}
Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
{
- if (getDepthStencil())
+ if (mDepthStencil)
{
- mFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
- // will expect one of the valid renderbuffer formats for use in
- // glRenderbufferStorage
+ mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function
+ // will expect one of the valid renderbuffer formats for use in
+ // glRenderbufferStorage
}
}
@@ -428,37 +457,23 @@ Depthbuffer::~Depthbuffer()
{
}
-bool Depthbuffer::isDepthbuffer() const
-{
- return true;
-}
-
-bool Depthbuffer::isStencilbuffer() const
-{
- return false;
-}
-
Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil)
{
if (depthStencil)
{
- mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
- // will expect one of the valid renderbuffer formats for use in
- // glRenderbufferStorage
- }
- else
- {
- mFormat = GL_RGBA4; //default format
+ mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
+ // will expect one of the valid renderbuffer formats for use in
+ // glRenderbufferStorage
}
}
Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples)
{
- if (getDepthStencil())
+ if (mDepthStencil)
{
- mFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
- // will expect one of the valid renderbuffer formats for use in
- // glRenderbufferStorage
+ mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function
+ // will expect one of the valid renderbuffer formats for use in
+ // glRenderbufferStorage
}
}
@@ -466,13 +481,4 @@ Stencilbuffer::~Stencilbuffer()
{
}
-bool Stencilbuffer::isDepthbuffer() const
-{
- return false;
-}
-
-bool Stencilbuffer::isStencilbuffer() const
-{
- return true;
-}
}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h
index 98510c2..60ec058 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Renderbuffer.h
@@ -17,143 +17,196 @@
#include <d3d9.h>
#include "common/angleutils.h"
-#include "libGLESv2/RefCountObject.h"
+#include "common/RefCountObject.h"
namespace gl
{
- class Texture;
+class Texture;
+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 IDirect3DSurface9 *getRenderTarget() = 0;
+ virtual IDirect3DSurface9 *getDepthStencil() = 0;
+
+ virtual GLsizei getWidth() const = 0;
+ virtual GLsizei getHeight() const = 0;
+ virtual GLenum getInternalFormat() const = 0;
+ virtual D3DFORMAT getD3DFormat() 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;
+
+ virtual unsigned int getSerial() const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface);
+};
+
+class RenderbufferTexture : public RenderbufferInterface
+{
+ public:
+ RenderbufferTexture(Texture *texture, GLenum target);
+
+ virtual ~RenderbufferTexture();
+
+ void addProxyRef(const Renderbuffer *proxy);
+ void releaseProxy(const Renderbuffer *proxy);
+
+ IDirect3DSurface9 *getRenderTarget();
+ IDirect3DSurface9 *getDepthStencil();
+
+ virtual GLsizei getWidth() const;
+ virtual GLsizei getHeight() const;
+ virtual GLenum getInternalFormat() const;
+ virtual D3DFORMAT getD3DFormat() const;
+ virtual GLsizei getSamples() const;
+
+ virtual unsigned int getSerial() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture);
+
+ BindingPointer <Texture> mTexture;
+ GLenum mTarget;
+};
// 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
+class RenderbufferStorage : public RenderbufferInterface
{
public:
RenderbufferStorage();
virtual ~RenderbufferStorage() = 0;
- virtual bool isColorbuffer() const;
- virtual bool isDepthbuffer() const;
- virtual bool isStencilbuffer() const;
-
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
- virtual int getWidth() const;
- virtual int getHeight() const;
- virtual GLenum getFormat() const;
- virtual bool isFloatingPoint() const;
- D3DFORMAT getD3DFormat() const;
- GLsizei getSamples() const;
- unsigned int getSerial() const;
+ virtual GLsizei getWidth() const;
+ virtual GLsizei getHeight() const;
+ virtual GLenum getInternalFormat() const;
+ virtual D3DFORMAT getD3DFormat() const;
+ virtual GLsizei getSamples() const;
+
+ virtual unsigned int getSerial() const;
static unsigned int issueSerial();
+ static unsigned int issueCubeSerials();
protected:
- void setSize(int width, int height);
- GLenum mFormat;
+ GLsizei mWidth;
+ GLsizei mHeight;
+ GLenum mInternalFormat;
D3DFORMAT mD3DFormat;
GLsizei mSamples;
- const unsigned int mSerial;
private:
DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage);
- static unsigned int mCurrentSerial;
+ const unsigned int mSerial;
- int mWidth;
- int mHeight;
+ static unsigned int mCurrentSerial;
};
// Renderbuffer implements the GL renderbuffer object.
-// It's only a wrapper for a RenderbufferStorage, but the internal object
+// It's only a proxy for a RenderbufferInterface instance; the internal object
// can change whenever glRenderbufferStorage is called.
class Renderbuffer : public RefCountObject
{
public:
- Renderbuffer(GLuint id, RenderbufferStorage *storage);
+ Renderbuffer(GLuint id, RenderbufferInterface *storage);
- ~Renderbuffer();
+ virtual ~Renderbuffer();
- bool isColorbuffer() const;
- bool isDepthbuffer() const;
- bool isStencilbuffer() const;
+ // These functions from RefCountObject 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.
+ void addRef() const;
+ void release() const;
IDirect3DSurface9 *getRenderTarget();
IDirect3DSurface9 *getDepthStencil();
- int getWidth() const;
- int getHeight() const;
- GLenum getFormat() const;
+ GLsizei getWidth() const;
+ GLsizei getHeight() const;
+ GLenum getInternalFormat() const;
D3DFORMAT getD3DFormat() const;
+ GLuint getRedSize() const;
+ GLuint getGreenSize() const;
+ GLuint getBlueSize() const;
+ GLuint getAlphaSize() const;
+ GLuint getDepthSize() const;
+ GLuint getStencilSize() const;
+ GLsizei getSamples() const;
+
unsigned int getSerial() const;
void setStorage(RenderbufferStorage *newStorage);
- RenderbufferStorage *getStorage() { return mStorage; }
private:
DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
- RenderbufferStorage *mStorage;
+ RenderbufferInterface *mInstance;
};
class Colorbuffer : public RenderbufferStorage
{
public:
explicit Colorbuffer(IDirect3DSurface9 *renderTarget);
- explicit Colorbuffer(const Texture* texture);
- Colorbuffer(int width, int height, GLenum format, GLsizei samples);
-
- ~Colorbuffer();
-
- bool isColorbuffer() const;
-
- GLuint getRedSize() const;
- GLuint getGreenSize() const;
- GLuint getBlueSize() const;
- GLuint getAlphaSize() const;
+ Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples);
- IDirect3DSurface9 *getRenderTarget();
+ virtual ~Colorbuffer();
- protected:
- IDirect3DSurface9 *mRenderTarget;
+ virtual IDirect3DSurface9 *getRenderTarget();
private:
DISALLOW_COPY_AND_ASSIGN(Colorbuffer);
+
+ IDirect3DSurface9 *mRenderTarget;
};
class DepthStencilbuffer : public RenderbufferStorage
{
public:
explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil);
- DepthStencilbuffer(int width, int height, GLsizei samples);
+ DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
~DepthStencilbuffer();
- virtual bool isDepthbuffer() const;
- virtual bool isStencilbuffer() const;
-
- GLuint getDepthSize() const;
- GLuint getStencilSize() const;
+ virtual IDirect3DSurface9 *getDepthStencil();
- IDirect3DSurface9 *getDepthStencil();
+ protected:
+ IDirect3DSurface9 *mDepthStencil;
private:
DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer);
- IDirect3DSurface9 *mDepthStencil;
};
class Depthbuffer : public DepthStencilbuffer
{
public:
explicit Depthbuffer(IDirect3DSurface9 *depthStencil);
- Depthbuffer(int width, int height, GLsizei samples);
+ Depthbuffer(GLsizei width, GLsizei height, GLsizei samples);
- ~Depthbuffer();
-
- bool isDepthbuffer() const;
- bool isStencilbuffer() const;
+ virtual ~Depthbuffer();
private:
DISALLOW_COPY_AND_ASSIGN(Depthbuffer);
@@ -163,12 +216,9 @@ class Stencilbuffer : public DepthStencilbuffer
{
public:
explicit Stencilbuffer(IDirect3DSurface9 *depthStencil);
- Stencilbuffer(int width, int height, GLsizei samples);
-
- ~Stencilbuffer();
+ Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
- bool isDepthbuffer() const;
- bool isStencilbuffer() const;
+ virtual ~Stencilbuffer();
private:
DISALLOW_COPY_AND_ASSIGN(Stencilbuffer);
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp
index 12a86c1..ae26352 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.cpp
@@ -66,12 +66,7 @@ void ResourceManager::release()
// Returns an unused buffer name
GLuint ResourceManager::createBuffer()
{
- unsigned int handle = 1;
-
- while (mBufferMap.find(handle) != mBufferMap.end())
- {
- handle++;
- }
+ GLuint handle = mBufferHandleAllocator.allocate();
mBufferMap[handle] = NULL;
@@ -81,12 +76,7 @@ GLuint ResourceManager::createBuffer()
// Returns an unused shader/program name
GLuint ResourceManager::createShader(GLenum type)
{
- unsigned int handle = 1;
-
- while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
- {
- handle++;
- }
+ GLuint handle = mProgramShaderHandleAllocator.allocate();
if (type == GL_VERTEX_SHADER)
{
@@ -104,12 +94,7 @@ GLuint ResourceManager::createShader(GLenum type)
// Returns an unused program/shader name
GLuint ResourceManager::createProgram()
{
- unsigned int handle = 1;
-
- while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
- {
- handle++;
- }
+ GLuint handle = mProgramShaderHandleAllocator.allocate();
mProgramMap[handle] = new Program(this, handle);
@@ -119,12 +104,7 @@ GLuint ResourceManager::createProgram()
// Returns an unused texture name
GLuint ResourceManager::createTexture()
{
- unsigned int handle = 1;
-
- while (mTextureMap.find(handle) != mTextureMap.end())
- {
- handle++;
- }
+ GLuint handle = mTextureHandleAllocator.allocate();
mTextureMap[handle] = NULL;
@@ -134,12 +114,7 @@ GLuint ResourceManager::createTexture()
// Returns an unused renderbuffer name
GLuint ResourceManager::createRenderbuffer()
{
- unsigned int handle = 1;
-
- while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
- {
- handle++;
- }
+ GLuint handle = mRenderbufferHandleAllocator.allocate();
mRenderbufferMap[handle] = NULL;
@@ -152,6 +127,7 @@ void ResourceManager::deleteBuffer(GLuint buffer)
if (bufferObject != mBufferMap.end())
{
+ mBufferHandleAllocator.release(bufferObject->first);
if (bufferObject->second) bufferObject->second->release();
mBufferMap.erase(bufferObject);
}
@@ -165,6 +141,7 @@ void ResourceManager::deleteShader(GLuint shader)
{
if (shaderObject->second->getRefCount() == 0)
{
+ mProgramShaderHandleAllocator.release(shaderObject->first);
delete shaderObject->second;
mShaderMap.erase(shaderObject);
}
@@ -183,6 +160,7 @@ void ResourceManager::deleteProgram(GLuint program)
{
if (programObject->second->getRefCount() == 0)
{
+ mProgramShaderHandleAllocator.release(programObject->first);
delete programObject->second;
mProgramMap.erase(programObject);
}
@@ -199,6 +177,7 @@ void ResourceManager::deleteTexture(GLuint texture)
if (textureObject != mTextureMap.end())
{
+ mTextureHandleAllocator.release(textureObject->first);
if (textureObject->second) textureObject->second->release();
mTextureMap.erase(textureObject);
}
@@ -210,6 +189,7 @@ void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
if (renderbufferObject != mRenderbufferMap.end())
{
+ mRenderbufferHandleAllocator.release(renderbufferObject->first);
if (renderbufferObject->second) renderbufferObject->second->release();
mRenderbufferMap.erase(renderbufferObject);
}
@@ -302,17 +282,17 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer)
}
}
-void ResourceManager::checkTextureAllocation(GLuint texture, SamplerType type)
+void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
{
if (!getTexture(texture) && texture != 0)
{
Texture *textureObject;
- if (type == SAMPLER_2D)
+ if (type == TEXTURE_2D)
{
textureObject = new Texture2D(texture);
}
- else if (type == SAMPLER_CUBE)
+ else if (type == TEXTURE_CUBE)
{
textureObject = new TextureCubeMap(texture);
}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h
index 346e51f..5185fc9 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/ResourceManager.h
@@ -13,9 +13,10 @@
#define GL_APICALL
#include <GLES2/gl2.h>
-#include <map>
+#include <hash_map>
#include "common/angleutils.h"
+#include "libGLESv2/HandleAllocator.h"
namespace gl
{
@@ -25,12 +26,19 @@ class Program;
class Texture;
class Renderbuffer;
-enum SamplerType
+enum TextureType
{
- SAMPLER_2D,
- SAMPLER_CUBE,
+ TEXTURE_2D,
+ TEXTURE_CUBE,
+
+ TEXTURE_TYPE_COUNT,
+ TEXTURE_UNKNOWN
+};
- SAMPLER_TYPE_COUNT
+enum SamplerType
+{
+ SAMPLER_PIXEL,
+ SAMPLER_VERTEX
};
class ResourceManager
@@ -63,7 +71,7 @@ class ResourceManager
void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
void checkBufferAllocation(unsigned int buffer);
- void checkTextureAllocation(GLuint texture, SamplerType type);
+ void checkTextureAllocation(GLuint texture, TextureType type);
void checkRenderbufferAllocation(GLuint renderbuffer);
private:
@@ -71,20 +79,24 @@ class ResourceManager
std::size_t mRefCount;
- typedef std::map<GLuint, Buffer*> BufferMap;
+ typedef stdext::hash_map<GLuint, Buffer*> BufferMap;
BufferMap mBufferMap;
+ HandleAllocator mBufferHandleAllocator;
- typedef std::map<GLuint, Shader*> ShaderMap;
+ typedef stdext::hash_map<GLuint, Shader*> ShaderMap;
ShaderMap mShaderMap;
- typedef std::map<GLuint, Program*> ProgramMap;
+ typedef stdext::hash_map<GLuint, Program*> ProgramMap;
ProgramMap mProgramMap;
+ HandleAllocator mProgramShaderHandleAllocator;
- typedef std::map<GLuint, Texture*> TextureMap;
+ typedef stdext::hash_map<GLuint, Texture*> TextureMap;
TextureMap mTextureMap;
+ HandleAllocator mTextureHandleAllocator;
- typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
+ typedef stdext::hash_map<GLuint, Renderbuffer*> RenderbufferMap;
RenderbufferMap mRenderbufferMap;
+ HandleAllocator mRenderbufferHandleAllocator;
};
}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp
index 4c969d6..ac58abe 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -27,31 +27,8 @@ Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mReso
mHlsl = NULL;
mInfoLog = NULL;
- // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
- if (!mFragmentCompiler)
- {
- int result = ShInitialize();
-
- if (result)
- {
- ShBuiltInResources resources;
- ShInitBuiltInResources(&resources);
- Context *context = getContext();
-
- resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
- resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
- resources.MaxVaryingVectors = context->getMaximumVaryingVectors();
- resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
- resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
- resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
- resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors();
- resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
- resources.OES_standard_derivatives = 1;
-
- mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources);
- mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources);
- }
- }
+ uncompile();
+ initializeCompiler();
mRefCount = 0;
mDeleteStatus = false;
@@ -127,11 +104,8 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
if (mInfoLog)
{
- while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
- {
- infoLog[index] = mInfoLog[index];
- index++;
- }
+ index = std::min(bufSize - 1, (int)strlen(mInfoLog));
+ memcpy(infoLog, mInfoLog, index);
}
if (bufSize)
@@ -157,22 +131,31 @@ int Shader::getSourceLength() const
}
}
-void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
+int Shader::getTranslatedSourceLength() const
+{
+ if (!mHlsl)
+ {
+ return 0;
+ }
+ else
+ {
+ return strlen(mHlsl) + 1;
+ }
+}
+
+void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer)
{
int index = 0;
- if (mSource)
+ if (source)
{
- while (index < bufSize - 1 && index < (int)strlen(mSource))
- {
- source[index] = mSource[index];
- index++;
- }
+ index = std::min(bufSize - 1, (int)strlen(source));
+ memcpy(buffer, source, index);
}
if (bufSize)
{
- source[index] = '\0';
+ buffer[index] = '\0';
}
if (length)
@@ -181,6 +164,16 @@ void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
}
}
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer)
+{
+ getSourceImpl(mSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
+{
+ getSourceImpl(mHlsl, bufSize, length, buffer);
+}
+
bool Shader::isCompiled()
{
return mHlsl != NULL;
@@ -221,6 +214,36 @@ void Shader::flagForDeletion()
mDeleteStatus = true;
}
+// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
+void Shader::initializeCompiler()
+{
+ if (!mFragmentCompiler)
+ {
+ int result = ShInitialize();
+
+ if (result)
+ {
+ ShBuiltInResources resources;
+ ShInitBuiltInResources(&resources);
+ Context *context = getContext();
+
+ resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
+ resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
+ resources.MaxVaryingVectors = context->getMaximumVaryingVectors();
+ resources.MaxVertexTextureImageUnits = context->getMaximumVertexTextureImageUnits();
+ resources.MaxCombinedTextureImageUnits = context->getMaximumCombinedTextureImageUnits();
+ resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
+ resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors();
+ resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
+ resources.OES_standard_derivatives = 1;
+ // resources.OES_EGL_image_external = getDisplay()->isD3d9ExDevice() ? 1 : 0; // TODO: commented out until the extension is actually supported.
+
+ mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
+ mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
+ }
+ }
+}
+
void Shader::releaseCompiler()
{
ShDestruct(mFragmentCompiler);
@@ -259,7 +282,7 @@ void Shader::parseVaryings()
*array = '\0';
}
- varyings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
+ mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
input = strstr(input, ";") + 2;
}
@@ -271,19 +294,60 @@ void Shader::parseVaryings()
}
}
+// initialize/clean up previous state
+void Shader::uncompile()
+{
+ // set by compileToHLSL
+ delete[] mHlsl;
+ mHlsl = NULL;
+ delete[] mInfoLog;
+ mInfoLog = NULL;
+
+ // set by parseVaryings
+ mVaryings.clear();
+
+ mUsesFragCoord = false;
+ mUsesFrontFacing = false;
+ mUsesPointSize = false;
+ mUsesPointCoord = false;
+}
+
void Shader::compileToHLSL(void *compiler)
{
- if (isCompiled() || !mSource)
+ // ensure we don't pass a NULL source to the compiler
+ char *source = "\0";
+ if (mSource)
{
- return;
+ source = mSource;
}
- TRACE("\n%s", mSource);
+ // ensure the compiler is loaded
+ initializeCompiler();
- delete[] mInfoLog;
- mInfoLog = NULL;
+ int compileOptions = SH_OBJECT_CODE;
+ std::string sourcePath;
+ if (perfActive())
+ {
+ sourcePath = getTempPath();
+ writeFile(sourcePath.c_str(), source, strlen(source));
+ compileOptions |= SH_LINE_DIRECTIVES;
+ }
+
+ int result;
+ if (sourcePath.empty())
+ {
+ result = ShCompile(compiler, &source, 1, compileOptions);
+ }
+ else
+ {
+ const char* sourceStrings[2] =
+ {
+ sourcePath.c_str(),
+ source
+ };
- int result = ShCompile(compiler, &mSource, 1, SH_OBJECT_CODE);
+ result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
+ }
if (result)
{
@@ -291,8 +355,6 @@ void Shader::compileToHLSL(void *compiler)
ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
mHlsl = new char[objCodeLen];
ShGetObjectCode(compiler, mHlsl);
-
- TRACE("\n%s", mHlsl);
}
else
{
@@ -436,8 +498,18 @@ GLenum VertexShader::getType()
return GL_VERTEX_SHADER;
}
+void VertexShader::uncompile()
+{
+ Shader::uncompile();
+
+ // set by ParseAttributes
+ mAttributes.clear();
+};
+
void VertexShader::compile()
{
+ uncompile();
+
compileToHLSL(mVertexCompiler);
parseAttributes();
parseVaryings();
@@ -464,9 +536,10 @@ int VertexShader::getSemanticIndex(const std::string &attributeName)
void VertexShader::parseAttributes()
{
- if (mHlsl)
+ const char *hlsl = getHLSL();
+ if (hlsl)
{
- const char *input = strstr(mHlsl, "// Attributes") + 14;
+ const char *input = strstr(hlsl, "// Attributes") + 14;
while(true)
{
@@ -502,8 +575,10 @@ GLenum FragmentShader::getType()
void FragmentShader::compile()
{
+ uncompile();
+
compileToHLSL(mFragmentCompiler);
parseVaryings();
- varyings.sort(compareVarying);
+ mVaryings.sort(compareVarying);
}
}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h
index 5eaa053..9c7c0df 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Shader.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -57,9 +57,12 @@ class Shader
int getInfoLogLength() const;
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
int getSourceLength() const;
- void getSource(GLsizei bufSize, GLsizei *length, char *source);
+ void getSource(GLsizei bufSize, GLsizei *length, char *buffer);
+ int getTranslatedSourceLength() const;
+ void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer);
virtual void compile() = 0;
+ virtual void uncompile();
bool isCompiled();
const char *getHLSL();
@@ -72,15 +75,30 @@ class Shader
static void releaseCompiler();
protected:
- DISALLOW_COPY_AND_ASSIGN(Shader);
-
void parseVaryings();
void compileToHLSL(void *compiler);
+ void getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer);
+
static GLenum parseType(const std::string &type);
static bool compareVarying(const Varying &x, const Varying &y);
+ VaryingList mVaryings;
+
+ bool mUsesFragCoord;
+ bool mUsesFrontFacing;
+ bool mUsesPointSize;
+ bool mUsesPointCoord;
+
+ static void *mFragmentCompiler;
+ static void *mVertexCompiler;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Shader);
+
+ void initializeCompiler();
+
const GLuint mHandle;
unsigned int mRefCount; // Number of program objects this shader is attached to
bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use
@@ -89,17 +107,7 @@ class Shader
char *mHlsl;
char *mInfoLog;
- VaryingList varyings;
-
- bool mUsesFragCoord;
- bool mUsesFrontFacing;
- bool mUsesPointSize;
- bool mUsesPointCoord;
-
ResourceManager *mResourceManager;
-
- static void *mFragmentCompiler;
- static void *mVertexCompiler;
};
struct Attribute
@@ -127,8 +135,9 @@ class VertexShader : public Shader
~VertexShader();
- GLenum getType();
- void compile();
+ virtual GLenum getType();
+ virtual void compile();
+ virtual void uncompile();
int getSemanticIndex(const std::string &attributeName);
private:
@@ -146,8 +155,8 @@ class FragmentShader : public Shader
~FragmentShader();
- GLenum getType();
- void compile();
+ virtual GLenum getType();
+ virtual void compile();
private:
DISALLOW_COPY_AND_ASSIGN(FragmentShader);
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
index 7c040f8..29177d2 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.cpp
@@ -13,334 +13,384 @@
#include <d3dx9tex.h>
#include <algorithm>
+#include <intrin.h>
#include "common/debug.h"
+#include "libEGL/Display.h"
+
#include "libGLESv2/main.h"
#include "libGLESv2/mathutil.h"
#include "libGLESv2/utilities.h"
#include "libGLESv2/Blit.h"
+#include "libGLESv2/Framebuffer.h"
namespace gl
{
+unsigned int TextureStorage::mCurrentTextureSerial = 1;
-Texture::Image::Image()
- : width(0), height(0), dirty(false), surface(NULL), format(GL_NONE)
+static D3DFORMAT ConvertTextureFormatType(GLenum format, GLenum type)
{
+ if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ {
+ return D3DFMT_DXT1;
+ }
+ else if (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
+ {
+ return D3DFMT_DXT3;
+ }
+ else if (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
+ {
+ return D3DFMT_DXT5;
+ }
+ else if (type == GL_FLOAT)
+ {
+ return D3DFMT_A32B32G32R32F;
+ }
+ else if (type == GL_HALF_FLOAT_OES)
+ {
+ return D3DFMT_A16B16G16R16F;
+ }
+ else if (type == GL_UNSIGNED_BYTE)
+ {
+ if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
+ {
+ return D3DFMT_L8;
+ }
+ else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
+ {
+ return D3DFMT_A8L8;
+ }
+ else if (format == GL_RGB)
+ {
+ return D3DFMT_X8R8G8B8;
+ }
+
+ return D3DFMT_A8R8G8B8;
+ }
+
+ return D3DFMT_A8R8G8B8;
}
-Texture::Image::~Image()
+static bool IsTextureFormatRenderable(D3DFORMAT format)
{
- if (surface) surface->Release();
+ switch(format)
+ {
+ case D3DFMT_L8:
+ case D3DFMT_A8L8:
+ case D3DFMT_DXT1:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT5:
+ return false;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_A32B32G32R32F:
+ return true;
+ default:
+ UNREACHABLE();
+ }
+
+ return false;
}
-Texture::Texture(GLuint id) : RefCountObject(id)
+Image::Image()
{
- mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
- mMagFilter = GL_LINEAR;
- mWrapS = GL_REPEAT;
- mWrapT = GL_REPEAT;
-
- mWidth = 0;
+ mWidth = 0;
mHeight = 0;
-
- mDirtyMetaData = true;
- mDirty = true;
- mIsRenderable = false;
+ mFormat = GL_NONE;
mType = GL_UNSIGNED_BYTE;
- mBaseTexture = NULL;
-}
-Texture::~Texture()
-{
-}
+ mSurface = NULL;
-Blit *Texture::getBlitter()
-{
- Context *context = getContext();
- return context->getBlitter();
+ mDirty = false;
+
+ mD3DPool = D3DPOOL_SYSTEMMEM;
+ mD3DFormat = D3DFMT_UNKNOWN;
}
-// Returns true on successful filter state update (valid enum parameter)
-bool Texture::setMinFilter(GLenum filter)
+Image::~Image()
{
- switch (filter)
+ if (mSurface)
{
- case GL_NEAREST:
- case GL_LINEAR:
- case GL_NEAREST_MIPMAP_NEAREST:
- case GL_LINEAR_MIPMAP_NEAREST:
- case GL_NEAREST_MIPMAP_LINEAR:
- case GL_LINEAR_MIPMAP_LINEAR:
- {
- if (mMinFilter != filter)
- {
- mMinFilter = filter;
- mDirty = true;
- }
- return true;
- }
- default:
- return false;
+ mSurface->Release();
}
}
-// Returns true on successful filter state update (valid enum parameter)
-bool Texture::setMagFilter(GLenum filter)
+bool Image::redefine(GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRelease)
{
- switch (filter)
+ if (mWidth != width ||
+ mHeight != height ||
+ mFormat != format ||
+ mType != type ||
+ forceRelease)
{
- case GL_NEAREST:
- case GL_LINEAR:
+ mWidth = width;
+ mHeight = height;
+ mFormat = format;
+ mType = type;
+ // compute the d3d format that will be used
+ mD3DFormat = ConvertTextureFormatType(mFormat, mType);
+
+ if (mSurface)
{
- if (mMagFilter != filter)
- {
- mMagFilter = filter;
- mDirty = true;
- }
- return true;
+ mSurface->Release();
+ mSurface = NULL;
}
- default:
- return false;
+
+ return true;
}
+
+ return false;
}
-// Returns true on successful wrap state update (valid enum parameter)
-bool Texture::setWrapS(GLenum wrap)
+void Image::createSurface()
{
- switch (wrap)
+ if(mSurface)
{
- case GL_REPEAT:
- case GL_CLAMP_TO_EDGE:
- case GL_MIRRORED_REPEAT:
- {
- if (mWrapS != wrap)
- {
- mWrapS = wrap;
- mDirty = true;
- }
- return true;
- }
- default:
- return false;
+ return;
}
-}
-// Returns true on successful wrap state update (valid enum parameter)
-bool Texture::setWrapT(GLenum wrap)
-{
- switch (wrap)
+ IDirect3DTexture9 *newTexture = NULL;
+ IDirect3DSurface9 *newSurface = NULL;
+ const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
+
+ if (mWidth != 0 && mHeight != 0)
{
- case GL_REPEAT:
- case GL_CLAMP_TO_EDGE:
- case GL_MIRRORED_REPEAT:
+ int levelToFetch = 0;
+ GLsizei requestWidth = mWidth;
+ GLsizei requestHeight = mHeight;
+ if (IsCompressed(mFormat) && (mWidth % 4 != 0 || mHeight % 4 != 0))
{
- if (mWrapT != wrap)
+ bool isMult4 = false;
+ int upsampleCount = 0;
+ while (!isMult4)
{
- mWrapT = wrap;
- mDirty = true;
+ requestWidth <<= 1;
+ requestHeight <<= 1;
+ upsampleCount++;
+ if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
+ {
+ isMult4 = true;
+ }
}
- return true;
+ levelToFetch = upsampleCount;
}
- default:
- return false;
+
+ HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, getD3DFormat(),
+ poolToUse, &newTexture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ ERR("Creating image surface failed.");
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
+ newTexture->Release();
}
-}
-GLenum Texture::getMinFilter() const
-{
- return mMinFilter;
+ mSurface = newSurface;
+ mDirty = false;
+ mD3DPool = poolToUse;
}
-GLenum Texture::getMagFilter() const
+HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
{
- return mMagFilter;
-}
+ createSurface();
-GLenum Texture::getWrapS() const
-{
- return mWrapS;
+ HRESULT result = D3DERR_INVALIDCALL;
+
+ if (mSurface)
+ {
+ result = mSurface->LockRect(lockedRect, rect, 0);
+ ASSERT(SUCCEEDED(result));
+
+ mDirty = true;
+ }
+
+ return result;
}
-GLenum Texture::getWrapT() const
+void Image::unlock()
{
- return mWrapT;
+ if (mSurface)
+ {
+ HRESULT result = mSurface->UnlockRect();
+ ASSERT(SUCCEEDED(result));
+ }
}
-GLuint Texture::getWidth() const
-{
- return mWidth;
+bool Image::isRenderableFormat() const
+{
+ return IsTextureFormatRenderable(getD3DFormat());
}
-GLuint Texture::getHeight() const
+D3DFORMAT Image::getD3DFormat() const
{
- return mHeight;
+ // this should only happen if the image hasn't been redefined first
+ // which would be a bug by the caller
+ ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
+
+ return mD3DFormat;
}
-bool Texture::isFloatingPoint() const
+IDirect3DSurface9 *Image::getSurface()
{
- return (mType == GL_FLOAT || mType == GL_HALF_FLOAT_OES);
+ createSurface();
+
+ return mSurface;
}
-bool Texture::isRenderableFormat() const
+void Image::setManagedSurface(IDirect3DSurface9 *surface)
{
- D3DFORMAT format = getD3DFormat();
-
- switch(format)
+ if (mSurface)
{
- case D3DFMT_L8:
- case D3DFMT_A8L8:
- case D3DFMT_DXT1:
- return false;
- case D3DFMT_A8R8G8B8:
- case D3DFMT_X8R8G8B8:
- case D3DFMT_A16B16G16R16F:
- case D3DFMT_A32B32G32R32F:
- return true;
- default:
- UNREACHABLE();
+ D3DXLoadSurfaceFromSurface(surface, NULL, NULL, mSurface, NULL, NULL, D3DX_FILTER_BOX, 0);
+ mSurface->Release();
}
- return false;
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+ ASSERT(desc.Pool == D3DPOOL_MANAGED);
+
+ mSurface = surface;
+ mD3DPool = desc.Pool;
}
-// Selects an internal Direct3D 9 format for storing an Image
-D3DFORMAT Texture::selectFormat(GLenum format, GLenum type)
+void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
- if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
- format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
- {
- return D3DFMT_DXT1;
- }
- else if (type == GL_FLOAT)
- {
- return D3DFMT_A32B32G32R32F;
- }
- else if (type == GL_HALF_FLOAT_OES)
- {
- return D3DFMT_A16B16G16R16F;
- }
- else if (type == GL_UNSIGNED_BYTE)
+ IDirect3DSurface9 *sourceSurface = getSurface();
+
+ if (sourceSurface != destSurface)
{
- if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
- {
- return D3DFMT_L8;
- }
- else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
+ RECT rect = transformPixelRect(xoffset, yoffset, width, height, mHeight);
+
+ if (mD3DPool == D3DPOOL_MANAGED)
{
- return D3DFMT_A8L8;
+ HRESULT result = D3DXLoadSurfaceFromSurface(destSurface, NULL, &rect, sourceSurface, NULL, &rect, D3DX_FILTER_BOX, 0);
+ ASSERT(SUCCEEDED(result));
}
- else if (format == GL_RGB)
+ else
{
- return D3DFMT_X8R8G8B8;
+ // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
+ POINT point = {rect.left, rect.top};
+ HRESULT result = getDevice()->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+ ASSERT(SUCCEEDED(result));
}
-
- return D3DFMT_A8R8G8B8;
}
-
- return D3DFMT_A8R8G8B8;
}
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
// into the target pixel rectangle at output with outputPitch bytes in between each line.
-void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
- GLint unpackAlignment, const void *input, size_t outputPitch, void *output, D3DSURFACE_DESC *description) const
+void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum type,
+ GLint unpackAlignment, const void *input, size_t outputPitch, void *output) const
{
- GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment);
+ GLsizei inputPitch = -ComputePitch(width, mFormat, type, unpackAlignment);
+ input = ((char*)input) - inputPitch * (height - 1);
switch (type)
{
case GL_UNSIGNED_BYTE:
- switch (format)
+ switch (mFormat)
{
case GL_ALPHA:
- loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadAlphaData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_LUMINANCE:
- loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_L8);
+ loadLuminanceData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, getD3DFormat() == D3DFMT_L8);
break;
case GL_LUMINANCE_ALPHA:
- loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_A8L8);
+ loadLuminanceAlphaData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, getD3DFormat() == D3DFMT_A8L8);
break;
case GL_RGB:
- loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadRGBUByteData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_RGBA:
- loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ if (supportsSSE2())
+ {
+ loadRGBAUByteDataSSE2(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ }
+ else
+ {
+ loadRGBAUByteData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ }
break;
case GL_BGRA_EXT:
- loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadBGRAData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
default: UNREACHABLE();
}
break;
case GL_UNSIGNED_SHORT_5_6_5:
- switch (format)
+ switch (mFormat)
{
case GL_RGB:
- loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadRGB565Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
default: UNREACHABLE();
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
- switch (format)
+ switch (mFormat)
{
case GL_RGBA:
- loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadRGBA4444Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
default: UNREACHABLE();
}
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
- switch (format)
+ switch (mFormat)
{
case GL_RGBA:
- loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadRGBA5551Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
default: UNREACHABLE();
}
break;
case GL_FLOAT:
- switch (format)
+ switch (mFormat)
{
// float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
case GL_ALPHA:
- loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadAlphaFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_LUMINANCE:
- loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadLuminanceFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_LUMINANCE_ALPHA:
- loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadLuminanceAlphaFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_RGB:
- loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadRGBFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_RGBA:
- loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadRGBAFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
default: UNREACHABLE();
}
break;
case GL_HALF_FLOAT_OES:
- switch (format)
+ switch (mFormat)
{
// float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
case GL_ALPHA:
- loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadAlphaHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_LUMINANCE:
- loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadLuminanceHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_LUMINANCE_ALPHA:
- loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadLuminanceAlphaHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_RGB:
- loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadRGBHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
case GL_RGBA:
- loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ loadRGBAHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
break;
default: UNREACHABLE();
}
@@ -349,8 +399,8 @@ void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei
}
}
-void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned char *source = NULL;
unsigned char *dest = NULL;
@@ -369,8 +419,8 @@ void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GL
}
}
-void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const float *source = NULL;
float *dest = NULL;
@@ -389,8 +439,8 @@ void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei widt
}
}
-void Texture::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned short *source = NULL;
unsigned short *dest = NULL;
@@ -409,8 +459,8 @@ void Texture::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei
}
}
-void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
+void Image::loadLuminanceData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
{
const int destBytesPerPixel = native? 1: 4;
const unsigned char *source = NULL;
@@ -438,8 +488,8 @@ void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width
}
}
-void Texture::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadLuminanceFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const float *source = NULL;
float *dest = NULL;
@@ -458,8 +508,8 @@ void Texture::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei
}
}
-void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadLuminanceHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned short *source = NULL;
unsigned short *dest = NULL;
@@ -478,8 +528,8 @@ void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsi
}
}
-void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
+void Image::loadLuminanceAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
{
const int destBytesPerPixel = native? 2: 4;
const unsigned char *source = NULL;
@@ -507,8 +557,8 @@ void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei
}
}
-void Texture::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadLuminanceAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const float *source = NULL;
float *dest = NULL;
@@ -527,8 +577,8 @@ void Texture::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLs
}
}
-void Texture::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadLuminanceAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned short *source = NULL;
unsigned short *dest = NULL;
@@ -547,8 +597,8 @@ void Texture::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset,
}
}
-void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned char *source = NULL;
unsigned char *dest = NULL;
@@ -567,8 +617,8 @@ void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width,
}
}
-void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGB565Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned short *source = NULL;
unsigned char *dest = NULL;
@@ -588,8 +638,8 @@ void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, G
}
}
-void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const float *source = NULL;
float *dest = NULL;
@@ -608,8 +658,8 @@ void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width,
}
}
-void Texture::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned short *source = NULL;
unsigned short *dest = NULL;
@@ -628,28 +678,68 @@ void Texture::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei wi
}
}
-void Texture::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBAUByteDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
- const unsigned char *source = NULL;
- unsigned char *dest = NULL;
+ const unsigned int *source = NULL;
+ unsigned int *dest = NULL;
+ __m128i brMask = _mm_set1_epi32(0x00ff00ff);
for (int y = 0; y < height; y++)
{
- source = static_cast<const unsigned char*>(input) + y * inputPitch;
- dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
+ source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+ dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
+ int x = 0;
+
+ // Make output writes aligned
+ for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
+ {
+ unsigned int rgba = source[x];
+ dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ }
+
+ for (; x + 3 < width; x += 4)
+ {
+ __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
+ // Mask out g and a, which don't change
+ __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
+ // Mask out b and r
+ __m128i brComponents = _mm_and_si128(sourceData, brMask);
+ // Swap b and r
+ __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i result = _mm_or_si128(gaComponents, brSwapped);
+ _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
+ }
+
+ // Perform leftover writes
+ for (; x < width; x++)
+ {
+ unsigned int rgba = source[x];
+ dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ }
+ }
+}
+
+void Image::loadRGBAUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+ const unsigned int *source = NULL;
+ unsigned int *dest = NULL;
+ for (int y = 0; y < height; y++)
+ {
+ source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+ dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
+
for (int x = 0; x < width; x++)
{
- dest[4 * x + 0] = source[x * 4 + 2];
- dest[4 * x + 1] = source[x * 4 + 1];
- dest[4 * x + 2] = source[x * 4 + 0];
- dest[4 * x + 3] = source[x * 4 + 3];
+ unsigned int rgba = source[x];
+ dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
}
}
}
-void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBA4444Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned short *source = NULL;
unsigned char *dest = NULL;
@@ -669,8 +759,8 @@ void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width,
}
}
-void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBA5551Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned short *source = NULL;
unsigned char *dest = NULL;
@@ -690,8 +780,8 @@ void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width,
}
}
-void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBAFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const float *source = NULL;
float *dest = NULL;
@@ -704,8 +794,8 @@ void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width
}
}
-void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadRGBAHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned char *source = NULL;
unsigned char *dest = NULL;
@@ -718,8 +808,8 @@ void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei w
}
}
-void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const
+void Image::loadBGRAData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
const unsigned char *source = NULL;
unsigned char *dest = NULL;
@@ -732,158 +822,718 @@ void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLs
}
}
-void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img)
+void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const {
+ switch (getD3DFormat())
+ {
+ case D3DFMT_DXT1:
+ loadDXT1Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+ case D3DFMT_DXT3:
+ loadDXT3Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+ case D3DFMT_DXT5:
+ loadDXT5Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
+ break;
+ }
+}
+
+static void FlipCopyDXT1BlockFull(const unsigned int* source, unsigned int* dest) {
+ // A DXT1 block layout is:
+ // [0-1] color0.
+ // [2-3] color1.
+ // [4-7] color bitmap, 2 bits per pixel.
+ // So each of the 4-7 bytes represents one line, flipping a block is just
+ // flipping those bytes.
+
+ // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
+ dest[0] = source[0];
+
+ // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.
+ dest[1] = (source[1] >> 24) |
+ ((source[1] << 8) & 0x00FF0000) |
+ ((source[1] >> 8) & 0x0000FF00) |
+ (source[1] << 24);
+}
+
+// Flips the first 2 lines of a DXT1 block in the y direction.
+static void FlipCopyDXT1BlockHalf(const unsigned int* source, unsigned int* dest) {
+ // See layout above.
+ dest[0] = source[0];
+ dest[1] = ((source[1] << 8) & 0x0000FF00) |
+ ((source[1] >> 8) & 0x000000FF);
+}
+
+// Flips a full DXT3 block in the y direction.
+static void FlipCopyDXT3BlockFull(const unsigned int* source, unsigned int* dest) {
+ // A DXT3 block layout is:
+ // [0-7] alpha bitmap, 4 bits per pixel.
+ // [8-15] a DXT1 block.
+
+ // First and Second 32 bits are 4bit per pixel alpha and need to be flipped.
+ dest[0] = (source[1] >> 16) | (source[1] << 16);
+ dest[1] = (source[0] >> 16) | (source[0] << 16);
+
+ // And flip the DXT1 block using the above function.
+ FlipCopyDXT1BlockFull(source + 2, dest + 2);
+}
+
+// Flips the first 2 lines of a DXT3 block in the y direction.
+static void FlipCopyDXT3BlockHalf(const unsigned int* source, unsigned int* dest) {
+ // See layout above.
+ dest[0] = (source[1] >> 16) | (source[1] << 16);
+ FlipCopyDXT1BlockHalf(source + 2, dest + 2);
+}
+
+// Flips a full DXT5 block in the y direction.
+static void FlipCopyDXT5BlockFull(const unsigned int* source, unsigned int* dest) {
+ // A DXT5 block layout is:
+ // [0] alpha0.
+ // [1] alpha1.
+ // [2-7] alpha bitmap, 3 bits per pixel.
+ // [8-15] a DXT1 block.
+
+ // The alpha bitmap doesn't easily map lines to bytes, so we have to
+ // interpret it correctly. Extracted from
+ // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt :
+ //
+ // The 6 "bits" bytes of the block are decoded into one 48-bit integer:
+ //
+ // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
+ // 256 * (bits_4 + 256 * bits_5))))
+ //
+ // bits is a 48-bit unsigned integer, from which a three-bit control code
+ // is extracted for a texel at location (x,y) in the block using:
+ //
+ // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
+ //
+ // where bit 47 is the most significant and bit 0 is the least
+ // significant bit.
+ const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
+ unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
+ unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
+ unsigned int line_2_3 = sourceBytes[5] + 256 * (sourceBytes[6] + 256 * sourceBytes[7]);
+ // swap lines 0 and 1 in line_0_1.
+ unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
+ ((line_0_1 & 0xfff000) >> 12);
+ // swap lines 2 and 3 in line_2_3.
+ unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) |
+ ((line_2_3 & 0xfff000) >> 12);
+ destBytes[0] = sourceBytes[0];
+ destBytes[1] = sourceBytes[1];
+ destBytes[2] = line_3_2 & 0xff;
+ destBytes[3] = (line_3_2 & 0xff00) >> 8;
+ destBytes[4] = (line_3_2 & 0xff0000) >> 16;
+ destBytes[5] = line_1_0 & 0xff;
+ destBytes[6] = (line_1_0 & 0xff00) >> 8;
+ destBytes[7] = (line_1_0 & 0xff0000) >> 16;
+
+ // And flip the DXT1 block using the above function.
+ FlipCopyDXT1BlockFull(source + 2, dest + 2);
+}
+
+// Flips the first 2 lines of a DXT5 block in the y direction.
+static void FlipCopyDXT5BlockHalf(const unsigned int* source, unsigned int* dest) {
+ // See layout above.
+ const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
+ unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
+ unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
+ unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
+ ((line_0_1 & 0xfff000) >> 12);
+ destBytes[0] = sourceBytes[0];
+ destBytes[1] = sourceBytes[1];
+ destBytes[2] = line_1_0 & 0xff;
+ destBytes[3] = (line_1_0 & 0xff00) >> 8;
+ destBytes[4] = (line_1_0 & 0xff0000) >> 16;
+ FlipCopyDXT1BlockHalf(source + 2, dest + 2);
+}
+
+void Image::loadDXT1Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+ ASSERT(xoffset % 4 == 0);
+ ASSERT(yoffset % 4 == 0);
+ ASSERT(width % 4 == 0 || width == 2 || width == 1);
+ ASSERT(inputPitch % 8 == 0);
+ ASSERT(outputPitch % 8 == 0);
+
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(output);
+
+ // Round width up in case it is less than 4.
+ int blocksAcross = (width + 3) / 4;
+ int intsAcross = blocksAcross * 2;
+
+ switch (height)
+ {
+ case 1:
+ for (int x = 0; x < intsAcross; x += 2)
+ {
+ // just copy the block
+ dest[x] = source[x];
+ dest[x + 1] = source[x + 1];
+ }
+ break;
+ case 2:
+ for (int x = 0; x < intsAcross; x += 2)
+ {
+ FlipCopyDXT1BlockHalf(source + x, dest + x);
+ }
+ break;
+ default:
+ ASSERT(height % 4 == 0);
+ for (int y = 0; y < height / 4; ++y)
+ {
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
+
+ for (int x = 0; x < intsAcross; x += 2)
+ {
+ FlipCopyDXT1BlockFull(source + x, dest + x);
+ }
+ }
+ break;
+ }
+}
+
+void Image::loadDXT3Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
{
- IDirect3DTexture9 *newTexture = NULL;
- IDirect3DSurface9 *newSurface = NULL;
+ ASSERT(xoffset % 4 == 0);
+ ASSERT(yoffset % 4 == 0);
+ ASSERT(width % 4 == 0 || width == 2 || width == 1);
+ ASSERT(inputPitch % 16 == 0);
+ ASSERT(outputPitch % 16 == 0);
+
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(output);
+
+ // Round width up in case it is less than 4.
+ int blocksAcross = (width + 3) / 4;
+ int intsAcross = blocksAcross * 4;
- if (width != 0 && height != 0)
+ switch (height)
{
- int levelToFetch = 0;
- GLsizei requestWidth = width;
- GLsizei requestHeight = height;
- if (IsCompressed(format) && (width % 4 != 0 || height % 4 != 0))
- {
- bool isMult4 = false;
- int upsampleCount = 0;
- while (!isMult4)
+ case 1:
+ for (int x = 0; x < intsAcross; x += 4)
{
- requestWidth <<= 1;
- requestHeight <<= 1;
- upsampleCount++;
- if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
+ // just copy the block
+ dest[x] = source[x];
+ dest[x + 1] = source[x + 1];
+ dest[x + 2] = source[x + 2];
+ dest[x + 3] = source[x + 3];
+ }
+ break;
+ case 2:
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ FlipCopyDXT3BlockHalf(source + x, dest + x);
+ }
+ break;
+ default:
+ ASSERT(height % 4 == 0);
+ for (int y = 0; y < height / 4; ++y)
+ {
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
+
+ for (int x = 0; x < intsAcross; x += 4)
{
- isMult4 = true;
+ FlipCopyDXT3BlockFull(source + x, dest + x);
}
}
- levelToFetch = upsampleCount;
+ break;
+ }
+}
+
+void Image::loadDXT5Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const
+{
+ ASSERT(xoffset % 4 == 0);
+ ASSERT(yoffset % 4 == 0);
+ ASSERT(width % 4 == 0 || width == 2 || width == 1);
+ ASSERT(inputPitch % 16 == 0);
+ ASSERT(outputPitch % 16 == 0);
+
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(output);
+
+ // Round width up in case it is less than 4.
+ int blocksAcross = (width + 3) / 4;
+ int intsAcross = blocksAcross * 4;
+
+ switch (height)
+ {
+ case 1:
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ // just copy the block
+ dest[x] = source[x];
+ dest[x + 1] = source[x + 1];
+ dest[x + 2] = source[x + 2];
+ dest[x + 3] = source[x + 3];
+ }
+ break;
+ case 2:
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ FlipCopyDXT5BlockHalf(source + x, dest + x);
+ }
+ break;
+ default:
+ ASSERT(height % 4 == 0);
+ for (int y = 0; y < height / 4; ++y)
+ {
+ const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
+ unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
+
+ for (int x = 0; x < intsAcross; x += 4)
+ {
+ FlipCopyDXT5BlockFull(source + x, dest + x);
+ }
+ }
+ break;
+ }
+}
+
+// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
+void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
+{
+ IDirect3DDevice9 *device = getDevice();
+ IDirect3DSurface9 *renderTargetData = NULL;
+ D3DSURFACE_DESC description;
+ renderTarget->GetDesc(&description);
+
+ HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
+
+ if (FAILED(result))
+ {
+ ERR("Could not create matching destination surface.");
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ result = device->GetRenderTargetData(renderTarget, renderTargetData);
+
+ if (FAILED(result))
+ {
+ ERR("GetRenderTargetData unexpectedly failed.");
+ renderTargetData->Release();
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);
+ int destYOffset = transformPixelYOffset(yoffset, height, mHeight);
+ RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};
+
+ if (isRenderableFormat())
+ {
+ result = D3DXLoadSurfaceFromSurface(getSurface(), NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0);
+
+ if (FAILED(result))
+ {
+ ERR("Copying surfaces unexpectedly failed.");
+ renderTargetData->Release();
+ return error(GL_OUT_OF_MEMORY);
}
+ }
+ else
+ {
+ D3DLOCKED_RECT sourceLock = {0};
+ result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
- HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, selectFormat(format, type),
- D3DPOOL_SYSTEMMEM, &newTexture, NULL);
+ if (FAILED(result))
+ {
+ ERR("Failed to lock the source surface (rectangle might be invalid).");
+ renderTargetData->Release();
+ return error(GL_OUT_OF_MEMORY);
+ }
+ D3DLOCKED_RECT destLock = {0};
+ result = lock(&destLock, &destRect);
+
if (FAILED(result))
{
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ ERR("Failed to lock the destination surface (rectangle might be invalid).");
+ renderTargetData->UnlockRect();
+ renderTargetData->Release();
return error(GL_OUT_OF_MEMORY);
}
- newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
- newTexture->Release();
+ if (destLock.pBits && sourceLock.pBits)
+ {
+ unsigned char *source = (unsigned char*)sourceLock.pBits;
+ unsigned char *dest = (unsigned char*)destLock.pBits;
+
+ switch (description.Format)
+ {
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ switch(getD3DFormat())
+ {
+ case D3DFMT_L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ dest[x] = source[x * 4 + 2];
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ dest[x * 2 + 0] = source[x * 4 + 2];
+ dest[x * 2 + 1] = source[x * 4 + 3];
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case D3DFMT_R5G6B5:
+ switch(getD3DFormat())
+ {
+ case D3DFMT_L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned char red = source[x * 2 + 1] & 0xF8;
+ dest[x] = red | (red >> 5);
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case D3DFMT_A1R5G5B5:
+ switch(getD3DFormat())
+ {
+ case D3DFMT_L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned char red = source[x * 2 + 1] & 0x7C;
+ dest[x] = (red << 1) | (red >> 4);
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned char red = source[x * 2 + 1] & 0x7C;
+ dest[x * 2 + 0] = (red << 1) | (red >> 4);
+ dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ unlock();
+ renderTargetData->UnlockRect();
}
- if (img->surface) img->surface->Release();
- img->surface = newSurface;
+ renderTargetData->Release();
+
+ mDirty = true;
+}
+
+TextureStorage::TextureStorage(bool renderTarget)
+ : mRenderTarget(renderTarget),
+ mD3DPool(getDisplay()->getTexturePool(mRenderTarget)),
+ mTextureSerial(issueTextureSerial())
+{
+}
+
+TextureStorage::~TextureStorage()
+{
+}
+
+bool TextureStorage::isRenderTarget() const
+{
+ return mRenderTarget;
+}
+
+bool TextureStorage::isManaged() const
+{
+ return (mD3DPool == D3DPOOL_MANAGED);
+}
+
+D3DPOOL TextureStorage::getPool() const
+{
+ return mD3DPool;
+}
- img->width = width;
- img->height = height;
- img->format = format;
+unsigned int TextureStorage::getTextureSerial() const
+{
+ return mTextureSerial;
}
-void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
+unsigned int TextureStorage::issueTextureSerial()
{
- createSurface(width, height, format, type, img);
+ return mCurrentTextureSerial++;
+}
- if (pixels != NULL && img->surface != NULL)
+Texture::Texture(GLuint id) : RefCountObject(id)
+{
+ mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
+ mMagFilter = GL_LINEAR;
+ mWrapS = GL_REPEAT;
+ mWrapT = GL_REPEAT;
+ mDirtyParameters = true;
+ mUsage = GL_NONE;
+
+ mDirtyImages = true;
+
+ mImmutable = false;
+}
+
+Texture::~Texture()
+{
+}
+
+// Returns true on successful filter state update (valid enum parameter)
+bool Texture::setMinFilter(GLenum filter)
+{
+ switch (filter)
{
- D3DSURFACE_DESC description;
- img->surface->GetDesc(&description);
+ case GL_NEAREST:
+ case GL_LINEAR:
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ {
+ if (mMinFilter != filter)
+ {
+ mMinFilter = filter;
+ mDirtyParameters = true;
+ }
+ return true;
+ }
+ default:
+ return false;
+ }
+}
- D3DLOCKED_RECT locked;
- HRESULT result = img->surface->LockRect(&locked, NULL, 0);
+// Returns true on successful filter state update (valid enum parameter)
+bool Texture::setMagFilter(GLenum filter)
+{
+ switch (filter)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ {
+ if (mMagFilter != filter)
+ {
+ mMagFilter = filter;
+ mDirtyParameters = true;
+ }
+ return true;
+ }
+ default:
+ return false;
+ }
+}
- ASSERT(SUCCEEDED(result));
+// Returns true on successful wrap state update (valid enum parameter)
+bool Texture::setWrapS(GLenum wrap)
+{
+ switch (wrap)
+ {
+ case GL_REPEAT:
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
+ {
+ if (mWrapS != wrap)
+ {
+ mWrapS = wrap;
+ mDirtyParameters = true;
+ }
+ return true;
+ }
+ default:
+ return false;
+ }
+}
- if (SUCCEEDED(result))
+// Returns true on successful wrap state update (valid enum parameter)
+bool Texture::setWrapT(GLenum wrap)
+{
+ switch (wrap)
+ {
+ case GL_REPEAT:
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
{
- loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
- img->surface->UnlockRect();
+ if (mWrapT != wrap)
+ {
+ mWrapT = wrap;
+ mDirtyParameters = true;
+ }
+ return true;
}
+ default:
+ return false;
+ }
+}
- img->dirty = true;
+// Returns true on successful usage state update (valid enum parameter)
+bool Texture::setUsage(GLenum usage)
+{
+ switch (usage)
+ {
+ case GL_NONE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
+ mUsage = usage;
+ return true;
+ default:
+ return false;
}
+}
- mDirtyMetaData = true;
+GLenum Texture::getMinFilter() const
+{
+ return mMinFilter;
}
-void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
+GLenum Texture::getMagFilter() const
+{
+ return mMagFilter;
+}
+
+GLenum Texture::getWrapS() const
{
- createSurface(width, height, format, GL_UNSIGNED_BYTE, img);
+ return mWrapS;
+}
- if (pixels != NULL && img->surface != NULL)
+GLenum Texture::getWrapT() const
+{
+ return mWrapT;
+}
+
+GLenum Texture::getUsage() const
+{
+ return mUsage;
+}
+
+void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image)
+{
+ if (pixels != NULL)
{
D3DLOCKED_RECT locked;
- HRESULT result = img->surface->LockRect(&locked, NULL, 0);
-
- ASSERT(SUCCEEDED(result));
+ HRESULT result = image->lock(&locked, NULL);
if (SUCCEEDED(result))
{
- memcpy(locked.pBits, pixels, imageSize);
- img->surface->UnlockRect();
+ image->loadData(0, 0, image->getWidth(), image->getHeight(), image->getType(), unpackAlignment, pixels, locked.Pitch, locked.pBits);
+ image->unlock();
}
- img->dirty = true;
+ mDirtyImages = true;
}
+}
+
+void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
+{
+ if (pixels != NULL)
+ {
+ D3DLOCKED_RECT locked;
+ HRESULT result = image->lock(&locked, NULL);
- mDirtyMetaData = true;
+ if (SUCCEEDED(result))
+ {
+ int inputPitch = ComputeCompressedPitch(image->getWidth(), image->getFormat());
+ int inputSize = ComputeCompressedSize(image->getWidth(), image->getHeight(), image->getFormat());
+ image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
+ image->unlock();
+ }
+
+ mDirtyImages = true;
+ }
}
-bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
+bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image)
{
- if (width + xoffset > img->width || height + yoffset > img->height)
+ if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
{
error(GL_INVALID_VALUE);
return false;
}
- if (!img->surface)
+ if (IsCompressed(image->getFormat()))
{
- createSurface(img->width, img->height, format, type, img);
+ error(GL_INVALID_OPERATION);
+ return false;
}
- if (pixels != NULL && img->surface != NULL)
+ if (format != image->getFormat())
{
- D3DSURFACE_DESC description;
- img->surface->GetDesc(&description);
+ error(GL_INVALID_OPERATION);
+ return false;
+ }
+ if (pixels != NULL)
+ {
D3DLOCKED_RECT locked;
- HRESULT result = img->surface->LockRect(&locked, NULL, 0);
-
- ASSERT(SUCCEEDED(result));
+ HRESULT result = image->lock(&locked, NULL);
if (SUCCEEDED(result))
{
- loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
- img->surface->UnlockRect();
+ image->loadData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
+ image->unlock();
}
- img->dirty = true;
+ mDirtyImages = true;
}
return true;
}
-bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
+bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image)
{
- if (width + xoffset > img->width || height + yoffset > img->height)
+ if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
{
error(GL_INVALID_VALUE);
return false;
}
- if (format != getFormat())
+ if (format != getInternalFormat())
{
error(GL_INVALID_OPERATION);
return false;
}
- if (!img->surface)
- {
- createSurface(img->width, img->height, format, GL_UNSIGNED_BYTE, img);
- }
-
- if (pixels != NULL && img->surface != NULL)
+ if (pixels != NULL)
{
RECT updateRegion;
updateRegion.left = xoffset;
@@ -892,419 +1542,354 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL
updateRegion.top = yoffset;
D3DLOCKED_RECT locked;
- HRESULT result = img->surface->LockRect(&locked, &updateRegion, 0);
-
- ASSERT(SUCCEEDED(result));
+ HRESULT result = image->lock(&locked, &updateRegion);
if (SUCCEEDED(result))
{
- GLsizei inputPitch = ComputeCompressedPitch(width, format);
- int rows = imageSize / inputPitch;
- for (int i = 0; i < rows; ++i)
- {
- memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch);
- }
- img->surface->UnlockRect();
+ int inputPitch = ComputeCompressedPitch(width, format);
+ int inputSize = ComputeCompressedSize(width, height, format);
+ image->loadCompressedData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
+ image->unlock();
}
- img->dirty = true;
+ mDirtyImages = true;
}
return true;
}
-// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats
-void Texture::copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
+IDirect3DBaseTexture9 *Texture::getTexture()
{
- IDirect3DDevice9 *device = getDevice();
- IDirect3DSurface9 *surface = NULL;
- D3DSURFACE_DESC description;
- renderTarget->GetDesc(&description);
-
- HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
-
- if (!SUCCEEDED(result))
+ if (!isSamplerComplete())
{
- ERR("Could not create matching destination surface.");
- return error(GL_OUT_OF_MEMORY);
+ return NULL;
}
- result = device->GetRenderTargetData(renderTarget, surface);
-
- if (!SUCCEEDED(result))
+ // ensure the underlying texture is created
+ if (getStorage(false) == NULL)
{
- ERR("GetRenderTargetData unexpectedly failed.");
- surface->Release();
- return error(GL_OUT_OF_MEMORY);
+ return NULL;
}
- D3DLOCKED_RECT sourceLock = {0};
- RECT sourceRect = {x, y, x + width, y + height};
- result = surface->LockRect(&sourceLock, &sourceRect, 0);
+ updateTexture();
- if (FAILED(result))
- {
- ERR("Failed to lock the source surface (rectangle might be invalid).");
- surface->UnlockRect();
- surface->Release();
- return error(GL_OUT_OF_MEMORY);
- }
+ return getBaseTexture();
+}
- if (!image->surface)
- {
- createSurface(width, height, internalFormat, mType, image);
- }
+bool Texture::hasDirtyParameters() const
+{
+ return mDirtyParameters;
+}
- if (image->surface == NULL)
- {
- ERR("Failed to create an image surface.");
- surface->UnlockRect();
- surface->Release();
- return error(GL_OUT_OF_MEMORY);
- }
+bool Texture::hasDirtyImages() const
+{
+ return mDirtyImages;
+}
- D3DLOCKED_RECT destLock = {0};
- RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
- result = image->surface->LockRect(&destLock, &destRect, 0);
-
- if (FAILED(result))
+void Texture::resetDirty()
+{
+ mDirtyParameters = false;
+ mDirtyImages = false;
+}
+
+unsigned int Texture::getTextureSerial()
+{
+ TextureStorage *texture = getStorage(false);
+ return texture ? texture->getTextureSerial() : 0;
+}
+
+unsigned int Texture::getRenderTargetSerial(GLenum target)
+{
+ TextureStorage *texture = getStorage(true);
+ return texture ? texture->getRenderTargetSerial(target) : 0;
+}
+
+bool Texture::isImmutable() const
+{
+ return mImmutable;
+}
+
+GLint Texture::creationLevels(GLsizei width, GLsizei height) const
+{
+ if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
{
- ERR("Failed to lock the destination surface (rectangle might be invalid).");
- surface->UnlockRect();
- surface->Release();
- return error(GL_OUT_OF_MEMORY);
+ return 0; // Maximum number of levels
}
-
- if (destLock.pBits && sourceLock.pBits)
+ else
{
- unsigned char *source = (unsigned char*)sourceLock.pBits;
- unsigned char *dest = (unsigned char*)destLock.pBits;
+ // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
+ return 1;
+ }
+}
- switch (description.Format)
- {
- case D3DFMT_X8R8G8B8:
- case D3DFMT_A8R8G8B8:
- switch(getD3DFormat())
- {
- case D3DFMT_L8:
- for(int y = 0; y < height; y++)
- {
- for(int x = 0; x < width; x++)
- {
- dest[x] = source[x * 4 + 2];
- }
+GLint Texture::creationLevels(GLsizei size) const
+{
+ return creationLevels(size, size);
+}
- source += sourceLock.Pitch;
- dest += destLock.Pitch;
- }
- break;
- case D3DFMT_A8L8:
- for(int y = 0; y < height; y++)
- {
- for(int x = 0; x < width; x++)
- {
- dest[x * 2 + 0] = source[x * 4 + 2];
- dest[x * 2 + 1] = source[x * 4 + 3];
- }
+int Texture::levelCount() const
+{
+ return getBaseTexture() ? getBaseTexture()->GetLevelCount() : 0;
+}
- source += sourceLock.Pitch;
- dest += destLock.Pitch;
- }
- break;
- default:
- UNREACHABLE();
- }
- break;
- case D3DFMT_R5G6B5:
- switch(getD3DFormat())
- {
- case D3DFMT_L8:
- for(int y = 0; y < height; y++)
- {
- for(int x = 0; x < width; x++)
- {
- unsigned char red = source[x * 2 + 1] & 0xF8;
- dest[x] = red | (red >> 5);
- }
+Blit *Texture::getBlitter()
+{
+ Context *context = getContext();
+ return context->getBlitter();
+}
- source += sourceLock.Pitch;
- dest += destLock.Pitch;
- }
- break;
- default:
- UNREACHABLE();
- }
- break;
- case D3DFMT_A1R5G5B5:
- switch(getD3DFormat())
- {
- case D3DFMT_L8:
- for(int y = 0; y < height; y++)
- {
- for(int x = 0; x < width; x++)
- {
- unsigned char red = source[x * 2 + 1] & 0x7C;
- dest[x] = (red << 1) | (red >> 4);
- }
+bool Texture::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
+{
+ if (source && dest)
+ {
+ HRESULT result;
- source += sourceLock.Pitch;
- dest += destLock.Pitch;
- }
- break;
- case D3DFMT_A8L8:
- for(int y = 0; y < height; y++)
- {
- for(int x = 0; x < width; x++)
- {
- unsigned char red = source[x * 2 + 1] & 0x7C;
- dest[x * 2 + 0] = (red << 1) | (red >> 4);
- dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
- }
+ if (fromManaged)
+ {
+ result = D3DXLoadSurfaceFromSurface(dest, NULL, NULL, source, NULL, NULL, D3DX_FILTER_BOX, 0);
+ }
+ else
+ {
+ egl::Display *display = getDisplay();
+ IDirect3DDevice9 *device = display->getDevice();
- source += sourceLock.Pitch;
- dest += destLock.Pitch;
- }
- break;
- default:
- UNREACHABLE();
- }
- break;
- default:
- UNREACHABLE();
+ display->endScene();
+ result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
}
- image->dirty = true;
- mDirtyMetaData = true;
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return false;
+ }
}
- image->surface->UnlockRect();
- surface->UnlockRect();
- surface->Release();
+ return true;
}
-D3DFORMAT Texture::getD3DFormat() const
+TextureStorage2D::TextureStorage2D(IDirect3DTexture9 *surfaceTexture) : TextureStorage(true), mRenderTargetSerial(RenderbufferStorage::issueSerial())
{
- return selectFormat(getFormat(), mType);
+ mTexture = surfaceTexture;
}
-IDirect3DBaseTexture9 *Texture::getTexture()
+TextureStorage2D::TextureStorage2D(int levels, D3DFORMAT format, int width, int height, bool renderTarget)
+ : TextureStorage(renderTarget), mRenderTargetSerial(RenderbufferStorage::issueSerial())
{
- if (!isComplete())
+ IDirect3DDevice9 *device = getDevice();
+
+ mTexture = NULL;
+ HRESULT result = device->CreateTexture(width, height, levels, isRenderTarget() ? D3DUSAGE_RENDERTARGET : 0, format, getPool(), &mTexture, NULL);
+
+ if (FAILED(result))
{
- return NULL;
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ error(GL_OUT_OF_MEMORY);
}
+}
- if (mDirtyMetaData)
+TextureStorage2D::~TextureStorage2D()
+{
+ if (mTexture)
{
- mBaseTexture = createTexture();
- mIsRenderable = false;
+ mTexture->Release();
}
+}
+
+IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level)
+{
+ IDirect3DSurface9 *surface = NULL;
- if (mDirtyMetaData || dirtyImageData())
+ if (mTexture)
{
- updateTexture();
+ HRESULT result = mTexture->GetSurfaceLevel(level, &surface);
+ ASSERT(SUCCEEDED(result));
}
- mDirtyMetaData = false;
- ASSERT(!dirtyImageData());
+ return surface;
+}
- return mBaseTexture;
+IDirect3DBaseTexture9 *TextureStorage2D::getBaseTexture() const
+{
+ return mTexture;
}
-bool Texture::isDirty() const
+unsigned int TextureStorage2D::getRenderTargetSerial(GLenum target) const
{
- return (mDirty || mDirtyMetaData || dirtyImageData());
+ return mRenderTargetSerial;
}
-// Returns the top-level texture surface as a render target
-void Texture::needRenderTarget()
+Texture2D::Texture2D(GLuint id) : Texture(id)
{
- if (!mIsRenderable)
- {
- mBaseTexture = convertToRenderTarget();
- mIsRenderable = true;
- }
+ mTexStorage = NULL;
+ mSurface = NULL;
+ mColorbufferProxy = NULL;
+ mProxyRefs = 0;
+}
- if (dirtyImageData())
+Texture2D::~Texture2D()
+{
+ mColorbufferProxy = NULL;
+
+ delete mTexStorage;
+ mTexStorage = NULL;
+
+ if (mSurface)
{
- updateTexture();
+ mSurface->setBoundTexture(NULL);
+ mSurface = NULL;
}
+}
- mDirtyMetaData = false;
+// 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 Texture::dropTexture()
+void Texture2D::releaseProxy(const Renderbuffer *proxy)
{
- if (mBaseTexture)
- {
- mBaseTexture = NULL;
- }
+ if (mProxyRefs > 0)
+ mProxyRefs--;
- mIsRenderable = false;
+ if (mProxyRefs == 0)
+ mColorbufferProxy = NULL;
}
-void Texture::pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable)
+GLenum Texture2D::getTarget() const
{
- mBaseTexture = newTexture;
- mDirtyMetaData = false;
- mIsRenderable = renderable;
- mDirty = true;
+ return GL_TEXTURE_2D;
}
-
-GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
+GLsizei Texture2D::getWidth(GLint level) const
{
- if (isPow2(width) && isPow2(height))
- {
- return maxlevel;
- }
+ if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level].getWidth();
else
- {
- // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
- return 1;
- }
+ return 0;
}
-GLint Texture::creationLevels(GLsizei size, GLint maxlevel) const
+GLsizei Texture2D::getHeight(GLint level) const
{
- return creationLevels(size, size, maxlevel);
+ if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level].getHeight();
+ else
+ return 0;
}
-int Texture::levelCount() const
+GLenum Texture2D::getInternalFormat() const
{
- return mBaseTexture ? mBaseTexture->GetLevelCount() : 0;
+ return mImageArray[0].getFormat();
}
-bool Texture::isRenderable() const
+GLenum Texture2D::getType() const
{
- return mIsRenderable;
+ return mImageArray[0].getType();
}
-Texture2D::Texture2D(GLuint id) : Texture(id)
+D3DFORMAT Texture2D::getD3DFormat() const
{
- mTexture = NULL;
+ return mImageArray[0].getD3DFormat();
}
-Texture2D::~Texture2D()
+void Texture2D::redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
{
- mColorbufferProxy.set(NULL);
+ releaseTexImage();
- if (mTexture)
+ bool redefined = mImageArray[level].redefine(format, width, height, type, false);
+
+ if (mTexStorage && redefined)
{
- mTexture->Release();
- mTexture = NULL;
+ for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mImageArray[i].markDirty();
+ }
+
+ delete mTexStorage;
+ mTexStorage = NULL;
+ mDirtyImages = true;
}
}
-GLenum Texture2D::getTarget() const
+void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
- return GL_TEXTURE_2D;
-}
+ redefineImage(level, format, width, height, type);
-GLenum Texture2D::getFormat() const
-{
- return mImageArray[0].format;
+ Texture::setImage(unpackAlignment, pixels, &mImageArray[level]);
}
-// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
-// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels.
-// Call this when a particular level of the texture must be defined with a specific format, width and height.
-//
-// Returns true if the existing texture was unsuitable and had to be destroyed. If so, it will also set
-// a new height and width for the texture by working backwards from the given width and height.
-bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type)
+void Texture2D::bindTexImage(egl::Surface *surface)
{
- bool widthOkay = (mWidth >> level == width);
- bool heightOkay = (mHeight >> level == height);
+ releaseTexImage();
- bool sizeOkay = ((widthOkay && heightOkay)
- || (widthOkay && mHeight >> level == 0 && height == 1)
- || (heightOkay && mWidth >> level == 0 && width == 1));
+ GLenum format;
- bool typeOkay = (type == mType);
+ switch(surface->getFormat())
+ {
+ case D3DFMT_A8R8G8B8:
+ format = GL_RGBA;
+ break;
+ case D3DFMT_X8R8G8B8:
+ format = GL_RGB;
+ break;
+ default:
+ UNIMPLEMENTED();
+ return;
+ }
- bool textureOkay = (sizeOkay && typeOkay && internalFormat == mImageArray[0].format);
+ mImageArray[0].redefine(format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true);
- if (!textureOkay)
- {
- TRACE("Redefining 2D texture (%d, 0x%04X, %d, %d => 0x%04X, %d, %d).", level,
- mImageArray[0].format, mWidth, mHeight,
- internalFormat, width, height);
+ delete mTexStorage;
+ mTexStorage = new TextureStorage2D(surface->getOffscreenTexture());
- // Purge all the levels and the texture.
+ mDirtyImages = true;
+ mSurface = surface;
+ mSurface->setBoundTexture(this);
+}
- for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- if (mImageArray[i].surface != NULL)
- {
- mImageArray[i].dirty = false;
+void Texture2D::releaseTexImage()
+{
+ if (mSurface)
+ {
+ mSurface->setBoundTexture(NULL);
+ mSurface = NULL;
- mImageArray[i].surface->Release();
- mImageArray[i].surface = NULL;
- }
+ if (mTexStorage)
+ {
+ delete mTexStorage;
+ mTexStorage = NULL;
}
- if (mTexture != NULL)
+ for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
- mTexture->Release();
- mTexture = NULL;
- dropTexture();
+ mImageArray[i].redefine(GL_RGBA, 0, 0, GL_UNSIGNED_BYTE, true);
}
-
- mWidth = width << level;
- mHeight = height << level;
- mImageArray[0].format = internalFormat;
- mType = type;
}
-
- return !textureOkay;
}
-void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
- redefineTexture(level, internalFormat, width, height, type);
+ redefineImage(level, format, width, height, GL_UNSIGNED_BYTE);
- Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]);
-}
-
-void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
-{
- redefineTexture(level, internalFormat, width, height, GL_UNSIGNED_BYTE);
-
- Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);
+ Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]);
}
void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
{
- ASSERT(mImageArray[level].surface != NULL);
+ ASSERT(mImageArray[level].getSurface() != NULL);
if (level < levelCount())
{
- IDirect3DSurface9 *destLevel = NULL;
- HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
+ IDirect3DSurface9 *destLevel = mTexStorage->getSurfaceLevel(level);
- ASSERT(SUCCEEDED(result));
-
- if (SUCCEEDED(result))
+ if (destLevel)
{
- Image *img = &mImageArray[level];
-
- RECT sourceRect;
- sourceRect.left = xoffset;
- sourceRect.top = yoffset;
- sourceRect.right = xoffset + width;
- sourceRect.bottom = yoffset + height;
-
- POINT destPoint;
- destPoint.x = xoffset;
- destPoint.y = yoffset;
-
- result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
- ASSERT(SUCCEEDED(result));
+ Image *image = &mImageArray[level];
+ image->updateSurface(destLevel, xoffset, yoffset, width, height);
destLevel->Release();
-
- img->dirty = false;
+ image->markClean();
}
}
}
@@ -1325,7 +1910,7 @@ void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GL
}
}
-void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
IDirect3DSurface9 *renderTarget = source->getRenderTarget();
@@ -1335,48 +1920,48 @@ void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y,
return error(GL_OUT_OF_MEMORY);
}
- bool redefined = redefineTexture(level, internalFormat, width, height, mType);
+ redefineImage(level, format, width, height, GL_UNSIGNED_BYTE);
- if (!isRenderableFormat())
+ if (!mImageArray[level].isRenderableFormat())
{
- copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget);
+ mImageArray[level].copy(0, 0, x, y, width, height, renderTarget);
+ mDirtyImages = true;
}
else
{
- if (redefined)
+ if (!mTexStorage || !mTexStorage->isRenderTarget())
{
convertToRenderTarget();
- pushTexture(mTexture, true);
- }
- else
- {
- needRenderTarget();
}
+
+ mImageArray[level].markClean();
if (width != 0 && height != 0 && level < levelCount())
{
- RECT sourceRect;
- sourceRect.left = x;
- sourceRect.right = x + width;
- sourceRect.top = y;
- sourceRect.bottom = y + height;
+ RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
+ sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
+ sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
+ sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
+ sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
- IDirect3DSurface9 *dest;
- HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
+ GLint destYOffset = transformPixelYOffset(0, height, mImageArray[level].getHeight());
+
+ IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level);
- getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
- dest->Release();
+ if (dest)
+ {
+ getBlitter()->copy(renderTarget, sourceRect, format, 0, destYOffset, dest);
+ dest->Release();
+ }
}
}
- mImageArray[level].width = width;
- mImageArray[level].height = height;
- mImageArray[level].format = internalFormat;
+ renderTarget->Release();
}
-void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
- if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
+ if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight())
{
return error(GL_INVALID_VALUE);
}
@@ -1389,46 +1974,83 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_OUT_OF_MEMORY);
}
- bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType);
-
- if (!isRenderableFormat())
+ if (!mImageArray[level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
{
- copyNonRenderable(&mImageArray[level], getFormat(), xoffset, yoffset, x, y, width, height, renderTarget);
+ mImageArray[level].copy(xoffset, yoffset, x, y, width, height, renderTarget);
+ mDirtyImages = true;
}
else
{
- if (redefined)
+ if (!mTexStorage || !mTexStorage->isRenderTarget())
{
convertToRenderTarget();
- pushTexture(mTexture, true);
- }
- else
- {
- needRenderTarget();
}
+
+ updateTexture();
if (level < levelCount())
{
- RECT sourceRect;
- sourceRect.left = x;
- sourceRect.right = x + width;
- sourceRect.top = y;
- sourceRect.bottom = y + height;
+ RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
+ sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
+ sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
+ sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
+ sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
+
+ GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[level].getHeight());
- IDirect3DSurface9 *dest;
- HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
+ IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level);
- getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest);
- dest->Release();
+ if (dest)
+ {
+ getBlitter()->copy(renderTarget, sourceRect, mImageArray[0].getFormat(), xoffset, destYOffset, dest);
+ dest->Release();
+ }
}
}
+
+ renderTarget->Release();
}
-// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool Texture2D::isComplete() const
+void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
- GLsizei width = mImageArray[0].width;
- GLsizei height = mImageArray[0].height;
+ GLenum format = gl::ExtractFormat(internalformat);
+ GLenum type = gl::ExtractType(internalformat);
+ D3DFORMAT d3dfmt = ConvertTextureFormatType(format, type);
+ const bool renderTarget = IsTextureFormatRenderable(d3dfmt) && (mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+
+ delete mTexStorage;
+ mTexStorage = new TextureStorage2D(levels, d3dfmt, width, height, renderTarget);
+ mImmutable = true;
+
+ for (int level = 0; level < levels; level++)
+ {
+ mImageArray[level].redefine(format, width, height, type, true);
+ width = std::max(1, width >> 1);
+ height = std::max(1, height >> 1);
+ }
+
+ for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mImageArray[level].redefine(GL_NONE, 0, 0, GL_UNSIGNED_BYTE, true);
+ }
+
+ if (mTexStorage->isManaged())
+ {
+ int levels = levelCount();
+
+ for (int level = 0; level < levels; level++)
+ {
+ IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level);
+ mImageArray[level].setManagedSurface(surface);
+ }
+ }
+}
+
+// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
+bool Texture2D::isSamplerComplete() const
+{
+ GLsizei width = mImageArray[0].getWidth();
+ GLsizei height = mImageArray[0].getHeight();
if (width <= 0 || height <= 0)
{
@@ -1449,11 +2071,11 @@ bool Texture2D::isComplete() const
case GL_LINEAR_MIPMAP_LINEAR:
mipmapping = true;
break;
- default: UNREACHABLE();
+ default: UNREACHABLE();
}
- if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
- (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
+ if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
+ (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsFloat16LinearFilter()))
{
if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
{
@@ -1461,38 +2083,74 @@ bool Texture2D::isComplete() const
}
}
+ bool npotSupport = getContext()->supportsNonPower2Texture();
- if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width))
- || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
+ if (!npotSupport)
{
- return false;
+ if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
+ (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
+ {
+ return false;
+ }
}
if (mipmapping)
{
- if (!isPow2(width) || !isPow2(height))
+ if (!npotSupport)
+ {
+ if (!isPow2(width) || !isPow2(height))
+ {
+ return false;
+ }
+ }
+
+ if (!isMipmapComplete())
{
return false;
}
+ }
- int q = log2(std::max(width, height));
+ return true;
+}
- for (int level = 1; level <= q; level++)
+// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture2D::isMipmapComplete() const
+{
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ GLsizei width = mImageArray[0].getWidth();
+ GLsizei height = mImageArray[0].getHeight();
+
+ if (width <= 0 || height <= 0)
+ {
+ return false;
+ }
+
+ int q = log2(std::max(width, height));
+
+ for (int level = 1; level <= q; level++)
+ {
+ if (mImageArray[level].getFormat() != mImageArray[0].getFormat())
{
- if (mImageArray[level].format != mImageArray[0].format)
- {
- return false;
- }
+ return false;
+ }
- if (mImageArray[level].width != std::max(1, width >> level))
- {
- return false;
- }
+ if (mImageArray[level].getType() != mImageArray[0].getType())
+ {
+ return false;
+ }
- if (mImageArray[level].height != std::max(1, height >> level))
- {
- return false;
- }
+ if (mImageArray[level].getWidth() != std::max(1, width >> level))
+ {
+ return false;
+ }
+
+ if (mImageArray[level].getHeight() != std::max(1, height >> level))
+ {
+ return false;
}
}
@@ -1501,186 +2159,122 @@ bool Texture2D::isComplete() const
bool Texture2D::isCompressed() const
{
- return IsCompressed(getFormat());
+ return IsCompressed(getInternalFormat());
}
-// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
-IDirect3DBaseTexture9 *Texture2D::createTexture()
+IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const
{
- IDirect3DTexture9 *texture;
-
- IDirect3DDevice9 *device = getDevice();
- D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
+ return mTexStorage ? mTexStorage->getBaseTexture() : NULL;
+}
- HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
+// Constructs a Direct3D 9 texture resource from the texture images
+void Texture2D::createTexture()
+{
+ GLsizei width = mImageArray[0].getWidth();
+ GLsizei height = mImageArray[0].getHeight();
+ GLint levels = creationLevels(width, height);
+ D3DFORMAT format = mImageArray[0].getD3DFormat();
+ const bool renderTarget = IsTextureFormatRenderable(format) && (mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
- if (FAILED(result))
+ delete mTexStorage;
+ mTexStorage = new TextureStorage2D(levels, format, width, height, renderTarget);
+
+ if (mTexStorage->isManaged())
{
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ int levels = levelCount();
+
+ for (int level = 0; level < levels; level++)
+ {
+ IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level);
+ mImageArray[level].setManagedSurface(surface);
+ }
}
- if (mTexture) mTexture->Release();
- mTexture = texture;
- return texture;
+ mDirtyImages = true;
}
void Texture2D::updateTexture()
{
- IDirect3DDevice9 *device = getDevice();
-
int levels = levelCount();
for (int level = 0; level < levels; level++)
{
- if (mImageArray[level].dirty)
- {
- IDirect3DSurface9 *levelSurface = NULL;
- HRESULT result = mTexture->GetSurfaceLevel(level, &levelSurface);
-
- ASSERT(SUCCEEDED(result));
-
- if (SUCCEEDED(result))
- {
- result = device->UpdateSurface(mImageArray[level].surface, NULL, levelSurface, NULL);
- ASSERT(SUCCEEDED(result));
+ Image *image = &mImageArray[level];
- levelSurface->Release();
-
- mImageArray[level].dirty = false;
- }
+ if (image->isDirty())
+ {
+ commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight());
}
}
}
-IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()
+void Texture2D::convertToRenderTarget()
{
- IDirect3DTexture9 *texture = NULL;
+ TextureStorage2D *newTexStorage = NULL;
- if (mWidth != 0 && mHeight != 0)
+ if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0)
{
- egl::Display *display = getDisplay();
- IDirect3DDevice9 *device = getDevice();
- D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
-
- HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
+ GLsizei width = mImageArray[0].getWidth();
+ GLsizei height = mImageArray[0].getHeight();
+ GLint levels = creationLevels(width, height);
+ D3DFORMAT format = mImageArray[0].getD3DFormat();
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
- }
+ newTexStorage = new TextureStorage2D(levels, format, width, height, true);
- if (mTexture != NULL)
+ if (mTexStorage != NULL)
{
int levels = levelCount();
for (int i = 0; i < levels; i++)
{
- IDirect3DSurface9 *source;
- result = mTexture->GetSurfaceLevel(i, &source);
-
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
- texture->Release();
-
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
- }
-
- IDirect3DSurface9 *dest;
- result = texture->GetSurfaceLevel(i, &dest);
-
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
- texture->Release();
- source->Release();
-
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ IDirect3DSurface9 *source = mTexStorage->getSurfaceLevel(i);
+ IDirect3DSurface9 *dest = newTexStorage->getSurfaceLevel(i);
+
+ if (!copyToRenderTarget(dest, source, mTexStorage->isManaged()))
+ {
+ delete newTexStorage;
+ source->Release();
+ dest->Release();
+ return error(GL_OUT_OF_MEMORY);
}
- display->endScene();
- result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
-
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
- texture->Release();
- source->Release();
- dest->Release();
-
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
- }
-
- source->Release();
- dest->Release();
+ if (source) source->Release();
+ if (dest) dest->Release();
}
}
}
- if (mTexture != NULL)
- {
- mTexture->Release();
- }
-
- mTexture = texture;
- return mTexture;
-}
-
-bool Texture2D::dirtyImageData() const
-{
- int q = log2(std::max(mWidth, mHeight));
+ delete mTexStorage;
+ mTexStorage = newTexStorage;
- for (int i = 0; i <= q; i++)
- {
- if (mImageArray[i].dirty) return true;
- }
-
- return false;
+ mDirtyImages = true;
}
void Texture2D::generateMipmaps()
{
- if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))
+ if (!getContext()->supportsNonPower2Texture())
{
- return error(GL_INVALID_OPERATION);
+ if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight()))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
}
// Purge array levels 1 through q and reset them to represent the generated mipmap levels.
- unsigned int q = log2(std::max(mWidth, mHeight));
+ unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight()));
for (unsigned int i = 1; i <= q; i++)
{
- if (mImageArray[i].surface != NULL)
- {
- mImageArray[i].surface->Release();
- mImageArray[i].surface = NULL;
- }
-
- mImageArray[i].dirty = false;
-
- mImageArray[i].format = mImageArray[0].format;
- mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);
- mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
+ redefineImage(i, mImageArray[0].getFormat(),
+ std::max(mImageArray[0].getWidth() >> i, 1),
+ std::max(mImageArray[0].getHeight() >> i, 1),
+ mImageArray[0].getType());
}
- if (isRenderable())
+ if (mTexStorage && mTexStorage->isRenderTarget())
{
- if (mTexture == NULL)
- {
- ERR(" failed because mTexture was null.");
- return;
- }
-
for (unsigned int i = 1; i <= q; i++)
{
- IDirect3DSurface9 *upper = NULL;
- IDirect3DSurface9 *lower = NULL;
-
- mTexture->GetSurfaceLevel(i-1, &upper);
- mTexture->GetSurfaceLevel(i, &lower);
+ IDirect3DSurface9 *upper = mTexStorage->getSurfaceLevel(i - 1);
+ IDirect3DSurface9 *lower = mTexStorage->getSurfaceLevel(i);
if (upper != NULL && lower != NULL)
{
@@ -1689,78 +2283,169 @@ void Texture2D::generateMipmaps()
if (upper != NULL) upper->Release();
if (lower != NULL) lower->Release();
+
+ mImageArray[i].markClean();
}
}
else
{
for (unsigned int i = 1; i <= q; i++)
{
- createSurface(mImageArray[i].width, mImageArray[i].height, mImageArray[i].format, mType, &mImageArray[i]);
- if (mImageArray[i].surface == NULL)
+ if (mImageArray[i].getSurface() == NULL)
{
return error(GL_OUT_OF_MEMORY);
}
- if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[i].surface, NULL, NULL, mImageArray[i - 1].surface, NULL, NULL, D3DX_FILTER_BOX, 0)))
+ if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[i].getSurface(), NULL, NULL, mImageArray[i - 1].getSurface(), NULL, NULL, D3DX_FILTER_BOX, 0)))
{
ERR(" failed to load filter %d to %d.", i - 1, i);
}
- mImageArray[i].dirty = true;
+ mImageArray[i].markDirty();
}
-
- mDirtyMetaData = true;
}
}
-Renderbuffer *Texture2D::getColorbuffer(GLenum target)
+Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
{
if (target != GL_TEXTURE_2D)
{
return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
}
- if (mColorbufferProxy.get() == NULL)
+ if (mColorbufferProxy == NULL)
{
- mColorbufferProxy.set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
+ mColorbufferProxy = new Renderbuffer(id(), new RenderbufferTexture(this, target));
}
- return mColorbufferProxy.get();
+ return mColorbufferProxy;
}
IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
{
ASSERT(target == GL_TEXTURE_2D);
- needRenderTarget();
-
- if (mTexture == NULL)
+ // ensure the underlying texture is created
+ if (getStorage(true) == NULL)
{
return NULL;
}
+
+ updateTexture();
- IDirect3DSurface9 *renderTarget = NULL;
- mTexture->GetSurfaceLevel(0, &renderTarget);
+ return mTexStorage->getSurfaceLevel(0);
+}
- return renderTarget;
+TextureStorage *Texture2D::getStorage(bool renderTarget)
+{
+ if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
+ {
+ if (renderTarget)
+ {
+ convertToRenderTarget();
+ }
+ else
+ {
+ createTexture();
+ }
+ }
+
+ return mTexStorage;
}
-TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
+TextureStorageCubeMap::TextureStorageCubeMap(int levels, D3DFORMAT format, int size, bool renderTarget)
+ : TextureStorage(renderTarget), mFirstRenderTargetSerial(RenderbufferStorage::issueCubeSerials())
{
+ IDirect3DDevice9 *device = getDevice();
+
mTexture = NULL;
+ HRESULT result = device->CreateCubeTexture(size, levels, isRenderTarget() ? D3DUSAGE_RENDERTARGET : 0, format, getPool(), &mTexture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ error(GL_OUT_OF_MEMORY);
+ }
+}
+
+TextureStorageCubeMap::~TextureStorageCubeMap()
+{
+ if (mTexture)
+ {
+ mTexture->Release();
+ }
+}
+
+IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, int level)
+{
+ IDirect3DSurface9 *surface = NULL;
+
+ if (mTexture)
+ {
+ HRESULT result = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(faceTarget), level, &surface);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return surface;
+}
+
+IDirect3DBaseTexture9 *TextureStorageCubeMap::getBaseTexture() const
+{
+ return mTexture;
+}
+
+unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const
+{
+ return mFirstRenderTargetSerial + TextureCubeMap::faceIndex(target);
+}
+
+TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
+{
+ mTexStorage = NULL;
+ for (int i = 0; i < 6; i++)
+ {
+ mFaceProxies[i] = NULL;
+ mFaceProxyRefs[i] = 0;
+ }
}
TextureCubeMap::~TextureCubeMap()
{
for (int i = 0; i < 6; i++)
{
- mFaceProxies[i].set(NULL);
+ mFaceProxies[i] = NULL;
}
- if (mTexture)
+ delete mTexStorage;
+ mTexStorage = NULL;
+}
+
+// We need to maintain a count of references to renderbuffers acting as
+// proxies for this texture, so that the texture is not deleted while
+// proxy references still exist. If the reference count drops to zero,
+// we set our proxy pointer NULL, so that a new attempt at referencing
+// will cause recreation.
+void TextureCubeMap::addProxyRef(const Renderbuffer *proxy)
+{
+ for (int i = 0; i < 6; i++)
{
- mTexture->Release();
- mTexture = NULL;
+ if (mFaceProxies[i] == proxy)
+ mFaceProxyRefs[i]++;
+ }
+}
+
+void TextureCubeMap::releaseProxy(const Renderbuffer *proxy)
+{
+ for (int i = 0; i < 6; i++)
+ {
+ if (mFaceProxies[i] == proxy)
+ {
+ if (mFaceProxyRefs[i] > 0)
+ mFaceProxyRefs[i]--;
+
+ if (mFaceProxyRefs[i] == 0)
+ mFaceProxies[i] = NULL;
+ }
}
}
@@ -1769,79 +2454,90 @@ GLenum TextureCubeMap::getTarget() const
return GL_TEXTURE_CUBE_MAP;
}
-GLenum TextureCubeMap::getFormat() const
+GLsizei TextureCubeMap::getWidth(GLint level) const
+{
+ if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[0][level].getWidth();
+ else
+ return 0;
+}
+
+GLsizei TextureCubeMap::getHeight(GLint level) const
+{
+ if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[0][level].getHeight();
+ else
+ return 0;
+}
+
+GLenum TextureCubeMap::getInternalFormat() const
{
- return mImageArray[0][0].format;
+ return mImageArray[0][0].getFormat();
}
-void TextureCubeMap::setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+GLenum TextureCubeMap::getType() const
{
- setImage(0, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+ return mImageArray[0][0].getType();
}
-void TextureCubeMap::setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+D3DFORMAT TextureCubeMap::getD3DFormat() const
{
- setImage(1, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+ return mImageArray[0][0].getD3DFormat();
}
-void TextureCubeMap::setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
- setImage(2, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+ setImage(0, level, width, height, format, type, unpackAlignment, pixels);
}
-void TextureCubeMap::setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
- setImage(3, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+ setImage(1, level, width, height, format, type, unpackAlignment, pixels);
}
-void TextureCubeMap::setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
- setImage(4, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+ setImage(2, level, width, height, format, type, unpackAlignment, pixels);
}
-void TextureCubeMap::setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
- setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
+ setImage(3, level, width, height, format, type, unpackAlignment, pixels);
}
-void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
+void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
- redefineTexture(level, internalFormat, width);
+ setImage(4, level, width, height, format, type, unpackAlignment, pixels);
+}
- Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);
+void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+{
+ setImage(5, level, width, height, format, type, unpackAlignment, pixels);
}
-void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
{
- int face = faceIndex(faceTarget);
+ redefineImage(faceIndex(face), level, format, width, height, GL_UNSIGNED_BYTE);
+
+ Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]);
+}
- ASSERT(mImageArray[face][level].surface != NULL);
+void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ ASSERT(mImageArray[face][level].getSurface() != NULL);
if (level < levelCount())
{
- IDirect3DSurface9 *destLevel = getCubeMapSurface(face, level);
+ IDirect3DSurface9 *destLevel = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
ASSERT(destLevel != NULL);
if (destLevel != NULL)
{
- Image *img = &mImageArray[face][level];
-
- RECT sourceRect;
- sourceRect.left = xoffset;
- sourceRect.top = yoffset;
- sourceRect.right = xoffset + width;
- sourceRect.bottom = yoffset + height;
-
- POINT destPoint;
- destPoint.x = xoffset;
- destPoint.y = yoffset;
-
- HRESULT result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
- ASSERT(SUCCEEDED(result));
+ Image *image = &mImageArray[face][level];
+ image->updateSurface(destLevel, xoffset, yoffset, width, height);
destLevel->Release();
-
- img->dirty = false;
+ image->markClean();
}
}
}
@@ -1850,7 +2546,7 @@ void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint y
{
if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
{
- commitRect(target, level, xoffset, yoffset, width, height);
+ commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
}
}
@@ -1858,19 +2554,14 @@ void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffse
{
if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
{
- commitRect(target, level, xoffset, yoffset, width, height);
+ commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
}
}
-// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool TextureCubeMap::isComplete() const
+// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
+bool TextureCubeMap::isSamplerComplete() const
{
- int size = mImageArray[0][0].width;
-
- if (size <= 0)
- {
- return false;
- }
+ int size = mImageArray[0][0].getWidth();
bool mipmapping;
@@ -1886,50 +2577,101 @@ bool TextureCubeMap::isComplete() const
case GL_LINEAR_MIPMAP_LINEAR:
mipmapping = true;
break;
- default: UNREACHABLE();
+ default:
+ UNREACHABLE();
+ return false;
}
- for (int face = 0; face < 6; face++)
+ if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
+ (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsFloat16LinearFilter()))
{
- if (mImageArray[face][0].width != size || mImageArray[face][0].height != size)
+ if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
{
return false;
}
}
- if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
- (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
+ if (!isPow2(size) && !getContext()->supportsNonPower2Texture())
{
- if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
+ if (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE || mipmapping)
{
return false;
}
}
- if (mipmapping)
+ if (!mipmapping)
+ {
+ if (!isCubeComplete())
+ {
+ return false;
+ }
+ }
+ else
{
- if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE))
+ if (!isMipmapCubeComplete()) // Also tests for isCubeComplete()
{
return false;
}
+ }
- int q = log2(size);
+ return true;
+}
- for (int face = 0; face < 6; face++)
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureCubeMap::isCubeComplete() const
+{
+ if (mImageArray[0][0].getWidth() <= 0 || mImageArray[0][0].getHeight() != mImageArray[0][0].getWidth())
+ {
+ return false;
+ }
+
+ for (unsigned int face = 1; face < 6; face++)
+ {
+ if (mImageArray[face][0].getWidth() != mImageArray[0][0].getWidth() ||
+ mImageArray[face][0].getWidth() != mImageArray[0][0].getHeight() ||
+ mImageArray[face][0].getFormat() != mImageArray[0][0].getFormat() ||
+ mImageArray[face][0].getType() != mImageArray[0][0].getType())
{
- for (int level = 1; level <= q; level++)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool TextureCubeMap::isMipmapCubeComplete() const
+{
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ if (!isCubeComplete())
+ {
+ return false;
+ }
+
+ GLsizei size = mImageArray[0][0].getWidth();
+
+ int q = log2(size);
+
+ for (int face = 0; face < 6; face++)
+ {
+ for (int level = 1; level <= q; level++)
+ {
+ if (mImageArray[face][level].getFormat() != mImageArray[0][0].getFormat())
{
- if (mImageArray[face][level].format != mImageArray[0][0].format)
- {
- return false;
- }
+ return false;
+ }
- if (mImageArray[face][level].width != std::max(1, size >> level))
- {
- return false;
- }
+ if (mImageArray[face][level].getType() != mImageArray[0][0].getType())
+ {
+ return false;
+ }
- ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);
+ if (mImageArray[face][level].getWidth() != std::max(1, size >> level))
+ {
+ return false;
}
}
}
@@ -1939,143 +2681,107 @@ bool TextureCubeMap::isComplete() const
bool TextureCubeMap::isCompressed() const
{
- return IsCompressed(getFormat());
+ return IsCompressed(getInternalFormat());
}
-// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
-IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
+IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const
{
- IDirect3DDevice9 *device = getDevice();
- D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
+ return mTexStorage ? mTexStorage->getBaseTexture() : NULL;
+}
- IDirect3DCubeTexture9 *texture;
+// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
+void TextureCubeMap::createTexture()
+{
+ GLsizei size = mImageArray[0][0].getWidth();
+ GLint levels = creationLevels(size, 0);
+ D3DFORMAT format = mImageArray[0][0].getD3DFormat();
+ const bool renderTarget = IsTextureFormatRenderable(format) && (mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
- HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
+ delete mTexStorage;
+ mTexStorage = new TextureStorageCubeMap(levels, format, size, renderTarget);
- if (FAILED(result))
+ if (mTexStorage->isManaged())
{
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
- }
+ int levels = levelCount();
- if (mTexture) mTexture->Release();
+ for (int face = 0; face < 6; face++)
+ {
+ for (int level = 0; level < levels; level++)
+ {
+ IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
+ mImageArray[face][level].setManagedSurface(surface);
+ }
+ }
+ }
- mTexture = texture;
- return mTexture;
+ mDirtyImages = true;
}
void TextureCubeMap::updateTexture()
{
- IDirect3DDevice9 *device = getDevice();
-
for (int face = 0; face < 6; face++)
{
int levels = levelCount();
for (int level = 0; level < levels; level++)
{
- Image *img = &mImageArray[face][level];
+ Image *image = &mImageArray[face][level];
- if (img->dirty)
+ if (image->isDirty())
{
- IDirect3DSurface9 *levelSurface = getCubeMapSurface(face, level);
- ASSERT(levelSurface != NULL);
-
- if (levelSurface != NULL)
- {
- HRESULT result = device->UpdateSurface(img->surface, NULL, levelSurface, NULL);
- ASSERT(SUCCEEDED(result));
-
- levelSurface->Release();
-
- img->dirty = false;
- }
+ commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
}
}
}
}
-IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()
+void TextureCubeMap::convertToRenderTarget()
{
- IDirect3DCubeTexture9 *texture = NULL;
+ TextureStorageCubeMap *newTexStorage = NULL;
- if (mWidth != 0)
+ if (mImageArray[0][0].getWidth() != 0)
{
- egl::Display *display = getDisplay();
- IDirect3DDevice9 *device = getDevice();
- D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
-
- HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
+ GLsizei size = mImageArray[0][0].getWidth();
+ GLint levels = creationLevels(size, 0);
+ D3DFORMAT format = mImageArray[0][0].getD3DFormat();
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
- }
+ newTexStorage = new TextureStorageCubeMap(levels, format, size, true);
- if (mTexture != NULL)
+ if (mTexStorage != NULL)
{
int levels = levelCount();
for (int f = 0; f < 6; f++)
{
for (int i = 0; i < levels; i++)
{
- IDirect3DSurface9 *source;
- result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
-
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
- texture->Release();
-
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
- }
-
- IDirect3DSurface9 *dest;
- result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
+ IDirect3DSurface9 *source = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
+ IDirect3DSurface9 *dest = newTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
- if (FAILED(result))
+ if (!copyToRenderTarget(dest, source, mTexStorage->isManaged()))
{
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
- texture->Release();
- source->Release();
-
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
+ delete newTexStorage;
+ source->Release();
+ dest->Release();
+ return error(GL_OUT_OF_MEMORY);
}
- display->endScene();
- result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
-
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
-
- texture->Release();
- source->Release();
- dest->Release();
-
- return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
- }
+ if (source) source->Release();
+ if (dest) dest->Release();
}
}
}
}
- if (mTexture != NULL)
- {
- mTexture->Release();
- }
+ delete mTexStorage;
+ mTexStorage = newTexStorage;
- mTexture = texture;
- return mTexture;
+ mDirtyImages = true;
}
-void TextureCubeMap::setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
+void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
{
- redefineTexture(level, internalFormat, width);
+ redefineImage(faceIndex, level, format, width, height, type);
- Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[face][level]);
+ Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]);
}
unsigned int TextureCubeMap::faceIndex(GLenum face)
@@ -2089,74 +2795,28 @@ unsigned int TextureCubeMap::faceIndex(GLenum face)
return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
}
-bool TextureCubeMap::dirtyImageData() const
+void TextureCubeMap::redefineImage(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
{
- int q = log2(mWidth);
+ bool redefined = mImageArray[face][level].redefine(format, width, height, type, false);
- for (int f = 0; f < 6; f++)
+ if (mTexStorage && redefined)
{
- for (int i = 0; i <= q; i++)
- {
- if (mImageArray[f][i].dirty) return true;
- }
- }
-
- return false;
-}
-
-// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
-// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels & faces.
-// Call this when a particular level of the texture must be defined with a specific format, width and height.
-//
-// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set
-// a new size for the texture by working backwards from the given size.
-bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei width)
-{
- // Are these settings compatible with level 0?
- bool sizeOkay = (mImageArray[0][0].width >> level == width);
-
- bool textureOkay = (sizeOkay && internalFormat == mImageArray[0][0].format);
-
- if (!textureOkay)
- {
- TRACE("Redefining cube texture (%d, 0x%04X, %d => 0x%04X, %d).", level,
- mImageArray[0][0].format, mImageArray[0][0].width,
- internalFormat, width);
-
- // Purge all the levels and the texture.
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
for (int f = 0; f < 6; f++)
{
- if (mImageArray[f][i].surface != NULL)
- {
- mImageArray[f][i].dirty = false;
-
- mImageArray[f][i].surface->Release();
- mImageArray[f][i].surface = NULL;
- }
+ mImageArray[f][i].markDirty();
}
}
- if (mTexture != NULL)
- {
- mTexture->Release();
- mTexture = NULL;
- dropTexture();
- }
-
- mWidth = width << level;
- mImageArray[0][0].width = width << level;
- mHeight = width << level;
- mImageArray[0][0].height = width << level;
+ delete mTexStorage;
+ mTexStorage = NULL;
- mImageArray[0][0].format = internalFormat;
+ mDirtyImages = true;
}
-
- return !textureOkay;
}
-void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
IDirect3DSurface9 *renderTarget = source->getRenderTarget();
@@ -2167,80 +2827,50 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat
}
unsigned int faceindex = faceIndex(target);
- bool redefined = redefineTexture(level, internalFormat, width);
+ redefineImage(faceindex, level, format, width, height, GL_UNSIGNED_BYTE);
- if (!isRenderableFormat())
+ if (!mImageArray[faceindex][level].isRenderableFormat())
{
- copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget);
+ mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
+ mDirtyImages = true;
}
else
{
- if (redefined)
+ if (!mTexStorage || !mTexStorage->isRenderTarget())
{
convertToRenderTarget();
- pushTexture(mTexture, true);
- }
- else
- {
- needRenderTarget();
}
+
+ mImageArray[faceindex][level].markClean();
ASSERT(width == height);
if (width > 0 && level < levelCount())
{
- RECT sourceRect;
- sourceRect.left = x;
- sourceRect.right = x + width;
- sourceRect.top = y;
- sourceRect.bottom = y + height;
+ RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
+ sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
+ sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
+ sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
+ sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
- IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
+ GLint destYOffset = transformPixelYOffset(0, height, mImageArray[faceindex][level].getWidth());
- getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
- dest->Release();
- }
- }
-
- mImageArray[faceindex][level].width = width;
- mImageArray[faceindex][level].height = height;
- mImageArray[faceindex][level].format = internalFormat;
-}
-
-IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier, unsigned int level)
-{
- unsigned int faceIndex;
-
- if (faceIdentifier < 6)
- {
- faceIndex = faceIdentifier;
- }
- else if (faceIdentifier >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && faceIdentifier <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
- {
- faceIndex = faceIdentifier - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- }
- else
- {
- UNREACHABLE();
- faceIndex = 0;
- }
+ IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level);
- if (mTexture == NULL)
- {
- UNREACHABLE();
- return NULL;
+ if (dest)
+ {
+ getBlitter()->copy(renderTarget, sourceRect, format, 0, destYOffset, dest);
+ dest->Release();
+ }
+ }
}
- IDirect3DSurface9 *surface = NULL;
-
- HRESULT hr = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex), level, &surface);
-
- return (SUCCEEDED(hr)) ? surface : NULL;
+ renderTarget->Release();
}
-void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
+void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
{
- GLsizei size = mImageArray[faceIndex(target)][level].width;
+ GLsizei size = mImageArray[faceIndex(target)][level].getWidth();
if (xoffset + width > size || yoffset + height > size)
{
@@ -2256,99 +2886,123 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi
}
unsigned int faceindex = faceIndex(target);
- bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width);
-
- if (!isRenderableFormat())
+
+ if (!mImageArray[faceindex][level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
{
- copyNonRenderable(&mImageArray[faceindex][level], getFormat(), 0, 0, x, y, width, height, renderTarget);
+ mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
+ mDirtyImages = true;
}
else
{
- if (redefined)
+ if (!mTexStorage || !mTexStorage->isRenderTarget())
{
convertToRenderTarget();
- pushTexture(mTexture, true);
- }
- else
- {
- needRenderTarget();
}
+
+ updateTexture();
if (level < levelCount())
{
- RECT sourceRect;
- sourceRect.left = x;
- sourceRect.right = x + width;
- sourceRect.top = y;
- sourceRect.bottom = y + height;
+ RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
+ sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
+ sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
+ sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
+ sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
+
+ GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[faceindex][level].getWidth());
- IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
+ IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level);
- getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
- dest->Release();
+ if (dest)
+ {
+ getBlitter()->copy(renderTarget, sourceRect, mImageArray[0][0].getFormat(), xoffset, destYOffset, dest);
+ dest->Release();
+ }
}
}
+
+ renderTarget->Release();
}
-bool TextureCubeMap::isCubeComplete() const
+void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
{
- if (mImageArray[0][0].width == 0)
+ GLenum format = gl::ExtractFormat(internalformat);
+ GLenum type = gl::ExtractType(internalformat);
+ D3DFORMAT d3dfmt = ConvertTextureFormatType(format, type);
+ const bool renderTarget = IsTextureFormatRenderable(d3dfmt) && (mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+
+ delete mTexStorage;
+ mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, size, renderTarget);
+ mImmutable = true;
+
+ for (int level = 0; level < levels; level++)
{
- return false;
+ for (int face = 0; face < 6; face++)
+ {
+ mImageArray[face][level].redefine(format, size, size, type, true);
+ size = std::max(1, size >> 1);
+ }
}
- for (unsigned int f = 1; f < 6; f++)
+ for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
- if (mImageArray[f][0].width != mImageArray[0][0].width
- || mImageArray[f][0].format != mImageArray[0][0].format)
+ for (int face = 0; face < 6; face++)
{
- return false;
+ mImageArray[face][level].redefine(GL_NONE, 0, 0, GL_UNSIGNED_BYTE, true);
}
}
- return true;
+ if (mTexStorage->isManaged())
+ {
+ int levels = levelCount();
+
+ for (int face = 0; face < 6; face++)
+ {
+ for (int level = 0; level < levels; level++)
+ {
+ IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
+ mImageArray[face][level].setManagedSurface(surface);
+ }
+ }
+ }
}
void TextureCubeMap::generateMipmaps()
{
- if (!isPow2(mImageArray[0][0].width) || !isCubeComplete())
+ if (!isCubeComplete())
{
return error(GL_INVALID_OPERATION);
}
- // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
- unsigned int q = log2(mImageArray[0][0].width);
- for (unsigned int f = 0; f < 6; f++)
+ if (!getContext()->supportsNonPower2Texture())
{
- for (unsigned int i = 1; i <= q; i++)
+ if (!isPow2(mImageArray[0][0].getWidth()))
{
- if (mImageArray[f][i].surface != NULL)
- {
- mImageArray[f][i].surface->Release();
- mImageArray[f][i].surface = NULL;
- }
-
- mImageArray[f][i].dirty = false;
-
- mImageArray[f][i].format = mImageArray[f][0].format;
- mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);
- mImageArray[f][i].height = mImageArray[f][i].width;
+ return error(GL_INVALID_OPERATION);
}
}
- if (isRenderable())
+ // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
+ unsigned int q = log2(mImageArray[0][0].getWidth());
+ for (unsigned int f = 0; f < 6; f++)
{
- if (mTexture == NULL)
+ for (unsigned int i = 1; i <= q; i++)
{
- return;
+ redefineImage(f, i, mImageArray[f][0].getFormat(),
+ std::max(mImageArray[f][0].getWidth() >> i, 1),
+ std::max(mImageArray[f][0].getWidth() >> i, 1),
+ mImageArray[f][0].getType());
}
+ }
+ if (mTexStorage && mTexStorage->isRenderTarget())
+ {
for (unsigned int f = 0; f < 6; f++)
{
for (unsigned int i = 1; i <= q; i++)
{
- IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1);
- IDirect3DSurface9 *lower = getCubeMapSurface(f, i);
+ IDirect3DSurface9 *upper = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i-1);
+ IDirect3DSurface9 *lower = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
if (upper != NULL && lower != NULL)
{
@@ -2357,6 +3011,8 @@ void TextureCubeMap::generateMipmaps()
if (upper != NULL) upper->Release();
if (lower != NULL) lower->Release();
+
+ mImageArray[f][i].markClean();
}
}
}
@@ -2366,26 +3022,23 @@ void TextureCubeMap::generateMipmaps()
{
for (unsigned int i = 1; i <= q; i++)
{
- createSurface(mImageArray[f][i].width, mImageArray[f][i].height, mImageArray[f][i].format, mType, &mImageArray[f][i]);
- if (mImageArray[f][i].surface == NULL)
+ if (mImageArray[f][i].getSurface() == NULL)
{
return error(GL_OUT_OF_MEMORY);
}
- if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[f][i].surface, NULL, NULL, mImageArray[f][i - 1].surface, NULL, NULL, D3DX_FILTER_BOX, 0)))
+ if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[f][i].getSurface(), NULL, NULL, mImageArray[f][i - 1].getSurface(), NULL, NULL, D3DX_FILTER_BOX, 0)))
{
ERR(" failed to load filter %d to %d.", i - 1, i);
}
- mImageArray[f][i].dirty = true;
+ mImageArray[f][i].markDirty();
}
}
-
- mDirtyMetaData = true;
}
}
-Renderbuffer *TextureCubeMap::getColorbuffer(GLenum target)
+Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
{
if (!IsCubemapTextureTarget(target))
{
@@ -2394,74 +3047,44 @@ Renderbuffer *TextureCubeMap::getColorbuffer(GLenum target)
unsigned int face = faceIndex(target);
- if (mFaceProxies[face].get() == NULL)
+ if (mFaceProxies[face] == NULL)
{
- mFaceProxies[face].set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
+ mFaceProxies[face] = new Renderbuffer(id(), new RenderbufferTexture(this, target));
}
- return mFaceProxies[face].get();
+ return mFaceProxies[face];
}
IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
{
ASSERT(IsCubemapTextureTarget(target));
- needRenderTarget();
-
- if (mTexture == NULL)
+ // ensure the underlying texture is created
+ if (getStorage(true) == NULL)
{
return NULL;
}
-
- IDirect3DSurface9 *renderTarget = NULL;
- mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex(target)), 0, &renderTarget);
-
- return renderTarget;
-}
-
-Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target)
- : Colorbuffer(texture), mTexture(texture), mTarget(target)
-{
- ASSERT(IsTextureTarget(target));
-}
-
-void Texture::TextureColorbufferProxy::addRef() const
-{
- mTexture->addRef();
-}
-
-void Texture::TextureColorbufferProxy::release() const
-{
- mTexture->release();
-}
-
-IDirect3DSurface9 *Texture::TextureColorbufferProxy::getRenderTarget()
-{
- if (mRenderTarget) mRenderTarget->Release();
-
- mRenderTarget = mTexture->getRenderTarget(mTarget);
- return mRenderTarget;
-}
-
-int Texture::TextureColorbufferProxy::getWidth() const
-{
- return mTexture->getWidth();
-}
-
-int Texture::TextureColorbufferProxy::getHeight() const
-{
- return mTexture->getHeight();
+ updateTexture();
+
+ return mTexStorage->getCubeMapSurface(target, 0);
}
-GLenum Texture::TextureColorbufferProxy::getFormat() const
+TextureStorage *TextureCubeMap::getStorage(bool renderTarget)
{
- return mTexture->getFormat();
-}
+ if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
+ {
+ if (renderTarget)
+ {
+ convertToRenderTarget();
+ }
+ else
+ {
+ createTexture();
+ }
+ }
-bool Texture::TextureColorbufferProxy::isFloatingPoint() const
-{
- return mTexture->isFloatingPoint();
+ return mTexStorage;
}
-}
+} \ No newline at end of file
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h
index ca7aec7..19a6eb5 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/Texture.h
@@ -17,14 +17,20 @@
#include <GLES2/gl2.h>
#include <d3d9.h>
+#include "common/debug.h"
+#include "common/RefCountObject.h"
#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/RefCountObject.h"
#include "libGLESv2/utilities.h"
-#include "common/debug.h"
+
+namespace egl
+{
+class Surface;
+}
namespace gl
{
class Blit;
+class Framebuffer;
enum
{
@@ -37,6 +43,129 @@ enum
IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE
};
+class Image
+{
+ public:
+ Image();
+ ~Image();
+
+ bool redefine(GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRelease);
+ void markDirty() {mDirty = true;}
+ void markClean() {mDirty = false;}
+
+ HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
+ void unlock();
+
+ bool isRenderableFormat() const;
+ D3DFORMAT getD3DFormat() const;
+
+ GLsizei getWidth() const {return mWidth;}
+ GLsizei getHeight() const {return mHeight;}
+ GLenum getFormat() const {return mFormat;}
+ GLenum getType() const {return mType;}
+ bool isDirty() const {return mSurface && mDirty;}
+ IDirect3DSurface9 *getSurface();
+
+ void setManagedSurface(IDirect3DSurface9 *surface);
+ void updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum type,
+ GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output) const;
+
+ void loadAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadLuminanceData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
+ void loadLuminanceFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadLuminanceHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadLuminanceAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
+ void loadLuminanceAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadLuminanceAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGB565Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBAUByteDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBAUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBA4444Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBA5551Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBAFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadRGBAHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadBGRAData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadDXT1Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadDXT3Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+ void loadDXT5Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ int inputPitch, const void *input, size_t outputPitch, void *output) const;
+
+ void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Image);
+
+ void createSurface();
+
+ GLsizei mWidth;
+ GLsizei mHeight;
+ GLenum mFormat;
+ GLenum mType;
+
+ bool mDirty;
+
+ D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable.
+ D3DFORMAT mD3DFormat;
+
+ IDirect3DSurface9 *mSurface;
+};
+
+class TextureStorage
+{
+ public:
+ explicit TextureStorage(bool renderTarget);
+
+ virtual ~TextureStorage();
+
+ bool isRenderTarget() const;
+ bool isManaged() const;
+ D3DPOOL getPool() const;
+ unsigned int getTextureSerial() const;
+ virtual unsigned int getRenderTargetSerial(GLenum target) const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage);
+
+ const bool mRenderTarget;
+ const D3DPOOL mD3DPool;
+
+ const unsigned int mTextureSerial;
+ static unsigned int issueTextureSerial();
+
+ static unsigned int mCurrentTextureSerial;
+};
+
class Texture : public RefCountObject
{
public:
@@ -44,167 +173,105 @@ class Texture : public RefCountObject
virtual ~Texture();
+ 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 setUsage(GLenum usage);
GLenum getMinFilter() const;
GLenum getMagFilter() const;
GLenum getWrapS() const;
GLenum getWrapT() const;
+ GLenum getUsage() const;
- GLuint getWidth() const;
- GLuint getHeight() const;
+ virtual GLsizei getWidth(GLint level) const = 0;
+ virtual GLsizei getHeight(GLint level) const = 0;
+ virtual GLenum getInternalFormat() const = 0;
+ virtual GLenum getType() const = 0;
+ virtual D3DFORMAT getD3DFormat() const = 0;
- virtual GLenum getFormat() const = 0;
- virtual bool isComplete() const = 0;
+ virtual bool isSamplerComplete() const = 0;
virtual bool isCompressed() const = 0;
- bool isFloatingPoint() const;
- bool isRenderableFormat() const;
- D3DFORMAT getD3DFormat() const;
IDirect3DBaseTexture9 *getTexture();
- virtual Renderbuffer *getColorbuffer(GLenum target) = 0;
+ virtual Renderbuffer *getRenderbuffer(GLenum target) = 0;
virtual void generateMipmaps() = 0;
- virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source) = 0;
-
- bool isDirty() const;
-
- static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
-
- protected:
- class TextureColorbufferProxy;
- friend class TextureColorbufferProxy;
- class TextureColorbufferProxy : public Colorbuffer
- {
- public:
- TextureColorbufferProxy(Texture *texture, GLenum target);
- // target is a 2D-like texture target (GL_TEXTURE_2D or one of the cube face targets)
-
- virtual void addRef() const;
- virtual void release() const;
-
- virtual IDirect3DSurface9 *getRenderTarget();
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0;
- virtual int getWidth() const;
- virtual int getHeight() const;
- virtual GLenum getFormat() const;
- virtual bool isFloatingPoint() const;
+ bool hasDirtyParameters() const;
+ bool hasDirtyImages() const;
+ void resetDirty();
+ unsigned int getTextureSerial();
+ unsigned int getRenderTargetSerial(GLenum target);
- private:
- Texture *mTexture;
- GLenum mTarget;
- };
+ bool isImmutable() const;
- // Helper structure representing a single image layer
- struct Image
- {
- Image();
- ~Image();
+ static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
- GLsizei width;
- GLsizei height;
- GLenum format;
-
- bool dirty;
-
- IDirect3DSurface9 *surface;
- };
-
- static D3DFORMAT selectFormat(GLenum format, GLenum type);
-
- void setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
- bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img);
- void setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img);
- bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img);
- void copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
+ protected:
+ friend class RenderbufferTexture;
- void needRenderTarget();
+ void setImage(GLint unpackAlignment, const void *pixels, Image *image);
+ bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image);
+ void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image);
+ bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image);
- GLint creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const;
- GLint creationLevels(GLsizei size, GLint maxlevel) const;
+ GLint creationLevels(GLsizei width, GLsizei height) const;
+ GLint creationLevels(GLsizei size) const;
- // The pointer returned is weak and it is assumed the derived class will keep a strong pointer until the next createTexture() call.
- virtual IDirect3DBaseTexture9 *createTexture() = 0;
+ virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
+ virtual void createTexture() = 0;
virtual void updateTexture() = 0;
- virtual IDirect3DBaseTexture9 *convertToRenderTarget() = 0;
+ virtual void convertToRenderTarget() = 0;
virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0;
- virtual bool dirtyImageData() const = 0;
-
- void dropTexture();
- void pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable);
- void createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img);
-
- Blit *getBlitter();
-
int levelCount() const;
- bool isRenderable() const;
+ static Blit *getBlitter();
+ static bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
- unsigned int mWidth;
- unsigned int mHeight;
GLenum mMinFilter;
GLenum mMagFilter;
GLenum mWrapS;
GLenum mWrapT;
- GLenum mType;
+ bool mDirtyParameters;
+ GLenum mUsage;
- bool mDirtyMetaData;
+ bool mDirtyImages;
+
+ bool mImmutable;
private:
DISALLOW_COPY_AND_ASSIGN(Texture);
- void loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
- GLint unpackAlignment, const void *input, std::size_t outputPitch, void *output, D3DSURFACE_DESC *description) const;
-
- void loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
- void loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const;
- void loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
- void loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- size_t inputPitch, const void *input, size_t outputPitch, void *output) const;
-
- IDirect3DBaseTexture9 *mBaseTexture; // This is a weak pointer. The derived class is assumed to own a strong pointer.
+ virtual TextureStorage *getStorage(bool renderTarget) = 0;
+};
+
+class TextureStorage2D : public TextureStorage
+{
+ public:
+ explicit TextureStorage2D(IDirect3DTexture9 *surfaceTexture);
+ TextureStorage2D(int levels, D3DFORMAT format, int width, int height, bool renderTarget);
+
+ virtual ~TextureStorage2D();
- bool mDirty;
- bool mIsRenderable;
+ IDirect3DSurface9 *getSurfaceLevel(int level);
+ IDirect3DBaseTexture9 *getBaseTexture() const;
+
+ virtual unsigned int getRenderTargetSerial(GLenum target) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage2D);
+
+ IDirect3DTexture9 *mTexture;
+ const unsigned int mRenderTargetSerial;
};
class Texture2D : public Texture
@@ -214,41 +281,80 @@ class Texture2D : public Texture
~Texture2D();
- GLenum getTarget() const;
- GLenum getFormat() const;
+ void addProxyRef(const Renderbuffer *proxy);
+ void releaseProxy(const Renderbuffer *proxy);
+
+ virtual GLenum getTarget() const;
- void setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+ virtual GLsizei getWidth(GLint level) const;
+ virtual GLsizei getHeight(GLint level) const;
+ virtual GLenum getInternalFormat() const;
+ virtual GLenum getType() const;
+ virtual D3DFORMAT getD3DFormat() 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 internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
- void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
+ void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+ void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
- bool isComplete() const;
- bool isCompressed() const;
+ virtual bool isSamplerComplete() const;
+ virtual bool isCompressed() const;
+ virtual void bindTexImage(egl::Surface *surface);
+ virtual void releaseTexImage();
virtual void generateMipmaps();
- virtual Renderbuffer *getColorbuffer(GLenum target);
+ virtual Renderbuffer *getRenderbuffer(GLenum target);
private:
DISALLOW_COPY_AND_ASSIGN(Texture2D);
- virtual IDirect3DBaseTexture9 *createTexture();
+ virtual IDirect3DBaseTexture9 *getBaseTexture() const;
+ virtual void createTexture();
virtual void updateTexture();
- virtual IDirect3DBaseTexture9 *convertToRenderTarget();
+ virtual void convertToRenderTarget();
virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
+ virtual TextureStorage *getStorage(bool renderTarget);
- virtual bool dirtyImageData() const;
+ bool isMipmapComplete() const;
- bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type);
+ void redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS];
- IDirect3DTexture9 *mTexture;
+ TextureStorage2D *mTexStorage;
+ egl::Surface *mSurface;
- BindingPointer<Renderbuffer> mColorbufferProxy;
+ // 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 TextureStorageCubeMap : public TextureStorage
+{
+ public:
+ TextureStorageCubeMap(int levels, D3DFORMAT format, int size, bool renderTarget);
+
+ virtual ~TextureStorageCubeMap();
+
+ IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level);
+ IDirect3DBaseTexture9 *getBaseTexture() const;
+
+ virtual unsigned int getRenderTargetSerial(GLenum target) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorageCubeMap);
+
+ IDirect3DCubeTexture9 *mTexture;
+ const unsigned int mFirstRenderTargetSerial;
};
class TextureCubeMap : public Texture
@@ -258,58 +364,70 @@ class TextureCubeMap : public Texture
~TextureCubeMap();
- GLenum getTarget() const;
- GLenum getFormat() const;
+ void addProxyRef(const Renderbuffer *proxy);
+ void releaseProxy(const Renderbuffer *proxy);
+
+ virtual GLenum getTarget() const;
+
+ virtual GLsizei getWidth(GLint level) const;
+ virtual GLsizei getHeight(GLint level) const;
+ virtual GLenum getInternalFormat() const;
+ virtual GLenum getType() const;
+ virtual D3DFORMAT getD3DFormat() const;
- void setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
+ void setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels);
void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels);
- void copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
- void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source);
+ void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+ virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
+ void storage(GLsizei levels, GLenum internalformat, GLsizei size);
- bool isComplete() const;
- bool isCompressed() const;
+ virtual bool isSamplerComplete() const;
+ virtual bool isCompressed() const;
virtual void generateMipmaps();
- virtual Renderbuffer *getColorbuffer(GLenum target);
+ virtual Renderbuffer *getRenderbuffer(GLenum target);
+
+ static unsigned int faceIndex(GLenum face);
private:
DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
- virtual IDirect3DBaseTexture9 *createTexture();
+ virtual IDirect3DBaseTexture9 *getBaseTexture() const;
+ virtual void createTexture();
virtual void updateTexture();
- virtual IDirect3DBaseTexture9 *convertToRenderTarget();
+ virtual void convertToRenderTarget();
virtual IDirect3DSurface9 *getRenderTarget(GLenum target);
-
- virtual bool dirtyImageData() const;
-
- // faceIdentifier is 0-5 or one of the GL_TEXTURE_CUBE_MAP_* enumerants.
- // Returns NULL if the call underlying Direct3D call fails.
- IDirect3DSurface9 *getCubeMapSurface(unsigned int faceIdentifier, unsigned int level);
-
- static unsigned int faceIndex(GLenum face);
+ virtual TextureStorage *getStorage(bool renderTarget);
bool isCubeComplete() const;
+ bool isMipmapCubeComplete() const;
- void setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
- void commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
- bool redefineTexture(GLint level, GLenum internalFormat, GLsizei width);
+ void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels);
+ void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ void redefineImage(int faceIndex, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type);
Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS];
- IDirect3DCubeTexture9 *mTexture;
+ TextureStorageCubeMap *mTexStorage;
- BindingPointer<Renderbuffer> mFaceProxies[6];
+ // 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 *mFaceProxies[6];
+ unsigned int *mFaceProxyRefs[6];
};
}
-#endif // LIBGLESV2_TEXTURE_H_
+#endif // LIBGLESV2_TEXTURE_H_ \ No newline at end of file
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.cpp
new file mode 100644
index 0000000..95bc3fb
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.cpp
@@ -0,0 +1,782 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#include "libGLESv2/VertexDataManager.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Program.h"
+#include "libGLESv2/main.h"
+
+#include "libGLESv2/vertexconversion.h"
+#include "libGLESv2/IndexDataManager.h"
+
+namespace
+{
+ enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
+ // This has to be at least 4k or else it fails on ATI cards.
+ enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
+}
+
+namespace gl
+{
+unsigned int VertexBuffer::mCurrentSerial = 1;
+
+int elementsInBuffer(const VertexAttribute &attribute, int size)
+{
+ int stride = attribute.stride();
+ return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride;
+}
+
+VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device)
+{
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ mDirtyCurrentValue[i] = true;
+ mCurrentValueBuffer[i] = NULL;
+ mCurrentValueOffsets[i] = 0;
+ }
+
+ const D3DCAPS9 &caps = context->getDeviceCaps();
+ checkVertexCaps(caps.DeclTypes);
+
+ mStreamingBuffer = new StreamingVertexBuffer(mDevice, 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];
+ }
+}
+
+std::size_t VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances)
+{
+ Buffer *buffer = attribute.mBoundBuffer.get();
+
+ int inputStride = attribute.stride();
+ int elementSize = attribute.typeSize();
+ const FormatConverter &converter = formatConverter(attribute);
+ std::size_t streamOffset = 0;
+
+ void *output = NULL;
+
+ if (vertexBuffer)
+ {
+ output = vertexBuffer->map(attribute, spaceRequired(attribute, count, instances), &streamOffset);
+ }
+
+ if (output == NULL)
+ {
+ ERR("Failed to map vertex buffer.");
+ return -1;
+ }
+
+ const char *input = NULL;
+
+ if (buffer)
+ {
+ int offset = attribute.mOffset;
+
+ input = static_cast<const char*>(buffer->data()) + offset;
+ }
+ else
+ {
+ input = static_cast<const char*>(attribute.mPointer);
+ }
+
+ if (instances == 0 || attribute.mDivisor == 0)
+ {
+ input += inputStride * start;
+ }
+
+ if (converter.identity && inputStride == elementSize)
+ {
+ memcpy(output, input, count * inputStride);
+ }
+ else
+ {
+ converter.convertArray(input, inputStride, count, output);
+ }
+
+ vertexBuffer->unmap();
+
+ return streamOffset;
+}
+
+GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
+{
+ if (!mStreamingBuffer)
+ {
+ return GL_OUT_OF_MEMORY;
+ }
+
+ const VertexAttributeArray &attribs = mContext->getVertexAttributes();
+ Program *program = mContext->getCurrentProgram();
+
+ for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ translated[attributeIndex].active = (program->getSemanticIndex(attributeIndex) != -1);
+ }
+
+ // Determine the required storage size per used buffer, and invalidate static buffers that don't contain matching attributes
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (translated[i].active && attribs[i].mArrayEnabled)
+ {
+ Buffer *buffer = attribs[i].mBoundBuffer.get();
+ StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+
+ if (staticBuffer)
+ {
+ if (staticBuffer->size() == 0)
+ {
+ int totalCount = elementsInBuffer(attribs[i], buffer->size());
+ staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount, 0));
+ }
+ else if (staticBuffer->lookupAttribute(attribs[i]) == -1)
+ {
+ // This static buffer doesn't have matching attributes, so fall back to using the streaming buffer
+ // Add the space of all previous attributes belonging to the invalidated static buffer to the streaming buffer
+ for (int previous = 0; previous < i; previous++)
+ {
+ if (translated[previous].active && attribs[previous].mArrayEnabled)
+ {
+ Buffer *previousBuffer = attribs[previous].mBoundBuffer.get();
+ StaticVertexBuffer *previousStaticBuffer = previousBuffer ? previousBuffer->getStaticVertexBuffer() : NULL;
+
+ if (staticBuffer == previousStaticBuffer)
+ {
+ mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[previous], count, instances));
+ }
+ }
+ }
+
+ mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances));
+
+ buffer->invalidateStaticData();
+ }
+ }
+ else
+ {
+ mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances));
+ }
+ }
+ }
+
+ // Reserve the required space per used buffer
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (translated[i].active && attribs[i].mArrayEnabled)
+ {
+ Buffer *buffer = attribs[i].mBoundBuffer.get();
+ ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+ ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer;
+
+ if (vertexBuffer)
+ {
+ vertexBuffer->reserveRequiredSpace();
+ }
+ }
+ }
+
+ // Perform the vertex data translations
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (translated[i].active)
+ {
+ if (attribs[i].mArrayEnabled)
+ {
+ Buffer *buffer = attribs[i].mBoundBuffer.get();
+
+ 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;
+ }
+
+ const FormatConverter &converter = formatConverter(attribs[i]);
+
+ StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL;
+ ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast<ArrayVertexBuffer*>(mStreamingBuffer);
+
+ std::size_t streamOffset = -1;
+
+ if (staticBuffer)
+ {
+ streamOffset = staticBuffer->lookupAttribute(attribs[i]);
+
+ if (streamOffset == -1)
+ {
+ // Convert the entire buffer
+ int totalCount = elementsInBuffer(attribs[i], buffer->size());
+ int startIndex = attribs[i].mOffset / attribs[i].stride();
+
+ streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i], 0);
+ }
+
+ if (streamOffset != -1)
+ {
+ streamOffset += (attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize;
+
+ if (instances == 0 || attribs[i].mDivisor == 0)
+ {
+ streamOffset += start * converter.outputElementSize;
+ }
+ }
+ }
+ else
+ {
+ streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i], instances);
+ }
+
+ if (streamOffset == -1)
+ {
+ return GL_OUT_OF_MEMORY;
+ }
+
+ translated[i].vertexBuffer = vertexBuffer->getBuffer();
+ translated[i].serial = vertexBuffer->getSerial();
+ translated[i].divisor = attribs[i].mDivisor;
+
+ translated[i].type = converter.d3dDeclType;
+ translated[i].stride = converter.outputElementSize;
+ translated[i].offset = streamOffset;
+ }
+ else
+ {
+ if (!mCurrentValueBuffer[i])
+ {
+ mCurrentValueBuffer[i] = new StreamingVertexBuffer(mDevice, CONSTANT_VERTEX_BUFFER_SIZE);
+ }
+
+ StreamingVertexBuffer *buffer = mCurrentValueBuffer[i];
+
+ if (mDirtyCurrentValue[i])
+ {
+ const int requiredSpace = 4 * sizeof(float);
+ buffer->addRequiredSpace(requiredSpace);
+ buffer->reserveRequiredSpace();
+ float *data = static_cast<float*>(buffer->map(VertexAttribute(), requiredSpace, &mCurrentValueOffsets[i]));
+ if (data)
+ {
+ data[0] = attribs[i].mCurrentValue[0];
+ data[1] = attribs[i].mCurrentValue[1];
+ data[2] = attribs[i].mCurrentValue[2];
+ data[3] = attribs[i].mCurrentValue[3];
+ buffer->unmap();
+ mDirtyCurrentValue[i] = false;
+ }
+ }
+
+ translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer();
+ translated[i].serial = mCurrentValueBuffer[i]->getSerial();
+ translated[i].divisor = 0;
+
+ translated[i].type = D3DDECLTYPE_FLOAT4;
+ translated[i].stride = 0;
+ translated[i].offset = mCurrentValueOffsets[i];
+ }
+ }
+ }
+
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (translated[i].active && attribs[i].mArrayEnabled)
+ {
+ Buffer *buffer = attribs[i].mBoundBuffer.get();
+
+ if (buffer)
+ {
+ buffer->promoteStaticUsage(count * attribs[i].typeSize());
+ }
+ }
+ }
+
+ return GL_NO_ERROR;
+}
+
+std::size_t VertexDataManager::spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const
+{
+ size_t elementSize = formatConverter(attrib).outputElementSize;
+
+ if (instances == 0 || attrib.mDivisor == 0)
+ {
+ return elementSize * count;
+ }
+ else
+ {
+ return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor);
+ }
+}
+
+// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
+//
+// BYTE SHORT (Cast)
+// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
+// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast)
+// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize)
+// SHORT SHORT (Identity)
+// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize)
+// UNSIGNED_SHORT FLOAT (Cast)
+// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize)
+// FIXED (not in WebGL) FLOAT (FixedToFloat)
+// FLOAT FLOAT (Identity)
+
+// GLToCType maps from GL type (as GLenum) to the C typedef.
+template <GLenum GLType> struct GLToCType { };
+
+template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
+template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
+template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
+template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
+template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
+template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
+
+// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
+enum D3DVertexType
+{
+ D3DVT_FLOAT,
+ D3DVT_SHORT,
+ D3DVT_SHORT_NORM,
+ D3DVT_UBYTE,
+ D3DVT_UBYTE_NORM,
+ D3DVT_USHORT_NORM
+};
+
+// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
+template <unsigned int D3DType> struct D3DToCType { };
+
+template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
+template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
+template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
+template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
+
+// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
+template <unsigned int type, int size>
+struct WidenRule
+{
+};
+
+template <int size> struct WidenRule<D3DVT_FLOAT, size> : gl::NoWiden<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT, size> : gl::WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : gl::WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE, size> : gl::WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : gl::WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : gl::WidenToEven<size> { };
+
+// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
+template <unsigned int d3dtype, int size>
+struct VertexTypeFlags
+{
+};
+
+template <unsigned int capflag, unsigned int declflag>
+struct VertexTypeFlagsHelper
+{
+ enum { capflag = capflag };
+ enum { declflag = declflag };
+};
+
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
+
+
+// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
+template <GLenum GLtype, bool normalized>
+struct VertexTypeMapping
+{
+};
+
+template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
+struct VertexTypeMappingBase
+{
+ enum { preferred = Preferred };
+ enum { fallback = Fallback };
+};
+
+template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast
+template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize
+template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity
+template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
+template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat
+template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity
+
+
+// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
+// The conversion rules themselves are defined in vertexconversion.h.
+
+// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
+template <GLenum fromType, bool normalized, unsigned int toType>
+struct ConversionRule : gl::Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type>
+{
+};
+
+// All conversions from normalized types to float use the Normalize operator.
+template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : gl::Normalize<typename GLToCType<fromType>::type> { };
+
+// Use a full specialisation for this so that it preferentially matches ahead of the generic normalize-to-float rules.
+template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : gl::FixedToFloat<GLuint, 16> { };
+template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : gl::FixedToFloat<GLuint, 16> { };
+
+// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
+// whether it is normalized or not.
+template <class T, bool normalized>
+struct DefaultVertexValuesStage2
+{
+};
+
+template <class T> struct DefaultVertexValuesStage2<T, true> : gl::NormalizedDefaultValues<T> { };
+template <class T> struct DefaultVertexValuesStage2<T, false> : gl::SimpleDefaultValues<T> { };
+
+// Work out the default value rule for a D3D type (expressed as the C type) and
+template <class T, bool normalized>
+struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized>
+{
+};
+
+template <bool normalized> struct DefaultVertexValues<float, normalized> : gl::SimpleDefaultValues<float> { };
+
+// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
+// The fallback conversion produces an output that all D3D9 devices must support.
+template <class T> struct UsePreferred { enum { type = T::preferred }; };
+template <class T> struct UseFallback { enum { type = T::fallback }; };
+
+// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
+// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
+// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
+template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
+struct Converter
+ : gl::VertexDataConverter<typename GLToCType<fromType>::type,
+ WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
+ ConversionRule<fromType,
+ normalized,
+ PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
+ DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
+{
+private:
+ enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
+ enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
+
+public:
+ enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
+ enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
+};
+
+// Initialise a TranslationInfo
+#define TRANSLATION(type, norm, size, preferred) \
+ { \
+ Converter<type, norm, size, preferred>::identity, \
+ Converter<type, norm, size, preferred>::finalSize, \
+ Converter<type, norm, size, preferred>::convertArray, \
+ static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \
+ }
+
+#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \
+ { \
+ Converter<type, norm, size, UsePreferred>::capflag, \
+ TRANSLATION(type, norm, size, UsePreferred), \
+ TRANSLATION(type, norm, size, UseFallback) \
+ }
+
+#define TRANSLATIONS_FOR_TYPE(type) \
+ { \
+ { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+ { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \
+ }
+
+#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \
+ { \
+ { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+ { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+ }
+
+const VertexDataManager::TranslationDescription VertexDataManager::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
+{
+ TRANSLATIONS_FOR_TYPE(GL_BYTE),
+ TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
+ TRANSLATIONS_FOR_TYPE(GL_SHORT),
+ TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
+ TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
+ TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
+};
+
+void VertexDataManager::checkVertexCaps(DWORD declTypes)
+{
+ for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
+ {
+ for (unsigned int j = 0; j < 2; j++)
+ {
+ for (unsigned int k = 0; k < 4; k++)
+ {
+ if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
+ {
+ mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
+ }
+ else
+ {
+ mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
+ }
+ }
+ }
+ }
+}
+
+// This is used to index mAttributeTypes and mPossibleTranslations.
+unsigned int VertexDataManager::typeIndex(GLenum type) const
+{
+ switch (type)
+ {
+ case GL_BYTE: return 0;
+ case GL_UNSIGNED_BYTE: return 1;
+ case GL_SHORT: return 2;
+ case GL_UNSIGNED_SHORT: return 3;
+ case GL_FIXED: return 4;
+ case GL_FLOAT: return 5;
+
+ default: UNREACHABLE(); return 5;
+ }
+}
+
+VertexBuffer::VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : mDevice(device), mVertexBuffer(NULL)
+{
+ if (size > 0)
+ {
+ D3DPOOL pool = getDisplay()->getBufferPool(usageFlags);
+ HRESULT result = device->CreateVertexBuffer(size, usageFlags, 0, pool, &mVertexBuffer, NULL);
+ mSerial = issueSerial();
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", size);
+ }
+ }
+}
+
+VertexBuffer::~VertexBuffer()
+{
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->Release();
+ }
+}
+
+void VertexBuffer::unmap()
+{
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->Unlock();
+ }
+}
+
+IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const
+{
+ return mVertexBuffer;
+}
+
+unsigned int VertexBuffer::getSerial() const
+{
+ return mSerial;
+}
+
+unsigned int VertexBuffer::issueSerial()
+{
+ return mCurrentSerial++;
+}
+
+ArrayVertexBuffer::ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : VertexBuffer(device, size, usageFlags)
+{
+ mBufferSize = size;
+ mWritePosition = 0;
+ mRequiredSpace = 0;
+}
+
+ArrayVertexBuffer::~ArrayVertexBuffer()
+{
+}
+
+void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace)
+{
+ mRequiredSpace += requiredSpace;
+}
+
+StreamingVertexBuffer::StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize) : ArrayVertexBuffer(device, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)
+{
+}
+
+StreamingVertexBuffer::~StreamingVertexBuffer()
+{
+}
+
+void *StreamingVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset)
+{
+ void *mapPtr = NULL;
+
+ if (mVertexBuffer)
+ {
+ HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
+
+ if (FAILED(result))
+ {
+ ERR("Lock failed with error 0x%08x", result);
+ return NULL;
+ }
+
+ *offset = mWritePosition;
+ mWritePosition += requiredSpace;
+ }
+
+ return mapPtr;
+}
+
+void StreamingVertexBuffer::reserveRequiredSpace()
+{
+ if (mRequiredSpace > mBufferSize)
+ {
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->Release();
+ mVertexBuffer = NULL;
+ }
+
+ 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.
+
+ D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
+ HRESULT result = mDevice->CreateVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL);
+ mSerial = issueSerial();
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
+ }
+
+ mWritePosition = 0;
+ }
+ else if (mWritePosition + mRequiredSpace > mBufferSize) // Recycle
+ {
+ if (mVertexBuffer)
+ {
+ void *dummy;
+ mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ mVertexBuffer->Unlock();
+ }
+
+ mWritePosition = 0;
+ }
+
+ mRequiredSpace = 0;
+}
+
+StaticVertexBuffer::StaticVertexBuffer(IDirect3DDevice9 *device) : ArrayVertexBuffer(device, 0, D3DUSAGE_WRITEONLY)
+{
+}
+
+StaticVertexBuffer::~StaticVertexBuffer()
+{
+}
+
+void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset)
+{
+ void *mapPtr = NULL;
+
+ if (mVertexBuffer)
+ {
+ HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0);
+
+ if (FAILED(result))
+ {
+ ERR("Lock failed with error 0x%08x", result);
+ return NULL;
+ }
+
+ int attributeOffset = attribute.mOffset % attribute.stride();
+ VertexElement element = {attribute.mType, attribute.mSize, attribute.stride(), attribute.mNormalized, attributeOffset, mWritePosition};
+ mCache.push_back(element);
+
+ *streamOffset = mWritePosition;
+ mWritePosition += requiredSpace;
+ }
+
+ return mapPtr;
+}
+
+void StaticVertexBuffer::reserveRequiredSpace()
+{
+ if (!mVertexBuffer && mBufferSize == 0)
+ {
+ D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY);
+ HRESULT result = mDevice->CreateVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL);
+ mSerial = issueSerial();
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace);
+ }
+
+ mBufferSize = mRequiredSpace;
+ }
+ else if (mVertexBuffer && mBufferSize >= mRequiredSpace)
+ {
+ // Already allocated
+ }
+ else UNREACHABLE(); // Static vertex buffers can't be resized
+
+ mRequiredSpace = 0;
+}
+
+std::size_t StaticVertexBuffer::lookupAttribute(const VertexAttribute &attribute)
+{
+ for (unsigned int element = 0; element < mCache.size(); element++)
+ {
+ if (mCache[element].type == attribute.mType &&
+ mCache[element].size == attribute.mSize &&
+ mCache[element].stride == attribute.stride() &&
+ mCache[element].normalized == attribute.mNormalized)
+ {
+ if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
+ {
+ return mCache[element].streamOffset;
+ }
+ }
+ }
+
+ return -1;
+}
+
+const VertexDataManager::FormatConverter &VertexDataManager::formatConverter(const VertexAttribute &attribute) const
+{
+ return mAttributeTypes[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
+}
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.h b/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.h
new file mode 100644
index 0000000..857591a
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/VertexDataManager.h
@@ -0,0 +1,169 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#ifndef LIBGLESV2_VERTEXDATAMANAGER_H_
+#define LIBGLESV2_VERTEXDATAMANAGER_H_
+
+#include <vector>
+#include <cstddef>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+
+struct TranslatedAttribute
+{
+ bool active;
+
+ D3DDECLTYPE type;
+ UINT offset;
+ UINT stride; // 0 means not to advance the read pointer at all
+
+ IDirect3DVertexBuffer9 *vertexBuffer;
+ unsigned int serial;
+ unsigned int divisor;
+};
+
+class VertexBuffer
+{
+ public:
+ VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags);
+ virtual ~VertexBuffer();
+
+ void unmap();
+
+ IDirect3DVertexBuffer9 *getBuffer() const;
+ unsigned int getSerial() const;
+
+ protected:
+ IDirect3DDevice9 *const mDevice;
+ IDirect3DVertexBuffer9 *mVertexBuffer;
+
+ unsigned int mSerial;
+ static unsigned int issueSerial();
+ static unsigned int mCurrentSerial;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
+};
+
+class ArrayVertexBuffer : public VertexBuffer
+{
+ public:
+ ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags);
+ ~ArrayVertexBuffer();
+
+ std::size_t size() const { return mBufferSize; }
+ virtual void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset) = 0;
+ virtual void reserveRequiredSpace() = 0;
+ void addRequiredSpace(UINT requiredSpace);
+
+ protected:
+ std::size_t mBufferSize;
+ std::size_t mWritePosition;
+ std::size_t mRequiredSpace;
+};
+
+class StreamingVertexBuffer : public ArrayVertexBuffer
+{
+ public:
+ StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize);
+ ~StreamingVertexBuffer();
+
+ void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset);
+ void reserveRequiredSpace();
+};
+
+class StaticVertexBuffer : public ArrayVertexBuffer
+{
+ public:
+ explicit StaticVertexBuffer(IDirect3DDevice9 *device);
+ ~StaticVertexBuffer();
+
+ void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset);
+ void reserveRequiredSpace();
+
+ std::size_t lookupAttribute(const VertexAttribute &attribute); // Returns the offset into the vertex buffer, or -1 if not found
+
+ private:
+ struct VertexElement
+ {
+ GLenum type;
+ GLint size;
+ GLsizei stride;
+ bool normalized;
+ int attributeOffset;
+
+ std::size_t streamOffset;
+ };
+
+ std::vector<VertexElement> mCache;
+};
+
+class VertexDataManager
+{
+ public:
+ VertexDataManager(Context *context, IDirect3DDevice9 *backend);
+ virtual ~VertexDataManager();
+
+ void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; }
+
+ GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
+
+ std::size_t spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const;
+ std::size_t writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances);
+
+ Context *const mContext;
+ IDirect3DDevice9 *const mDevice;
+
+ StreamingVertexBuffer *mStreamingBuffer;
+
+ bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS];
+ StreamingVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS];
+ std::size_t mCurrentValueOffsets[MAX_VERTEX_ATTRIBS];
+
+ // Attribute format conversion
+ struct FormatConverter
+ {
+ bool identity;
+ std::size_t outputElementSize;
+ void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
+ D3DDECLTYPE d3dDeclType;
+ };
+
+ enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
+
+ FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
+
+ struct TranslationDescription
+ {
+ DWORD capsFlag;
+ FormatConverter preferredConversion;
+ FormatConverter fallbackConversion;
+ };
+
+ // This table is used to generate mAttributeTypes.
+ static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
+
+ void checkVertexCaps(DWORD declTypes);
+
+ unsigned int typeIndex(GLenum type) const;
+ const FormatConverter &formatConverter(const VertexAttribute &attribute) const;
+};
+
+}
+
+#endif // LIBGLESV2_VERTEXDATAMANAGER_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp
index 543c0d2..ee8eca9 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -14,6 +14,7 @@
#include <limits>
#include "common/debug.h"
+#include "common/version.h"
#include "libGLESv2/main.h"
#include "libGLESv2/mathutil.h"
@@ -26,25 +27,126 @@
#include "libGLESv2/Renderbuffer.h"
#include "libGLESv2/Shader.h"
#include "libGLESv2/Texture.h"
+#include "libGLESv2/Query.h"
-extern "C"
+bool validImageSize(GLint level, GLsizei width, GLsizei height)
{
+ if (level < 0 || width < 0 || height < 0)
+ {
+ return false;
+ }
-void __stdcall glActiveTexture(GLenum texture)
+ if (gl::getContext() && gl::getContext()->supportsNonPower2Texture())
+ {
+ return true;
+ }
+
+ if (level == 0)
+ {
+ return true;
+ }
+
+ if (gl::isPow2(width) && gl::isPow2(height))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLint level, GLenum format, gl::Texture *texture)
{
- TRACE("(GLenum texture = 0x%X)", texture);
+ if (!texture)
+ {
+ return error(GL_INVALID_OPERATION, false);
+ }
- try
+ if (compressed != texture->isCompressed())
{
- if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + gl::MAX_TEXTURE_IMAGE_UNITS - 1)
+ return error(GL_INVALID_OPERATION, false);
+ }
+
+ if (format != GL_NONE && format != texture->getInternalFormat())
+ {
+ return error(GL_INVALID_OPERATION, false);
+ }
+
+ if (compressed)
+ {
+ if ((width % 4 != 0 && width != texture->getWidth(0)) ||
+ (height % 4 != 0 && height != texture->getHeight(0)))
{
- return error(GL_INVALID_ENUM);
+ return error(GL_INVALID_OPERATION, false);
}
+ }
- gl::Context *context = gl::getContext();
+ if (xoffset + width > texture->getWidth(level) ||
+ yoffset + height > texture->getHeight(level))
+ {
+ return error(GL_INVALID_VALUE, false);
+ }
+
+ return true;
+}
+
+// check for combinations of format and type that are valid for ReadPixels
+bool validReadFormatType(GLenum format, GLenum type)
+{
+ switch (format)
+ {
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ return false;
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ break;
+ default:
+ return false;
+ }
+ break;
+ case gl::IMPLEMENTATION_COLOR_READ_FORMAT:
+ switch (type)
+ {
+ case gl::IMPLEMENTATION_COLOR_READ_TYPE:
+ break;
+ default:
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+extern "C"
+{
+
+void __stdcall glActiveTexture(GLenum texture)
+{
+ EVENT("(GLenum texture = 0x%X)", texture);
+
+ try
+ {
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
+ if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
context->setActiveSampler(texture - GL_TEXTURE0);
}
}
@@ -56,11 +158,11 @@ void __stdcall glActiveTexture(GLenum texture)
void __stdcall glAttachShader(GLuint program, GLuint shader)
{
- TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
+ EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -103,9 +205,42 @@ void __stdcall glAttachShader(GLuint program, GLuint shader)
}
}
+void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
+{
+ EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
+
+ try
+ {
+ switch (target)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (id == 0)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ context->beginQuery(target, id);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
{
- TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
+ EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
try
{
@@ -114,7 +249,7 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar*
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -148,11 +283,11 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar*
void __stdcall glBindBuffer(GLenum target, GLuint buffer)
{
- TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
+ EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -177,7 +312,7 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer)
void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
{
- TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
+ EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
try
{
@@ -186,7 +321,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -209,7 +344,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
{
- TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
+ EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
try
{
@@ -218,7 +353,7 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -233,11 +368,11 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
void __stdcall glBindTexture(GLenum target, GLuint texture)
{
- TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
+ EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -269,12 +404,12 @@ void __stdcall glBindTexture(GLenum target, GLuint texture)
void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
- TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
+ EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
red, green, blue, alpha);
try
{
- gl::Context* context = gl::getContext();
+ gl::Context* context = gl::getNonLostContext();
if (context)
{
@@ -294,7 +429,7 @@ void __stdcall glBlendEquation(GLenum mode)
void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
{
- TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
+ EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
try
{
@@ -318,7 +453,7 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -338,7 +473,7 @@ void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor)
void __stdcall glBlendFuncSeparate(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)",
+ EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
srcRGB, dstRGB, srcAlpha, dstAlpha);
try
@@ -441,7 +576,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
return error(GL_INVALID_OPERATION);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -456,7 +591,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha
void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
{
- TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
+ EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
target, size, data, usage);
try
@@ -476,7 +611,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -510,7 +645,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
{
- TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
target, offset, size, data);
try
@@ -525,7 +660,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -564,7 +699,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
GLenum __stdcall glCheckFramebufferStatus(GLenum target)
{
- TRACE("(GLenum target = 0x%X)", target);
+ EVENT("(GLenum target = 0x%X)", target);
try
{
@@ -573,7 +708,7 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target)
return error(GL_INVALID_ENUM, 0);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -600,11 +735,11 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target)
void __stdcall glClear(GLbitfield mask)
{
- TRACE("(GLbitfield mask = %X)", mask);
+ EVENT("(GLbitfield mask = %X)", mask);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -619,12 +754,12 @@ void __stdcall glClear(GLbitfield mask)
void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
- TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
+ EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
red, green, blue, alpha);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -639,11 +774,11 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp
void __stdcall glClearDepthf(GLclampf depth)
{
- TRACE("(GLclampf depth = %f)", depth);
+ EVENT("(GLclampf depth = %f)", depth);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -658,11 +793,11 @@ void __stdcall glClearDepthf(GLclampf depth)
void __stdcall glClearStencil(GLint s)
{
- TRACE("(GLint s = %d)", s);
+ EVENT("(GLint s = %d)", s);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -677,12 +812,12 @@ void __stdcall glClearStencil(GLint s)
void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
{
- TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
+ EVENT("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
red, green, blue, alpha);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -697,11 +832,11 @@ void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboo
void __stdcall glCompileShader(GLuint shader)
{
- TRACE("(GLuint shader = %d)", shader);
+ EVENT("(GLuint shader = %d)", shader);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -731,18 +866,13 @@ void __stdcall glCompileShader(GLuint shader)
void __stdcall glCompressedTexImage2D(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, "
+ EVENT("(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 = 0x%0.8p)",
target, level, internalformat, width, height, border, imageSize, data);
try
{
- if (level < 0)
- {
- return error(GL_INVALID_VALUE);
- }
-
- if (width < 0 || height < 0 || (level > 0 && !gl::isPow2(width)) || (level > 0 && !gl::isPow2(height)) || border != 0 || imageSize < 0)
+ if (!validImageSize(level, width, height) || border != 0 || imageSize < 0)
{
return error(GL_INVALID_VALUE);
}
@@ -751,6 +881,8 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
break;
default:
return error(GL_INVALID_ENUM);
@@ -761,7 +893,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -800,9 +932,27 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
return error(GL_INVALID_ENUM);
}
- if (!context->supportsCompressedTextures())
- {
- return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ switch (internalformat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->supportsDXT1Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->supportsDXT5Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ default: UNREACHABLE();
}
if (imageSize != gl::ComputeCompressedSize(width, height, internalformat))
@@ -819,6 +969,11 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
return error(GL_INVALID_OPERATION);
}
+ if (texture->isImmutable())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
}
else
@@ -830,6 +985,11 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
return error(GL_INVALID_OPERATION);
}
+ if (texture->isImmutable())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
switch (target)
{
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
@@ -855,25 +1015,19 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna
void __stdcall glCompressedTexSubImage2D(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, "
+ EVENT("(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 = 0x%0.8p)",
target, level, xoffset, yoffset, width, height, format, imageSize, data);
try
{
- if (!gl::IsTextureTarget(target))
+ if (!gl::IsInternalTextureTarget(target))
{
return error(GL_INVALID_ENUM);
}
- if (level < 0)
- {
- return error(GL_INVALID_VALUE);
- }
-
- if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0 ||
- (level > 0 && !gl::isPow2(width)) || (level > 0 && !gl::isPow2(height)) || imageSize < 0)
+ if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
{
return error(GL_INVALID_VALUE);
}
@@ -882,6 +1036,8 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
break;
default:
return error(GL_INVALID_ENUM);
@@ -892,7 +1048,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -901,9 +1057,27 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
return error(GL_INVALID_VALUE);
}
- if (!context->supportsCompressedTextures())
- {
- return error(GL_INVALID_ENUM); // in this case, it's as though the format switch has failed.
+ switch (format) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->supportsDXT1Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->supportsDXT5Textures())
+ {
+ return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed
+ }
+ break;
+ default: UNREACHABLE();
}
if (imageSize != gl::ComputeCompressedSize(width, height, format))
@@ -914,52 +1088,24 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
if (xoffset % 4 != 0 || yoffset % 4 != 0)
{
return error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction
- // does not exist unless DXT1 textures are supported.
+ // does not exist unless DXT textures are supported.
}
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
-
- if (!texture)
- {
- return error(GL_INVALID_OPERATION);
- }
-
- if (!texture->isCompressed())
+ if (validateSubImageParams(true, width, height, xoffset, yoffset, level, GL_NONE, texture))
{
- return error(GL_INVALID_OPERATION);
+ texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
}
-
- if ((width % 4 != 0 && width != texture->getWidth()) ||
- (height % 4 != 0 && height != texture->getHeight()))
- {
- return error(GL_INVALID_OPERATION);
- }
-
- texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
}
else if (gl::IsCubemapTextureTarget(target))
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
-
- if (!texture)
- {
- return error(GL_INVALID_OPERATION);
- }
-
- if (!texture->isCompressed())
- {
- return error(GL_INVALID_OPERATION);
- }
-
- if ((width % 4 != 0 && width != texture->getWidth()) ||
- (height % 4 != 0 && height != texture->getHeight()))
+ if (validateSubImageParams(true, width, height, xoffset, yoffset, level, GL_NONE, texture))
{
- return error(GL_INVALID_OPERATION);
+ texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
}
-
- texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
}
else
{
@@ -975,18 +1121,13 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs
void __stdcall glCopyTexImage2D(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, "
+ EVENT("(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);
try
{
- if (level < 0 || width < 0 || height < 0)
- {
- return error(GL_INVALID_VALUE);
- }
-
- if (level > 0 && (!gl::isPow2(width) || !gl::isPow2(height)))
+ if (!validImageSize(level, width, height))
{
return error(GL_INVALID_VALUE);
}
@@ -996,10 +1137,15 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
+ if (level > context->getMaximumTextureLevel())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
switch (target)
{
case GL_TEXTURE_2D:
@@ -1042,8 +1188,8 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_OPERATION);
}
- gl::Colorbuffer *source = framebuffer->getColorbuffer();
- GLenum colorbufferFormat = source->getFormat();
+ gl::Renderbuffer *source = framebuffer->getColorbuffer();
+ GLenum colorbufferFormat = source->getInternalFormat();
// [OpenGL ES 2.0.24] table 3.9
switch (internalformat)
@@ -1083,7 +1229,27 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->supportsCompressedTextures())
+ if (context->supportsDXT1Textures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->supportsDXT5Textures())
{
return error(GL_INVALID_OPERATION);
}
@@ -1105,7 +1271,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_OPERATION);
}
- texture->copyImage(level, internalformat, x, y, width, height, source);
+ if (texture->isImmutable())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
}
else if (gl::IsCubemapTextureTarget(target))
{
@@ -1116,7 +1287,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
return error(GL_INVALID_OPERATION);
}
- texture->copyImage(target, level, internalformat, x, y, width, height, source);
+ if (texture->isImmutable())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
}
else UNREACHABLE();
}
@@ -1129,13 +1305,13 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma
void __stdcall glCopyTexSubImage2D(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, "
+ EVENT("(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);
try
{
- if (!gl::IsTextureTarget(target))
+ if (!gl::IsInternalTextureTarget(target))
{
return error(GL_INVALID_ENUM);
}
@@ -1155,7 +1331,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1176,8 +1352,8 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
return error(GL_INVALID_OPERATION);
}
- gl::Colorbuffer *source = framebuffer->getColorbuffer();
- GLenum colorbufferFormat = source->getFormat();
+ gl::Renderbuffer *source = framebuffer->getColorbuffer();
+ GLenum colorbufferFormat = source->getInternalFormat();
gl::Texture *texture = NULL;
if (target == GL_TEXTURE_2D)
@@ -1190,12 +1366,12 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
}
else UNREACHABLE();
- if (!texture)
+ if (!validateSubImageParams(false, width, height, xoffset, yoffset, level, GL_NONE, texture))
{
- return error(GL_INVALID_OPERATION);
+ return; // error already registered by validateSubImageParams
}
- GLenum textureFormat = texture->getFormat();
+ GLenum textureFormat = texture->getInternalFormat();
// [OpenGL ES 2.0.24] table 3.9
switch (textureFormat)
@@ -1235,12 +1411,14 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
return error(GL_INVALID_OPERATION);
default:
return error(GL_INVALID_OPERATION);
}
- texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, source);
+ texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer);
}
}
@@ -1252,11 +1430,11 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL
GLuint __stdcall glCreateProgram(void)
{
- TRACE("()");
+ EVENT("()");
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1273,11 +1451,11 @@ GLuint __stdcall glCreateProgram(void)
GLuint __stdcall glCreateShader(GLenum type)
{
- TRACE("(GLenum type = 0x%X)", type);
+ EVENT("(GLenum type = 0x%X)", type);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1301,7 +1479,7 @@ GLuint __stdcall glCreateShader(GLenum type)
void __stdcall glCullFace(GLenum mode)
{
- TRACE("(GLenum mode = 0x%X)", mode);
+ EVENT("(GLenum mode = 0x%X)", mode);
try
{
@@ -1311,7 +1489,7 @@ void __stdcall glCullFace(GLenum mode)
case GL_BACK:
case GL_FRONT_AND_BACK:
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1331,7 +1509,7 @@ void __stdcall glCullFace(GLenum mode)
void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
{
- TRACE("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
+ EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
try
{
@@ -1340,7 +1518,7 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1358,7 +1536,7 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
{
- TRACE("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
+ EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
try
{
@@ -1367,7 +1545,7 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1385,7 +1563,7 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
{
- TRACE("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
+ EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
try
{
@@ -1394,7 +1572,7 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1415,7 +1593,7 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
void __stdcall glDeleteProgram(GLuint program)
{
- TRACE("(GLuint program = %d)", program);
+ EVENT("(GLuint program = %d)", program);
try
{
@@ -1424,7 +1602,7 @@ void __stdcall glDeleteProgram(GLuint program)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1449,9 +1627,36 @@ void __stdcall glDeleteProgram(GLuint program)
}
}
+void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
+{
+ EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteQuery(ids[i]);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
{
- TRACE("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
+ EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
try
{
@@ -1460,7 +1665,7 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1478,7 +1683,7 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
void __stdcall glDeleteShader(GLuint shader)
{
- TRACE("(GLuint shader = %d)", shader);
+ EVENT("(GLuint shader = %d)", shader);
try
{
@@ -1487,7 +1692,7 @@ void __stdcall glDeleteShader(GLuint shader)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1514,7 +1719,7 @@ void __stdcall glDeleteShader(GLuint shader)
void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
{
- TRACE("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
+ EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
try
{
@@ -1523,7 +1728,7 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1544,7 +1749,7 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
void __stdcall glDepthFunc(GLenum func)
{
- TRACE("(GLenum func = 0x%X)", func);
+ EVENT("(GLenum func = 0x%X)", func);
try
{
@@ -1563,7 +1768,7 @@ void __stdcall glDepthFunc(GLenum func)
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1578,11 +1783,11 @@ void __stdcall glDepthFunc(GLenum func)
void __stdcall glDepthMask(GLboolean flag)
{
- TRACE("(GLboolean flag = %d)", flag);
+ EVENT("(GLboolean flag = %d)", flag);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1597,11 +1802,11 @@ void __stdcall glDepthMask(GLboolean flag)
void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
{
- TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
+ EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1616,11 +1821,11 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
void __stdcall glDetachShader(GLuint program, GLuint shader)
{
- TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
+ EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1669,11 +1874,11 @@ void __stdcall glDetachShader(GLuint program, GLuint shader)
void __stdcall glDisable(GLenum cap)
{
- TRACE("(GLenum cap = 0x%X)", cap);
+ EVENT("(GLenum cap = 0x%X)", cap);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1701,7 +1906,7 @@ void __stdcall glDisable(GLenum cap)
void __stdcall glDisableVertexAttribArray(GLuint index)
{
- TRACE("(GLuint index = %d)", index);
+ EVENT("(GLuint index = %d)", index);
try
{
@@ -1710,7 +1915,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1725,7 +1930,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index)
void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
- TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
+ EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
try
{
@@ -1734,11 +1939,38 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
- context->drawArrays(mode, first, count);
+ context->drawArrays(mode, first, count, 0);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+{
+ EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount);
+
+ try
+ {
+ if (count < 0 || first < 0 || primcount < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (primcount > 0)
+ {
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ context->drawArrays(mode, first, count, primcount);
+ }
}
}
catch(std::bad_alloc&)
@@ -1749,7 +1981,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
{
- TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
+ EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
mode, count, type, indices);
try
@@ -1759,7 +1991,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1778,7 +2010,50 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
return error(GL_INVALID_ENUM);
}
- context->drawElements(mode, count, type, indices);
+ context->drawElements(mode, count, type, indices, 0);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
+{
+ EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)",
+ mode, count, type, indices, primcount);
+
+ try
+ {
+ if (count < 0 || primcount < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (primcount > 0)
+ {
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT:
+ break;
+ case GL_UNSIGNED_INT:
+ if (!context->supports32bitIndices())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ context->drawElements(mode, count, type, indices, primcount);
+ }
}
}
catch(std::bad_alloc&)
@@ -1789,11 +2064,11 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
void __stdcall glEnable(GLenum cap)
{
- TRACE("(GLenum cap = 0x%X)", cap);
+ EVENT("(GLenum cap = 0x%X)", cap);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1821,7 +2096,7 @@ void __stdcall glEnable(GLenum cap)
void __stdcall glEnableVertexAttribArray(GLuint index)
{
- TRACE("(GLuint index = %d)", index);
+ EVENT("(GLuint index = %d)", index);
try
{
@@ -1830,7 +2105,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1843,13 +2118,41 @@ void __stdcall glEnableVertexAttribArray(GLuint index)
}
}
+void __stdcall glEndQueryEXT(GLenum target)
+{
+ EVENT("GLenum target = 0x%X)", target);
+
+ try
+ {
+ switch (target)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ context->endQuery(target);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
void __stdcall glFinishFenceNV(GLuint fence)
{
- TRACE("(GLuint fence = %d)", fence);
+ EVENT("(GLuint fence = %d)", fence);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1871,15 +2174,15 @@ void __stdcall glFinishFenceNV(GLuint fence)
void __stdcall glFinish(void)
{
- TRACE("()");
+ EVENT("()");
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
- context->finish();
+ context->sync(true);
}
}
catch(std::bad_alloc&)
@@ -1890,15 +2193,15 @@ void __stdcall glFinish(void)
void __stdcall glFlush(void)
{
- TRACE("()");
+ EVENT("()");
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
- context->flush();
+ context->sync(false);
}
}
catch(std::bad_alloc&)
@@ -1909,18 +2212,18 @@ void __stdcall glFlush(void)
void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
{
- TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
+ EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
"GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
try
{
if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
- || renderbuffertarget != GL_RENDERBUFFER)
+ || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
{
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -1931,13 +2234,13 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu
framebuffer = context->getReadFramebuffer();
framebufferHandle = context->getReadFramebufferHandle();
}
- else
+ else
{
framebuffer = context->getDrawFramebuffer();
framebufferHandle = context->getDrawFramebufferHandle();
}
- if (framebufferHandle == 0 || !framebuffer)
+ if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
{
return error(GL_INVALID_OPERATION);
}
@@ -1966,7 +2269,7 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu
void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
{
- TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
+ EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
"GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
try
@@ -1986,7 +2289,7 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2073,7 +2376,7 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t
void __stdcall glFrontFace(GLenum mode)
{
- TRACE("(GLenum mode = 0x%X)", mode);
+ EVENT("(GLenum mode = 0x%X)", mode);
try
{
@@ -2082,7 +2385,7 @@ void __stdcall glFrontFace(GLenum mode)
case GL_CW:
case GL_CCW:
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2102,7 +2405,7 @@ void __stdcall glFrontFace(GLenum mode)
void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
{
- TRACE("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
+ EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
try
{
@@ -2111,7 +2414,7 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2129,11 +2432,11 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
void __stdcall glGenerateMipmap(GLenum target)
{
- TRACE("(GLenum target = 0x%X)", target);
+ EVENT("(GLenum target = 0x%X)", target);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2169,7 +2472,7 @@ void __stdcall glGenerateMipmap(GLenum target)
void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
{
- TRACE("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
+ EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
try
{
@@ -2178,7 +2481,7 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2196,7 +2499,7 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
{
- TRACE("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
+ EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
try
{
@@ -2205,7 +2508,7 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2221,9 +2524,36 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
}
}
+void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids)
+{
+ EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+ try
+ {
+ if (n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ ids[i] = context->createQuery();
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
{
- TRACE("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
+ EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
try
{
@@ -2232,7 +2562,7 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2250,7 +2580,7 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
void __stdcall glGenTextures(GLsizei n, GLuint* textures)
{
- TRACE("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
+ EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
try
{
@@ -2259,7 +2589,7 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2277,7 +2607,7 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures)
void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
{
- TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
+ EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
"GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
program, index, bufsize, length, size, type, name);
@@ -2288,7 +2618,7 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2322,7 +2652,7 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
{
- TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
+ EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
"GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
program, index, bufsize, length, size, type, name);
@@ -2333,7 +2663,7 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2367,7 +2697,7 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
{
- TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
+ EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
program, maxcount, count, shaders);
try
@@ -2377,7 +2707,7 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2406,11 +2736,11 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c
int __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
{
- TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
+ EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2447,11 +2777,11 @@ int __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
{
- TRACE("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
+ EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2510,11 +2840,11 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
- TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2557,7 +2887,7 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params
GLenum __stdcall glGetError(void)
{
- TRACE("()");
+ EVENT("()");
gl::Context *context = gl::getContext();
@@ -2571,12 +2901,12 @@ GLenum __stdcall glGetError(void)
void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
{
- TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
+ EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2598,11 +2928,11 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
{
- TRACE("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
+ EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2658,12 +2988,12 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
{
- TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
target, attachment, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2716,11 +3046,15 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac
{
attachmentObjectType = attachmentType;
}
- else if (gl::IsTextureTarget(attachmentType))
+ else if (gl::IsInternalTextureTarget(attachmentType))
{
attachmentObjectType = GL_TEXTURE;
}
- else UNREACHABLE();
+ else
+ {
+ UNREACHABLE();
+ return;
+ }
switch (pname)
{
@@ -2775,9 +3109,9 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac
}
}
-void __stdcall glGetIntegerv(GLenum pname, GLint* params)
+GLenum __stdcall glGetGraphicsResetStatusEXT(void)
{
- TRACE("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
+ EVENT("()");
try
{
@@ -2785,6 +3119,27 @@ void __stdcall glGetIntegerv(GLenum pname, GLint* params)
if (context)
{
+ return context->getResetStatus();
+ }
+
+ return GL_NO_ERROR;
+ }
+ catch(std::bad_alloc&)
+ {
+ return GL_OUT_OF_MEMORY;
+ }
+}
+
+void __stdcall glGetIntegerv(GLenum pname, GLint* params)
+{
+ EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
+
+ try
+ {
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
if (!(context->getIntegerv(pname, params)))
{
GLenum nativeType;
@@ -2842,11 +3197,11 @@ void __stdcall glGetIntegerv(GLenum pname, GLint* params)
void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params)
{
- TRACE("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
+ EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2899,7 +3254,7 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params)
void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
{
- TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
+ EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
program, bufsize, length, infolog);
try
@@ -2909,7 +3264,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2929,13 +3284,89 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len
}
}
+void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
+{
+ EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
+
+ try
+ {
+ switch (pname)
+ {
+ case GL_CURRENT_QUERY_EXT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ params[0] = context->getActiveQuery(target);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
+{
+ EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
+
+ try
+ {
+ switch (pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+ if (!queryObject)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (context->getActiveQuery(queryObject->getType()) == id)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch(pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ params[0] = queryObject->getResult();
+ break;
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ params[0] = queryObject->isResultAvailable();
+ break;
+ default:
+ ASSERT(false);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
- TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -2953,85 +3384,23 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint*
switch (pname)
{
- case GL_RENDERBUFFER_WIDTH:
- *params = renderbuffer->getWidth();
- break;
- case GL_RENDERBUFFER_HEIGHT:
- *params = renderbuffer->getHeight();
- break;
- case GL_RENDERBUFFER_INTERNAL_FORMAT:
- *params = renderbuffer->getFormat();
- break;
- case GL_RENDERBUFFER_RED_SIZE:
- if (renderbuffer->isColorbuffer())
- {
- *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getRedSize();
- }
- else
- {
- *params = 0;
- }
- break;
- case GL_RENDERBUFFER_GREEN_SIZE:
- if (renderbuffer->isColorbuffer())
- {
- *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getGreenSize();
- }
- else
- {
- *params = 0;
- }
- break;
- case GL_RENDERBUFFER_BLUE_SIZE:
- if (renderbuffer->isColorbuffer())
- {
- *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getBlueSize();
- }
- else
- {
- *params = 0;
- }
- break;
- case GL_RENDERBUFFER_ALPHA_SIZE:
- if (renderbuffer->isColorbuffer())
- {
- *params = static_cast<gl::Colorbuffer*>(renderbuffer->getStorage())->getAlphaSize();
- }
- else
- {
- *params = 0;
- }
- break;
- case GL_RENDERBUFFER_DEPTH_SIZE:
- if (renderbuffer->isDepthbuffer())
- {
- *params = static_cast<gl::Depthbuffer*>(renderbuffer->getStorage())->getDepthSize();
- }
- else
- {
- *params = 0;
- }
- break;
- case GL_RENDERBUFFER_STENCIL_SIZE:
- if (renderbuffer->isStencilbuffer())
+ case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
+ case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
+ case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
+ case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
+ case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
+ case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
+ case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
+ case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
+ case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
+ case GL_RENDERBUFFER_SAMPLES_ANGLE:
+ if (context->getMaxSupportedSamples() != 0)
{
- *params = static_cast<gl::Stencilbuffer*>(renderbuffer->getStorage())->getStencilSize();
+ *params = renderbuffer->getSamples();
}
else
{
- *params = 0;
- }
- break;
- case GL_RENDERBUFFER_SAMPLES_ANGLE:
- {
- if (context->getMaxSupportedSamples() != 0)
- {
- *params = renderbuffer->getStorage()->getSamples();
- }
- else
- {
- return error(GL_INVALID_ENUM);
- }
+ return error(GL_INVALID_ENUM);
}
break;
default:
@@ -3047,11 +3416,11 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint*
void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
{
- TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
+ EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3079,6 +3448,9 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
case GL_SHADER_SOURCE_LENGTH:
*params = shaderObject->getSourceLength();
return;
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ *params = shaderObject->getTranslatedSourceLength();
+ return;
default:
return error(GL_INVALID_ENUM);
}
@@ -3092,7 +3464,7 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
{
- TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
+ EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
shader, bufsize, length, infolog);
try
@@ -3102,7 +3474,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3124,7 +3496,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt
void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
{
- TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
+ EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
shadertype, precisiontype, range, precision);
try
@@ -3169,7 +3541,7 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp
void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
{
- TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
+ EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
shader, bufsize, length, source);
try
@@ -3179,7 +3551,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3199,24 +3571,56 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length
}
}
+void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+ EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
+ shader, bufsize, length, source);
+
+ try
+ {
+ if (bufsize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ gl::Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ shaderObject->getTranslatedSource(bufsize, length, source);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
const GLubyte* __stdcall glGetString(GLenum name)
{
- TRACE("(GLenum name = 0x%X)", name);
+ EVENT("(GLenum name = 0x%X)", name);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
switch (name)
{
case GL_VENDOR:
- return (GLubyte*)"TransGaming Inc.";
+ return (GLubyte*)"Google Inc.";
case GL_RENDERER:
- return (GLubyte*)"ANGLE";
+ return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE");
case GL_VERSION:
- return (GLubyte*)"OpenGL ES 2.0 (git-devel "__DATE__ " " __TIME__")";
+ return (GLubyte*)"OpenGL ES 2.0 (ANGLE "VERSION_STRING")";
case GL_SHADING_LANGUAGE_VERSION:
- return (GLubyte*)"OpenGL ES GLSL ES 1.00 (git-devel "__DATE__ " " __TIME__")";
+ return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE "VERSION_STRING")";
case GL_EXTENSIONS:
return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
default:
@@ -3227,17 +3631,15 @@ const GLubyte* __stdcall glGetString(GLenum name)
{
return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);
}
-
- return NULL;
}
void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
{
- TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3269,6 +3671,12 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
case GL_TEXTURE_WRAP_T:
*params = (GLfloat)texture->getWrapT();
break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
+ *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = (GLfloat)texture->getUsage();
+ break;
default:
return error(GL_INVALID_ENUM);
}
@@ -3282,11 +3690,11 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
{
- TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3318,6 +3726,12 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
case GL_TEXTURE_WRAP_T:
*params = texture->getWrapT();
break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT_EXT:
+ *params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = texture->getUsage();
+ break;
default:
return error(GL_INVALID_ENUM);
}
@@ -3329,13 +3743,93 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
}
}
+void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+{
+ EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
+ program, location, bufSize, params);
+
+ try
+ {
+ if (bufSize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ if (program == 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject || !programObject->isLinked())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!programObject->getUniformfv(location, &bufSize, params))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
{
- TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
+ EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ if (program == 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Program *programObject = context->getProgram(program);
+
+ if (!programObject || !programObject->isLinked())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!programObject->getUniformfv(location, NULL, params))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+{
+ EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
+ program, location, bufSize, params);
+
+ try
+ {
+ if (bufSize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3351,7 +3845,12 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
return error(GL_INVALID_OPERATION);
}
- if (!programObject->getUniformfv(location, params))
+ if (!programObject)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if (!programObject->getUniformiv(location, &bufSize, params))
{
return error(GL_INVALID_OPERATION);
}
@@ -3365,11 +3864,11 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
{
- TRACE("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
+ EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3390,7 +3889,7 @@ void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
return error(GL_INVALID_OPERATION);
}
- if (!programObject->getUniformiv(location, params))
+ if (!programObject->getUniformiv(location, NULL, params))
{
return error(GL_INVALID_OPERATION);
}
@@ -3404,11 +3903,11 @@ void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
int __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
{
- TRACE("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
+ EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (strstr(name, "gl_") == name)
{
@@ -3436,7 +3935,7 @@ int __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
return error(GL_INVALID_OPERATION, -1);
}
- return programObject->getUniformLocation(name, false);
+ return programObject->getUniformLocation(name);
}
}
catch(std::bad_alloc&)
@@ -3449,11 +3948,11 @@ int __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
{
- TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
+ EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3490,6 +3989,9 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
params[i] = attribState.mCurrentValue[i];
}
break;
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
+ *params = (GLfloat)attribState.mDivisor;
+ break;
default: return error(GL_INVALID_ENUM);
}
}
@@ -3502,11 +4004,11 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
{
- TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
+ EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3544,6 +4046,9 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
}
break;
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
+ *params = (GLint)attribState.mDivisor;
+ break;
default: return error(GL_INVALID_ENUM);
}
}
@@ -3556,11 +4061,11 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
{
- TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
+ EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3585,7 +4090,7 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po
void __stdcall glHint(GLenum target, GLenum mode)
{
- TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
+ EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
try
{
@@ -3599,7 +4104,7 @@ void __stdcall glHint(GLenum target, GLenum mode)
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
switch (target)
{
case GL_GENERATE_MIPMAP_HINT:
@@ -3620,11 +4125,11 @@ void __stdcall glHint(GLenum target, GLenum mode)
GLboolean __stdcall glIsBuffer(GLuint buffer)
{
- TRACE("(GLuint buffer = %d)", buffer);
+ EVENT("(GLuint buffer = %d)", buffer);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context && buffer)
{
@@ -3646,11 +4151,11 @@ GLboolean __stdcall glIsBuffer(GLuint buffer)
GLboolean __stdcall glIsEnabled(GLenum cap)
{
- TRACE("(GLenum cap = 0x%X)", cap);
+ EVENT("(GLenum cap = 0x%X)", cap);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3680,11 +4185,11 @@ GLboolean __stdcall glIsEnabled(GLenum cap)
GLboolean __stdcall glIsFenceNV(GLuint fence)
{
- TRACE("(GLuint fence = %d)", fence);
+ EVENT("(GLuint fence = %d)", fence);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3708,11 +4213,11 @@ GLboolean __stdcall glIsFenceNV(GLuint fence)
GLboolean __stdcall glIsFramebuffer(GLuint framebuffer)
{
- TRACE("(GLuint framebuffer = %d)", framebuffer);
+ EVENT("(GLuint framebuffer = %d)", framebuffer);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context && framebuffer)
{
@@ -3734,11 +4239,11 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer)
GLboolean __stdcall glIsProgram(GLuint program)
{
- TRACE("(GLuint program = %d)", program);
+ EVENT("(GLuint program = %d)", program);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context && program)
{
@@ -3758,13 +4263,44 @@ GLboolean __stdcall glIsProgram(GLuint program)
return GL_FALSE;
}
+GLboolean __stdcall glIsQueryEXT(GLuint id)
+{
+ EVENT("(GLuint id = %d)", id);
+
+ try
+ {
+ if (id == 0)
+ {
+ return GL_FALSE;
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+ if (queryObject)
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
{
- TRACE("(GLuint renderbuffer = %d)", renderbuffer);
+ EVENT("(GLuint renderbuffer = %d)", renderbuffer);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context && renderbuffer)
{
@@ -3786,11 +4322,11 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
GLboolean __stdcall glIsShader(GLuint shader)
{
- TRACE("(GLuint shader = %d)", shader);
+ EVENT("(GLuint shader = %d)", shader);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context && shader)
{
@@ -3812,11 +4348,11 @@ GLboolean __stdcall glIsShader(GLuint shader)
GLboolean __stdcall glIsTexture(GLuint texture)
{
- TRACE("(GLuint texture = %d)", texture);
+ EVENT("(GLuint texture = %d)", texture);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context && texture)
{
@@ -3838,7 +4374,7 @@ GLboolean __stdcall glIsTexture(GLuint texture)
void __stdcall glLineWidth(GLfloat width)
{
- TRACE("(GLfloat width = %f)", width);
+ EVENT("(GLfloat width = %f)", width);
try
{
@@ -3847,7 +4383,7 @@ void __stdcall glLineWidth(GLfloat width)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3862,11 +4398,11 @@ void __stdcall glLineWidth(GLfloat width)
void __stdcall glLinkProgram(GLuint program)
{
- TRACE("(GLuint program = %d)", program);
+ EVENT("(GLuint program = %d)", program);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3895,11 +4431,11 @@ void __stdcall glLinkProgram(GLuint program)
void __stdcall glPixelStorei(GLenum pname, GLint param)
{
- TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
+ EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3923,6 +4459,10 @@ void __stdcall glPixelStorei(GLenum pname, GLint param)
context->setPackAlignment(param);
break;
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ context->setPackReverseRowOrder(param != 0);
+ break;
+
default:
return error(GL_INVALID_ENUM);
}
@@ -3936,11 +4476,11 @@ void __stdcall glPixelStorei(GLenum pname, GLint param)
void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
{
- TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
+ EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -3953,9 +4493,43 @@ void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
}
}
-void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLsizei bufSize,
+ GLvoid *data)
+{
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
+ x, y, width, height, format, type, bufSize, data);
+
+ try
+ {
+ if (width < 0 || height < 0 || bufSize < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (!validReadFormatType(format, type))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ context->readPixels(x, y, width, height, format, type, &bufSize, data);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glReadPixels(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, "
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
"GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
x, y, width, height, format, type, pixels);
@@ -3966,46 +4540,16 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLe
return error(GL_INVALID_VALUE);
}
- switch (format)
+ if (!validReadFormatType(format, type))
{
- case GL_RGBA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- break;
- default:
- return error(GL_INVALID_OPERATION);
- }
- break;
- case GL_BGRA_EXT:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
- break;
- default:
- return error(GL_INVALID_OPERATION);
- }
- break;
- case gl::IMPLEMENTATION_COLOR_READ_FORMAT:
- switch (type)
- {
- case gl::IMPLEMENTATION_COLOR_READ_TYPE:
- break;
- default:
- return error(GL_INVALID_OPERATION);
- }
- break;
- default:
return error(GL_INVALID_OPERATION);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
- context->readPixels(x, y, width, height, format, type, pixels);
+ context->readPixels(x, y, width, height, format, type, NULL, pixels);
}
}
catch(std::bad_alloc&)
@@ -4016,7 +4560,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLe
void __stdcall glReleaseShaderCompiler(void)
{
- TRACE("()");
+ EVENT("()");
try
{
@@ -4030,7 +4574,7 @@ void __stdcall glReleaseShaderCompiler(void)
void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
{
- TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
target, samples, internalformat, width, height);
try
@@ -4053,7 +4597,7 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4106,11 +4650,11 @@ void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsiz
void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
{
- TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
+ EVENT("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
try
{
- gl::Context* context = gl::getContext();
+ gl::Context* context = gl::getNonLostContext();
if (context)
{
@@ -4125,7 +4669,7 @@ void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
{
- TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
+ EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
try
{
@@ -4134,7 +4678,7 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4156,7 +4700,7 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
void __stdcall glScissor(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);
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
try
{
@@ -4165,7 +4709,7 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
return error(GL_INVALID_VALUE);
}
- gl::Context* context = gl::getContext();
+ gl::Context* context = gl::getNonLostContext();
if (context)
{
@@ -4180,7 +4724,7 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
{
- TRACE("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
+ EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
"const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
n, shaders, binaryformat, binary, length);
@@ -4197,7 +4741,7 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor
void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
{
- TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
+ EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
shader, count, string, length);
try
@@ -4207,7 +4751,7 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** strin
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4241,7 +4785,7 @@ void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask)
void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
{
- TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
+ EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
try
{
@@ -4270,7 +4814,7 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4298,7 +4842,7 @@ void __stdcall glStencilMask(GLuint mask)
void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
{
- TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
+ EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
try
{
@@ -4312,7 +4856,7 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4340,7 +4884,7 @@ void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
{
- TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
+ EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
face, fail, zfail, zpass);
try
@@ -4400,7 +4944,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu
return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4423,11 +4967,11 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu
GLboolean __stdcall glTestFenceNV(GLuint fence)
{
- TRACE("(GLuint fence = %d)", fence);
+ EVENT("(GLuint fence = %d)", fence);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4452,28 +4996,23 @@ GLboolean __stdcall glTestFenceNV(GLuint fence)
void __stdcall glTexImage2D(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, "
+ EVENT("(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 = 0x%0.8p)",
target, level, internalformat, width, height, border, format, type, pixels);
try
{
- if (level < 0 || width < 0 || height < 0)
- {
- return error(GL_INVALID_VALUE);
- }
-
- if (level > 0 && (!gl::isPow2(width) || !gl::isPow2(height)))
+ if (!validImageSize(level, width, height))
{
return error(GL_INVALID_VALUE);
}
- if (internalformat != format)
+ if (internalformat != GLint(format))
{
return error(GL_INVALID_OPERATION);
}
- switch (internalformat)
+ switch (format)
{
case GL_ALPHA:
case GL_LUMINANCE:
@@ -4524,6 +5063,8 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
break;
default:
return error(GL_INVALID_VALUE);
@@ -4534,10 +5075,15 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
+ if (level > context->getMaximumTextureLevel())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
switch (target)
{
case GL_TEXTURE_2D:
@@ -4568,10 +5114,30 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_ENUM);
}
- if (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
- internalformat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
- {
- if (context->supportsCompressedTextures())
+ switch (format) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (context->supportsDXT1Textures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ else
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->supportsDXT5Textures())
{
return error(GL_INVALID_OPERATION);
}
@@ -4579,18 +5145,21 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
{
return error(GL_INVALID_ENUM);
}
+ break;
+ default:
+ break;
}
if (type == GL_FLOAT)
{
- if (!context->supportsFloatTextures())
+ if (!context->supportsFloat32Textures())
{
return error(GL_INVALID_ENUM);
}
}
else if (type == GL_HALF_FLOAT_OES)
{
- if (!context->supportsHalfFloatTextures())
+ if (!context->supportsFloat16Textures())
{
return error(GL_INVALID_ENUM);
}
@@ -4605,7 +5174,12 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_OPERATION);
}
- texture->setImage(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ if (texture->isImmutable())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
}
else
{
@@ -4616,25 +5190,30 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL
return error(GL_INVALID_OPERATION);
}
+ if (texture->isImmutable())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
switch (target)
{
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- texture->setImagePosX(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ texture->setImagePosX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- texture->setImageNegX(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ texture->setImageNegX(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- texture->setImagePosY(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ texture->setImagePosY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- texture->setImageNegY(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ texture->setImageNegY(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- texture->setImagePosZ(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ texture->setImagePosZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- texture->setImageNegZ(level, internalformat, width, height, format, type, context->getUnpackAlignment(), pixels);
+ texture->setImageNegZ(level, width, height, format, type, context->getUnpackAlignment(), pixels);
break;
default: UNREACHABLE();
}
@@ -4659,11 +5238,11 @@ void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* para
void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
{
- TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4707,6 +5286,12 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
return error(GL_INVALID_ENUM);
}
break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ if (!texture->setUsage((GLenum)param))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
default:
return error(GL_INVALID_ENUM);
}
@@ -4723,106 +5308,231 @@ void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params
glTexParameteri(target, pname, *params);
}
-void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, GLenum type, const GLvoid* pixels)
+void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
- 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 = 0x%0.8p)",
- target, level, xoffset, yoffset, width, height, format, type, pixels);
+ EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, levels, internalformat, width, height);
try
{
- if (!gl::IsTextureTarget(target))
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
{
return error(GL_INVALID_ENUM);
}
- if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+ if (width < 1 || height < 1 || levels < 1)
{
return error(GL_INVALID_VALUE);
}
- if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+ if (target == GL_TEXTURE_CUBE_MAP && width != height)
{
return error(GL_INVALID_VALUE);
}
- if (!gl::CheckTextureFormatType(format, type))
+ if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
{
- return error(GL_INVALID_ENUM);
+ return error(GL_INVALID_OPERATION);
}
- if (width == 0 || height == 0 || pixels == NULL)
+ GLenum format = gl::ExtractFormat(internalformat);
+ GLenum type = gl::ExtractType(internalformat);
+
+ if (format == GL_NONE || type == GL_NONE)
{
- return;
+ return error(GL_INVALID_ENUM);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
- if (level > context->getMaximumTextureLevel())
+ switch (target)
{
- return error(GL_INVALID_VALUE);
+ case GL_TEXTURE_2D:
+ if (width > context->getMaximumTextureDimension() ||
+ height > context->getMaximumTextureDimension())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ if (width > context->getMaximumCubeTextureDimension() ||
+ height > context->getMaximumCubeTextureDimension())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
}
- if (format == GL_FLOAT)
+ if (levels != 1 && !context->supportsNonPower2Texture())
{
- if (!context->supportsFloatTextures())
+ if (!gl::isPow2(width) || !gl::isPow2(height))
{
- return error(GL_INVALID_ENUM);
+ return error(GL_INVALID_OPERATION);
}
}
- else if (format == GL_HALF_FLOAT_OES)
+
+ switch (internalformat)
{
- if (!context->supportsHalfFloatTextures())
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->supportsDXT1Textures())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->supportsDXT3Textures())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->supportsDXT5Textures())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_RGBA32F_EXT:
+ case GL_RGB32F_EXT:
+ case GL_ALPHA32F_EXT:
+ case GL_LUMINANCE32F_EXT:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ if (!context->supportsFloat32Textures())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_RGBA16F_EXT:
+ case GL_RGB16F_EXT:
+ case GL_ALPHA16F_EXT:
+ case GL_LUMINANCE16F_EXT:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ if (!context->supportsFloat16Textures())
{
return error(GL_INVALID_ENUM);
}
+ break;
}
if (target == GL_TEXTURE_2D)
{
gl::Texture2D *texture = context->getTexture2D();
- if (!texture)
- {
- return error(GL_INVALID_OPERATION);
- }
-
- if (texture->isCompressed())
+ if (!texture || texture->id() == 0)
{
return error(GL_INVALID_OPERATION);
}
- if (format != texture->getFormat())
+ if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
- texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
+ texture->storage(levels, internalformat, width, height);
}
- else if (gl::IsCubemapTextureTarget(target))
+ else if (target == GL_TEXTURE_CUBE_MAP)
{
gl::TextureCubeMap *texture = context->getTextureCubeMap();
- if (!texture)
+ if (!texture || texture->id() == 0)
{
return error(GL_INVALID_OPERATION);
}
- if (texture->isCompressed())
+ if (texture->isImmutable())
{
return error(GL_INVALID_OPERATION);
}
- if (format != texture->getFormat())
+ texture->storage(levels, internalformat, width);
+ }
+ else UNREACHABLE();
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
+void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(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 = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+
+ try
+ {
+ if (!gl::IsInternalTextureTarget(target))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (level < 0 || 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 (!gl::CheckTextureFormatType(format, type))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ if (width == 0 || height == 0 || pixels == NULL)
+ {
+ return;
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ if (level > context->getMaximumTextureLevel())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ if (format == GL_FLOAT)
+ {
+ if (!context->supportsFloat32Textures())
{
- return error(GL_INVALID_OPERATION);
+ return error(GL_INVALID_ENUM);
}
+ }
+ else if (format == GL_HALF_FLOAT_OES)
+ {
+ if (!context->supportsFloat16Textures())
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ }
- texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
+ if (target == GL_TEXTURE_2D)
+ {
+ gl::Texture2D *texture = context->getTexture2D();
+ if (validateSubImageParams(false, width, height, xoffset, yoffset, level, format, texture))
+ {
+ texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
+ }
+ }
+ else if (gl::IsCubemapTextureTarget(target))
+ {
+ gl::TextureCubeMap *texture = context->getTextureCubeMap();
+ if (validateSubImageParams(false, width, height, xoffset, yoffset, level, format, texture))
+ {
+ texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
+ }
}
else
{
@@ -4843,7 +5553,7 @@ void __stdcall glUniform1f(GLint location, GLfloat x)
void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
{
- TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
try
{
@@ -4857,7 +5567,7 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4887,7 +5597,7 @@ void __stdcall glUniform1i(GLint location, GLint x)
void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
{
- TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
try
{
@@ -4901,7 +5611,7 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4933,7 +5643,7 @@ void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
{
- TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
try
{
@@ -4947,7 +5657,7 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -4979,7 +5689,7 @@ void __stdcall glUniform2i(GLint location, GLint x, GLint y)
void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
{
- TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
try
{
@@ -4993,7 +5703,7 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5025,7 +5735,7 @@ void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
{
- TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
try
{
@@ -5039,7 +5749,7 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5071,7 +5781,7 @@ void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
{
- TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
try
{
@@ -5085,7 +5795,7 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5117,7 +5827,7 @@ void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfl
void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
{
- TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
try
{
@@ -5131,7 +5841,7 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5163,7 +5873,7 @@ void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
{
- TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
try
{
@@ -5177,7 +5887,7 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5202,7 +5912,7 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
location, count, transpose, value);
try
@@ -5217,7 +5927,7 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5242,7 +5952,7 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans
void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
location, count, transpose, value);
try
@@ -5257,7 +5967,7 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5282,7 +5992,7 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans
void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
location, count, transpose, value);
try
@@ -5297,7 +6007,7 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans
return;
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5322,11 +6032,11 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans
void __stdcall glUseProgram(GLuint program)
{
- TRACE("(GLuint program = %d)", program);
+ EVENT("(GLuint program = %d)", program);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5360,11 +6070,11 @@ void __stdcall glUseProgram(GLuint program)
void __stdcall glValidateProgram(GLuint program)
{
- TRACE("(GLuint program = %d)", program);
+ EVENT("(GLuint program = %d)", program);
try
{
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5393,7 +6103,7 @@ void __stdcall glValidateProgram(GLuint program)
void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
{
- TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
+ EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
try
{
@@ -5402,7 +6112,7 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5418,7 +6128,7 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
{
- TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
try
{
@@ -5427,7 +6137,7 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5443,7 +6153,7 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
{
- TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
try
{
@@ -5452,7 +6162,7 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5468,7 +6178,7 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
{
- TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
try
{
@@ -5477,7 +6187,7 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5493,7 +6203,7 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
{
- TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
try
{
@@ -5502,7 +6212,7 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5518,7 +6228,7 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
{
- TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
try
{
@@ -5527,7 +6237,7 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5543,7 +6253,7 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
- TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
try
{
@@ -5552,7 +6262,7 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5568,7 +6278,7 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G
void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
{
- TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
try
{
@@ -5577,7 +6287,7 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5590,9 +6300,33 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
}
}
+void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+{
+ EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
+
+ try
+ {
+ if (index >= gl::MAX_VERTEX_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ context->setVertexAttribDivisor(index, divisor);
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY);
+ }
+}
+
void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
{
- TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
+ EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
"GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
index, size, type, normalized, stride, ptr);
@@ -5626,7 +6360,7 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5641,7 +6375,7 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo
void __stdcall glViewport(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);
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
try
{
@@ -5650,7 +6384,7 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
return error(GL_INVALID_VALUE);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5666,7 +6400,7 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
- TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
+ EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
"GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
"GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
@@ -5692,7 +6426,7 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi
return error(GL_INVALID_OPERATION);
}
- gl::Context *context = gl::getContext();
+ gl::Context *context = gl::getNonLostContext();
if (context)
{
@@ -5714,7 +6448,7 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi
void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
- TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
"GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
"GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
target, level, internalformat, width, height, depth, border, format, type, pixels);
@@ -5749,6 +6483,22 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *
{"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV},
{"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV},
{"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV},
+ {"glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)glGetTranslatedShaderSourceANGLE},
+ {"glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)glTexStorage2DEXT},
+ {"glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)glGetGraphicsResetStatusEXT},
+ {"glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)glReadnPixelsEXT},
+ {"glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformfvEXT},
+ {"glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformivEXT},
+ {"glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)glGenQueriesEXT},
+ {"glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)glDeleteQueriesEXT},
+ {"glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)glIsQueryEXT},
+ {"glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)glBeginQueryEXT},
+ {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT},
+ {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT},
+ {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT},
+ {"glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)glVertexAttribDivisorANGLE},
+ {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE},
+ {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE},
};
for (int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
@@ -5762,4 +6512,38 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *
return NULL;
}
+// Non-public functions used by EGL
+
+bool __stdcall glBindTexImage(egl::Surface *surface)
+{
+ EVENT("(egl::Surface* surface = 0x%0.8p)",
+ surface);
+
+ try
+ {
+ gl::Context *context = gl::getNonLostContext();
+
+ if (context)
+ {
+ gl::Texture2D *textureObject = context->getTexture2D();
+
+ if (textureObject->isImmutable())
+ {
+ return false;
+ }
+
+ if (textureObject)
+ {
+ textureObject->bindTexImage(surface);
+ }
+ }
+ }
+ catch(std::bad_alloc&)
+ {
+ return error(GL_OUT_OF_MEMORY, false);
+ }
+
+ return true;
+}
+
}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def
index b2dc23c..ea7769b 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.def
@@ -154,10 +154,27 @@ EXPORTS
glIsFenceNV @155
glSetFenceNV @156
glTestFenceNV @157
+ glGetTranslatedShaderSourceANGLE @159
+ glTexStorage2DEXT @160
+ glGetGraphicsResetStatusEXT @161
+ glReadnPixelsEXT @162
+ glGetnUniformfvEXT @163
+ glGetnUniformivEXT @164
+ glGenQueriesEXT @165
+ glDeleteQueriesEXT @166
+ glIsQueryEXT @167
+ glBeginQueryEXT @168
+ glEndQueryEXT @169
+ glGetQueryivEXT @170
+ glGetQueryObjectuivEXT @171
+ glVertexAttribDivisorANGLE @172
+ glDrawArraysInstancedANGLE @173
+ glDrawElementsInstancedANGLE @174
; EGL dependencies
glCreateContext @144 NONAME
glDestroyContext @145 NONAME
glMakeCurrent @146 NONAME
glGetCurrentContext @147 NONAME
- glGetProcAddress @148 NONAME \ No newline at end of file
+ glGetProcAddress @148 NONAME
+ glBindTexImage @158 NONAME
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.rc b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.rc
new file mode 100644
index 0000000..0ad21e4
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.rc
@@ -0,0 +1,102 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <windows.h>
+#include "../common/version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "#include ""../common/version.h""\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,BUILD_VERSION,BUILD_REVISION
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library"
+ VALUE "FileVersion", VERSION_STRING
+ VALUE "InternalName", "libGLESv2"
+ VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc."
+ VALUE "OriginalFilename", "libGLESv2.dll"
+ VALUE "PrivateBuild", VERSION_STRING
+ VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library"
+ VALUE "ProductVersion", VERSION_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj
index 0d95080..7d2b649 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/libGLESv2.vcproj
@@ -12,6 +12,9 @@
<Platform
Name="Win32"
/>
+ <Platform
+ Name="x64"
+ />
</Platforms>
<ToolFiles>
</ToolFiles>
@@ -47,9 +50,11 @@
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
- WarningLevel="3"
+ WarningLevel="4"
+ DisableSpecificWarnings="4100;4127;4189;4239;4244;4245;4512;4702"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
+ WarnAsError="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -62,7 +67,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="D3dx9.lib"
+ AdditionalDependencies="d3d9.lib D3dx9.lib d3dcompiler.lib"
LinkIncremental="2"
ModuleDefinitionFile="libGLESv2.def"
GenerateDebugInformation="true"
@@ -125,9 +130,11 @@
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
- WarningLevel="3"
+ WarningLevel="4"
+ DisableSpecificWarnings="4100;4127;4189;4239;4244;4245;4512;4702;4718"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
+ WarnAsError="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -140,7 +147,7 @@
/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="D3dx9.lib"
+ AdditionalDependencies="d3d9.lib D3dx9.lib d3dcompiler.lib"
LinkIncremental="1"
IgnoreAllDefaultLibraries="false"
ModuleDefinitionFile="libGLESv2.def"
@@ -175,6 +182,171 @@
CommandLine="@echo on&#x0D;&#x0A;mkdir &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.dll&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.lib&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;@echo off&#x0D;&#x0A;"
/>
</Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="$(ProjectDir)/..; $(ProjectDir)/../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ DisableSpecificWarnings="4100;4127;4189;4239;4244;4245;4512;4702;4718"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ WarnAsError="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="d3d9.lib D3dx9.lib d3dcompiler.lib"
+ LinkIncremental="2"
+ ModuleDefinitionFile="libGLESv2.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="@echo on&#x0D;&#x0A;mkdir &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.dll&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.lib&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;@echo off&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ AdditionalIncludeDirectories="$(ProjectDir)/..; $(ProjectDir)/../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ DisableSpecificWarnings="4100;4127;4189;4239;4244;4245;4512;4702;4718"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ WarnAsError="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="d3d9.lib D3dx9.lib d3dcompiler.lib"
+ LinkIncremental="1"
+ IgnoreAllDefaultLibraries="false"
+ ModuleDefinitionFile="libGLESv2.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="@echo on&#x0D;&#x0A;mkdir &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.dll&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;copy &quot;$(OutDir)\libGLESv2.lib&quot; &quot;$(ProjectDir)..\..\lib\$(ConfigurationName)\&quot;&#x0D;&#x0A;@echo off&#x0D;&#x0A;"
+ />
+ </Configuration>
</Configurations>
<References>
</References>
@@ -209,6 +381,14 @@
>
</File>
<File
+ RelativePath=".\HandleAllocator.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IndexDataManager.cpp"
+ >
+ </File>
+ <File
RelativePath=".\libGLESv2.cpp"
>
</File>
@@ -221,7 +401,11 @@
>
</File>
<File
- RelativePath=".\RefCountObject.cpp"
+ RelativePath=".\Query.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\common\RefCountObject.cpp"
>
</File>
<File
@@ -244,18 +428,10 @@
RelativePath=".\utilities.cpp"
>
</File>
- <Filter
- Name="Geometry"
+ <File
+ RelativePath=".\VertexDataManager.cpp"
>
- <File
- RelativePath=".\geometry\IndexDataManager.cpp"
- >
- </File>
- <File
- RelativePath=".\geometry\VertexDataManager.cpp"
- >
- </File>
- </Filter>
+ </File>
</Filter>
<Filter
Name="Header Files"
@@ -295,6 +471,14 @@
>
</File>
<File
+ RelativePath=".\HandleAllocator.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IndexDataManager.h"
+ >
+ </File>
+ <File
RelativePath=".\main.h"
>
</File>
@@ -307,7 +491,11 @@
>
</File>
<File
- RelativePath=".\RefCountObject.h"
+ RelativePath=".\Query.h"
+ >
+ </File>
+ <File
+ RelativePath="..\common\RefCountObject.h"
>
</File>
<File
@@ -315,6 +503,10 @@
>
</File>
<File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
RelativePath=".\ResourceManager.h"
>
</File>
@@ -330,27 +522,27 @@
RelativePath=".\utilities.h"
>
</File>
- <Filter
- Name="Geometry"
- >
- <File
- RelativePath=".\geometry\IndexDataManager.h"
- >
- </File>
- <File
- RelativePath=".\geometry\vertexconversion.h"
- >
- </File>
- <File
- RelativePath=".\geometry\VertexDataManager.h"
- >
- </File>
- </Filter>
+ <File
+ RelativePath="..\common\version.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vertexconversion.h"
+ >
+ </File>
+ <File
+ RelativePath=".\VertexDataManager.h"
+ >
+ </File>
</Filter>
<File
RelativePath=".\libGLESv2.def"
>
</File>
+ <File
+ RelativePath=".\libGLESv2.rc"
+ >
+ </File>
</Files>
<Globals>
</Globals>
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp
index a99ec44..154d277 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/main.cpp
@@ -7,6 +7,7 @@
// main.cpp: DLL entry point and management of thread-local data.
#include "libGLESv2/main.h"
+#include "libGLESv2/utilities.h"
#include "common/debug.h"
#include "libEGL/Surface.h"
@@ -93,6 +94,25 @@ Context *getContext()
return current->context;
}
+Context *getNonLostContext()
+{
+ Context *context = getContext();
+
+ if (context)
+ {
+ if (context->isContextLost())
+ {
+ error(GL_OUT_OF_MEMORY);
+ return NULL;
+ }
+ else
+ {
+ return context;
+ }
+ }
+ return NULL;
+}
+
egl::Display *getDisplay()
{
Current *current = (Current*)TlsGetValue(currentTLS);
@@ -106,6 +126,19 @@ IDirect3DDevice9 *getDevice()
return display->getDevice();
}
+
+bool checkDeviceLost(HRESULT errorCode)
+{
+ egl::Display *display = NULL;
+
+ if (isDeviceLostError(errorCode))
+ {
+ display = gl::getDisplay();
+ display->notifyDeviceLost();
+ return true;
+ }
+ return false;
+}
}
// Records an error code
@@ -119,23 +152,23 @@ void error(GLenum errorCode)
{
case GL_INVALID_ENUM:
context->recordInvalidEnum();
- gl::trace("\t! Error generated: invalid enum\n");
+ TRACE("\t! Error generated: invalid enum\n");
break;
case GL_INVALID_VALUE:
context->recordInvalidValue();
- gl::trace("\t! Error generated: invalid value\n");
+ TRACE("\t! Error generated: invalid value\n");
break;
case GL_INVALID_OPERATION:
context->recordInvalidOperation();
- gl::trace("\t! Error generated: invalid operation\n");
+ TRACE("\t! Error generated: invalid operation\n");
break;
case GL_OUT_OF_MEMORY:
context->recordOutOfMemory();
- gl::trace("\t! Error generated: out of memory\n");
+ TRACE("\t! Error generated: out of memory\n");
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
context->recordInvalidFramebufferOperation();
- gl::trace("\t! Error generated: invalid framebuffer operation\n");
+ TRACE("\t! Error generated: invalid framebuffer operation\n");
break;
default: UNREACHABLE();
}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/main.h b/Source/ThirdParty/ANGLE/src/libGLESv2/main.h
index 7f9c880..504848a 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/main.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/main.h
@@ -29,9 +29,12 @@ struct Current
void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface);
Context *getContext();
+Context *getNonLostContext();
egl::Display *getDisplay();
IDirect3DDevice9 *getDevice();
+
+bool checkDeviceLost(HRESULT errorCode);
}
void error(GLenum errorCode);
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h b/Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h
index 31fa16f..7ca2d9f 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/mathutil.h
@@ -9,7 +9,9 @@
#ifndef LIBGLESV2_MATHUTIL_H_
#define LIBGLESV2_MATHUTIL_H_
+#include <intrin.h>
#include <math.h>
+#include <windows.h>
namespace gl
{
@@ -38,9 +40,15 @@ inline unsigned int ceilPow2(unsigned int x)
return x;
}
+template<typename T, typename MIN, typename MAX>
+inline T clamp(T x, MIN min, MAX max)
+{
+ return x < min ? min : (x > max ? max : x);
+}
+
inline float clamp01(float x)
{
- return x < 0 ? 0 : (x > 1 ? 1 : x);
+ return clamp(x, 0.0f, 1.0f);
}
template<const int n>
@@ -61,6 +69,51 @@ inline unsigned int unorm(float x)
return (unsigned int)(max * x + 0.5f);
}
}
+
+inline RECT transformPixelRect(GLint x, GLint y, GLint w, GLint h, GLint surfaceHeight)
+{
+ RECT rect = {x,
+ surfaceHeight - y - h,
+ x + w,
+ surfaceHeight - y};
+ return rect;
+}
+
+inline int transformPixelYOffset(GLint yoffset, GLint h, GLint surfaceHeight)
+{
+ return surfaceHeight - yoffset - h;
+}
+
+inline GLenum adjustWinding(GLenum winding)
+{
+ ASSERT(winding == GL_CW || winding == GL_CCW);
+ return winding == GL_CW ? GL_CCW : GL_CW;
+}
+
+inline bool supportsSSE2()
+{
+ static bool checked = false;
+ static bool supports = false;
+
+ if (checked)
+ {
+ return supports;
+ }
+
+ int info[4];
+ __cpuid(info, 0);
+
+ if (info[0] >= 1)
+ {
+ __cpuid(info, 1);
+
+ supports = (info[3] >> 26) & 1;
+ }
+
+ checked = true;
+
+ return supports;
+}
}
#endif // LIBGLESV2_MATHUTIL_H_
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/resource.h b/Source/ThirdParty/ANGLE/src/libGLESv2/resource.h
new file mode 100644
index 0000000..39adaad
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by libGLESv2.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp
index a3f5243..6589eb1 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.cpp
@@ -9,6 +9,8 @@
#include "libGLESv2/utilities.h"
#include <limits>
+#include <stdio.h>
+#include <windows.h>
#include "common/debug.h"
@@ -18,7 +20,8 @@
namespace gl
{
-int UniformComponentCount(GLenum type)
+// This is how much data the application expects for a uniform
+int UniformExternalComponentCount(GLenum type)
{
switch (type)
{
@@ -52,6 +55,42 @@ int UniformComponentCount(GLenum type)
return 0;
}
+// This is how much data we actually store for a uniform
+int UniformInternalComponentCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BOOL:
+ case GL_INT:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ return 1;
+ case GL_BOOL_VEC2:
+ case GL_INT_VEC2:
+ return 2;
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ return 3;
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ return 4;
+ case GL_FLOAT_MAT2:
+ return 8;
+ case GL_FLOAT_MAT3:
+ return 12;
+ case GL_FLOAT_MAT4:
+ return 16;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
GLenum UniformComponentType(GLenum type)
{
switch(type)
@@ -83,16 +122,27 @@ GLenum UniformComponentType(GLenum type)
return GL_NONE;
}
-size_t UniformTypeSize(GLenum type)
+size_t UniformComponentSize(GLenum type)
{
switch(type)
{
- case GL_BOOL: return sizeof(GLboolean);
+ case GL_BOOL: return sizeof(GLint);
case GL_FLOAT: return sizeof(GLfloat);
case GL_INT: return sizeof(GLint);
+ default: UNREACHABLE();
}
- return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
+ return 0;
+}
+
+size_t UniformInternalSize(GLenum type)
+{
+ return UniformComponentSize(UniformComponentType(type)) * UniformInternalComponentCount(type);
+}
+
+size_t UniformExternalSize(GLenum type)
+{
+ return UniformComponentSize(UniformComponentType(type)) * UniformExternalComponentCount(type);
}
int VariableRowCount(GLenum type)
@@ -189,18 +239,7 @@ GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
{
- switch (format)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- break;
- default:
- return 0;
- }
-
- ASSERT(width % 4 == 0);
-
- return 8 * width / 4;
+ return ComputeCompressedSize(width, 1, format);
}
GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
@@ -209,18 +248,23 @@ GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
default:
return 0;
}
- return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
}
bool IsCompressed(GLenum format)
{
if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
- format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
{
return true;
}
@@ -284,7 +328,7 @@ bool IsCubemapTextureTarget(GLenum target)
return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
}
-bool IsTextureTarget(GLenum target)
+bool IsInternalTextureTarget(GLenum target)
{
return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
}
@@ -336,6 +380,68 @@ bool CheckTextureFormatType(GLenum format, GLenum type)
}
}
+GLenum ExtractFormat(GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_RGB565: return GL_RGB;
+ case GL_RGBA4: return GL_RGBA;
+ case GL_RGB5_A1: return GL_RGBA;
+ case GL_RGB8_OES: return GL_RGB;
+ case GL_RGBA8_OES: return GL_RGBA;
+ case GL_LUMINANCE8_ALPHA8_EXT: return GL_LUMINANCE_ALPHA;
+ case GL_LUMINANCE8_EXT: return GL_LUMINANCE;
+ case GL_ALPHA8_EXT: return GL_ALPHA;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+ case GL_RGBA32F_EXT: return GL_RGBA;
+ case GL_RGB32F_EXT: return GL_RGB;
+ case GL_ALPHA32F_EXT: return GL_ALPHA;
+ case GL_LUMINANCE32F_EXT: return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA32F_EXT: return GL_LUMINANCE_ALPHA;
+ case GL_RGBA16F_EXT: return GL_RGBA;
+ case GL_RGB16F_EXT: return GL_RGB;
+ case GL_ALPHA16F_EXT: return GL_ALPHA;
+ case GL_LUMINANCE16F_EXT: return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA16F_EXT: return GL_LUMINANCE_ALPHA;
+ case GL_BGRA8_EXT: return GL_BGRA_EXT;
+ default: return GL_NONE; // Unsupported
+ }
+}
+
+GLenum ExtractType(GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
+ case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
+ case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
+ case GL_RGB8_OES: return GL_UNSIGNED_BYTE;
+ case GL_RGBA8_OES: return GL_UNSIGNED_BYTE;
+ case GL_LUMINANCE8_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
+ case GL_LUMINANCE8_EXT: return GL_UNSIGNED_BYTE;
+ case GL_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
+ case GL_RGBA32F_EXT: return GL_FLOAT;
+ case GL_RGB32F_EXT: return GL_FLOAT;
+ case GL_ALPHA32F_EXT: return GL_FLOAT;
+ case GL_LUMINANCE32F_EXT: return GL_FLOAT;
+ case GL_LUMINANCE_ALPHA32F_EXT: return GL_FLOAT;
+ case GL_RGBA16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_RGB16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_LUMINANCE16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_LUMINANCE_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE;
+ default: return GL_NONE; // Unsupported
+ }
+}
+
bool IsColorRenderable(GLenum internalformat)
{
switch (internalformat)
@@ -528,6 +634,39 @@ D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
return cull;
}
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
+{
+ D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
+
+ // Map a cube map texture target to the corresponding D3D surface index. Note that the
+ // Y faces are swapped because the Y coordinate to the texture lookup intrinsic functions
+ // are negated in the pixel shader.
+ switch (cubeFace)
+ {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ face = D3DCUBEMAP_FACE_POSITIVE_X;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ face = D3DCUBEMAP_FACE_NEGATIVE_X;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Y;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ face = D3DCUBEMAP_FACE_POSITIVE_Y;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ face = D3DCUBEMAP_FACE_POSITIVE_Z;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Z;
+ break;
+ default: UNREACHABLE();
+ }
+
+ return face;
+}
+
DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
{
return (red ? D3DCOLORWRITEENABLE_RED : 0) |
@@ -584,6 +723,75 @@ void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DT
}
}
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
+ D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
+{
+ switch (primitiveType)
+ {
+ case GL_POINTS:
+ *d3dPrimitiveType = D3DPT_POINTLIST;
+ *d3dPrimitiveCount = elementCount;
+ break;
+ case GL_LINES:
+ *d3dPrimitiveType = D3DPT_LINELIST;
+ *d3dPrimitiveCount = elementCount / 2;
+ break;
+ case GL_LINE_LOOP:
+ *d3dPrimitiveType = D3DPT_LINESTRIP;
+ *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately
+ break;
+ case GL_LINE_STRIP:
+ *d3dPrimitiveType = D3DPT_LINESTRIP;
+ *d3dPrimitiveCount = elementCount - 1;
+ break;
+ case GL_TRIANGLES:
+ *d3dPrimitiveType = D3DPT_TRIANGLELIST;
+ *d3dPrimitiveCount = elementCount / 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
+ *d3dPrimitiveCount = elementCount - 2;
+ break;
+ case GL_TRIANGLE_FAN:
+ *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
+ *d3dPrimitiveCount = elementCount - 2;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+D3DFORMAT ConvertRenderbufferFormat(GLenum format)
+{
+ switch (format)
+ {
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
+ case GL_RGB565: return D3DFMT_R5G6B5;
+ case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
+ case GL_DEPTH_COMPONENT16:
+ case GL_STENCIL_INDEX8:
+ case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
+ default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
+ }
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
+{
+ if (samples <= 1)
+ return D3DMULTISAMPLE_NONE;
+ else
+ return (D3DMULTISAMPLE_TYPE)samples;
+}
+
+}
+
+namespace dx2es
+{
+
unsigned int GetStencilSize(D3DFORMAT stencilFormat)
{
switch(stencilFormat)
@@ -601,11 +809,11 @@ unsigned int GetStencilSize(D3DFORMAT stencilFormat)
case D3DFMT_D32F_LOCKABLE:
case D3DFMT_D16:
return 0;
-// case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
-// case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
- default: UNREACHABLE();
+ //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
+ //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
+ default:
+ return 0;
}
- return 0;
}
unsigned int GetAlphaSize(D3DFORMAT colorFormat)
@@ -625,9 +833,9 @@ unsigned int GetAlphaSize(D3DFORMAT colorFormat)
case D3DFMT_X8R8G8B8:
case D3DFMT_R5G6B5:
return 0;
- default: UNREACHABLE();
+ default:
+ return 0;
}
- return 0;
}
unsigned int GetRedSize(D3DFORMAT colorFormat)
@@ -646,9 +854,9 @@ unsigned int GetRedSize(D3DFORMAT colorFormat)
case D3DFMT_A1R5G5B5:
case D3DFMT_R5G6B5:
return 5;
- default: UNREACHABLE();
+ default:
+ return 0;
}
- return 0;
}
unsigned int GetGreenSize(D3DFORMAT colorFormat)
@@ -668,9 +876,9 @@ unsigned int GetGreenSize(D3DFORMAT colorFormat)
return 5;
case D3DFMT_R5G6B5:
return 6;
- default: UNREACHABLE();
+ default:
+ return 0;
}
- return 0;
}
unsigned int GetBlueSize(D3DFORMAT colorFormat)
@@ -689,9 +897,9 @@ unsigned int GetBlueSize(D3DFORMAT colorFormat)
case D3DFMT_A1R5G5B5:
case D3DFMT_R5G6B5:
return 5;
- default: UNREACHABLE();
+ default:
+ return 0;
}
- return 0;
}
unsigned int GetDepthSize(D3DFORMAT depthFormat)
@@ -709,66 +917,52 @@ unsigned int GetDepthSize(D3DFORMAT depthFormat)
case D3DFMT_D24FS8: return 24;
//case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only
//case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only
- default:
- UNREACHABLE();
+ default: return 0;
}
- return 0;
}
-bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
- D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
+bool IsFloat32Format(D3DFORMAT surfaceFormat)
{
- switch (primitiveType)
+ switch(surfaceFormat)
{
- case GL_POINTS:
- *d3dPrimitiveType = D3DPT_POINTLIST;
- *d3dPrimitiveCount = elementCount;
- break;
- case GL_LINES:
- *d3dPrimitiveType = D3DPT_LINELIST;
- *d3dPrimitiveCount = elementCount / 2;
- break;
- case GL_LINE_LOOP:
- *d3dPrimitiveType = D3DPT_LINESTRIP;
- *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately
- break;
- case GL_LINE_STRIP:
- *d3dPrimitiveType = D3DPT_LINESTRIP;
- *d3dPrimitiveCount = elementCount - 1;
- break;
- case GL_TRIANGLES:
- *d3dPrimitiveType = D3DPT_TRIANGLELIST;
- *d3dPrimitiveCount = elementCount / 3;
- break;
- case GL_TRIANGLE_STRIP:
- *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
- *d3dPrimitiveCount = elementCount - 2;
- break;
- case GL_TRIANGLE_FAN:
- *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
- *d3dPrimitiveCount = elementCount - 2;
- break;
- default:
+ case D3DFMT_R16F:
+ case D3DFMT_G16R16F:
+ case D3DFMT_A16B16G16R16F:
+ return false;
+ case D3DFMT_R32F:
+ case D3DFMT_G32R32F:
+ case D3DFMT_A32B32G32R32F:
+ return true;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_R5G6B5:
return false;
+ default: UNREACHABLE();
}
-
- return true;
+ return false;
}
-D3DFORMAT ConvertRenderbufferFormat(GLenum format)
+bool IsFloat16Format(D3DFORMAT surfaceFormat)
{
- switch (format)
+ switch(surfaceFormat)
{
- case GL_RGBA4:
- case GL_RGB5_A1:
- case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
- case GL_RGB565: return D3DFMT_R5G6B5;
- case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
- case GL_DEPTH_COMPONENT16:
- case GL_STENCIL_INDEX8:
- case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
- default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
+ case D3DFMT_R16F:
+ case D3DFMT_G16R16F:
+ case D3DFMT_A16B16G16R16F:
+ return true;
+ case D3DFMT_R32F:
+ case D3DFMT_G32R32F:
+ case D3DFMT_A32B32G32R32F:
+ return false;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_R5G6B5:
+ return false;
+ default: UNREACHABLE();
}
+ return false;
}
GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
@@ -779,19 +973,6 @@ GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
return type;
}
-D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
-{
- if (samples <= 1)
- return D3DMULTISAMPLE_NONE;
- else
- return (D3DMULTISAMPLE_TYPE)samples;
-}
-
-}
-
-namespace dx2es
-{
-
GLenum ConvertBackBufferFormat(D3DFORMAT format)
{
switch (format)
@@ -825,3 +1006,36 @@ GLenum ConvertDepthStencilFormat(D3DFORMAT format)
}
}
+
+std::string getTempPath()
+{
+ char path[MAX_PATH];
+ DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
+ if (pathLen == 0)
+ {
+ UNREACHABLE();
+ return std::string();
+ }
+
+ UINT unique = GetTempFileNameA(path, "sh", 0, path);
+ if (unique == 0)
+ {
+ UNREACHABLE();
+ return std::string();
+ }
+
+ return path;
+}
+
+void writeFile(const char* path, const void* content, size_t size)
+{
+ FILE* file = fopen(path, "w");
+ if (!file)
+ {
+ UNREACHABLE();
+ return;
+ }
+
+ fwrite(content, sizeof(char), size, file);
+ fclose(file);
+}
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h
index 85e8f26..88238dc 100644
--- a/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/utilities.h
@@ -14,14 +14,18 @@
#include <GLES2/gl2ext.h>
#include <d3d9.h>
+#include <string>
+
namespace gl
{
struct Color;
-int UniformComponentCount(GLenum type);
+int UniformExternalComponentCount(GLenum type);
+int UniformInternalComponentCount(GLenum type);
GLenum UniformComponentType(GLenum type);
-size_t UniformTypeSize(GLenum type);
+size_t UniformInternalSize(GLenum type);
+size_t UniformExternalSize(GLenum type);
int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type);
@@ -33,8 +37,10 @@ GLsizei ComputeCompressedPitch(GLsizei width, GLenum format);
GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format);
bool IsCompressed(GLenum format);
bool IsCubemapTextureTarget(GLenum target);
-bool IsTextureTarget(GLenum target);
+bool IsInternalTextureTarget(GLenum target);
bool CheckTextureFormatType(GLenum format, GLenum type);
+GLenum ExtractFormat(GLenum internalformat);
+GLenum ExtractType(GLenum internalformat);
bool IsColorRenderable(GLenum internalformat);
bool IsDepthRenderable(GLenum internalformat);
@@ -52,29 +58,50 @@ D3DBLENDOP ConvertBlendOp(GLenum blendOp);
D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace);
DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter);
void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter);
-unsigned int GetAlphaSize(D3DFORMAT colorFormat);
-unsigned int GetRedSize(D3DFORMAT colorFormat);
-unsigned int GetGreenSize(D3DFORMAT colorFormat);
-unsigned int GetBlueSize(D3DFORMAT colorFormat);
-unsigned int GetDepthSize(D3DFORMAT depthFormat);
-unsigned int GetStencilSize(D3DFORMAT stencilFormat);
bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount);
D3DFORMAT ConvertRenderbufferFormat(GLenum format);
D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);
-GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
}
namespace dx2es
{
+GLuint GetAlphaSize(D3DFORMAT colorFormat);
+GLuint GetRedSize(D3DFORMAT colorFormat);
+GLuint GetGreenSize(D3DFORMAT colorFormat);
+GLuint GetBlueSize(D3DFORMAT colorFormat);
+GLuint GetDepthSize(D3DFORMAT depthFormat);
+GLuint GetStencilSize(D3DFORMAT stencilFormat);
+bool IsFloat32Format(D3DFORMAT surfaceFormat);
+bool IsFloat16Format(D3DFORMAT surfaceFormat);
+
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
GLenum ConvertBackBufferFormat(D3DFORMAT format);
GLenum ConvertDepthStencilFormat(D3DFORMAT format);
}
+std::string getTempPath();
+void writeFile(const char* path, const void* data, size_t size);
+
+inline bool isDeviceLostError(HRESULT errorCode)
+{
+ switch (errorCode)
+ {
+ case D3DERR_DRIVERINTERNALERROR:
+ case D3DERR_DEVICELOST:
+ case D3DERR_DEVICEHUNG:
+ case D3DERR_DEVICEREMOVED:
+ return true;
+ default:
+ return false;
+ }
+};
+
#endif // LIBGLESV2_UTILITIES_H
diff --git a/Source/ThirdParty/ANGLE/src/libGLESv2/vertexconversion.h b/Source/ThirdParty/ANGLE/src/libGLESv2/vertexconversion.h
new file mode 100644
index 0000000..5bb8b89
--- /dev/null
+++ b/Source/ThirdParty/ANGLE/src/libGLESv2/vertexconversion.h
@@ -0,0 +1,208 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// vertexconversion.h: A library of vertex conversion classes that can be used to build
+// the FormatConverter objects used by the buffer conversion system.
+
+#ifndef LIBGLESV2_VERTEXCONVERSION_H_
+#define LIBGLESV2_VERTEXCONVERSION_H_
+
+#include <cstddef>
+#include <limits>
+
+#include "libGLESv2/Context.h" // Defines Index
+
+namespace gl
+{
+
+// Conversion types:
+// static const bool identity: true if this is an identity transform, false otherwise
+// static U convert(T): convert a single element from the input type to the output type
+// typedef ... OutputType: the type produced by this conversion
+
+template <class T>
+struct Identity
+{
+ static const bool identity = true;
+
+ typedef T OutputType;
+
+ static T convert(T x)
+ {
+ return x;
+ }
+};
+
+template <class FromT, class ToT>
+struct Cast
+{
+ static const bool identity = false;
+
+ typedef ToT OutputType;
+
+ static ToT convert(FromT x)
+ {
+ return static_cast<ToT>(x);
+ }
+};
+
+template <class T>
+struct Cast<T, T>
+{
+ static const bool identity = true;
+
+ typedef T OutputType;
+
+ static T convert(T x)
+ {
+ return static_cast<T>(x);
+ }
+};
+
+template <class T>
+struct Normalize
+{
+ static const bool identity = false;
+
+ typedef float OutputType;
+
+ static float convert(T x)
+ {
+ typedef std::numeric_limits<T> NL;
+ float f = static_cast<float>(x);
+
+ if (NL::is_signed)
+ {
+ // const float => VC2008 computes it at compile time
+ // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
+ const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
+ return (2*f+1)*divisor;
+ }
+ else
+ {
+ return f/NL::max();
+ }
+ }
+};
+
+template <class FromType, std::size_t ScaleBits>
+struct FixedToFloat
+{
+ static const bool identity = false;
+
+ typedef float OutputType;
+
+ static float convert(FromType x)
+ {
+ const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
+ return static_cast<float>(x) * divisor;
+ }
+};
+
+// Widen types:
+// static const unsigned int initialWidth: number of components before conversion
+// static const unsigned int finalWidth: number of components after conversion
+
+// Float is supported at any size.
+template <std::size_t N>
+struct NoWiden
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = N;
+};
+
+// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
+template <std::size_t N>
+struct WidenToEven
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = N+(N&1);
+};
+
+template <std::size_t N>
+struct WidenToFour
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = 4;
+};
+
+// Most types have 0 and 1 that are just that.
+template <class T>
+struct SimpleDefaultValues
+{
+ static T zero() { return static_cast<T>(0); }
+ static T one() { return static_cast<T>(1); }
+};
+
+// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
+template <class T>
+struct NormalizedDefaultValues
+{
+ static T zero() { return static_cast<T>(0); }
+ static T one() { return std::numeric_limits<T>::max(); }
+};
+
+// Converter:
+// static const bool identity: true if this is an identity transform (with no widening)
+// static const std::size_t finalSize: number of bytes per output vertex
+// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
+
+template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
+struct VertexDataConverter
+{
+ typedef typename Converter::OutputType OutputType;
+ typedef InT InputType;
+
+ static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
+ static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
+
+ static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
+ {
+ for (std::size_t i = 0; i < n; i++)
+ {
+ const InputType *ein = pointerAddBytes(in, i * stride);
+
+ copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
+
+ out += WidenRule::finalWidth;
+ }
+ }
+
+ static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
+ {
+ return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
+ }
+
+ private:
+ // Advance the given pointer by a number of bytes (not pointed-to elements).
+ template <class T>
+ static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
+ {
+ return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
+ }
+
+ static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
+ {
+ if (WidenRule::finalWidth > elementindex)
+ {
+ if (WidenRule::initialWidth > elementindex)
+ {
+ out[elementindex] = Converter::convert(in[elementindex]);
+ }
+ else
+ {
+ out[elementindex] = defaultvalue;
+ }
+ }
+ }
+};
+
+}
+
+#endif // LIBGLESV2_VERTEXCONVERSION_H_