diff options
author | Andrew Knight <andrew.knight@digia.com> | 2014-08-05 12:59:44 +0300 |
---|---|---|
committer | Andrew Knight <andrew.knight@digia.com> | 2014-08-05 16:43:22 +0200 |
commit | a6a12d8c0fc918972c15268f749ecc7c90b95d6c (patch) | |
tree | cb6d986d30ef97e932ab51768854d5d9b46729d3 /src/3rdparty/angle/src/libGLESv2/renderer | |
parent | 14f9c09542bd6cc19430473da9ce4c68f239ec7d (diff) |
ANGLE: upgrade to 2.1~07d49ef5350a
This version of ANGLE provides partial ES3 support, numerous
bug fixes, and several potentially useful vendor extensions.
All patches have been rebased. The following changes are noted:
0000-General-fixes-for-ANGLE-2.1.patch
contains compile fixes for the new ANGLE
0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch
has incorporated patch 0015.
0007-Make-DX9-DX11-mutually-exclusive.patch
has been removed as it was fixed upstream.
0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
has been moved up to fill the patch number gap.
0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch
now contains patch 0014 and 0017.
0013-ANGLE-Allow-for-universal-program-binaries.patch
has been removed as it is no longer relevant.
0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch
has been merged with patch 0010.
0015-ANGLE-Don-t-export-DLLMain-functions-for-static-buil.patch
has been merged with patch 0004.
0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch
has been removed and will be replaced by a follow-up patch using a
different technique.
0017-ANGLE-D3D11-Don-t-use-mipmaps-in-level-9-textures.patch
has been merged with patch 0010.
0018-ANGLE-WinRT-Create-swap-chain-using-physical-resolut.patch
has been removed and will be replaced by a follow-up patch extending
the EGL_ANGLE_window_fixed_size extension.
0019-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
is now patch 0007.
[ChangeLog][Third-party libraries] ANGLE has been upgraded to
version 2.1, bringing partial support for OpenGL ES3 over
Direct3D 11, numerous bug fixes, and several new vendor extensions.
Change-Id: I6d95ce1480462d67228d83c1e5c74a1706b5b21c
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/renderer')
146 files changed, 22370 insertions, 9889 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h new file mode 100644 index 0000000000..bea689b956 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h @@ -0,0 +1,34 @@ +// +// Copyright 2014 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. +// + +// BufferImpl.h: Defines the abstract rx::BufferImpl class. + +#ifndef LIBGLESV2_RENDERER_BUFFERIMPL_H_ +#define LIBGLESV2_RENDERER_BUFFERIMPL_H_ + +#include "common/angleutils.h" +#include "libGLESv2/Buffer.h" + +namespace rx +{ + +class BufferImpl +{ + public: + virtual ~BufferImpl() { } + + virtual void setData(const void* data, size_t size, GLenum usage) = 0; + virtual void *getData() = 0; + virtual void setSubData(const void* data, size_t size, size_t offset) = 0; + virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0; + virtual GLvoid* map(size_t offset, size_t length, GLbitfield access) = 0; + virtual void unmap() = 0; + virtual void markTransformFeedbackUsage() = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp deleted file mode 100644 index a49b7bab84..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 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. -// - -// BufferStorage.cpp Defines the abstract BufferStorage class. - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ - -unsigned int BufferStorage::mNextSerial = 1; - -BufferStorage::BufferStorage() -{ - updateSerial(); -} - -BufferStorage::~BufferStorage() -{ -} - -unsigned int BufferStorage::getSerial() const -{ - return mSerial; -} - -void BufferStorage::updateSerial() -{ - mSerial = mNextSerial++; -} - -void BufferStorage::markBufferUsage() -{ -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h deleted file mode 100644 index ace1a11bae..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2013 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. -// - -// BufferStorage.h Defines the abstract BufferStorage class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ - -#include "common/angleutils.h" - -namespace rx -{ - -class BufferStorage -{ - public: - BufferStorage(); - virtual ~BufferStorage(); - - // The data returned is only guaranteed valid until next non-const method. - virtual void *getData() = 0; - virtual void setData(const void* data, unsigned int size, unsigned int offset) = 0; - virtual void clear() = 0; - virtual unsigned int getSize() const = 0; - virtual bool supportsDirectBinding() const = 0; - virtual void markBufferUsage(); - unsigned int getSerial() const; - - protected: - void updateSerial(); - - private: - DISALLOW_COPY_AND_ASSIGN(BufferStorage); - - unsigned int mSerial; - static unsigned int mNextSerial; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h index d7f2102a2e..d54e6becd3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h @@ -17,27 +17,16 @@ namespace rx class FenceImpl { public: - FenceImpl() : mStatus(GL_FALSE), mCondition(GL_NONE) { }; + FenceImpl() { }; virtual ~FenceImpl() { }; - virtual GLboolean isFence() = 0; - virtual void setFence(GLenum condition) = 0; - virtual GLboolean testFence() = 0; - virtual void finishFence() = 0; - virtual void getFenceiv(GLenum pname, GLint *params) = 0; - - protected: - void setStatus(GLboolean status) { mStatus = status; } - GLboolean getStatus() const { return mStatus; } - - void setCondition(GLuint condition) { mCondition = condition; } - GLuint getCondition() const { return mCondition; } + virtual bool isSet() const = 0; + virtual void set() = 0; + virtual bool test(bool flushCommandBuffer) = 0; + virtual bool hasError() const = 0; private: DISALLOW_COPY_AND_ASSIGN(FenceImpl); - - GLboolean mStatus; - GLenum mCondition; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp index 57239ef74f..5963534e03 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp @@ -18,531 +18,12 @@ Image::Image() { mWidth = 0; mHeight = 0; + mDepth = 0; mInternalFormat = GL_NONE; mActualFormat = GL_NONE; -} - -void Image::loadAlphaDataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadAlphaDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = static_cast<unsigned char*>(output) + y * outputPitch; - memcpy(dest, source, width); - } -} - -void Image::loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = static_cast<unsigned char*>(output) + y * outputPitch; - - if (!native) // BGRA8 destination format - { - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0xFF; - } - } - else // L8 destination format - { - memcpy(dest, source, width); - } - } -} - -void Image::loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 1.0f; - } - } -} - -void Image::loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[3 * x + 0] = source[x]; - dest[3 * x + 1] = source[x]; - dest[3 * x + 2] = source[x]; - } - } -} - -void Image::loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 - } - } -} - -void Image::loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = static_cast<unsigned char*>(output) + y * outputPitch; - - if (!native) // BGRA8 destination format - { - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } - else - { - memcpy(dest, source, width * 2); - } - } -} - -void Image::loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } -} - -void Image::loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } -} - -void Image::loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 2]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 0]; - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGB565DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); - dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGB565DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 1.0f; - } - } -} - -void Image::loadRGBFloatDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch); - memcpy(dest, source, width * 12); - } -} - -void Image::loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 - } - } -} - -void Image::loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - 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 * outputPitch); - - for (int x = 0; x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } -} - -void Image::loadRGBAUByteDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - 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 * outputPitch); - - memcpy(dest, source, width * 4); - } -} - -void Image::loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); - dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); - dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); - dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); - } - } -} - -void Image::loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); - dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); - dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); - dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); - } - } -} - -void Image::loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); - dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; - } - } -} - -void Image::loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = static_cast<unsigned char*>(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); - dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); - dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; - } - } -} - -void Image::loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch); - dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch); - memcpy(dest, source, width * 16); - } -} - -void Image::loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = static_cast<unsigned char*>(output) + y * outputPitch; - memcpy(dest, source, width * 8); - } -} - -void Image::loadBGRADataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = static_cast<unsigned char*>(output) + y * outputPitch; - memcpy(dest, source, width*4); - } + mTarget = GL_NONE; + mRenderable = false; + mDirty = false; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h index 454e83e21e..8fcffa4309 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h @@ -20,9 +20,8 @@ class Framebuffer; namespace rx { + class Renderer; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; class Image { @@ -32,93 +31,33 @@ class Image GLsizei getWidth() const { return mWidth; } GLsizei getHeight() const { return mHeight; } + GLsizei getDepth() const { return mDepth; } GLenum getInternalFormat() const { return mInternalFormat; } GLenum getActualFormat() const { return mActualFormat; } + GLenum getTarget() const { return mTarget; } + bool isRenderableFormat() const { return mRenderable; } void markDirty() {mDirty = true;} void markClean() {mDirty = false;} virtual bool isDirty() const = 0; - virtual void setManagedSurface(TextureStorageInterface2D *storage, int level) {}; - virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) {}; - virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - - virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) = 0; + virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0; - virtual bool isRenderableFormat() const = 0; - - virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) = 0; - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input) = 0; + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, const void *input) = 0; - virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - - static void loadAlphaDataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadAlphaDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native); - static void loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native); - static void loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGB565DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGB565DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBFloatDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAUByteDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadBGRADataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); + virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; protected: GLsizei mWidth; GLsizei mHeight; - GLint mInternalFormat; + GLsizei mDepth; + GLenum mInternalFormat; GLenum mActualFormat; + bool mRenderable; + GLenum mTarget; bool mDirty; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp deleted file mode 100644 index b2a90ca961..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "precompiled.h" -// -// 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. -// - -// ImageSSE2.cpp: Implements SSE2-based functions of rx::Image class. It's -// in a separated file for GCC, which can enable SSE usage only per-file, -// not for code blocks that use SSE2 explicitly. - -#include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/Image.h" - -namespace rx -{ - -void Image::loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - __m128i brMask = _mm_set1_epi32(0x00ff00ff); - - 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 * outputPitch); - 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::loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned int *dest = NULL; - __m128i zeroWide = _mm_setzero_si128(); - - for (int y = 0; y < height; y++) - { - source = static_cast<const unsigned char*>(input) + y * inputPitch; - dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch); - - int x; - // Make output writes aligned - for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++) - { - dest[x] = static_cast<unsigned int>(source[x]) << 24; - } - - for (; x + 7 < width; x += 8) - { - __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x])); - // Interleave each byte to 16bit, make the lower byte to zero - sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); - // Interleave each 16bit to 32bit, make the lower 16bit to zero - __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); - __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); - - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); - } - - // Handle the remainder - for (; x < width; x++) - { - dest[x] = static_cast<unsigned int>(source[x]) << 24; - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp index 51d7f0b653..e957d96270 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp @@ -9,8 +9,8 @@ // ranges of indices. #include "libGLESv2/renderer/IndexRangeCache.h" +#include "libGLESv2/formatutils.h" #include "common/debug.h" -#include "libGLESv2/utilities.h" #include <tuple> namespace rx @@ -31,7 +31,7 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) while (i != mIndexRangeCache.end()) { unsigned int rangeStart = i->second.streamOffset; - unsigned int rangeEnd = i->second.streamOffset + (gl::ComputeTypeSize(i->first.type) * i->first.count); + unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeBytes(i->first.type) * i->first.count); if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h index 56834306f2..837a44acd3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h @@ -11,6 +11,7 @@ #define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ #include "common/angleutils.h" +#include <map> namespace rx { @@ -55,4 +56,4 @@ class IndexRangeCache } -#endif LIBGLESV2_RENDERER_INDEXRANGECACHE_H +#endif // LIBGLESV2_RENDERER_INDEXRANGECACHE_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h index a874047b0c..a6750a204b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h @@ -24,6 +24,7 @@ class QueryImpl virtual void end() = 0; virtual GLuint getResult() = 0; virtual GLboolean isResultAvailable() = 0; + virtual bool isStarted() const = 0; GLenum getType() const { return mType; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h index 80de39f4f7..44637ec7de 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h @@ -11,6 +11,7 @@ #define LIBGLESV2_RENDERER_RENDERTARGET_H_ #include "common/angleutils.h" +#include "libGLESv2/angletypes.h" namespace rx { @@ -21,6 +22,7 @@ class RenderTarget { mWidth = 0; mHeight = 0; + mDepth = 0; mInternalFormat = GL_NONE; mActualFormat = GL_NONE; mSamples = 0; @@ -28,21 +30,27 @@ class RenderTarget virtual ~RenderTarget() {}; - GLsizei getWidth() { return mWidth; } - GLsizei getHeight() { return mHeight; } - GLenum getInternalFormat() { return mInternalFormat; } - GLenum getActualFormat() { return mActualFormat; } - GLsizei getSamples() { return mSamples; } - + GLsizei getWidth() const { return mWidth; } + GLsizei getHeight() const { return mHeight; } + GLsizei getDepth() const { return mDepth; } + GLenum getInternalFormat() const { return mInternalFormat; } + GLenum getActualFormat() const { return mActualFormat; } + GLsizei getSamples() const { return mSamples; } + gl::Extents getExtents() const { return gl::Extents(mWidth, mHeight, mDepth); } + + virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) = 0; + struct Desc { GLsizei width; GLsizei height; + GLsizei depth; GLenum format; }; protected: GLsizei mWidth; GLsizei mHeight; + GLsizei mDepth; GLenum mInternalFormat; GLenum mActualFormat; GLsizei mSamples; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp index 5278113811..590004ac9b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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,212 +11,77 @@ #include "libGLESv2/main.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" -#if defined(ANGLE_ENABLE_D3D9) -# include "libGLESv2/renderer/d3d9/Renderer9.h" -#endif -#if defined(ANGLE_ENABLE_D3D11) -# include "libGLESv2/renderer/d3d11/Renderer11.h" -#endif -#include "libGLESv2/utilities.h" +#include "common/utilities.h" #include "third_party/trace_event/trace_event.h" +#include "libGLESv2/Shader.h" -#ifndef D3DERR_OUTOFVIDEOMEMORY -#define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) -#endif - -#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) - -#ifndef D3DCOMPILER_DLL - -// Add define + typedefs for older MinGW-w64 headers (pre 5783) - -#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" - -HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, - const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, - const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); -typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename, - const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, - const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); - -#endif // D3DCOMPILER_DLL +#if defined (ANGLE_ENABLE_D3D9) +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#endif // ANGLE_ENABLE_D3D9 -#endif // __MINGW32__ || ANGLE_OS_WINPHONE +#if defined (ANGLE_ENABLE_D3D11) +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#endif // ANGLE_ENABLE_D3D11 -#ifndef QT_D3DCOMPILER_DLL -#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#if !defined(ANGLE_DEFAULT_D3D11) +// Enables use of the Direct3D 11 API for a default display, when available +#define ANGLE_DEFAULT_D3D11 0 #endif namespace rx { -Renderer::Renderer(egl::Display *display) : mDisplay(display) +Renderer::Renderer(egl::Display *display) + : mDisplay(display), + mCapsInitialized(false), + mCurrentClientVersion(2) { - mD3dCompilerModule = NULL; - mD3DCompileFunc = NULL; } Renderer::~Renderer() { - if (mD3dCompilerModule) - { - FreeLibrary(mD3dCompilerModule); - mD3dCompilerModule = NULL; - } + gl::Shader::releaseCompiler(); } -bool Renderer::initializeCompiler() +const gl::Caps &Renderer::getRendererCaps() const { - TRACE_EVENT0("gpu", "initializeCompiler"); -#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) - // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. - static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; - - for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) + if (!mCapsInitialized) { - if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule)) - { - break; - } + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; } -#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES - - // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL -#if !defined(ANGLE_OS_WINRT) - const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); - if (!defaultCompiler) - defaultCompiler = QT_D3DCOMPILER_DLL; -#else // !ANGLE_OS_WINRT -# ifdef _DEBUG - const wchar_t *defaultCompiler = L"d3dcompiler_qtd.dll"; -# else - const wchar_t *defaultCompiler = L"d3dcompiler_qt.dll"; -# endif -#endif // ANGLE_OS_WINRT - - const wchar_t *compilerDlls[] = { - defaultCompiler, - L"d3dcompiler_47.dll", - L"d3dcompiler_46.dll", - L"d3dcompiler_45.dll", - L"d3dcompiler_44.dll", - L"d3dcompiler_43.dll", - 0 - }; - // Load the first available known compiler DLL - for (int i = 0; compilerDlls[i]; ++i) - { - // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. - mD3dCompilerModule = LoadLibrary(compilerDlls[i]); - if (mD3dCompilerModule) - break; - } - - if (!mD3dCompilerModule) - { - ERR("No D3D compiler module found - aborting!\n"); - return false; - } - - mD3DCompileFunc = reinterpret_cast<pCompileFunc>(GetProcAddress(mD3dCompilerModule, "D3DCompile")); - ASSERT(mD3DCompileFunc); - - return mD3DCompileFunc != NULL; + return mCaps; } -// Compiles HLSL code into executable binaries -ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags) +const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const { - if (!hlsl) + if (!mCapsInitialized) { - return NULL; + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; } - HRESULT result = S_OK; - UINT flags = 0; - std::string sourceText; - if (gl::perfActive()) - { - flags |= D3DCOMPILE_DEBUG; - -#ifdef NDEBUG - flags |= optimizationFlags; -#else - flags |= D3DCOMPILE_SKIP_OPTIMIZATION; -#endif + return mTextureCaps; +} - 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 +const gl::Extensions &Renderer::getRendererExtensions() const +{ + if (!mCapsInitialized) { - flags |= optimizationFlags; - sourceText = hlsl; + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; } - // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. - // Try the default flags first and if compilation fails, try some alternatives. - const static UINT extraFlags[] = - { - 0, - D3DCOMPILE_AVOID_FLOW_CONTROL, - D3DCOMPILE_PREFER_FLOW_CONTROL - }; - - const static char * const extraFlagNames[] = - { - "default", - "avoid flow control", - "prefer flow control" - }; - - int attempts = alternateFlags ? ArraySize(extraFlags) : 1; - pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc); - for (int i = 0; i < attempts; ++i) - { - ID3DBlob *errorMessage = NULL; - ID3DBlob *binary = NULL; - - result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, - "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage); - if (errorMessage) - { - const char *message = (const char*)errorMessage->GetBufferPointer(); - - infoLog.appendSanitized(message); - TRACE("\n%s", hlsl); - TRACE("\n%s", message); - - errorMessage->Release(); - errorMessage = NULL; - } - - if (SUCCEEDED(result)) - { - return (ShaderBlob*)binary; - } - else - { - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*) NULL); - } + return mExtensions; +} - infoLog.append("Warning: D3D shader compilation failed with "); - infoLog.append(extraFlagNames[i]); - infoLog.append(" flags."); - if (i + 1 < attempts) - { - infoLog.append(" Retrying with "); - infoLog.append(extraFlagNames[i + 1]); - infoLog.append(".\n"); - } - } - } +typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, EGLint); - return NULL; +template <typename RendererType> +Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType) +{ + return new RendererType(display, nativeDisplay, requestedDisplayType); } } @@ -224,56 +89,64 @@ ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, co extern "C" { -rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId) +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType) { - rx::Renderer *renderer = NULL; - EGLint status = EGL_BAD_ALLOC; - -#if defined(ANGLE_OS_WINRT) - if (displayId == EGL_DEFAULT_DISPLAY) - displayId = EGL_D3D11_ONLY_DISPLAY_ANGLE; -#endif - -#if defined(ANGLE_ENABLE_D3D11) - if (displayId == EGL_DEFAULT_DISPLAY || - displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || - displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) - { - renderer = new rx::Renderer11(display); + std::vector<rx::CreateRendererFunction> rendererCreationFunctions; - if (renderer) +# if defined(ANGLE_ENABLE_D3D11) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE) { - status = renderer->initialize(); + rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>); } +# endif - if (status == EGL_SUCCESS) +# if defined(ANGLE_ENABLE_D3D9) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) { - return renderer; + rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>); } - else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) - { - return NULL; - } - - // Failed to create a D3D11 renderer, try creating a D3D9 renderer - delete renderer; - } -#endif // ANGLE_ENABLE_D3D11 +# endif -#if defined(ANGLE_ENABLE_D3D9) - bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); - renderer = new rx::Renderer9(display, displayId, softwareDevice); - - if (renderer) + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) { - status = renderer->initialize(); + // The default display is requested, try the D3D9 and D3D11 renderers, order them using + // the definition of ANGLE_DEFAULT_D3D11 +# if ANGLE_DEFAULT_D3D11 +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>); +# endif +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>); +# endif +# else +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>); +# endif +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>); +# endif +# endif } - if (status == EGL_SUCCESS) + for (size_t i = 0; i < rendererCreationFunctions.size(); i++) { - return renderer; + rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, requestedDisplayType); + if (renderer->initialize() == EGL_SUCCESS) + { + return renderer; + } + else + { + // Failed to create the renderer, try the next + SafeDelete(renderer); + } } -#endif // ANGLE_ENABLE_D3D9 return NULL; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h index 79578b2458..f1e0fd2d99 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -1,6 +1,5 @@ -#include "../precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // @@ -13,24 +12,15 @@ #include "libGLESv2/Uniform.h" #include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#include <d3dcompiler.h> +// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. +// It should only be used selectively to work around specific bugs. +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 #endif -const int versionWindowsVista = MAKEWORD(0x00, 0x06); -const int versionWindows7 = MAKEWORD(0x01, 0x06); - -// Return the version of the operating system in a format suitable for ordering -// comparison. -inline int getComparableOSVersion() -{ - DWORD version = GetVersion(); - int majorVersion = LOBYTE(LOWORD(version)); - int minorVersion = HIBYTE(LOWORD(version)); - return MAKEWORD(minorVersion, majorVersion); -} - namespace egl { class Display; @@ -40,31 +30,38 @@ namespace gl { class InfoLog; class ProgramBinary; -class VertexAttribute; +struct LinkedVarying; +struct VertexAttribute; class Buffer; class Texture; class Framebuffer; +struct VertexAttribCurrentValueData; } namespace rx { class TextureStorageInterface2D; class TextureStorageInterfaceCube; +class TextureStorageInterface3D; +class TextureStorageInterface2DArray; class VertexBuffer; class IndexBuffer; class QueryImpl; class FenceImpl; +class BufferImpl; +class VertexArrayImpl; class BufferStorage; -class Blit; struct TranslatedIndexData; class ShaderExecutable; class SwapChain; class RenderTarget; class Image; class TextureStorage; - -typedef void * ShaderBlob; -typedef void (*pCompileFunc)(); +class UniformStorage; +class Texture2DImpl; +class TextureCubeImpl; +class Texture3DImpl; +class Texture2DArrayImpl; struct ConfigDesc { @@ -72,6 +69,7 @@ struct ConfigDesc GLenum depthStencilFormat; GLint multiSample; bool fastConfig; + bool es3Capable; }; struct dx_VertexConstants @@ -94,12 +92,6 @@ enum ShaderType SHADER_GEOMETRY }; -enum D3DWorkaroundType -{ - ANGLE_D3D_WORKAROUND_NONE, - ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER -}; - class Renderer { public: @@ -116,11 +108,14 @@ class Renderer virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + virtual void generateSwizzle(gl::Texture *texture) = 0; virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; + virtual bool setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0; + virtual void setRasterizerState(const gl::RasterizerState &rasterState) = 0; - virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, unsigned int sampleMask) = 0; virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW) = 0; @@ -130,14 +125,18 @@ class Renderer bool ignoreViewport) = 0; virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0; - virtual void applyShaders(gl::ProgramBinary *programBinary) = 0; - virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) = 0; + virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) = 0; + virtual void applyUniforms(const gl::ProgramBinary &programBinary) = 0; virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) = 0; + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + GLint first, GLsizei count, GLsizei instances) = 0; virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; + virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) = 0; - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances) = 0; - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0; + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0; @@ -149,20 +148,15 @@ class Renderer virtual bool testDeviceLost(bool notify) = 0; virtual bool testDeviceResettable() = 0; - // Renderer capabilities + // Renderer capabilities (virtual because it is used by egl::Display, do not override) + virtual const gl::Caps &getRendererCaps() const; + virtual const gl::TextureCapsMap &getRendererTextureCaps() const; + virtual const gl::Extensions &getRendererExtensions() const; + virtual DWORD getAdapterVendor() const = 0; virtual std::string getRendererDescription() const = 0; virtual GUID getAdapterIdentifier() const = 0; - virtual bool getBGRATextureSupport() const = 0; - virtual bool getDXT1TextureSupport() = 0; - virtual bool getDXT3TextureSupport() = 0; - virtual bool getDXT5TextureSupport() = 0; - virtual bool getEventQuerySupport() = 0; - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable) = 0; - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable) = 0; - virtual bool getLuminanceTextureSupport() = 0; - virtual bool getLuminanceAlphaTextureSupport() = 0; bool getVertexTextureSupport() const { return getMaxVertexTextureImageUnits() > 0; } virtual unsigned int getMaxVertexTextureImageUnits() const = 0; virtual unsigned int getMaxCombinedTextureImageUnits() const = 0; @@ -171,80 +165,117 @@ class Renderer virtual unsigned int getMaxVertexUniformVectors() const = 0; virtual unsigned int getMaxFragmentUniformVectors() const = 0; virtual unsigned int getMaxVaryingVectors() const = 0; - virtual bool getNonPower2TextureSupport() const = 0; - virtual bool getDepthTextureSupport() const = 0; - virtual bool getOcclusionQuerySupport() const = 0; - virtual bool getInstancingSupport() const = 0; - virtual bool getTextureFilterAnisotropySupport() const = 0; - virtual float getTextureMaxAnisotropy() const = 0; + virtual unsigned int getMaxVertexShaderUniformBuffers() const = 0; + virtual unsigned int getMaxFragmentShaderUniformBuffers() const = 0; + virtual unsigned int getReservedVertexUniformBuffers() const = 0; + virtual unsigned int getReservedFragmentUniformBuffers() const = 0; + virtual unsigned int getMaxTransformFeedbackBuffers() const = 0; + virtual unsigned int getMaxTransformFeedbackSeparateComponents() const = 0; + virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const = 0; + virtual unsigned int getMaxUniformBufferSize() const = 0; virtual bool getShareHandleSupport() const = 0; - virtual bool getDerivativeInstructionSupport() const = 0; virtual bool getPostSubBufferSupport() const = 0; + virtual int getMaxRecommendedElementsIndices() const = 0; + virtual int getMaxRecommendedElementsVertices() const = 0; + virtual bool getSRGBTextureSupport() const = 0; virtual int getMajorShaderModel() const = 0; - virtual float getMaxPointSize() const = 0; - virtual int getMaxViewportDimension() const = 0; - virtual int getMaxTextureWidth() const = 0; - virtual int getMaxTextureHeight() const = 0; - virtual bool get32BitIndexSupport() const = 0; virtual int getMinSwapInterval() const = 0; virtual int getMaxSwapInterval() const = 0; virtual GLsizei getMaxSupportedSamples() const = 0; - - virtual unsigned int getMaxRenderTargets() const = 0; + virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const = 0; + virtual GLsizei getNumSampleCounts(GLenum internalFormat) const = 0; + virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const = 0; // Pixel operations virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) = 0; virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) = 0; + virtual bool copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) = 0; + virtual bool copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) = 0; virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) = 0; virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) = 0; + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) = 0; + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) = 0; virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil) = 0; - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0; + const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) = 0; + virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) = 0; // RenderTarget creation virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0; - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) = 0; + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0; // Shader operations - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0; - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) = 0; + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers) = 0; + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0; + virtual UniformStorage *createUniformStorage(size_t storageSize) = 0; // Image operations virtual Image *createImage() = 0; virtual void generateMipmap(Image *dest, Image *source) = 0; virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; - virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) = 0; - virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) = 0; + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0; + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0; + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + + // Texture creation + virtual Texture2DImpl *createTexture2D() = 0; + virtual TextureCubeImpl *createTextureCube() = 0; + virtual Texture3DImpl *createTexture3D() = 0; + virtual Texture2DArrayImpl *createTexture2DArray() = 0; // Buffer creation + virtual BufferImpl *createBuffer() = 0; virtual VertexBuffer *createVertexBuffer() = 0; virtual IndexBuffer *createIndexBuffer() = 0; - virtual BufferStorage *createBufferStorage() = 0; + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray() = 0; // Query and Fence creation virtual QueryImpl *createQuery(GLenum type) = 0; virtual FenceImpl *createFence() = 0; + // Current GLES client version + void setCurrentClientVersion(int clientVersion) { mCurrentClientVersion = clientVersion; } + int getCurrentClientVersion() const { return mCurrentClientVersion; } + + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; + virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; + virtual bool getLUID(LUID *adapterLuid) const = 0; + virtual GLenum getNativeTextureFormat(GLenum internalFormat) const = 0; + virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; + virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; protected: - bool initializeCompiler(); - ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags); - egl::Display *mDisplay; private: DISALLOW_COPY_AND_ASSIGN(Renderer); - HMODULE mD3dCompilerModule; - pCompileFunc mD3DCompileFunc; + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; + + mutable bool mCapsInitialized; + mutable gl::Caps mCaps; + mutable gl::TextureCapsMap mTextureCaps; + mutable gl::Extensions mExtensions; + + int mCurrentClientVersion; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h index 293e340845..054d00a712 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h @@ -11,6 +11,7 @@ #define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ #include "common/angleutils.h" +#include "common/debug.h" namespace rx { @@ -18,32 +19,44 @@ namespace rx class ShaderExecutable { public: - ShaderExecutable(const void *function, size_t length) : mLength(length) + ShaderExecutable(const void *function, size_t length) + : mFunctionBuffer(length) { - mFunction = new char[length]; - memcpy(mFunction, function, length); - } - - virtual ~ShaderExecutable() - { - delete[] mFunction; + memcpy(mFunctionBuffer.data(), function, length); } - void *getFunction() const + virtual ~ShaderExecutable() {} + + const uint8_t *getFunction() const { - return mFunction; + return mFunctionBuffer.data(); } size_t getLength() const { - return mLength; + return mFunctionBuffer.size(); } private: DISALLOW_COPY_AND_ASSIGN(ShaderExecutable); - void *mFunction; - const size_t mLength; + std::vector<uint8_t> mFunctionBuffer; +}; + +class UniformStorage +{ + public: + UniformStorage(size_t initialSize) + : mSize(initialSize) + { + } + + virtual ~UniformStorage() {} + + size_t size() const { return mSize; } + + private: + size_t mSize; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h index 8231fbcb25..77546f81e7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h @@ -1,4 +1,3 @@ -#include "../precompiled.h" // // 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 @@ -11,6 +10,7 @@ #ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_ #define LIBGLESV2_RENDERER_SWAPCHAIN_H_ +#include <EGL/eglplatform.h> #include "common/angleutils.h" #if !defined(ANGLE_FORCE_VSYNC_OFF) @@ -20,6 +20,14 @@ namespace rx { +enum SwapFlags +{ + SWAP_NORMAL = 0, + SWAP_ROTATE_90 = 1, + SWAP_ROTATE_270 = 2, + SWAP_ROTATE_180 = SWAP_ROTATE_90|SWAP_ROTATE_270, +}; + class SwapChain { public: @@ -32,13 +40,13 @@ class SwapChain virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0; virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0; - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) = 0; virtual void recreate() = 0; virtual HANDLE getShareHandle() {return mShareHandle;}; protected: - const EGLNativeWindowType mWindow; // Window that the surface is created for. + const EGLNativeWindowType mWindow; // Window that the surface is created for. const GLenum mBackBufferFormat; const GLenum mDepthBufferFormat; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h new file mode 100644 index 0000000000..35c9166023 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h @@ -0,0 +1,166 @@ +// +// Copyright 2014 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. +// + +// TextureImpl.h: Defines the abstract rx::TextureImpl classes. + +#ifndef LIBGLESV2_RENDERER_TEXTUREIMPL_H_ +#define LIBGLESV2_RENDERER_TEXTUREIMPL_H_ + +#include "common/angleutils.h" + +namespace egl +{ +class Surface; +} + +namespace gl +{ +class Framebuffer; +struct PixelUnpackState; +struct SamplerState; +} + +namespace rx +{ + +class Image; +class RenderTarget; +class Renderer; +class TextureStorageInterface; + +class Texture2DImpl +{ + public: + virtual ~Texture2DImpl() {} + + // TODO: If this methods could go away that would be ideal; + // TextureStorage should only be necessary for the D3D backend, and as such + // higher level code should not rely on it. + virtual TextureStorageInterface *getNativeTexture() = 0; + + virtual Image *getImage(int level) const = 0; + + virtual void setUsage(GLenum usage) = 0; + virtual bool hasDirtyImages() const = 0; + virtual void resetDirty() = 0; + + virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0; + virtual void bindTexImage(egl::Surface *surface) = 0; + virtual void releaseTexImage() = 0; + + virtual void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) = 0; + virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) = 0; + virtual void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) = 0; + virtual void generateMipmaps() = 0; + + virtual unsigned int getRenderTargetSerial(GLint level) = 0; + + virtual RenderTarget *getRenderTarget(GLint level) = 0; + virtual RenderTarget *getDepthSencil(GLint level) = 0; + + virtual void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) = 0; +}; + +class TextureCubeImpl +{ + public: + virtual ~TextureCubeImpl() {} + + virtual TextureStorageInterface *getNativeTexture() = 0; + + virtual Image *getImage(GLenum target, int level) const = 0; + + virtual void setUsage(GLenum usage) = 0; + virtual bool hasDirtyImages() const = 0; + virtual void resetDirty() = 0; + + virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0; + virtual bool isCubeComplete() const = 0; + + virtual void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) = 0; + virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) = 0; + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual void storage(GLsizei levels, GLenum internalformat, GLsizei size) = 0; + virtual void generateMipmaps() = 0; + + virtual unsigned int getRenderTargetSerial(GLenum target, GLint level) = 0; + + virtual RenderTarget *getRenderTarget(GLenum target, GLint level) = 0; + virtual RenderTarget *getDepthStencil(GLenum target, GLint level) = 0; +}; + +class Texture3DImpl +{ + public: + virtual ~Texture3DImpl() {} + + virtual TextureStorageInterface *getNativeTexture() = 0; + + virtual Image *getImage(int level) const = 0; + + virtual void setUsage(GLenum usage) = 0; + virtual bool hasDirtyImages() const = 0; + virtual void resetDirty() = 0; + + virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0; + virtual bool isMipmapComplete() const = 0; + + virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0; + virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0; + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; + virtual void generateMipmaps() = 0; + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) = 0; + + virtual RenderTarget *getRenderTarget(GLint level) = 0; + virtual RenderTarget *getRenderTarget(GLint level, GLint layer) = 0; + virtual RenderTarget *getDepthStencil(GLint level, GLint layer) = 0; +}; + +class Texture2DArrayImpl +{ + public: + virtual ~Texture2DArrayImpl() {} + + virtual TextureStorageInterface *getNativeTexture() = 0; + + virtual Image *getImage(int level, int layer) const = 0; + virtual GLsizei getLayerCount(int level) const = 0; + + virtual void setUsage(GLenum usage) = 0; + virtual bool hasDirtyImages() const = 0; + virtual void resetDirty() = 0; + + virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0; + virtual bool isMipmapComplete() const = 0; + + virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0; + virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0; + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; + virtual void generateMipmaps() = 0; + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) = 0; + + virtual RenderTarget *getRenderTarget(GLint level, GLint layer) = 0; + virtual RenderTarget *getDepthStencil(GLint level, GLint layer) = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp deleted file mode 100644 index 00b316f1cc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "precompiled.h" -// -// 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. -// - -// TextureStorage.cpp: Implements the abstract rx::TextureStorageInterface class and its concrete derived -// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the -// GPU-side texture. - -#include "libGLESv2/renderer/TextureStorage.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" - -#include "common/debug.h" - -namespace rx -{ -unsigned int TextureStorageInterface::mCurrentTextureSerial = 1; - -TextureStorageInterface::TextureStorageInterface() - : mTextureSerial(issueTextureSerial()), - mInstance(NULL) -{ -} - -TextureStorageInterface::~TextureStorageInterface() -{ - delete mInstance; -} - -bool TextureStorageInterface::isRenderTarget() const -{ - return mInstance->isRenderTarget(); -} - - -bool TextureStorageInterface::isManaged() const -{ - return mInstance->isManaged(); -} - -unsigned int TextureStorageInterface::getTextureSerial() const -{ - return mTextureSerial; -} - -unsigned int TextureStorageInterface::issueTextureSerial() -{ - return mCurrentTextureSerial++; -} - -int TextureStorageInterface::getLodOffset() const -{ - return mInstance->getLodOffset(); -} - - -int TextureStorageInterface::levelCount() -{ - return mInstance->levelCount(); -} - -TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain) - : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial()) -{ - mInstance = renderer->createTextureStorage2D(swapchain); -} - -TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) - : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial()) -{ - mInstance = renderer->createTextureStorage2D(levels, internalformat, usage, forceRenderable, width, height); -} - -TextureStorageInterface2D::~TextureStorageInterface2D() -{ -} - -RenderTarget *TextureStorageInterface2D::getRenderTarget() const -{ - return mInstance->getRenderTarget(); -} - -void TextureStorageInterface2D::generateMipmap(int level) -{ - mInstance->generateMipmap(level); -} - -unsigned int TextureStorageInterface2D::getRenderTargetSerial(GLenum target) const -{ - return mRenderTargetSerial; -} - -TextureStorageInterfaceCube::TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) - : mFirstRenderTargetSerial(gl::RenderbufferStorage::issueCubeSerials()) -{ - mInstance = renderer->createTextureStorageCube(levels, internalformat, usage, forceRenderable, size); -} - -TextureStorageInterfaceCube::~TextureStorageInterfaceCube() -{ -} - -RenderTarget *TextureStorageInterfaceCube::getRenderTarget(GLenum faceTarget) const -{ - return mInstance->getRenderTarget(faceTarget); -} - -void TextureStorageInterfaceCube::generateMipmap(int face, int level) -{ - mInstance->generateMipmap(face, level); -} - -unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target) const -{ - return mFirstRenderTargetSerial + gl::TextureCubeMap::faceIndex(target); -} - -}
\ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h deleted file mode 100644 index edddb75f3f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// 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. -// - -// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived -// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the -// GPU-side texture. - -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ - -#include "common/debug.h" - -namespace rx -{ -class Renderer; -class SwapChain; -class RenderTarget; -class Blit; - -class TextureStorage -{ - public: - TextureStorage() {}; - virtual ~TextureStorage() {}; - - virtual int getLodOffset() const = 0; - virtual bool isRenderTarget() const = 0; - virtual bool isManaged() const = 0; - virtual int levelCount() = 0; - - virtual RenderTarget *getRenderTarget() = 0; - virtual RenderTarget *getRenderTarget(GLenum faceTarget) = 0; - virtual void generateMipmap(int level) = 0; - virtual void generateMipmap(int face, int level) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage); - -}; - -class TextureStorageInterface -{ - public: - TextureStorageInterface(); - virtual ~TextureStorageInterface(); - - TextureStorage *getStorageInstance() { return mInstance; } - - unsigned int getTextureSerial() const; - virtual unsigned int getRenderTargetSerial(GLenum target) const = 0; - - virtual int getLodOffset() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int levelCount(); - - protected: - TextureStorage *mInstance; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface); - - const unsigned int mTextureSerial; - static unsigned int issueTextureSerial(); - - static unsigned int mCurrentTextureSerial; -}; - -class TextureStorageInterface2D : public TextureStorageInterface -{ - public: - TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain); - TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual ~TextureStorageInterface2D(); - - void generateMipmap(int level); - RenderTarget *getRenderTarget() const; - - virtual unsigned int getRenderTargetSerial(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2D); - - const unsigned int mRenderTargetSerial; -}; - -class TextureStorageInterfaceCube : public TextureStorageInterface -{ - public: - TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - virtual ~TextureStorageInterfaceCube(); - - void generateMipmap(int face, int level); - RenderTarget *getRenderTarget(GLenum faceTarget) const; - - virtual unsigned int getRenderTargetSerial(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterfaceCube); - - const unsigned int mFirstRenderTargetSerial; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ - diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h new file mode 100644 index 0000000000..b013f9cdf4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h @@ -0,0 +1,32 @@ +// +// Copyright 2014 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. +// + +// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ + +#include "common/angleutils.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/VertexAttribute.h" + +namespace rx +{ + +class VertexArrayImpl +{ + public: + virtual ~VertexArrayImpl() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) = 0; + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) = 0; + virtual void setAttributeDivisor(size_t idx, GLuint divisor) = 0; + virtual void enableAttribute(size_t idx, bool enabledState) = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp new file mode 100644 index 0000000000..765089cc96 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp @@ -0,0 +1,23 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 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. +// + +// copyimage.cpp: Defines image copying functions + +#include "libGLESv2/renderer/copyImage.h" + +namespace rx +{ + +void CopyBGRAUByteToRGBAUByte(const void *source, void *dest) +{ + unsigned int argb = *(unsigned int*)source; + *(unsigned int*)dest = (argb & 0xFF00FF00) | // Keep alpha and green + (argb & 0x00FF0000) >> 16 | // Move red to blue + (argb & 0x000000FF) << 16; // Move blue to red +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h new file mode 100644 index 0000000000..9b94404ee3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2013 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. +// + +// copyimage.h: Defines image copying functions + +#ifndef LIBGLESV2_RENDERER_COPYIMAGE_H_ +#define LIBGLESV2_RENDERER_COPYIMAGE_H_ + +#include "common/mathutil.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ + +template <typename sourceType, typename colorDataType> +void ReadColor(const void *source, void *dest) +{ + sourceType::readColor(reinterpret_cast<gl::Color<colorDataType>*>(dest), reinterpret_cast<const sourceType*>(source)); +} + +template <typename destType, typename colorDataType> +void WriteColor(const void *source, void *dest) +{ + destType::writeColor(reinterpret_cast<destType*>(dest), reinterpret_cast<const gl::Color<colorDataType>*>(source)); +} + +template <typename sourceType, typename destType, typename colorDataType> +void CopyPixel(const void *source, void *dest) +{ + colorDataType temp; + ReadColor<sourceType, colorDataType>(source, &temp); + WriteColor<destType, colorDataType>(&temp, dest); +} + +void CopyBGRAUByteToRGBAUByte(const void *source, void *dest); + +} + +#endif // LIBGLESV2_RENDERER_COPYIMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h new file mode 100644 index 0000000000..aca031701e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h @@ -0,0 +1,309 @@ +// +// Copyright (c) 2013 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. +// + +// copyvertex.h: Defines vertex buffer copying and conversion functions + +#ifndef LIBGLESV2_RENDERER_COPYVERTEX_H_ +#define LIBGLESV2_RENDERER_COPYVERTEX_H_ + +#include "common/mathutil.h" + +// 'widenDefaultValueBits' gives the default value for the alpha channel (4th component) +// the sentinel value 0 means we do not want to widen the input or add an alpha channel +template <typename T, unsigned int componentCount, unsigned int widenDefaultValueBits> +inline void copyVertexData(const void *input, size_t stride, size_t count, void *output) +{ + const unsigned int attribSize = sizeof(T) * componentCount; + const T defaultValue = gl::bitCast<T>(widenDefaultValueBits); + const bool widen = (widenDefaultValueBits != 0); + + if (attribSize == stride && !widen) + { + memcpy(output, input, count * attribSize); + } + else + { + unsigned int outputStride = widen ? 4 : componentCount; + + for (unsigned int i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + i * stride); + T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride; + + for (unsigned int j = 0; j < componentCount; j++) + { + offsetOutput[j] = offsetInput[j]; + } + + if (widen) + { + offsetOutput[3] = defaultValue; + } + } + } +} + +template <unsigned int componentCount> +inline void copyFixedVertexData(const void* input, size_t stride, size_t count, void* output) +{ + static const float divisor = 1.0f / (1 << 16); + + for (unsigned int i = 0; i < count; i++) + { + const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(reinterpret_cast<const char*>(input) + stride * i); + float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount; + + for (unsigned int j = 0; j < componentCount; j++) + { + offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor; + } + } +} + +template <typename T, unsigned int componentCount, bool normalized> +inline void copyToFloatVertexData(const void* input, size_t stride, size_t count, void* output) +{ + typedef std::numeric_limits<T> NL; + + for (unsigned int i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + stride * i); + float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount; + + for (unsigned int j = 0; j < componentCount; j++) + { + if (normalized) + { + if (NL::is_signed) + { + const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1); + offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor; + } + else + { + offsetOutput[j] = static_cast<float>(offsetInput[j]) / NL::max(); + } + } + else + { + offsetOutput[j] = static_cast<float>(offsetInput[j]); + } + } + } +} + +inline void copyPackedUnsignedVertexData(const void* input, size_t stride, size_t count, void* output) +{ + const unsigned int attribSize = 4; + + if (attribSize == stride) + { + memcpy(output, input, count * attribSize); + } + else + { + for (unsigned int i = 0; i < count; i++) + { + const GLuint *offsetInput = reinterpret_cast<const GLuint*>(reinterpret_cast<const char*>(input) + (i * stride)); + GLuint *offsetOutput = reinterpret_cast<GLuint*>(output) + (i * attribSize); + + offsetOutput[i] = offsetInput[i]; + } + } +} + +template <bool isSigned, bool normalized, bool toFloat> +static inline void copyPackedRGB(unsigned int data, void *output) +{ + const unsigned int rgbSignMask = 0x200; // 1 set at the 9 bit + const unsigned int negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1 + + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output); + if (isSigned) + { + GLfloat finalValue = 0; + if (data & rgbSignMask) + { + int negativeNumber = data | negativeMask; + finalValue = static_cast<GLfloat>(negativeNumber); + } + else + { + finalValue = static_cast<GLfloat>(data); + } + + if (normalized) + { + const int maxValue = 0x1FF; // 1 set in bits 0 through 8 + const int minValue = 0xFFFFFE01; // Inverse of maxValue + + // A 10-bit two's complement number has the possibility of being minValue - 1 but + // OpenGL's normalization rules dictate that it should be clamped to minValue in this + // case. + if (finalValue < minValue) + { + finalValue = minValue; + } + + const int halfRange = (maxValue - minValue) >> 1; + *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; + } + else + { + *floatOutput = finalValue; + } + } + else + { + if (normalized) + { + const unsigned int maxValue = 0x3FF; // 1 set in bits 0 through 9 + *floatOutput = static_cast<GLfloat>(data) / static_cast<GLfloat>(maxValue); + } + else + { + *floatOutput = static_cast<GLfloat>(data); + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast<GLshort*>(output); + + if (data & rgbSignMask) + { + *intOutput = data | negativeMask; + } + else + { + *intOutput = data; + } + } + else + { + GLushort *uintOutput = reinterpret_cast<GLushort*>(output); + *uintOutput = data; + } + } +} + +template <bool isSigned, bool normalized, bool toFloat> +inline void copyPackedAlpha(unsigned int data, void *output) +{ + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output); + if (isSigned) + { + if (normalized) + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = -1.0f; break; + case 0x3: *floatOutput = -1.0f; break; + default: UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = -2.0f; break; + case 0x3: *floatOutput = -1.0f; break; + default: UNREACHABLE(); + } + } + } + else + { + if (normalized) + { + switch (data) + { + case 0x0: *floatOutput = 0.0f / 3.0f; break; + case 0x1: *floatOutput = 1.0f / 3.0f; break; + case 0x2: *floatOutput = 2.0f / 3.0f; break; + case 0x3: *floatOutput = 3.0f / 3.0f; break; + default: UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = 2.0f; break; + case 0x3: *floatOutput = 3.0f; break; + default: UNREACHABLE(); + } + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast<GLshort*>(output); + switch (data) + { + case 0x0: *intOutput = 0; break; + case 0x1: *intOutput = 1; break; + case 0x2: *intOutput = -2; break; + case 0x3: *intOutput = -1; break; + default: UNREACHABLE(); + } + } + else + { + GLushort *uintOutput = reinterpret_cast<GLushort*>(output); + switch (data) + { + case 0x0: *uintOutput = 0; break; + case 0x1: *uintOutput = 1; break; + case 0x2: *uintOutput = 2; break; + case 0x3: *uintOutput = 3; break; + default: UNREACHABLE(); + } + } + } +} + +template <bool isSigned, bool normalized, bool toFloat> +inline void copyPackedVertexData(const void* input, size_t stride, size_t count, void* output) +{ + const unsigned int outputComponentSize = toFloat ? 4 : 2; + const unsigned int componentCount = 4; + + const unsigned int rgbMask = 0x3FF; // 1 set in bits 0 through 9 + const unsigned int redShift = 0; // red is bits 0 through 9 + const unsigned int greenShift = 10; // green is bits 10 through 19 + const unsigned int blueShift = 20; // blue is bits 20 through 29 + + const unsigned int alphaMask = 0x3; // 1 set in bits 0 and 1 + const unsigned int alphaShift = 30; // Alpha is the 30 and 31 bits + + for (unsigned int i = 0; i < count; i++) + { + GLuint packedValue = *reinterpret_cast<const GLuint*>(reinterpret_cast<const char*>(input) + (i * stride)); + GLbyte *offsetOutput = reinterpret_cast<GLbyte*>(output) + (i * outputComponentSize * componentCount); + + copyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); + copyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); + copyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); + copyPackedAlpha<isSigned, normalized, toFloat>((packedValue >> alphaShift) & alphaMask, offsetOutput + (3* outputComponentSize)); + } +} + +#endif // LIBGLESV2_RENDERER_COPYVERTEX_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp new file mode 100644 index 0000000000..08457af76d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp @@ -0,0 +1,83 @@ +#include "precompiled.h" +// +// Copyright 2014 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. +// + +// BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes. + +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/VertexBuffer.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +unsigned int BufferD3D::mNextSerial = 1; + +BufferD3D::BufferD3D() + : BufferImpl(), + mStaticVertexBuffer(NULL), + mStaticIndexBuffer(NULL) +{ + updateSerial(); +} + +BufferD3D::~BufferD3D() +{ + SafeDelete(mStaticVertexBuffer); + SafeDelete(mStaticIndexBuffer); +} + +BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(BufferD3D*, buffer)); + return static_cast<BufferD3D*>(buffer); +} + +void BufferD3D::updateSerial() +{ + mSerial = mNextSerial++; +} + +void BufferD3D::initializeStaticData() +{ + if (!mStaticVertexBuffer) + { + mStaticVertexBuffer = new rx::StaticVertexBufferInterface(getRenderer()); + } + if (!mStaticIndexBuffer) + { + mStaticIndexBuffer = new rx::StaticIndexBufferInterface(getRenderer()); + } +} + +void BufferD3D::invalidateStaticData() +{ + if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) + { + SafeDelete(mStaticVertexBuffer); + SafeDelete(mStaticIndexBuffer); + } + + mUnmodifiedDataUse = 0; +} + +// Creates static buffers if sufficient used data has been left unmodified +void BufferD3D::promoteStaticUsage(int dataSize) +{ + if (!mStaticVertexBuffer && !mStaticIndexBuffer) + { + mUnmodifiedDataUse += dataSize; + + if (mUnmodifiedDataUse > 3 * getSize()) + { + initializeStaticData(); + } + } +} + +}
\ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h new file mode 100644 index 0000000000..8e204b9139 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h @@ -0,0 +1,60 @@ +// +// Copyright 2014 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. +// + +// BufferImpl.h: Defines the abstract rx::BufferImpl class. + +#ifndef LIBGLESV2_RENDERER_BUFFERD3D_H_ +#define LIBGLESV2_RENDERER_BUFFERD3D_H_ + +#include "libGLESv2/renderer/BufferImpl.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/renderer/IndexRangeCache.h" + +namespace rx +{ + +class Renderer; +class StaticIndexBufferInterface; +class StaticVertexBufferInterface; + +class BufferD3D : public BufferImpl +{ + public: + BufferD3D(); + virtual ~BufferD3D(); + + static BufferD3D *makeBufferD3D(BufferImpl *buffer); + + unsigned int getSerial() const { return mSerial; } + + virtual size_t getSize() const = 0; + virtual void clear() = 0; + virtual bool supportsDirectBinding() const = 0; + virtual Renderer* getRenderer() = 0; + + rx::StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } + rx::StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } + rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } + + void initializeStaticData(); + void invalidateStaticData(); + void promoteStaticUsage(int dataSize); + + protected: + unsigned int mSerial; + static unsigned int mNextSerial; + + void updateSerial(); + + rx::StaticVertexBufferInterface *mStaticVertexBuffer; + rx::StaticIndexBufferInterface *mStaticIndexBuffer; + rx::IndexRangeCache mIndexRangeCache; + unsigned int mUnmodifiedDataUse; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERIMPLD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp new file mode 100644 index 0000000000..e3b88d506d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp @@ -0,0 +1,171 @@ +#include "precompiled.h" +#include "libGLESv2/renderer/d3d/HLSLCompiler.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/main.h" + +#include "common/utilities.h" +#include "common/platform.h" + +#include "third_party/trace_event/trace_event.h" + +#include <d3dcompiler.h> + +#if defined(__MINGW32__) && !defined(D3DCOMPILER_DLL) + +// Add define + typedefs for older MinGW-w64 headers (pre 5783) + +#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" + +HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, + const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, + const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); +typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename, + const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, + const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); + +#endif // __MINGW32__ && !D3DCOMPILER_DLL + +#ifndef QT_D3DCOMPILER_DLL +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#endif + +#ifndef LoadLibrary +#define LoadLibrary(dll) LoadPackagedLibrary(dll, NULL) +#endif + +namespace rx +{ + +HLSLCompiler::HLSLCompiler() + : mD3DCompilerModule(NULL), + mD3DCompileFunc(NULL) +{ +} + +HLSLCompiler::~HLSLCompiler() +{ + release(); +} + +bool HLSLCompiler::initialize() +{ + TRACE_EVENT0("gpu", "initializeCompiler"); +#if !defined(ANGLE_PLATFORM_WINRT) +#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) + // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. + static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; + + for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) + { + if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule)) + { + break; + } + } +#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + + // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL + const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); + if (!defaultCompiler) + defaultCompiler = QT_D3DCOMPILER_DLL; + + const wchar_t *compilerDlls[] = { + defaultCompiler, + L"d3dcompiler_47.dll", + L"d3dcompiler_46.dll", + L"d3dcompiler_45.dll", + L"d3dcompiler_44.dll", + L"d3dcompiler_43.dll", + 0 + }; + + // Load the first available known compiler DLL + for (int i = 0; compilerDlls[i]; ++i) + { + mD3DCompilerModule = LoadLibrary(compilerDlls[i]); + if (mD3DCompilerModule) + break; + } + + if (!mD3DCompilerModule) + { + ERR("No D3D compiler module found - aborting!\n"); + return false; + } + + mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(GetProcAddress(mD3DCompilerModule, "D3DCompile")); + ASSERT(mD3DCompileFunc); +#else + mD3DCompileFunc = reinterpret_cast<CompileFuncPtr>(&D3DCompile); +#endif + return mD3DCompileFunc != NULL; +} + +void HLSLCompiler::release() +{ + if (mD3DCompilerModule) + { + FreeLibrary(mD3DCompilerModule); + mD3DCompilerModule = NULL; + mD3DCompileFunc = NULL; + } +} + +ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, + const UINT optimizationFlags[], const char *flagNames[], int attempts) const +{ +#if !defined(ANGLE_PLATFORM_WINRT) + ASSERT(mD3DCompilerModule && mD3DCompileFunc); +#endif + + if (!hlsl) + { + return NULL; + } + + pD3DCompile compileFunc = reinterpret_cast<pD3DCompile>(mD3DCompileFunc); + for (int i = 0; i < attempts; ++i) + { + ID3DBlob *errorMessage = NULL; + ID3DBlob *binary = NULL; + + HRESULT result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, "main", profile, optimizationFlags[i], 0, &binary, &errorMessage); + + if (errorMessage) + { + const char *message = (const char*)errorMessage->GetBufferPointer(); + + infoLog.appendSanitized(message); + TRACE("\n%s", hlsl); + TRACE("\n%s", message); + + SafeRelease(errorMessage); + } + + if (SUCCEEDED(result)) + { + return (ShaderBlob*)binary; + } + else + { + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL); + } + + infoLog.append("Warning: D3D shader compilation failed with "); + infoLog.append(flagNames[i]); + infoLog.append(" flags."); + if (i + 1 < attempts) + { + infoLog.append(" Retrying with "); + infoLog.append(flagNames[i + 1]); + infoLog.append(".\n"); + } + } + } + + return NULL; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h new file mode 100644 index 0000000000..0ce9e44be5 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h @@ -0,0 +1,38 @@ +#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ +#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ + +#include "common/angleutils.h" + +namespace gl +{ +class InfoLog; +} + +namespace rx +{ + +typedef void* ShaderBlob; +typedef void(*CompileFuncPtr)(); + +class HLSLCompiler +{ + public: + HLSLCompiler(); + ~HLSLCompiler(); + + bool initialize(); + void release(); + + ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, + const UINT optimizationFlags[], const char *flagNames[], int attempts) const; + + private: + DISALLOW_COPY_AND_ASSIGN(HLSLCompiler); + + HMODULE mD3DCompilerModule; + CompileFuncPtr mD3DCompileFunc; +}; + +} + +#endif // LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp new file mode 100644 index 0000000000..615d11a1f1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp @@ -0,0 +1,27 @@ +#include "precompiled.h" +// +// 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. +// + +// Image.h: Implements the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#include "libGLESv2/renderer/d3d/ImageD3D.h" + +namespace rx +{ + +ImageD3D::ImageD3D() +{ +} + +ImageD3D *ImageD3D::makeImageD3D(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::ImageD3D*, img)); + return static_cast<rx::ImageD3D*>(img); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h new file mode 100644 index 0000000000..242ce5af70 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h @@ -0,0 +1,54 @@ +// +// 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. +// + +// Image.h: Defines the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#ifndef LIBGLESV2_RENDERER_IMAGED3D_H_ +#define LIBGLESV2_RENDERER_IMAGED3D_H_ + +#include "common/debug.h" +#include "libGLESv2/renderer/Image.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class TextureStorageInterface3D; +class TextureStorageInterface2DArray; + +class ImageD3D : public Image +{ + public: + ImageD3D(); + virtual ~ImageD3D() {}; + + static ImageD3D *makeImageD3D(Image *img); + + virtual bool isDirty() const = 0; + + virtual void setManagedSurface(TextureStorageInterface2D *storage, int level) {}; + virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) {}; + virtual void setManagedSurface(TextureStorageInterface3D *storage, int level) {}; + virtual void setManagedSurface(TextureStorageInterface2DArray *storage, int layer, int level) {}; + virtual bool copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + virtual bool copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + virtual bool copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0; + virtual bool copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(ImageD3D); +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp index 37dbd3e195..13e35e09ec 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp @@ -8,7 +8,7 @@ // IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface // class with derivations, classes that perform graphics API agnostic index buffer operations. -#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" #include "libGLESv2/renderer/Renderer.h" namespace rx @@ -194,4 +194,3 @@ IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache() } } - diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h index 6fb885a1cd..6fb885a1cd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp index 49bace8193..932524c132 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp @@ -8,13 +8,13 @@ // IndexDataManager.cpp: Defines the IndexDataManager, a class that // runs the Buffer translation process for index buffers. -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" namespace rx { @@ -118,7 +118,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer unsigned int offset = 0; bool alignedOffset = false; - BufferStorage *storage = NULL; + BufferD3D *storage = NULL; if (buffer != NULL) { @@ -128,7 +128,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer } offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices)); - storage = buffer->getStorage(); + storage = BufferD3D::makeBufferD3D(buffer->getImplementation()); switch (type) { @@ -138,7 +138,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer default: UNREACHABLE(); alignedOffset = false; } - unsigned int typeSize = gl::ComputeTypeSize(type); + unsigned int typeSize = gl::GetTypeBytes(type); // check for integer overflows if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeSize) || @@ -157,7 +157,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; - StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL; + StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; IndexBufferInterface *indexBuffer = streamingBuffer; bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && destinationIndexType == type; @@ -167,23 +167,23 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer { indexBuffer = streamingBuffer; streamOffset = offset; - storage->markBufferUsage(); - if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, + if (!storage->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, &translated->maxIndex, NULL)) { computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + storage->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, translated->maxIndex, offset); } } else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) { indexBuffer = staticBuffer; + if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, &translated->maxIndex, &streamOffset)) { - streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType); + streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, translated->maxIndex, streamOffset); @@ -198,11 +198,11 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer if (staticBuffer->getBufferSize() == 0 && alignedOffset) { indexBuffer = staticBuffer; - convertCount = storage->getSize() / gl::ComputeTypeSize(type); + convertCount = storage->getSize() / gl::GetTypeBytes(type); } else { - buffer->invalidateStaticData(); + storage->invalidateStaticData(); staticBuffer = NULL; } } @@ -213,7 +213,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer return GL_INVALID_OPERATION; } - unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType); + unsigned int indexTypeSize = gl::GetTypeBytes(destinationIndexType); if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize) { ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize); @@ -246,7 +246,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer if (staticBuffer) { - streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType); + streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, translated->maxIndex, streamOffset); } @@ -255,12 +255,12 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer translated->storage = directStorage ? storage : NULL; translated->indexBuffer = indexBuffer->getIndexBuffer(); translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType); + translated->startIndex = streamOffset / gl::GetTypeBytes(destinationIndexType); translated->startOffset = streamOffset; - if (buffer) + if (storage) { - buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type)); + storage->promoteStaticUsage(count * gl::GetTypeBytes(type)); } return GL_NO_ERROR; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h index 0e77c81d1b..8f981936ea 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h @@ -27,7 +27,7 @@ namespace rx class StaticIndexBufferInterface; class StreamingIndexBufferInterface; class IndexBuffer; -class BufferStorage; +class BufferD3D; class Renderer; struct TranslatedIndexData @@ -38,7 +38,7 @@ struct TranslatedIndexData unsigned int startOffset; // In bytes IndexBuffer *indexBuffer; - BufferStorage *storage; + BufferD3D *storage; unsigned int serial; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp new file mode 100644 index 0000000000..301bbe8d3d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2014 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. +// + +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" + +#include <algorithm> +#include <cstdlib> + +namespace rx +{ + +MemoryBuffer::MemoryBuffer() + : mSize(0), + mData(NULL) +{ +} + +MemoryBuffer::~MemoryBuffer() +{ + free(mData); + mData = NULL; +} + +bool MemoryBuffer::resize(size_t size) +{ + if (size == 0) + { + free(mData); + mData = NULL; + mSize = 0; + } + else + { + uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size)); + if (newMemory == NULL) + { + return false; + } + + if (mData) + { + // Copy the intersection of the old data and the new data + std::copy(mData, mData + std::min(mSize, size), newMemory); + free(mData); + } + + mData = newMemory; + mSize = size; + } + + return true; +} + +size_t MemoryBuffer::size() const +{ + return mSize; +} + +const uint8_t *MemoryBuffer::data() const +{ + return mData; +} + +uint8_t *MemoryBuffer::data() +{ + return mData; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h new file mode 100644 index 0000000000..2484c07455 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2014 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. +// + +#ifndef LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ +#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ + +#include <cstddef> +#include <cstdint> + +namespace rx +{ + +class MemoryBuffer +{ + public: + MemoryBuffer(); + ~MemoryBuffer(); + + bool resize(size_t size); + size_t size() const; + + const uint8_t *data() const; + uint8_t *data(); + + private: + size_t mSize; + uint8_t *mData; +}; + +} + +#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp new file mode 100644 index 0000000000..e725e2fefe --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp @@ -0,0 +1,2550 @@ +#include "precompiled.h" +// +// Copyright 2014 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. +// + +// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#include "common/mathutil.h" +#include "common/utilities.h" +#include "libEGL/Surface.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/main.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/renderer/BufferImpl.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/ImageD3D.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" + +namespace rx +{ + +bool IsMipmapFiltered(const gl::SamplerState &samplerState) +{ + switch (samplerState.minFilter) + { + case GL_NEAREST: + case GL_LINEAR: + return false; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return true; + default: UNREACHABLE(); + return false; + } +} + +bool IsRenderTargetUsage(GLenum usage) +{ + return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); +} + +TextureD3D::TextureD3D(Renderer *renderer) + : mRenderer(renderer), + mUsage(GL_NONE), + mDirtyImages(true), + mImmutable(false) +{ +} + +TextureD3D::~TextureD3D() +{ +} + +GLint TextureD3D::getBaseLevelWidth() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getWidth() : 0); +} + +GLint TextureD3D::getBaseLevelHeight() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getHeight() : 0); +} + +GLint TextureD3D::getBaseLevelDepth() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getDepth() : 0); +} + +// Note: "base level image" is loosely defined to be any image from the base level, +// where in the base of 2D array textures and cube maps there are several. Don't use +// the base level image for anything except querying texture format and size. +GLenum TextureD3D::getBaseLevelInternalFormat() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getInternalFormat() : GL_NONE); +} + +void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image) +{ + // No-op + if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) + { + return; + } + + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. + // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. + const void *pixelData = pixels; + + if (unpack.pixelBuffer.id() != 0) + { + // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels); + // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data. + // This functionality should be moved into renderer and the getData method of BufferImpl removed. + const void *bufferData = pixelBuffer->getImplementation()->getData(); + pixelData = static_cast<const unsigned char *>(bufferData) + offset; + } + + if (pixelData != NULL) + { + image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData); + mDirtyImages = true; + } +} + +bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, Image *image) +{ + const void *pixelData = pixels; + + // CPU readback & copy where direct GPU copy is not supported + if (unpack.pixelBuffer.id() != 0) + { + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + unsigned int offset = reinterpret_cast<unsigned int>(pixels); + // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data. + // This functionality should be moved into renderer and the getData method of BufferImpl removed. + const void *bufferData = pixelBuffer->getImplementation()->getData(); + pixelData = static_cast<const unsigned char *>(bufferData) + offset; + } + + if (pixelData != NULL) + { + image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData); + mDirtyImages = true; + } + + return true; +} + +void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image) +{ + if (pixels != NULL) + { + image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels); + mDirtyImages = true; + } +} + +bool TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const void *pixels, Image *image) +{ + if (pixels != NULL) + { + image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels); + mDirtyImages = true; + } + + return true; +} + +bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat) +{ + return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); +} + +bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget) +{ + if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) + { + return true; + } + + // In order to perform the fast copy through the shader, we must have the right format, and be able + // to create a render target. + ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); + + unsigned int offset = reinterpret_cast<unsigned int>(pixels); + + return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); +} + +GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const +{ + if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT) + { + // Maximum number of levels + return gl::log2(std::max(std::max(width, height), depth)) + 1; + } + else + { + // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps. + return 1; + } +} + +int TextureD3D::mipLevels() const +{ + return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; +} + + +TextureD3D_2D::TextureD3D_2D(Renderer *renderer) + : TextureD3D(renderer), + Texture2DImpl(), + mTexStorage(NULL) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); + } +} + +TextureD3D_2D::~TextureD3D_2D() +{ + SafeDelete(mTexStorage); + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } +} + +TextureD3D_2D *TextureD3D_2D::makeTextureD3D_2D(Texture2DImpl *texture) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_2D*, texture)); + return static_cast<TextureD3D_2D*>(texture); +} + +TextureStorageInterface *TextureD3D_2D::getNativeTexture() +{ + // ensure the underlying texture is created + initializeStorage(false); + + TextureStorageInterface *storage = getBaseLevelStorage(); + if (storage) + { + updateStorage(); + } + + return storage; +} + +Image *TextureD3D_2D::getImage(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mImageArray[level]; +} + +void TextureD3D_2D::setUsage(GLenum usage) +{ + mUsage = usage; +} + +void TextureD3D_2D::resetDirty() +{ + mDirtyImages = false; +} + +GLsizei TextureD3D_2D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_2D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLenum TextureD3D_2D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +GLenum TextureD3D_2D::getActualFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getActualFormat(); + else + return GL_NONE; +} + +bool TextureD3D_2D::isDepth(GLint level) const +{ + return gl::GetDepthBits(getInternalFormat(level)) > 0; +} + +void TextureD3D_2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat + : gl::GetSizedInternalFormat(format, type); + bool fastUnpacked = false; + + // Attempt a fast gpu copy of the pixel data to the surface + if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) + { + // Will try to create RT storage if it does not exist + RenderTarget *destRenderTarget = getRenderTarget(level); + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked) + { + TextureD3D::setImage(unpack, type, pixels, mImageArray[level]); + } +} + +void TextureD3D_2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +{ + TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]); +} + +void TextureD3D_2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + bool fastUnpacked = false; + + if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) + { + RenderTarget *renderTarget = getRenderTarget(level); + gl::Box destArea(xoffset, yoffset, 0, width, height, 1); + + if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[level])) + { + commitRect(level, xoffset, yoffset, width, height); + } +} + +void TextureD3D_2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +{ + if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level])) + { + commitRect(level, xoffset, yoffset, width, height); + } +} + +void TextureD3D_2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + if (!mImageArray[level]->isRenderableFormat()) + { + mImageArray[level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + mImageArray[level]->markClean(); + + if (width != 0 && height != 0 && isValidLevel(level)) + { + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level); + } + } +} + +void TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + // can only make our texture storage to a render target if level 0 is defined (with a width & height) and + // the current level we're copying to is defined (with appropriate format, width & height) + bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); + + if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, + gl::GetFormat(getBaseLevelInternalFormat()), + xoffset, yoffset, mTexStorage, level); + } + } +} + +void TextureD3D_2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + for (int level = 0; level < levels; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true); + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); + } + + mImmutable = true; + + setCompleteTexStorage(new TextureStorageInterface2D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, levels)); +} + +// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. +bool TextureD3D_2D::isSamplerComplete(const gl::SamplerState &samplerState) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + + if (width <= 0 || height <= 0) + { + return false; + } + + if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(0)).filterable) + { + if (samplerState.magFilter != GL_NEAREST || + (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) + { + return false; + } + } + + // TODO(geofflang): use context's extensions + bool npotSupport = mRenderer->getRendererExtensions().textureNPOT; + + if (!npotSupport) + { + if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) || + (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height))) + { + return false; + } + } + + if (IsMipmapFiltered(samplerState)) + { + if (!npotSupport) + { + if (!gl::isPow2(width) || !gl::isPow2(height)) + { + return false; + } + } + + if (!isMipmapComplete()) + { + return false; + } + } + + // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if: + // The internalformat specified for the texture arrays is a sized internal depth or + // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_- + // MODE is NONE, and either the magnification filter is not NEAREST or the mini- + // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST. + if (gl::GetDepthBits(getInternalFormat(0)) > 0 && mRenderer->getCurrentClientVersion() > 2) + { + if (samplerState.compareMode == GL_NONE) + { + if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) || + samplerState.magFilter != GL_NEAREST) + { + return false; + } + } + } + + return true; +} + +void TextureD3D_2D::bindTexImage(egl::Surface *surface) +{ + GLenum internalformat = surface->getFormat(); + + mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true); + + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + mTexStorage = new TextureStorageInterface2D(mRenderer, surface->getSwapChain()); + + mDirtyImages = true; +} + +void TextureD3D_2D::releaseTexImage() +{ + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); + } +} + +void TextureD3D_2D::generateMipmaps() +{ + int levelCount = mipLevels(); + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + mImageArray[level]->markClean(); + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); + } + } +} + +unsigned int TextureD3D_2D::getRenderTargetSerial(GLint level) +{ + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level) : 0); +} + +RenderTarget *TextureD3D_2D::getRenderTarget(GLint level) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + + // ensure this is NOT a depth texture + if (isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level); +} + +RenderTarget *TextureD3D_2D::getDepthSencil(GLint level) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + + // ensure this is actually a depth texture + if (!isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level); +} + +// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool TextureD3D_2D::isMipmapComplete() const +{ + int levelCount = mipLevels(); + + for (int level = 0; level < levelCount; level++) + { + if (!isLevelComplete(level)) + { + return false; + } + } + + return true; +} + +bool TextureD3D_2D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false); +} + +bool TextureD3D_2D::isLevelComplete(int level) const +{ + if (isImmutable()) + { + return true; + } + + const Image *baseImage = getBaseLevelImage(); + + GLsizei width = baseImage->getWidth(); + GLsizei height = baseImage->getHeight(); + + if (width <= 0 || height <= 0) + { + return false; + } + + // The base image level is complete if the width and height are positive + if (level == 0) + { + return true; + } + + ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ImageD3D *image = mImageArray[level]; + + if (image->getInternalFormat() != baseImage->getInternalFormat()) + { + return false; + } + + if (image->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (image->getHeight() != std::max(1, height >> level)) + { + return false; + } + + return true; +} + +// Constructs a native texture resource from the texture images +void TextureD3D_2D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + + ASSERT(width > 0 && height > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + + return new TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels); +} + +void TextureD3D_2D::setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + if (mTexStorage && mTexStorage->isManaged()) + { + for (int level = 0; level < mTexStorage->getLevelCount(); level++) + { + mImageArray[level]->setManagedSurface(mTexStorage, level); + } + } + + mDirtyImages = true; +} + +void TextureD3D_2D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_2D::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_2D::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_2D::getBaseLevelImage() const +{ + return mImageArray[0]; +} + +void TextureD3D_2D::updateStorageLevel(int level) +{ + ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + commitRect(level, 0, 0, getWidth(level), getHeight(level)); + } +} + +void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + + SafeDelete(mTexStorage); + mDirtyImages = true; + } + } +} + +void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + if (isValidLevel(level)) + { + ImageD3D *image = mImageArray[level]; + if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height)) + { + image->markClean(); + } + } +} + + +TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer) + : TextureCubeImpl(), + TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + mImageArray[i][j] = ImageD3D::makeImageD3D(renderer->createImage()); + } + } +} + +TextureD3D_Cube::~TextureD3D_Cube() +{ + SafeDelete(mTexStorage); + + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + SafeDelete(mImageArray[i][j]); + } + } +} + +TextureD3D_Cube *TextureD3D_Cube::makeTextureD3D_Cube(TextureCubeImpl *texture) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_Cube*, texture)); + return static_cast<TextureD3D_Cube*>(texture); +} + +TextureStorageInterface *TextureD3D_Cube::getNativeTexture() +{ + // ensure the underlying texture is created + initializeStorage(false); + + TextureStorageInterface *storage = getBaseLevelStorage(); + if (storage) + { + updateStorage(); + } + + return storage; +} + +Image *TextureD3D_Cube::getImage(GLenum target, int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mImageArray[targetToIndex(target)][level]; +} + +void TextureD3D_Cube::setUsage(GLenum usage) +{ + mUsage = usage; +} + +void TextureD3D_Cube::resetDirty() +{ + mDirtyImages = false; +} + +GLenum TextureD3D_Cube::getInternalFormat(GLenum target, GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[targetToIndex(target)][level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_Cube::isDepth(GLenum target, GLint level) const +{ + return gl::GetDepthBits(getInternalFormat(target, level)) > 0; +} + +void TextureD3D_Cube::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat + : gl::GetSizedInternalFormat(format, type); + + redefineImage(faceIndex, level, sizedInternalFormat, width, height); + + TextureD3D::setImage(unpack, type, pixels, mImageArray[faceIndex][level]); +} + +void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +{ + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + int faceIndex = targetToIndex(target); + redefineImage(faceIndex, level, format, width, height); + + TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]); +} + +void TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + int faceIndex = targetToIndex(target); + if (TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[faceIndex][level])) + { + commitRect(faceIndex, level, xoffset, yoffset, width, height); + } +} + +void TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +{ + int faceIndex = targetToIndex(target); + if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level])) + { + commitRect(faceIndex, level, xoffset, yoffset, width, height); + } +} + +void TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + int faceIndex = targetToIndex(target); + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(format) ? format + : gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); + redefineImage(faceIndex, level, sizedInternalFormat, width, height); + + if (!mImageArray[faceIndex][level]->isRenderableFormat()) + { + mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + mImageArray[faceIndex][level]->markClean(); + + ASSERT(width == height); + + if (width > 0 && isValidFaceLevel(faceIndex, level)) + { + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level); + } + } +} + +void TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + int faceIndex = targetToIndex(target); + + // We can only make our texture storage to a render target if the level we're copying *to* is complete + // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot + // rely on the "getBaseLevel*" methods reliably otherwise. + bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete(); + + if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidFaceLevel(faceIndex, level)) + { + updateStorageFaceLevel(faceIndex, level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, gl::GetFormat(getBaseLevelInternalFormat()), + xoffset, yoffset, mTexStorage, target, level); + } + } +} + +void TextureD3D_Cube::storage(GLsizei levels, GLenum internalformat, GLsizei size) +{ + for (int level = 0; level < levels; level++) + { + GLsizei mipSize = std::max(1, size >> level); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true); + } + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true); + } + } + + mImmutable = true; + + setCompleteTexStorage(new TextureStorageInterfaceCube(mRenderer, internalformat, IsRenderTargetUsage(mUsage), size, levels)); +} + +bool TextureD3D_Cube::isSamplerComplete(const gl::SamplerState &samplerState) const +{ + int size = getBaseLevelWidth(); + + bool mipmapping = IsMipmapFiltered(samplerState); + + // TODO(geofflang): use context's texture caps + if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable) + { + if (samplerState.magFilter != GL_NEAREST || + (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) + { + return false; + } + } + + // TODO(geofflang): use context's extensions + if (!gl::isPow2(size) && !mRenderer->getRendererExtensions().textureNPOT) + { + if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) + { + return false; + } + } + + if (!mipmapping) + { + if (!isCubeComplete()) + { + return false; + } + } + else + { + if (!isMipmapCubeComplete()) // Also tests for isCubeComplete() + { + return false; + } + } + + return true; +} + +// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool TextureD3D_Cube::isCubeComplete() const +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + GLenum baseFormat = getBaseLevelInternalFormat(); + + if (baseWidth <= 0 || baseWidth != baseHeight) + { + return false; + } + + for (int faceIndex = 1; faceIndex < 6; faceIndex++) + { + const ImageD3D &faceBaseImage = *mImageArray[faceIndex][0]; + + if (faceBaseImage.getWidth() != baseWidth || + faceBaseImage.getHeight() != baseHeight || + faceBaseImage.getInternalFormat() != baseFormat ) + { + return false; + } + } + + return true; +} + +void TextureD3D_Cube::generateMipmaps() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1)); + redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize); + } + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(faceIndex, level); + + mImageArray[faceIndex][level]->markClean(); + } + } + } + else + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[faceIndex][level], mImageArray[faceIndex][level - 1]); + } + } + } +} + +unsigned int TextureD3D_Cube::getRenderTargetSerial(GLenum target, GLint level) +{ + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(target, level) : 0); +} + +RenderTarget *TextureD3D_Cube::getRenderTarget(GLenum target, GLint level) +{ + ASSERT(gl::IsCubemapTextureTarget(target)); + + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageFaceLevel(targetToIndex(target), level); + + // ensure this is NOT a depth texture + if (isDepth(target, level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(target, level); +} + +RenderTarget *TextureD3D_Cube::getDepthStencil(GLenum target, GLint level) +{ + ASSERT(gl::IsCubemapTextureTarget(target)); + + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageFaceLevel(targetToIndex(target), level); + + // ensure this is a depth texture + if (!isDepth(target, level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(target, level); +} + +int TextureD3D_Cube::targetToIndex(GLenum target) +{ + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); + META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); + META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); + META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); + + return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X; +} + +void TextureD3D_Cube::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isFaceLevelComplete(0, 0)) + { + return; + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterfaceCube *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const +{ + GLsizei size = getBaseLevelWidth(); + + ASSERT(size > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); + + return new TextureStorageInterfaceCube(mRenderer, getBaseLevelInternalFormat(), renderTarget, size, levels); +} + +void TextureD3D_Cube::setCompleteTexStorage(TextureStorageInterfaceCube *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + if (mTexStorage && mTexStorage->isManaged()) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 0; level < mTexStorage->getLevelCount(); level++) + { + mImageArray[faceIndex][level]->setManagedSurface(mTexStorage, faceIndex, level); + } + } + } + + mDirtyImages = true; +} + +void TextureD3D_Cube::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int face = 0; face < 6; face++) + { + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) + { + updateStorageFaceLevel(face, level); + } + } + } +} + +bool TextureD3D_Cube::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterfaceCube *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_Cube::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_Cube::getBaseLevelImage() const +{ + // Note: if we are not cube-complete, there is no single base level image that can describe all + // cube faces, so this method is only well-defined for a cube-complete base level. + return mImageArray[0][0]; +} + +bool TextureD3D_Cube::isMipmapCubeComplete() const +{ + if (isImmutable()) + { + return true; + } + + if (!isCubeComplete()) + { + return false; + } + + int levelCount = mipLevels(); + + for (int face = 0; face < 6; face++) + { + for (int level = 1; level < levelCount; level++) + { + if (!isFaceLevelComplete(face, level)) + { + return false; + } + } + } + + return true; +} + +bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + + +bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const +{ + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + + if (isImmutable()) + { + return true; + } + + int baseSize = getBaseLevelWidth(); + + if (baseSize <= 0) + { + return false; + } + + // "isCubeComplete" checks for base level completeness and we must call that + // to determine if any face at level 0 is complete. We omit that check here + // to avoid re-checking cube-completeness for every face at level 0. + if (level == 0) + { + return true; + } + + // Check that non-zero levels are consistent with the base level. + const ImageD3D *faceLevelImage = mImageArray[faceIndex][level]; + + if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) + { + return false; + } + + return true; +} + +void TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) +{ + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + ImageD3D *image = mImageArray[faceIndex][level]; + + if (image->isDirty()) + { + commitRect(faceIndex, level, 0, 0, image->getWidth(), image->getHeight()); + } +} + +void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->markDirty(); + } + } + + SafeDelete(mTexStorage); + + mDirtyImages = true; + } + } +} + +void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + if (isValidFaceLevel(faceIndex, level)) + { + ImageD3D *image = mImageArray[faceIndex][level]; + if (image->copyToStorage(mTexStorage, faceIndex, level, xoffset, yoffset, width, height)) + image->markClean(); + } +} + + +TextureD3D_3D::TextureD3D_3D(Renderer *renderer) + : Texture3DImpl(), + TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); + } +} + +TextureD3D_3D::~TextureD3D_3D() +{ + SafeDelete(mTexStorage); + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } +} + +TextureD3D_3D *TextureD3D_3D::makeTextureD3D_3D(Texture3DImpl *texture) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_3D*, texture)); + return static_cast<TextureD3D_3D*>(texture); +} + +TextureStorageInterface *TextureD3D_3D::getNativeTexture() +{ + // ensure the underlying texture is created + initializeStorage(false); + + TextureStorageInterface *storage = getBaseLevelStorage(); + if (storage) + { + updateStorage(); + } + + return storage; +} + +Image *TextureD3D_3D::getImage(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mImageArray[level]; +} + +void TextureD3D_3D::setUsage(GLenum usage) +{ + mUsage = usage; +} + +void TextureD3D_3D::resetDirty() +{ + mDirtyImages = false; +} + +GLsizei TextureD3D_3D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_3D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLsizei TextureD3D_3D::getDepth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getDepth(); + else + return 0; +} + +GLenum TextureD3D_3D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_3D::isDepth(GLint level) const +{ + return gl::GetDepthBits(getInternalFormat(level)) > 0; +} + +void TextureD3D_3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat + : gl::GetSizedInternalFormat(format, type); + redefineImage(level, sizedInternalFormat, width, height, depth); + + bool fastUnpacked = false; + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, sizedInternalFormat)) + { + // Will try to create RT storage if it does not exist + RenderTarget *destRenderTarget = getRenderTarget(level); + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked) + { + TextureD3D::setImage(unpack, type, pixels, mImageArray[level]); + } +} + +void TextureD3D_3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +{ + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, format, width, height, depth); + + TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]); +} + +void TextureD3D_3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + bool fastUnpacked = false; + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, getInternalFormat(level))) + { + RenderTarget *destRenderTarget = getRenderTarget(level); + gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level])) + { + commitRect(level, xoffset, yoffset, zoffset, width, height, depth); + } +} + +void TextureD3D_3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +{ + if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level])) + { + commitRect(level, xoffset, yoffset, zoffset, width, height, depth); + } +} + +void TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + // can only make our texture storage to a render target if level 0 is defined (with a width & height) and + // the current level we're copying to is defined (with appropriate format, width & height) + bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); + + if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level]->copy(xoffset, yoffset, zoffset, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, + gl::GetFormat(getBaseLevelInternalFormat()), + xoffset, yoffset, zoffset, mTexStorage, level); + } + } +} + +void TextureD3D_3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + for (int level = 0; level < levels; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + GLsizei levelDepth = std::max(1, depth >> level); + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true); + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true); + } + + mImmutable = true; + + setCompleteTexStorage(new TextureStorageInterface3D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); +} + +bool TextureD3D_3D::isSamplerComplete(const gl::SamplerState &samplerState) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } + + // TODO(geofflang): use context's texture caps + if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(0)).filterable) + { + if (samplerState.magFilter != GL_NEAREST || + (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) + { + return false; + } + } + + if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) + { + return false; + } + + return true; +} + +bool TextureD3D_3D::isMipmapComplete() const +{ + int levelCount = mipLevels(); + + for (int level = 0; level < levelCount; level++) + { + if (!isLevelComplete(level)) + { + return false; + } + } + + return true; +} + +void TextureD3D_3D::generateMipmaps() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + redefineImage(level, getBaseLevelInternalFormat(), + std::max(getBaseLevelWidth() >> level, 1), + std::max(getBaseLevelHeight() >> level, 1), + std::max(getBaseLevelDepth() >> level, 1)); + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + mImageArray[level]->markClean(); + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); + } + } +} + +unsigned int TextureD3D_3D::getRenderTargetSerial(GLint level, GLint layer) +{ + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); +} + +RenderTarget *TextureD3D_3D::getRenderTarget(GLint level) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + + // ensure this is NOT a depth texture + if (isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level); +} + +RenderTarget *TextureD3D_3D::getRenderTarget(GLint level, GLint layer) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorage(); + + // ensure this is NOT a depth texture + if (isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level, layer); +} + +RenderTarget *TextureD3D_3D::getDepthStencil(GLint level, GLint layer) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + + // ensure this is a depth texture + if (!isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level, layer); +} + +void TextureD3D_3D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface3D *TextureD3D_3D::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + + ASSERT(width > 0 && height > 0 && depth > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth)); + + return new TextureStorageInterface3D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels); +} + +void TextureD3D_3D::setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 3D storage, as that is D3D9/ES2-only + ASSERT(!mTexStorage->isManaged()); +} + +void TextureD3D_3D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_3D::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface3D *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_3D::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_3D::getBaseLevelImage() const +{ + return mImageArray[0]; +} + +bool TextureD3D_3D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_3D::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } + + if (level == 0) + { + return true; + } + + ImageD3D *levelImage = mImageArray[level]; + + if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (levelImage->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (levelImage->getHeight() != std::max(1, height >> level)) + { + return false; + } + + if (levelImage->getDepth() != std::max(1, depth >> level)) + { + return false; + } + + return true; +} + +void TextureD3D_3D::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + } +} + +void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const int storageDepth = std::max(1, getBaseLevelDepth() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + + SafeDelete(mTexStorage); + mDirtyImages = true; + } + } +} + +void TextureD3D_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +{ + if (isValidLevel(level)) + { + ImageD3D *image = mImageArray[level]; + if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth)) + { + image->markClean(); + } + } +} + + +TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer) + : Texture2DArrayImpl(), + TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + mLayerCounts[level] = 0; + mImageArray[level] = NULL; + } +} + +TextureD3D_2DArray::~TextureD3D_2DArray() +{ + SafeDelete(mTexStorage); + + deleteImages(); +} + +TextureD3D_2DArray *TextureD3D_2DArray::makeTextureD3D_2DArray(Texture2DArrayImpl *texture) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_2DArray*, texture)); + return static_cast<TextureD3D_2DArray*>(texture); +} + +TextureStorageInterface *TextureD3D_2DArray::getNativeTexture() +{ + // ensure the underlying texture is created + initializeStorage(false); + + TextureStorageInterface *storage = getBaseLevelStorage(); + if (storage) + { + updateStorage(); + } + + return storage; +} + +Image *TextureD3D_2DArray::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer < mLayerCounts[level]); + return mImageArray[level][layer]; +} + +GLsizei TextureD3D_2DArray::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mLayerCounts[level]; +} + +void TextureD3D_2DArray::setUsage(GLenum usage) +{ + mUsage = usage; +} + +void TextureD3D_2DArray::resetDirty() +{ + mDirtyImages = false; +} + +GLsizei TextureD3D_2DArray::getWidth(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0; +} + +GLsizei TextureD3D_2DArray::getHeight(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0; +} + +GLsizei TextureD3D_2DArray::getLayers(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mLayerCounts[level] : 0; +} + +GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE; +} + +bool TextureD3D_2DArray::isDepth(GLint level) const +{ + return gl::GetDepthBits(getInternalFormat(level)) > 0; +} + +void TextureD3D_2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat + : gl::GetSizedInternalFormat(format, type); + redefineImage(level, sizedInternalFormat, width, height, depth); + + GLsizei inputDepthPitch = gl::GetDepthPitch(sizedInternalFormat, type, width, height, unpack.alignment); + + for (int i = 0; i < depth; i++) + { + const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; + TextureD3D::setImage(unpack, type, layerPixels, mImageArray[level][i]); + } +} + +void TextureD3D_2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +{ + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, format, width, height, depth); + + GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1); + + for (int i = 0; i < depth; i++) + { + const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; + TextureD3D::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]); + } +} + +void TextureD3D_2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + GLenum internalformat = getInternalFormat(level); + GLsizei inputDepthPitch = gl::GetDepthPitch(internalformat, type, width, height, unpack.alignment); + + for (int i = 0; i < depth; i++) + { + int layer = zoffset + i; + const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; + + if (TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, mImageArray[level][layer])) + { + commitRect(level, xoffset, yoffset, layer, width, height); + } + } +} + +void TextureD3D_2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +{ + GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1); + + for (int i = 0; i < depth; i++) + { + int layer = zoffset + i; + const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL; + + if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer])) + { + commitRect(level, xoffset, yoffset, layer, width, height); + } + } +} + +void TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + // can only make our texture storage to a render target if level 0 is defined (with a width & height) and + // the current level we're copying to is defined (with appropriate format, width & height) + bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); + + if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, gl::GetFormat(getInternalFormat(0)), + xoffset, yoffset, zoffset, mTexStorage, level); + } + } +} + +void TextureD3D_2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + deleteImages(); + + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + + mLayerCounts[level] = (level < levels ? depth : 0); + + if (mLayerCounts[level] > 0) + { + // Create new images for this level + mImageArray[level] = new ImageD3D*[mLayerCounts[level]]; + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); + mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth, + levelHeight, 1, true); + } + } + } + + mImmutable = true; + setCompleteTexStorage(new TextureStorageInterface2DArray(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); +} + +bool TextureD3D_2DArray::isSamplerComplete(const gl::SamplerState &samplerState) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getLayers(0); + + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } + + // TODO(geofflang): use context's texture caps + if (!mRenderer->getRendererTextureCaps().get(getBaseLevelInternalFormat()).filterable) + { + if (samplerState.magFilter != GL_NEAREST || + (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) + { + return false; + } + } + + if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) + { + return false; + } + + return true; +} + +bool TextureD3D_2DArray::isMipmapComplete() const +{ + int levelCount = mipLevels(); + + for (int level = 1; level < levelCount; level++) + { + if (!isLevelComplete(level)) + { + return false; + } + } + + return true; +} + +void TextureD3D_2DArray::generateMipmaps() +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + int baseDepth = getBaseLevelDepth(); + GLenum baseFormat = getBaseLevelInternalFormat(); + + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth); + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer]->markClean(); + } + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]); + } + } + } +} + +unsigned int TextureD3D_2DArray::getRenderTargetSerial(GLint level, GLint layer) +{ + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); +} + +RenderTarget *TextureD3D_2DArray::getRenderTarget(GLint level, GLint layer) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + + // ensure this is NOT a depth texture + if (isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level, layer); +} + +RenderTarget *TextureD3D_2DArray::getDepthStencil(GLint level, GLint layer) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + + // ensure this is a depth texture + if (!isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level, layer); +} + +void TextureD3D_2DArray::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface2DArray *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getLayers(0); + + ASSERT(width > 0 && height > 0 && depth > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + + return new TextureStorageInterface2DArray(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels); +} + +void TextureD3D_2DArray::setCompleteTexStorage(TextureStorageInterface2DArray *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only + ASSERT(!mTexStorage->isManaged()); +} + +void TextureD3D_2DArray::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_2DArray::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface2DArray *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +const ImageD3D *TextureD3D_2DArray::getBaseLevelImage() const +{ + return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL); +} + +TextureStorageInterface *TextureD3D_2DArray::getBaseLevelStorage() +{ + return mTexStorage; +} + +bool TextureD3D_2DArray::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_2DArray::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray)); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei layers = getLayers(0); + + if (width <= 0 || height <= 0 || layers <= 0) + { + return false; + } + + if (level == 0) + { + return true; + } + + if (getInternalFormat(level) != getInternalFormat(0)) + { + return false; + } + + if (getWidth(level) != std::max(1, width >> level)) + { + return false; + } + + if (getHeight(level) != std::max(1, height >> level)) + { + return false; + } + + if (getLayers(level) != layers) + { + return false; + } + + return true; +} + +void TextureD3D_2DArray::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); + ASSERT(isLevelComplete(level)); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); + if (mImageArray[level][layer]->isDirty()) + { + commitRect(level, 0, 0, layer, getWidth(level), getHeight(level)); + } + } +} + +void TextureD3D_2DArray::deleteImages() +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + for (int layer = 0; layer < mLayerCounts[level]; ++layer) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = 0; + } +} + +void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const int storageDepth = getLayers(0); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = depth; + + if (depth > 0) + { + mImageArray[level] = new ImageD3D*[depth](); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); + mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false); + } + } + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer]->markDirty(); + } + } + + delete mTexStorage; + mTexStorage = NULL; + mDirtyImages = true; + } + } +} + +void TextureD3D_2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height) +{ + if (isValidLevel(level) && layerTarget < getLayers(level)) + { + ImageD3D *image = mImageArray[level][layerTarget]; + if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, layerTarget, width, height)) + { + image->markClean(); + } + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h new file mode 100644 index 0000000000..4a1737a9c4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h @@ -0,0 +1,343 @@ +// +// Copyright 2014 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. +// + +// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#ifndef LIBGLESV2_RENDERER_TEXTURED3D_H_ +#define LIBGLESV2_RENDERER_TEXTURED3D_H_ + +#include "libGLESv2/renderer/TextureImpl.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/constants.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ + +class Image; +class ImageD3D; +class Renderer; +class TextureStorageInterface; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class TextureStorageInterface3D; +class TextureStorageInterface2DArray; + +bool IsMipmapFiltered(const gl::SamplerState &samplerState); + +class TextureD3D +{ + public: + TextureD3D(Renderer *renderer); + virtual ~TextureD3D(); + + GLint getBaseLevelWidth() const; + GLint getBaseLevelHeight() const; + GLint getBaseLevelDepth() const; + GLenum getBaseLevelInternalFormat() const; + + bool isImmutable() const { return mImmutable; } + + protected: + void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image); + bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, Image *image); + void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image); + bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const void *pixels, Image *image); + bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); + bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget); + + GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; + int mipLevels() const; + + Renderer *mRenderer; + + GLenum mUsage; + + bool mDirtyImages; + + bool mImmutable; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D); + + virtual TextureStorageInterface *getBaseLevelStorage() = 0; + virtual const ImageD3D *getBaseLevelImage() const = 0; +}; + +class TextureD3D_2D : public Texture2DImpl, public TextureD3D +{ + public: + TextureD3D_2D(Renderer *renderer); + virtual ~TextureD3D_2D(); + + static TextureD3D_2D *makeTextureD3D_2D(Texture2DImpl *texture); + + virtual TextureStorageInterface *getNativeTexture(); + + virtual Image *getImage(int level) const; + + virtual void setUsage(GLenum usage); + virtual bool hasDirtyImages() const { return mDirtyImages; } + virtual void resetDirty(); + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLenum getInternalFormat(GLint level) const; + GLenum getActualFormat(GLint level) const; + bool isDepth(GLint level) const; + + virtual void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); + virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + + virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const; + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual void generateMipmaps(); + + virtual unsigned int getRenderTargetSerial(GLint level); + + virtual RenderTarget *getRenderTarget(GLint level); + virtual RenderTarget *getDepthSencil(GLint level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D); + + void initializeStorage(bool renderTarget); + TextureStorageInterface2D *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage); + + void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isMipmapComplete() const; + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + + void updateStorageLevel(int level); + + virtual void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + TextureStorageInterface2D *mTexStorage; + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_Cube : public TextureCubeImpl, public TextureD3D +{ + public: + TextureD3D_Cube(Renderer *renderer); + virtual ~TextureD3D_Cube(); + + static TextureD3D_Cube *makeTextureD3D_Cube(TextureCubeImpl *texture); + + virtual TextureStorageInterface *getNativeTexture(); + + virtual Image *getImage(GLenum target, int level) const; + + virtual void setUsage(GLenum usage); + virtual bool hasDirtyImages() const { return mDirtyImages; } + virtual void resetDirty(); + + GLenum getInternalFormat(GLenum target, GLint level) const; + bool isDepth(GLenum target, GLint level) const; + + virtual void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); + virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void storage(GLsizei levels, GLenum internalformat, GLsizei size); + + virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const; + virtual bool isCubeComplete() const; + + virtual void generateMipmaps(); + + virtual unsigned int getRenderTargetSerial(GLenum target, GLint level); + + virtual RenderTarget *getRenderTarget(GLenum target, GLint level); + virtual RenderTarget *getDepthStencil(GLenum target, GLint level); + + static int targetToIndex(GLenum target); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube); + + void initializeStorage(bool renderTarget); + TextureStorageInterfaceCube *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterfaceCube *newCompleteTexStorage); + + void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isMipmapCubeComplete() const; + bool isValidFaceLevel(int faceIndex, int level) const; + bool isFaceLevelComplete(int faceIndex, int level) const; + void updateStorageFaceLevel(int faceIndex, int level); + + void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height); + void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterfaceCube *mTexStorage; +}; + +class TextureD3D_3D : public Texture3DImpl, public TextureD3D +{ + public: + TextureD3D_3D(Renderer *renderer); + virtual ~TextureD3D_3D(); + + static TextureD3D_3D *makeTextureD3D_3D(Texture3DImpl *texture); + + virtual TextureStorageInterface *getNativeTexture(); + + virtual Image *getImage(int level) const; + + virtual void setUsage(GLenum usage); + virtual bool hasDirtyImages() const { return mDirtyImages; } + virtual void resetDirty(); + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getDepth(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + + virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const; + virtual bool isMipmapComplete() const; + + virtual void generateMipmaps(); + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer); + + virtual RenderTarget *getRenderTarget(GLint level); + virtual RenderTarget *getRenderTarget(GLint level, GLint layer); + virtual RenderTarget *getDepthStencil(GLint level, GLint layer); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D); + + virtual void initializeStorage(bool renderTarget); + TextureStorageInterface3D *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage); + + void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + void updateStorageLevel(int level); + + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterface3D *mTexStorage; +}; + +class TextureD3D_2DArray : public Texture2DArrayImpl, public TextureD3D +{ + public: + TextureD3D_2DArray(Renderer *renderer); + virtual ~TextureD3D_2DArray(); + + static TextureD3D_2DArray *makeTextureD3D_2DArray(Texture2DArrayImpl *texture); + + virtual TextureStorageInterface *getNativeTexture(); + + virtual Image *getImage(int level, int layer) const; + virtual GLsizei getLayerCount(int level) const; + + virtual void setUsage(GLenum usage); + virtual bool hasDirtyImages() const { return mDirtyImages; } + virtual void resetDirty(); + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getLayers(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + + virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const; + virtual bool isMipmapComplete() const; + + virtual void generateMipmaps(); + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer); + + virtual RenderTarget *getRenderTarget(GLint level, GLint layer); + virtual RenderTarget *getDepthStencil(GLint level, GLint layer); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray); + + virtual void initializeStorage(bool renderTarget); + TextureStorageInterface2DArray *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface2DArray *newCompleteTexStorage); + + void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + void updateStorageLevel(int level); + + void deleteImages(); + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height); + + // Storing images as an array of single depth textures since D3D11 treats each array level of a + // Texture2D object as a separate subresource. Each layer would have to be looped over + // to update all the texture layers since they cannot all be updated at once and it makes the most + // sense for the Image class to not have to worry about layer subresource as well as mip subresources. + GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterface2DArray *mTexStorage; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp new file mode 100644 index 0000000000..846586984c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp @@ -0,0 +1,181 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2013 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. +// + +// TextureStorage.cpp: Implements the abstract rx::TextureStorageInterface class and its concrete derived +// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the +// GPU-side texture. + +#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/Texture.h" + +#include "common/debug.h" +#include "common/mathutil.h" + +namespace rx +{ +unsigned int TextureStorageInterface::mCurrentTextureSerial = 1; + +TextureStorageInterface::TextureStorageInterface() + : mTextureSerial(issueTextureSerial()), + mInstance(NULL) +{ +} + +TextureStorageInterface::~TextureStorageInterface() +{ + delete mInstance; +} + +bool TextureStorageInterface::isRenderTarget() const +{ + return mInstance->isRenderTarget(); +} + +bool TextureStorageInterface::isManaged() const +{ + return mInstance->isManaged(); +} + +unsigned int TextureStorageInterface::getTextureSerial() const +{ + return mTextureSerial; +} + +unsigned int TextureStorageInterface::issueTextureSerial() +{ + return mCurrentTextureSerial++; +} + +int TextureStorageInterface::getTopLevel() const +{ + return mInstance->getTopLevel(); +} + +int TextureStorageInterface::getLevelCount() const +{ + return mInstance->getLevelCount(); +} + +TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain) +{ + mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(1); + + mInstance = renderer->createTextureStorage2D(swapchain); +} + +TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) +{ + mInstance = renderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels); + mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(static_cast<GLuint>(mInstance->getLevelCount())); +} + +TextureStorageInterface2D::~TextureStorageInterface2D() +{ +} + +RenderTarget *TextureStorageInterface2D::getRenderTarget(GLint level) const +{ + return mInstance->getRenderTarget(level); +} + +void TextureStorageInterface2D::generateMipmap(int level) +{ + mInstance->generateMipmap(level); +} + +unsigned int TextureStorageInterface2D::getRenderTargetSerial(GLint level) const +{ + return mFirstRenderTargetSerial + level; +} + +TextureStorageInterfaceCube::TextureStorageInterfaceCube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) +{ + mInstance = renderer->createTextureStorageCube(internalformat, renderTarget, size, levels); + mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(static_cast<GLuint>(mInstance->getLevelCount() * 6)); +} + +TextureStorageInterfaceCube::~TextureStorageInterfaceCube() +{ +} + +RenderTarget *TextureStorageInterfaceCube::getRenderTarget(GLenum faceTarget, GLint level) const +{ + return mInstance->getRenderTargetFace(faceTarget, level); +} + +void TextureStorageInterfaceCube::generateMipmap(int faceIndex, int level) +{ + mInstance->generateMipmap(faceIndex, level); +} + +unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target, GLint level) const +{ + return mFirstRenderTargetSerial + (level * 6) + TextureD3D_Cube::targetToIndex(target); +} + +TextureStorageInterface3D::TextureStorageInterface3D(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + + mInstance = renderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels); + mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(static_cast<GLuint>(mInstance->getLevelCount() * depth)); +} + +TextureStorageInterface3D::~TextureStorageInterface3D() +{ +} + +void TextureStorageInterface3D::generateMipmap(int level) +{ + mInstance->generateMipmap(level); +} + +RenderTarget *TextureStorageInterface3D::getRenderTarget(GLint level) const +{ + return mInstance->getRenderTarget(level); +} + +RenderTarget *TextureStorageInterface3D::getRenderTarget(GLint level, GLint layer) const +{ + return mInstance->getRenderTargetLayer(level, layer); +} + +unsigned int TextureStorageInterface3D::getRenderTargetSerial(GLint level, GLint layer) const +{ + return mFirstRenderTargetSerial + static_cast<unsigned int>((layer * mInstance->getLevelCount()) + level); +} + +TextureStorageInterface2DArray::TextureStorageInterface2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + mInstance = renderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels); + mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(static_cast<GLuint>(mInstance->getLevelCount() * depth)); +} + +TextureStorageInterface2DArray::~TextureStorageInterface2DArray() +{ +} + +void TextureStorageInterface2DArray::generateMipmap(int level) +{ + mInstance->generateMipmap(level); +} + +RenderTarget *TextureStorageInterface2DArray::getRenderTarget(GLint level, GLint layer) const +{ + return mInstance->getRenderTargetLayer(level, layer); +} + +unsigned int TextureStorageInterface2DArray::getRenderTargetSerial(GLint level, GLint layer) const +{ + return mFirstRenderTargetSerial + static_cast<unsigned int>((layer * mInstance->getLevelCount()) + level); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h new file mode 100644 index 0000000000..0a212e16f2 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h @@ -0,0 +1,145 @@ +// +// Copyright (c) 2002-2013 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. +// + +// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived +// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the +// GPU-side texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ + +#include "common/debug.h" + +namespace rx +{ +class Renderer; +class SwapChain; +class RenderTarget; + +class TextureStorage +{ + public: + TextureStorage() {}; + virtual ~TextureStorage() {}; + + virtual int getTopLevel() const = 0; + virtual bool isRenderTarget() const = 0; + virtual bool isManaged() const = 0; + virtual int getLevelCount() const = 0; + + virtual RenderTarget *getRenderTarget(int level) = 0; + virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level) = 0; + virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer) = 0; + virtual void generateMipmap(int level) = 0; + virtual void generateMipmap(int face, int level) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage); + +}; + +class TextureStorageInterface +{ + public: + TextureStorageInterface(); + virtual ~TextureStorageInterface(); + + TextureStorage *getStorageInstance() { return mInstance; } + + unsigned int getTextureSerial() const; + + virtual int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int getLevelCount() const; + + protected: + TextureStorage *mInstance; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface); + + const unsigned int mTextureSerial; + static unsigned int issueTextureSerial(); + + static unsigned int mCurrentTextureSerial; +}; + +class TextureStorageInterface2D : public TextureStorageInterface +{ + public: + TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain); + TextureStorageInterface2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual ~TextureStorageInterface2D(); + + void generateMipmap(int level); + RenderTarget *getRenderTarget(GLint level) const; + + unsigned int getRenderTargetSerial(GLint level) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2D); + + unsigned int mFirstRenderTargetSerial; +}; + +class TextureStorageInterfaceCube : public TextureStorageInterface +{ + public: + TextureStorageInterfaceCube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels); + virtual ~TextureStorageInterfaceCube(); + + void generateMipmap(int faceIndex, int level); + RenderTarget *getRenderTarget(GLenum faceTarget, GLint level) const; + + virtual unsigned int getRenderTargetSerial(GLenum target, GLint level) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterfaceCube); + + unsigned int mFirstRenderTargetSerial; +}; + +class TextureStorageInterface3D : public TextureStorageInterface +{ + public: + TextureStorageInterface3D(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorageInterface3D(); + + void generateMipmap(int level); + RenderTarget *getRenderTarget(GLint level) const; + RenderTarget *getRenderTarget(GLint level, GLint layer) const; + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface3D); + + unsigned int mFirstRenderTargetSerial; +}; + +class TextureStorageInterface2DArray : public TextureStorageInterface +{ + public: + TextureStorageInterface2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorageInterface2DArray(); + + void generateMipmap(int level); + RenderTarget *getRenderTarget(GLint level, GLint layer) const; + + virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2DArray); + + unsigned int mFirstRenderTargetSerial; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp index a073d95033..901ca196a8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp @@ -8,9 +8,11 @@ // VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface // class with derivations, classes that perform graphics API agnostic vertex buffer operations. -#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/d3d/VertexBuffer.h" #include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Context.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "common/mathutil.h" namespace rx { @@ -87,8 +89,8 @@ bool VertexBufferInterface::discard() return mVertexBuffer->discard(); } -bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int *outStreamOffset) +bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) { unsigned int spaceRequired; if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired)) @@ -107,7 +109,7 @@ bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &att } mReservedSpace = 0; - if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition)) + if (!mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition)) { return false; } @@ -119,73 +121,73 @@ bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &att mWritePosition += spaceRequired; + // Align to 16-byte boundary + mWritePosition = rx::roundUp(mWritePosition, 16u); + return true; } -bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset) +bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) { - if (mWritePosition + size < mWritePosition) - { - return false; - } - - if (!reserveSpace(mReservedSpace)) + unsigned int requiredSpace; + if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace)) { return false; } - mReservedSpace = 0; - if (!mVertexBuffer->storeRawData(data, size, mWritePosition)) + // Protect against integer overflow + if (mReservedSpace + requiredSpace < mReservedSpace) { - return false; + return false; } - if (outStreamOffset) - { - *outStreamOffset = mWritePosition; - } + mReservedSpace += requiredSpace; - mWritePosition += size; + // Align to 16-byte boundary + mReservedSpace = rx::roundUp(mReservedSpace, 16u); return true; } -bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) +VertexBuffer* VertexBufferInterface::getVertexBuffer() const { - unsigned int requiredSpace; - if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace)) + return mVertexBuffer; +} + +bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const +{ + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + + if (!storage || !storage->supportsDirectBinding()) { return false; } - // Protect against integer overflow - if (mReservedSpace + requiredSpace < mReservedSpace) + // Alignment restrictions: In D3D, vertex data must be aligned to + // the format stride, or to a 4-byte boundary, whichever is smaller. + // (Undocumented, and experimentally confirmed) + size_t alignment = 4; + bool requiresConversion = false; + + if (attrib.type != GL_FLOAT) { - return false; - } + gl::VertexFormat vertexFormat(attrib, currentValue.Type); - mReservedSpace += requiredSpace; - return true; -} + unsigned int outputElementSize; + getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); + alignment = std::min<size_t>(outputElementSize, 4); -bool VertexBufferInterface::reserveRawDataSpace(unsigned int size) -{ - // Protect against integer overflow - if (mReservedSpace + size < mReservedSpace) - { - return false; + requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; } - mReservedSpace += size; - return true; -} + bool isAligned = (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) && + (static_cast<size_t>(attrib.offset) % alignment == 0); -VertexBuffer* VertexBufferInterface::getVertexBuffer() const -{ - return mVertexBuffer; + return !requiresConversion && isAligned; } - StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) { setBufferSize(initialSize); @@ -224,16 +226,18 @@ StaticVertexBufferInterface::~StaticVertexBufferInterface() { } -bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset) +bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, unsigned int *outStreamOffset) { 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].type == attrib.type && + mCache[element].size == attrib.size && + mCache[element].stride == ComputeVertexAttributeStride(attrib) && + mCache[element].normalized == attrib.normalized && + mCache[element].pureInteger == attrib.pureInteger) { - if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) + size_t offset = (static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib)); + if (mCache[element].attributeOffset == offset) { if (outStreamOffset) { @@ -266,14 +270,14 @@ bool StaticVertexBufferInterface::reserveSpace(unsigned int size) } } -bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int *outStreamOffset) +bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) { unsigned int streamOffset; - if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset)) + if (VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset)) { - int attributeOffset = attrib.mOffset % attrib.stride(); - VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset }; + size_t attributeOffset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib); + VertexElement element = { attrib.type, attrib.size, ComputeVertexAttributeStride(attrib), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset }; mCache.push_back(element); if (outStreamOffset) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h index cbafdd20f6..c5022d8c9c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h @@ -14,7 +14,8 @@ namespace gl { -class VertexAttribute; +struct VertexAttribute; +struct VertexAttribCurrentValueData; } namespace rx @@ -29,15 +30,11 @@ class VertexBuffer virtual bool initialize(unsigned int size, bool dynamicUsage) = 0; - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, - GLsizei instances, unsigned int offset) = 0; - virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset) = 0; - + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) = 0; virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const = 0; - virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0; - virtual unsigned int getBufferSize() const = 0; virtual bool setBufferSize(unsigned int size) = 0; virtual bool discard() = 0; @@ -61,15 +58,16 @@ class VertexBufferInterface virtual ~VertexBufferInterface(); bool reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); - bool reserveRawDataSpace(unsigned int size); unsigned int getBufferSize() const; unsigned int getSerial() const; - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int *outStreamOffset); - virtual bool storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset); + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); + + bool directStoragePossible(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const; VertexBuffer* getVertexBuffer() const; @@ -111,10 +109,10 @@ class StaticVertexBufferInterface : public VertexBufferInterface explicit StaticVertexBufferInterface(rx::Renderer *renderer); ~StaticVertexBufferInterface(); - bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int *outStreamOffset); + bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); - bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamOffset); + bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset); protected: bool reserveSpace(unsigned int size); @@ -123,10 +121,11 @@ class StaticVertexBufferInterface : public VertexBufferInterface struct VertexElement { GLenum type; - GLint size; - GLsizei stride; + GLuint size; + GLuint stride; bool normalized; - int attributeOffset; + bool pureInteger; + size_t attributeOffset; unsigned int streamOffset; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp index 8034aed8c9..fc2b8ff0df 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp @@ -8,13 +8,14 @@ // VertexDataManager.h: Defines the VertexDataManager, a class that // runs the Buffer translation process. -#include "libGLESv2/renderer/VertexDataManager.h" -#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/renderer/d3d/VertexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" namespace { @@ -26,7 +27,7 @@ namespace namespace rx { -static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size) +static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size) { // Size cannot be larger than a GLsizei if (size > static_cast<unsigned int>(std::numeric_limits<int>::max())) @@ -34,19 +35,19 @@ static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int s size = static_cast<unsigned int>(std::numeric_limits<int>::max()); } - GLsizei stride = attribute.stride(); - return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; + GLsizei stride = ComputeVertexAttributeStride(attrib); + return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride; } -static int StreamingBufferElementCount(const gl::VertexAttribute &attribute, int vertexDrawCount, int instanceDrawCount) +static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount) { // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. // // A vertex attribute with a positive divisor loads one instanced vertex for every set of // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. - if (instanceDrawCount > 0 && attribute.mDivisor > 0) + if (instanceDrawCount > 0 && attrib.divisor > 0) { - return instanceDrawCount / attribute.mDivisor; + return instanceDrawCount / attrib.divisor; } return vertexDrawCount; @@ -56,10 +57,11 @@ VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) { for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - mCurrentValue[i][0] = std::numeric_limits<float>::quiet_NaN(); - mCurrentValue[i][1] = std::numeric_limits<float>::quiet_NaN(); - mCurrentValue[i][2] = std::numeric_limits<float>::quiet_NaN(); - mCurrentValue[i][3] = std::numeric_limits<float>::quiet_NaN(); + mCurrentValue[i].FloatValues[0] = std::numeric_limits<float>::quiet_NaN(); + mCurrentValue[i].FloatValues[1] = std::numeric_limits<float>::quiet_NaN(); + mCurrentValue[i].FloatValues[2] = std::numeric_limits<float>::quiet_NaN(); + mCurrentValue[i].FloatValues[3] = std::numeric_limits<float>::quiet_NaN(); + mCurrentValue[i].Type = GL_FLOAT; mCurrentValueBuffer[i] = NULL; mCurrentValueOffsets[i] = 0; } @@ -82,17 +84,8 @@ VertexDataManager::~VertexDataManager() } } -static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib) -{ - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - BufferStorage *storage = buffer ? buffer->getStorage() : NULL; - - const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0); - - return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned; -} - -GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) +GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], + gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) { if (!mStreamingBuffer) { @@ -107,15 +100,20 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], // Invalidate static buffers that don't contain matching attributes for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - if (translated[i].active && attribs[i].mArrayEnabled) + if (translated[i].active && attribs[i].enabled) { - gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); - StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + gl::Buffer *buffer = attribs[i].buffer.get(); - if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) && - !directStoragePossible(staticBuffer, attribs[i])) + if (buffer) { - buffer->invalidateStaticData(); + BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); + StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); + + if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) && + !staticBuffer->directStoragePossible(attribs[i], currentValues[i])) + { + bufferImpl->invalidateStaticData(); + } } } } @@ -123,19 +121,20 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], // Reserve the required space in the buffers for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - if (translated[i].active && attribs[i].mArrayEnabled) + if (translated[i].active && attribs[i].enabled) { - gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); - StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + gl::Buffer *buffer = attribs[i].buffer.get(); + BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); - if (!directStoragePossible(vertexBuffer, attribs[i])) + if (!vertexBuffer->directStoragePossible(attribs[i], currentValues[i])) { if (staticBuffer) { if (staticBuffer->getBufferSize() == 0) { - int totalCount = elementsInBuffer(attribs[i], buffer->size()); + int totalCount = ElementsInBuffer(attribs[i], bufferImpl->getSize()); if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0)) { return GL_OUT_OF_MEMORY; @@ -146,9 +145,9 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], { int totalCount = StreamingBufferElementCount(attribs[i], count, instances); - // Undefined behaviour: + // [OpenGL ES 3.0.2] section 2.9.4 page 40: // We can return INVALID_OPERATION if our vertex attribute does not have enough backing data. - if (buffer && elementsInBuffer(attribs[i], buffer->size()) < totalCount) + if (bufferImpl && ElementsInBuffer(attribs[i], bufferImpl->getSize()) < totalCount) { return GL_INVALID_OPERATION; } @@ -167,31 +166,29 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], { if (translated[i].active) { - if (attribs[i].mArrayEnabled) + if (attribs[i].enabled) { - gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + gl::Buffer *buffer = attribs[i].buffer.get(); - if (!buffer && attribs[i].mPointer == NULL) + if (!buffer && attribs[i].pointer == 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; } - StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); - - BufferStorage *storage = buffer ? buffer->getStorage() : NULL; - bool directStorage = directStoragePossible(vertexBuffer, attribs[i]); + bool directStorage = vertexBuffer->directStoragePossible(attribs[i], currentValues[i]); unsigned int streamOffset = 0; unsigned int outputElementSize = 0; if (directStorage) { - outputElementSize = attribs[i].stride(); - streamOffset = attribs[i].mOffset + outputElementSize * start; - storage->markBufferUsage(); + outputElementSize = ComputeVertexAttributeStride(attribs[i]); + streamOffset = attribs[i].offset + outputElementSize * start; } else if (staticBuffer) { @@ -203,17 +200,18 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset)) { // Convert the entire buffer - int totalCount = elementsInBuffer(attribs[i], storage->getSize()); - int startIndex = attribs[i].mOffset / attribs[i].stride(); + int totalCount = ElementsInBuffer(attribs[i], storage->getSize()); + int startIndex = attribs[i].offset / ComputeVertexAttributeStride(attribs[i]); - if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset)) + if (!staticBuffer->storeVertexAttributes(attribs[i], currentValues[i], -startIndex, totalCount, + 0, &streamOffset)) { return GL_OUT_OF_MEMORY; } } - unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; - unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 0) ? start * outputElementSize : 0; + unsigned int firstElementOffset = (attribs[i].offset / ComputeVertexAttributeStride(attribs[i])) * outputElementSize; + unsigned int startOffset = (instances == 0 || attribs[i].divisor == 0) ? start * outputElementSize : 0; if (streamOffset + firstElementOffset + startOffset < streamOffset) { return GL_OUT_OF_MEMORY; @@ -225,7 +223,8 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], { int totalCount = StreamingBufferElementCount(attribs[i], count, instances); if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) || - !mStreamingBuffer->storeVertexAttributes(attribs[i], start, totalCount, instances, &streamOffset)) + !mStreamingBuffer->storeVertexAttributes(attribs[i], currentValues[i], start, totalCount, instances, + &streamOffset)) { return GL_OUT_OF_MEMORY; } @@ -234,9 +233,10 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], translated[i].storage = directStorage ? storage : NULL; translated[i].vertexBuffer = vertexBuffer->getVertexBuffer(); translated[i].serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); - translated[i].divisor = attribs[i].mDivisor; + translated[i].divisor = attribs[i].divisor; translated[i].attribute = &attribs[i]; + translated[i].currentValueType = currentValues[i].Type; translated[i].stride = outputElementSize; translated[i].offset = streamOffset; } @@ -249,27 +249,20 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i]; - if (mCurrentValue[i][0] != attribs[i].mCurrentValue[0] || - mCurrentValue[i][1] != attribs[i].mCurrentValue[1] || - mCurrentValue[i][2] != attribs[i].mCurrentValue[2] || - mCurrentValue[i][3] != attribs[i].mCurrentValue[3]) + if (mCurrentValue[i] != currentValues[i]) { - unsigned int requiredSpace = sizeof(float) * 4; - if (!buffer->reserveRawDataSpace(requiredSpace)) + if (!buffer->reserveVertexSpace(attribs[i], 1, 0)) { return GL_OUT_OF_MEMORY; } unsigned int streamOffset; - if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset)) + if (!buffer->storeVertexAttributes(attribs[i], currentValues[i], 0, 1, 0, &streamOffset)) { return GL_OUT_OF_MEMORY; } - mCurrentValue[i][0] = attribs[i].mCurrentValue[0]; - mCurrentValue[i][1] = attribs[i].mCurrentValue[1]; - mCurrentValue[i][2] = attribs[i].mCurrentValue[2]; - mCurrentValue[i][3] = attribs[i].mCurrentValue[3]; + mCurrentValue[i] = currentValues[i]; mCurrentValueOffsets[i] = streamOffset; } @@ -279,6 +272,7 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], translated[i].divisor = 0; translated[i].attribute = &attribs[i]; + translated[i].currentValueType = currentValues[i].Type; translated[i].stride = 0; translated[i].offset = mCurrentValueOffsets[i]; } @@ -287,13 +281,14 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - if (translated[i].active && attribs[i].mArrayEnabled) + if (translated[i].active && attribs[i].enabled) { - gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + gl::Buffer *buffer = attribs[i].buffer.get(); if (buffer) { - buffer->promoteStaticUsage(count * attribs[i].typeSize()); + BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); + bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(attribs[i])); } } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h index 1a8786552a..4164fbecbb 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h @@ -11,17 +11,19 @@ #define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ #include "libGLESv2/Constants.h" +#include "libGLESv2/VertexAttribute.h" #include "common/angleutils.h" namespace gl { -class VertexAttribute; +struct VertexAttribute; class ProgramBinary; +struct VertexAttribCurrentValueData; } namespace rx { -class BufferStorage; +class BufferD3D; class StreamingVertexBufferInterface; class VertexBuffer; class Renderer; @@ -31,11 +33,12 @@ struct TranslatedAttribute bool active; const gl::VertexAttribute *attribute; + GLenum currentValueType; unsigned int offset; unsigned int stride; // 0 means not to advance the read pointer at all VertexBuffer *vertexBuffer; - BufferStorage *storage; + BufferD3D *storage; unsigned int serial; unsigned int divisor; }; @@ -46,7 +49,8 @@ class VertexDataManager VertexDataManager(rx::Renderer *renderer); virtual ~VertexDataManager(); - GLenum prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); + GLenum prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], + gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); private: DISALLOW_COPY_AND_ASSIGN(VertexDataManager); @@ -55,7 +59,8 @@ class VertexDataManager StreamingVertexBufferInterface *mStreamingBuffer; - float mCurrentValue[gl::MAX_VERTEX_ATTRIBS][4]; + gl::VertexAttribCurrentValueData mCurrentValue[gl::MAX_VERTEX_ATTRIBS]; + StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS]; std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS]; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp new file mode 100644 index 0000000000..9b0f336ac7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp @@ -0,0 +1,1049 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 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. +// + +// Blit11.cpp: Texture copy utility class. + +#include "libGLESv2/main.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2dps.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dgs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3dps.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" + +namespace rx +{ + +static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) +{ + ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource); + if (!texture) + { + return DXGI_FORMAT_UNKNOWN; + } + + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + + SafeRelease(texture); + + return desc.Format; +} + +static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, + ID3D11Resource *source, unsigned int subresource, + const gl::Extents &size, unsigned int cpuAccessFlags) +{ + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = GetTextureFormat(source); + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.CPUAccessFlags = cpuAccessFlags; + stagingDesc.MiscFlags = 0; + stagingDesc.BindFlags = 0; + + ID3D11Texture2D *stagingTexture = NULL; + HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture); + if (FAILED(result)) + { + ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result); + return NULL; + } + + context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL); + + return stagingTexture; +} + +inline static void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + float *x1, float *y1, float *x2, float *y2, + float *u1, float *v1, float *u2, float *v2) +{ + *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f; + *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f; + *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f; + *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f; + + *u1 = sourceArea.x / float(sourceSize.width); + *v1 = sourceArea.y / float(sourceSize.height); + *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width); + *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height); +} + +static void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) +{ + float x1, y1, x2, y2, u1, v1, u2, v2; + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); + + d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(outVertices); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); + + *outStride = sizeof(d3d11::PositionTexCoordVertex); + *outVertexCount = 4; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; +} + +static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) +{ + ASSERT(sourceSize.depth > 0 && destSize.depth > 0); + + float x1, y1, x2, y2, u1, v1, u2, v2; + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); + + d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast<d3d11::PositionLayerTexCoord3DVertex*>(outVertices); + + for (int i = 0; i < destSize.depth; i++) + { + float readDepth = (float)i / std::max(destSize.depth - 1, 1); + + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth); + + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth); + } + + *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); + *outVertexCount = destSize.depth * 6; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; +} + +Blit11::Blit11(rx::Renderer11 *renderer) + : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters), + mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL), + mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL), + mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL), + mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL), + mSwizzleCB(NULL) +{ + HRESULT result; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) * + 6 * renderer->getRendererCaps().max3DTextureSize; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer"); + + D3D11_SAMPLER_DESC pointSamplerDesc; + pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.MipLODBias = 0.0f; + pointSamplerDesc.MaxAnisotropy = 0; + pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + pointSamplerDesc.BorderColor[0] = 0.0f; + pointSamplerDesc.BorderColor[1] = 0.0f; + pointSamplerDesc.BorderColor[2] = 0.0f; + pointSamplerDesc.BorderColor[3] = 0.0f; + pointSamplerDesc.MinLOD = 0.0f; + pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f; + + result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPointSampler, "Blit11 point sampler"); + + D3D11_SAMPLER_DESC linearSamplerDesc; + linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.MipLODBias = 0.0f; + linearSamplerDesc.MaxAnisotropy = 0; + linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + linearSamplerDesc.BorderColor[0] = 0.0f; + linearSamplerDesc.BorderColor[1] = 0.0f; + linearSamplerDesc.BorderColor[2] = 0.0f; + linearSamplerDesc.BorderColor[3] = 0.0f; + linearSamplerDesc.MinLOD = 0.0f; + linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f; + + result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler"); + + // Use a rasterizer state that will not cull so that inverted quads will not be culled + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + + rasterDesc.ScissorEnable = TRUE; + result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state"); + + rasterDesc.ScissorEnable = FALSE; + result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state"); + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); + + D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), &mQuad2DIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad2DIL, "Blit11 2D input layout"); + + result = device->CreateVertexShader(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), NULL, &mQuad2DVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader"); + + if (!renderer->isLevel9()) + { + result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader"); + + D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout"); + + result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); + + result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader"); + + } + + buildShaderMap(); + + D3D11_BUFFER_DESC swizzleBufferDesc; + swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4; + swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + swizzleBufferDesc.MiscFlags = 0; + swizzleBufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&swizzleBufferDesc, NULL, &mSwizzleCB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer"); +} + +Blit11::~Blit11() +{ + SafeRelease(mVertexBuffer); + SafeRelease(mPointSampler); + SafeRelease(mLinearSampler); + SafeRelease(mScissorEnabledRasterizerState); + SafeRelease(mScissorDisabledRasterizerState); + SafeRelease(mDepthStencilState); + + SafeRelease(mQuad2DIL); + SafeRelease(mQuad2DVS); + SafeRelease(mDepthPS); + + SafeRelease(mQuad3DIL); + SafeRelease(mQuad3DVS); + SafeRelease(mQuad3DGS); + + SafeRelease(mSwizzleCB); + + clearShaderMap(); +} + +static inline unsigned int GetSwizzleIndex(GLenum swizzle) +{ + unsigned int colorIndex = 0; + + switch (swizzle) + { + case GL_RED: colorIndex = 0; break; + case GL_GREEN: colorIndex = 1; break; + case GL_BLUE: colorIndex = 2; break; + case GL_ALPHA: colorIndex = 3; break; + case GL_ZERO: colorIndex = 4; break; + case GL_ONE: colorIndex = 5; break; + default: UNREACHABLE(); break; + } + + return colorIndex; +} + +bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, + GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +{ + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + source->GetDesc(&sourceSRVDesc); + GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format); + + GLenum shaderType = GL_NONE; + switch (gl::GetComponentType(sourceInternalFormat)) + { + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + shaderType = GL_FLOAT; + break; + case GL_INT: + shaderType = GL_INT; + break; + case GL_UNSIGNED_INT: + shaderType = GL_UNSIGNED_INT; + break; + default: + UNREACHABLE(); + break; + } + + SwizzleParameters parameters = { 0 }; + parameters.mDestinationType = shaderType; + parameters.mViewDimension = sourceSRVDesc.ViewDimension; + + SwizzleShaderMap::const_iterator i = mSwizzleShaderMap.find(parameters); + if (i == mSwizzleShaderMap.end()) + { + UNREACHABLE(); + return false; + } + + const Shader &shader = i->second; + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map vertex buffer for texture swizzle, HRESULT: 0x%X.", result); + return false; + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + gl::Box area(0, 0, 0, size.width, size.height, size.depth); + shader.mVertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Set constant buffer + result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map constant buffer for texture swizzle, HRESULT: 0x%X.", result); + return false; + } + + unsigned int *swizzleIndices = reinterpret_cast<unsigned int*>(mappedResource.pData); + swizzleIndices[0] = GetSwizzleIndex(swizzleRed); + swizzleIndices[1] = GetSwizzleIndex(swizzleGreen); + swizzleIndices[2] = GetSwizzleIndex(swizzleBlue); + swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha); + + deviceContext->Unmap(mSwizzleCB, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply constant buffer + deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + deviceContext->RSSetState(mScissorDisabledRasterizerState); + + // Apply shaders + deviceContext->IASetInputLayout(shader.mInputLayout); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); + + deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); + deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + // Apply render target + mRenderer->setOneTimeRenderTarget(dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = size.width; + viewport.Height = size.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &source); + + // Apply samplers + deviceContext->PSSetSamplers(0, 1, &mPointSampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return true; +} + +bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, GLenum destFormat, GLenum filter) +{ + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Determine if the source format is a signed integer format, the destFormat will already + // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned. + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + source->GetDesc(&sourceSRVDesc); + GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format); + + BlitParameters parameters = { 0 }; + parameters.mDestinationFormat = destFormat; + parameters.mSignedInteger = gl::GetComponentType(sourceInternalFormat) == GL_INT; + parameters.m3DBlit = sourceArea.depth > 1; + + BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters); + if (i == mBlitShaderMap.end()) + { + UNREACHABLE(); + return false; + } + + const Shader& shader = i->second; + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); + return false; + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + shader.mVertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, + &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + + if (scissor) + { + D3D11_RECT scissorRect; + scissorRect.left = scissor->x; + scissorRect.right = scissor->x + scissor->width; + scissorRect.top = scissor->y; + scissorRect.bottom = scissor->y + scissor->height; + + deviceContext->RSSetScissorRects(1, &scissorRect); + deviceContext->RSSetState(mScissorEnabledRasterizerState); + } + else + { + deviceContext->RSSetState(mScissorDisabledRasterizerState); + } + + // Apply shaders + deviceContext->IASetInputLayout(shader.mInputLayout); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); + + deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); + deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + // Apply render target + mRenderer->setOneTimeRenderTarget(dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &source); + + // Apply samplers + ID3D11SamplerState *sampler = NULL; + switch (filter) + { + case GL_NEAREST: sampler = mPointSampler; break; + case GL_LINEAR: sampler = mLinearSampler; break; + default: UNREACHABLE(); return false; + } + deviceContext->PSSetSamplers(0, 1, &sampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return true; +} + +bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, + dest, destSubresource, destArea, destSize, + scissor, true); +} + +bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); + return false; + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, + &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); + + if (scissor) + { + D3D11_RECT scissorRect; + scissorRect.left = scissor->x; + scissorRect.right = scissor->x + scissor->width; + scissorRect.top = scissor->y; + scissorRect.bottom = scissor->y + scissor->height; + + deviceContext->RSSetScissorRects(1, &scissorRect); + deviceContext->RSSetState(mScissorEnabledRasterizerState); + } + else + { + deviceContext->RSSetState(mScissorDisabledRasterizerState); + } + + // Apply shaders + deviceContext->IASetInputLayout(mQuad2DIL); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(mQuad2DVS, NULL, 0); + + deviceContext->PSSetShader(mDepthPS, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + // Apply render target + deviceContext->OMSetRenderTargets(0, NULL, dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &source); + + // Apply samplers + deviceContext->PSSetSamplers(0, 1, &mPointSampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return true; +} + +bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, + dest, destSubresource, destArea, destSize, + scissor, false); +} + +bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ); + // HACK: Create the destination staging buffer as a read/write texture so ID3D11DevicContext::UpdateSubresource can be called + // using it's mapped data as a source + ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE); + + if (!sourceStaging || !destStaging) + { + SafeRelease(sourceStaging); + SafeRelease(destStaging); + return false; + } + + DXGI_FORMAT format = GetTextureFormat(source); + ASSERT(format == GetTextureFormat(dest)); + + unsigned int pixelSize = d3d11::GetFormatPixelBytes(format); + unsigned int copyOffset = 0; + unsigned int copySize = pixelSize; + if (stencilOnly) + { + copyOffset = d3d11::GetStencilOffset(format) / 8; + copySize = d3d11::GetStencilBits(format) / 8; + + // It would be expensive to have non-byte sized stencil sizes since it would + // require reading from the destination, currently there aren't any though. + ASSERT(d3d11::GetStencilBits(format) % 8 == 0 && + d3d11::GetStencilOffset(format) % 8 == 0); + } + + D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping; + deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); + deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); + + if (!sourceMapping.pData || !destMapping.pData) + { + if (!sourceMapping.pData) + { + deviceContext->Unmap(sourceStaging, 0); + } + if (!destMapping.pData) + { + deviceContext->Unmap(destStaging, 0); + } + SafeRelease(sourceStaging); + SafeRelease(destStaging); + return false; + } + + gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); + + // Clip dest area to the destination size + gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea); + + // Clip dest area to the scissor + if (scissor) + { + gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea); + } + + // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is + // no out of bounds lookups required, the entire pixel is copied and no stretching + bool wholeRowCopy = sourceArea.width == clippedDestArea.width && + sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width && + copySize == pixelSize; + + for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++) + { + float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1); + + // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges + unsigned int readRow = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1); + unsigned int writeRow = y; + + if (wholeRowCopy) + { + void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) + + readRow * sourceMapping.RowPitch + + sourceArea.x * pixelSize; + + void *destRow = reinterpret_cast<char*>(destMapping.pData) + + writeRow * destMapping.RowPitch + + destArea.x * pixelSize; + + memcpy(destRow, sourceRow, pixelSize * destArea.width); + } + else + { + for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++) + { + float xPerc = static_cast<float>(x - destArea.x) / (destArea.width - 1); + + // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges + unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1); + unsigned int writeColumn = x; + + void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) + + readRow * sourceMapping.RowPitch + + readColumn * pixelSize + + copyOffset; + + void *destPixel = reinterpret_cast<char*>(destMapping.pData) + + writeRow * destMapping.RowPitch + + writeColumn * pixelSize + + copyOffset; + + memcpy(destPixel, sourcePixel, copySize); + } + } + } + + // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion + // according to MSDN. + deviceContext->UpdateSubresource(dest, destSubresource, NULL, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch); + + deviceContext->Unmap(sourceStaging, 0); + deviceContext->Unmap(destStaging, 0); + + // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some + // systems when called repeatedly. + // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, NULL); + + SafeRelease(sourceStaging); + SafeRelease(destStaging); + + return true; +} + +bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b) +{ + return memcmp(&a, &b, sizeof(Blit11::BlitParameters)) < 0; +} + +bool Blit11::compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b) +{ + return memcmp(&a, &b, sizeof(Blit11::SwizzleParameters)) < 0; +} + +void Blit11::add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) +{ + BlitParameters params = { 0 }; + params.mDestinationFormat = destFormat; + params.mSignedInteger = signedInteger; + params.m3DBlit = false; + + ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); + ASSERT(ps); + + Shader shader; + shader.mVertexWriteFunction = Write2DVertices; + shader.mInputLayout = mQuad2DIL; + shader.mVertexShader = mQuad2DVS; + shader.mGeometryShader = NULL; + shader.mPixelShader = ps; + + mBlitShaderMap[params] = shader; +} + +void Blit11::add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) +{ + BlitParameters params = { 0 }; + params.mDestinationFormat = destFormat; + params.mSignedInteger = signedInteger; + params.m3DBlit = true; + + ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); + ASSERT(ps); + + Shader shader; + shader.mVertexWriteFunction = Write3DVertices; + shader.mInputLayout = mQuad3DIL; + shader.mVertexShader = mQuad3DVS; + shader.mGeometryShader = mQuad3DGS; + shader.mPixelShader = ps; + + mBlitShaderMap[params] = shader; +} + +void Blit11::addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps) +{ + SwizzleParameters params = { 0 }; + params.mDestinationType = destType; + params.mViewDimension = viewDimension; + + ASSERT(mSwizzleShaderMap.find(params) == mSwizzleShaderMap.end()); + ASSERT(ps); + + Shader shader; + switch (viewDimension) + { + case D3D_SRV_DIMENSION_TEXTURE2D: + shader.mVertexWriteFunction = Write2DVertices; + shader.mInputLayout = mQuad2DIL; + shader.mVertexShader = mQuad2DVS; + shader.mGeometryShader = NULL; + break; + + case D3D_SRV_DIMENSION_TEXTURE3D: + case D3D_SRV_DIMENSION_TEXTURE2DARRAY: + case D3D_SRV_DIMENSION_TEXTURECUBE: + shader.mVertexWriteFunction = Write3DVertices; + shader.mInputLayout = mQuad3DIL; + shader.mVertexShader = mQuad3DVS; + shader.mGeometryShader = mQuad3DGS; + break; + + default: + UNREACHABLE(); + break; + } + shader.mPixelShader = ps; + + mSwizzleShaderMap[params] = shader; +} + +void Blit11::buildShaderMap() +{ + ID3D11Device *device = mRenderer->getDevice(); + + add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" )); + add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" )); + add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" )); + add2DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader" )); + add2DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader" )); + add2DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader" )); + add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" )); + add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader")); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); + + if (mRenderer->isLevel9()) + return; + + add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); + add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); + add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); + add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); + add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); + add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); + add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); + add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); + + add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); + add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); + add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); + add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); + add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); + add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); + add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); + add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); + add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); + add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); + add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); + add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); + add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); + add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); + add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); + add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); + + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" )); +} + +void Blit11::clearShaderMap() +{ + for (BlitShaderMap::iterator i = mBlitShaderMap.begin(); i != mBlitShaderMap.end(); ++i) + { + Shader &shader = i->second; + SafeRelease(shader.mPixelShader); + } + mBlitShaderMap.clear(); + + for (SwizzleShaderMap::iterator i = mSwizzleShaderMap.begin(); i != mSwizzleShaderMap.end(); ++i) + { + Shader &shader = i->second; + SafeRelease(shader.mPixelShader); + } + mSwizzleShaderMap.clear(); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h new file mode 100644 index 0000000000..fba89e20ba --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h @@ -0,0 +1,126 @@ +// +// Copyright (c) 2013 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. +// + +// Blit11.cpp: Texture copy utility class. + +#ifndef LIBGLESV2_BLIT11_H_ +#define LIBGLESV2_BLIT11_H_ + +#include "common/angleutils.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ +class Renderer11; + +enum Filter +{ + Point, + Linear, +}; + +class Blit11 +{ + public: + explicit Blit11(Renderer11 *renderer); + ~Blit11(); + + bool swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, + GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + + bool copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, GLenum destFormat, GLenum filter); + + bool copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + bool copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + private: + rx::Renderer11 *mRenderer; + + struct BlitParameters + { + GLenum mDestinationFormat; + bool mSignedInteger; + bool m3DBlit; + }; + + bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly); + + static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b); + + typedef void (*WriteVertexFunction)(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology); + + struct Shader + { + WriteVertexFunction mVertexWriteFunction; + ID3D11InputLayout *mInputLayout; + ID3D11VertexShader *mVertexShader; + ID3D11GeometryShader *mGeometryShader; + ID3D11PixelShader *mPixelShader; + }; + + typedef bool (*BlitParametersComparisonFunction)(const BlitParameters&, const BlitParameters &); + typedef std::map<BlitParameters, Shader, BlitParametersComparisonFunction> BlitShaderMap; + BlitShaderMap mBlitShaderMap; + + void add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); + void add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); + + struct SwizzleParameters + { + GLenum mDestinationType; + D3D11_SRV_DIMENSION mViewDimension; + }; + + static bool compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b); + + typedef bool (*SwizzleParametersComparisonFunction)(const SwizzleParameters&, const SwizzleParameters &); + typedef std::map<SwizzleParameters, Shader, SwizzleParametersComparisonFunction> SwizzleShaderMap; + SwizzleShaderMap mSwizzleShaderMap; + + void addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps); + + void buildShaderMap(); + void clearShaderMap(); + + ID3D11Buffer *mVertexBuffer; + ID3D11SamplerState *mPointSampler; + ID3D11SamplerState *mLinearSampler; + ID3D11RasterizerState *mScissorEnabledRasterizerState; + ID3D11RasterizerState *mScissorDisabledRasterizerState; + ID3D11DepthStencilState *mDepthStencilState; + + ID3D11InputLayout *mQuad2DIL; + ID3D11VertexShader *mQuad2DVS; + ID3D11PixelShader *mDepthPS; + + ID3D11InputLayout *mQuad3DIL; + ID3D11VertexShader *mQuad3DVS; + ID3D11GeometryShader *mQuad3DGS; + + ID3D11Buffer *mSwizzleCB; + + DISALLOW_COPY_AND_ASSIGN(Blit11); +}; + +} + +#endif // LIBGLESV2_BLIT11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp new file mode 100644 index 0000000000..352da9654a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp @@ -0,0 +1,900 @@ +#include "precompiled.h" +// +// Copyright 2014 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. +// + +// Buffer11.cpp Defines the Buffer11 class. + +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" + +namespace rx +{ + +PackPixelsParams::PackPixelsParams() + : format(GL_NONE), + type(GL_NONE), + outputPitch(0), + packBuffer(NULL), + offset(0) +{} + +PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, GLenum formatIn, GLenum typeIn, GLuint outputPitchIn, + const gl::PixelPackState &packIn, ptrdiff_t offsetIn) + : area(areaIn), + format(formatIn), + type(typeIn), + outputPitch(outputPitchIn), + packBuffer(packIn.pixelBuffer.get()), + pack(packIn.alignment, packIn.reverseRowOrder), + offset(offsetIn) +{} + +namespace gl_d3d11 +{ + +D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) +{ + bool readBit = ((access & GL_MAP_READ_BIT) != 0); + bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); + + ASSERT(readBit || writeBit); + + // Note : we ignore the discard bit, because in D3D11, staging buffers + // don't accept the map-discard flag (discard only works for DYNAMIC usage) + + if (readBit && !writeBit) + { + return D3D11_MAP_READ; + } + else if (writeBit && !readBit) + { + return D3D11_MAP_WRITE; + } + else if (writeBit && readBit) + { + return D3D11_MAP_READ_WRITE; + } + else + { + UNREACHABLE(); + return D3D11_MAP_READ; + } +} + +} + +// Each instance of Buffer11::BufferStorage11 is specialized for a class of D3D binding points +// - vertex/transform feedback buffers +// - index buffers +// - pixel unpack buffers +// - uniform buffers +class Buffer11::BufferStorage11 +{ + public: + virtual ~BufferStorage11() {} + + DataRevision getDataRevision() const { return mRevision; } + BufferUsage getUsage() const { return mUsage; } + size_t getSize() const { return mBufferSize; } + bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); } + + void setDataRevision(DataRevision rev) { mRevision = rev; } + + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset) = 0; + virtual bool resize(size_t size, bool preserveData) = 0; + + virtual void *map(size_t offset, size_t length, GLbitfield access) = 0; + virtual void unmap() = 0; + + protected: + BufferStorage11(Renderer11 *renderer, BufferUsage usage); + + Renderer11 *mRenderer; + DataRevision mRevision; + const BufferUsage mUsage; + size_t mBufferSize; +}; + +// A native buffer storage represents an underlying D3D11 buffer for a particular +// type of storage. +class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11 +{ + public: + NativeBuffer11(Renderer11 *renderer, BufferUsage usage); + ~NativeBuffer11(); + + ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; } + + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset); + virtual bool resize(size_t size, bool preserveData); + + virtual void *map(size_t offset, size_t length, GLbitfield access); + virtual void unmap(); + + private: + ID3D11Buffer *mNativeBuffer; + + static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize); +}; + +// Pack storage represents internal storage for pack buffers. We implement pack buffers +// as CPU memory, tied to a staging texture, for asynchronous texture readback. +class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 +{ + public: + PackStorage11(Renderer11 *renderer); + ~PackStorage11(); + + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset); + virtual bool resize(size_t size, bool preserveData); + + virtual void *map(size_t offset, size_t length, GLbitfield access); + virtual void unmap(); + + void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + + private: + + void flushQueuedPackCommand(); + + ID3D11Texture2D *mStagingTexture; + DXGI_FORMAT mTextureFormat; + gl::Extents mTextureSize; + MemoryBuffer mMemoryBuffer; + PackPixelsParams *mQueuedPackCommand; + PackPixelsParams mPackParams; + bool mDataModified; +}; + + +Buffer11::Buffer11(Renderer11 *renderer) + : BufferD3D(), + mRenderer(renderer), + mSize(0), + mMappedStorage(NULL), + mResolvedDataRevision(0), + mReadUsageCount(0) +{ +} + +Buffer11::~Buffer11() +{ + clear(); +} + +Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Buffer11*, buffer)); + return static_cast<Buffer11*>(buffer); +} + +void Buffer11::clear() +{ + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + { + SafeDelete(it->second); + } + + mBufferStorages.clear(); + + mSize = 0; + mResolvedDataRevision = 0; +} + +void Buffer11::setData(const void* data, size_t size, GLenum usage) +{ + mIndexRangeCache.clear(); + + setSubData(data, size, 0); + + if (usage == GL_STATIC_DRAW) + { + initializeStaticData(); + } +} + +void *Buffer11::getData() +{ + NativeBuffer11 *stagingBuffer = getStagingBuffer(); + + if (!stagingBuffer) + { + // Out-of-memory + return NULL; + } + + if (stagingBuffer->getDataRevision() > mResolvedDataRevision) + { + if (stagingBuffer->getSize() > mResolvedData.size()) + { + if (!mResolvedData.resize(stagingBuffer->getSize())) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } + } + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } + + memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize()); + + context->Unmap(stagingBuffer->getNativeBuffer(), 0); + + mResolvedDataRevision = stagingBuffer->getDataRevision(); + } + + mReadUsageCount = 0; + + return mResolvedData.data(); +} + +void Buffer11::setSubData(const void* data, size_t size, size_t offset) +{ + size_t requiredSize = size + offset; + mSize = std::max(mSize, requiredSize); + + mIndexRangeCache.invalidateRange(offset, size); + invalidateStaticData(); + + if (data && size > 0) + { + NativeBuffer11 *stagingBuffer = getStagingBuffer(); + + if (!stagingBuffer) + { + // Out-of-memory + return; + } + + // Explicitly resize the staging buffer, preserving data if the new data will not + // completely fill the buffer + if (stagingBuffer->getSize() < requiredSize) + { + bool preserveData = (offset > 0); + if (!stagingBuffer->resize(requiredSize, preserveData)) + { + // Out-of-memory + return; + } + } + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + + unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset; + memcpy(offsetBufferPointer, data, size); + + context->Unmap(stagingBuffer->getNativeBuffer(), 0); + + stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1); + } +} + +void Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + Buffer11 *sourceBuffer = makeBuffer11(source); + if (sourceBuffer) + { + BufferStorage11 *dest = getLatestBufferStorage(); + if (!dest) + { + dest = getStagingBuffer(); + } + + BufferStorage11 *source = sourceBuffer->getLatestBufferStorage(); + if (source && dest) + { + // If copying to/from a pixel pack buffer, we must have a staging or + // pack buffer partner, because other native buffers can't be mapped + if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable()) + { + source = sourceBuffer->getStagingBuffer(); + } + else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable()) + { + dest = getStagingBuffer(); + } + + dest->copyFromStorage(source, sourceOffset, size, destOffset); + dest->setDataRevision(dest->getDataRevision() + 1); + } + + mSize = std::max<size_t>(mSize, destOffset + size); + } + + invalidateStaticData(); +} + +GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(!mMappedStorage); + + BufferStorage11 *latestStorage = getLatestBufferStorage(); + if (latestStorage && + (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || + latestStorage->getUsage() == BUFFER_USAGE_STAGING)) + { + // Latest storage is mappable. + mMappedStorage = latestStorage; + } + else + { + // Fall back to using the staging buffer if the latest storage does + // not exist or is not CPU-accessible. + mMappedStorage = getStagingBuffer(); + } + + if (!mMappedStorage) + { + // Out-of-memory + return NULL; + } + + if ((access & GL_MAP_WRITE_BIT) > 0) + { + // Update the data revision immediately, since the data might be changed at any time + mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); + } + + return mMappedStorage->map(offset, length, access); +} + +void Buffer11::unmap() +{ + ASSERT(mMappedStorage); + mMappedStorage->unmap(); + mMappedStorage = NULL; +} + +void Buffer11::markTransformFeedbackUsage() +{ + BufferStorage11 *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + + if (transformFeedbackStorage) + { + transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); + } + + invalidateStaticData(); +} + +void Buffer11::markBufferUsage() +{ + mReadUsageCount++; + + const unsigned int usageLimit = 5; + + if (mReadUsageCount > usageLimit && mResolvedData.size() > 0) + { + mResolvedData.resize(0); + mResolvedDataRevision = 0; + } +} + +Renderer* Buffer11::getRenderer() +{ + return mRenderer; +} + +ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) +{ + markBufferUsage(); + + BufferStorage11 *bufferStorage = getBufferStorage(usage); + + if (!bufferStorage) + { + // Storage out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, bufferStorage)); + + return static_cast<NativeBuffer11*>(bufferStorage)->getNativeBuffer(); +} + +ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) +{ + BufferStorage11 *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); + + if (!storage) + { + // Storage out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, storage)); + ID3D11Buffer *buffer = static_cast<NativeBuffer11*>(storage)->getNativeBuffer(); + + auto bufferSRVIt = mBufferResourceViews.find(srvFormat); + + if (bufferSRVIt != mBufferResourceViews.end()) + { + if (bufferSRVIt->second.first == buffer) + { + return bufferSRVIt->second.second; + } + else + { + // The underlying buffer has changed since the SRV was created: recreate the SRV. + SafeRelease(bufferSRVIt->second.second); + } + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11ShaderResourceView *bufferSRV = NULL; + + D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; + bufferSRVDesc.Buffer.ElementOffset = 0; + bufferSRVDesc.Buffer.ElementWidth = mSize / d3d11::GetFormatPixelBytes(srvFormat); + bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + bufferSRVDesc.Format = srvFormat; + + HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV); + + return bufferSRV; +} + +void Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) +{ + PackStorage11 *packStorage = getPackStorage(); + + BufferStorage11 *latestStorage = getLatestBufferStorage(); + + if (packStorage) + { + packStorage->packPixels(srcTexture, srcSubresource, params); + packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1); + } +} + +Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage) +{ + BufferStorage11 *directBuffer = NULL; + auto directBufferIt = mBufferStorages.find(usage); + if (directBufferIt != mBufferStorages.end()) + { + directBuffer = directBufferIt->second; + } + + if (!directBuffer) + { + if (usage == BUFFER_USAGE_PIXEL_PACK) + { + directBuffer = new PackStorage11(mRenderer); + } + else + { + // buffer is not allocated, create it + directBuffer = new NativeBuffer11(mRenderer, usage); + } + + mBufferStorages.insert(std::make_pair(usage, directBuffer)); + } + + // resize buffer + if (directBuffer->getSize() < mSize) + { + if (!directBuffer->resize(mSize, true)) + { + // Out of memory error + return NULL; + } + } + + BufferStorage11 *latestBuffer = getLatestBufferStorage(); + if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision()) + { + // if copying from a pack buffer to a non-staging native buffer, we must first + // copy through the staging buffer, because other native buffers can't be mapped + if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable()) + { + NativeBuffer11 *stagingBuffer = getStagingBuffer(); + + stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); + directBuffer->setDataRevision(latestBuffer->getDataRevision()); + + latestBuffer = stagingBuffer; + } + + // if copyFromStorage returns true, the D3D buffer has been recreated + // and we should update our serial + if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) + { + updateSerial(); + } + directBuffer->setDataRevision(latestBuffer->getDataRevision()); + } + + return directBuffer; +} + +Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const +{ + // Even though we iterate over all the direct buffers, it is expected that only + // 1 or 2 will be present. + BufferStorage11 *latestStorage = NULL; + DataRevision latestRevision = 0; + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + { + BufferStorage11 *storage = it->second; + if (!latestStorage || storage->getDataRevision() > latestRevision) + { + latestStorage = storage; + latestRevision = storage->getDataRevision(); + } + } + + return latestStorage; +} + +Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer() +{ + BufferStorage11 *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); + + if (!stagingStorage) + { + // Out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, stagingStorage)); + return static_cast<NativeBuffer11*>(stagingStorage); +} + +Buffer11::PackStorage11 *Buffer11::getPackStorage() +{ + BufferStorage11 *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); + + if (!packStorage) + { + // Out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, packStorage)); + return static_cast<PackStorage11*>(packStorage); +} + +Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage) + : mRenderer(renderer), + mUsage(usage), + mRevision(0), + mBufferSize(0) +{ +} + +Buffer11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage) + : BufferStorage11(renderer, usage), + mNativeBuffer(NULL) +{ +} + +Buffer11::NativeBuffer11::~NativeBuffer11() +{ + SafeRelease(mNativeBuffer); +} + +// Returns true if it recreates the direct buffer +bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset) +{ + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + size_t requiredSize = sourceOffset + size; + bool createBuffer = !mNativeBuffer || mBufferSize < requiredSize; + + // (Re)initialize D3D buffer if needed + if (createBuffer) + { + bool preserveData = (destOffset > 0); + resize(source->getSize(), preserveData); + } + + if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK) + { + ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source)); + + void *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); + UNUSED_ASSERTION_VARIABLE(hr); + ASSERT(SUCCEEDED(hr)); + + unsigned char *destPointer = static_cast<unsigned char *>(mappedResource.pData) + destOffset; + + // Offset bounds are validated at the API layer + ASSERT(sourceOffset + size <= destOffset + mBufferSize); + memcpy(destPointer, sourcePointer, size); + } + else + { + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source)); + + D3D11_BOX srcBox; + srcBox.left = sourceOffset; + srcBox.right = sourceOffset + size; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source)); + ID3D11Buffer *sourceBuffer = static_cast<NativeBuffer11*>(source)->getNativeBuffer(); + + context->CopySubresourceRegion(mNativeBuffer, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox); + } + + return createBuffer; +} + +bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_BUFFER_DESC bufferDesc; + fillBufferDesc(&bufferDesc, mRenderer, mUsage, size); + + ID3D11Buffer *newBuffer; + HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); + + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, false); + } + + if (mNativeBuffer && preserveData) + { + // We don't call resize if the buffer is big enough already. + ASSERT(mBufferSize <= size); + + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = mBufferSize; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox); + } + + // No longer need the old buffer + SafeRelease(mNativeBuffer); + mNativeBuffer = newBuffer; + + mBufferSize = bufferDesc.ByteWidth; + + return true; +} + +void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, + BufferUsage usage, unsigned int bufferSize) +{ + bufferDesc->ByteWidth = bufferSize; + bufferDesc->MiscFlags = 0; + bufferDesc->StructureByteStride = 0; + + switch (usage) + { + case BUFFER_USAGE_STAGING: + bufferDesc->Usage = D3D11_USAGE_STAGING; + bufferDesc->BindFlags = 0; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + break; + + case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + if (renderer->getMaxTransformFeedbackBuffers() > 0) + bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_INDEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_PIXEL_UNPACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_UNIFORM: + bufferDesc->Usage = D3D11_USAGE_DYNAMIC; + bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + // Constant buffers must be of a limited size, and aligned to 16 byte boundaries + // For our purposes we ignore any buffer data past the maximum constant buffer size + bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u); + bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getMaxUniformBufferSize()); + break; + + default: + UNREACHABLE(); + } +} + +void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(mUsage == BUFFER_USAGE_STAGING); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); + UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); + + HRESULT result = context->Map(mNativeBuffer, 0, d3dMapType, d3dMapFlag, &mappedResource); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + return static_cast<GLubyte*>(mappedResource.pData) + offset; +} + +void Buffer11::NativeBuffer11::unmap() +{ + ASSERT(mUsage == BUFFER_USAGE_STAGING); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->Unmap(mNativeBuffer, 0); +} + +Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer) + : BufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK), + mStagingTexture(NULL), + mTextureFormat(DXGI_FORMAT_UNKNOWN), + mQueuedPackCommand(NULL), + mDataModified(false) +{ +} + +Buffer11::PackStorage11::~PackStorage11() +{ + SafeRelease(mStagingTexture); + SafeDelete(mQueuedPackCommand); +} + +bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset) +{ + UNIMPLEMENTED(); + return false; +} + +bool Buffer11::PackStorage11::resize(size_t size, bool preserveData) +{ + if (size != mBufferSize) + { + if (!mMemoryBuffer.resize(size)) + { + return false; + } + mBufferSize = size; + } + + return true; +} + +void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(offset + length <= getSize()); + // TODO: fast path + // We might be able to optimize out one or more memcpy calls by detecting when + // and if D3D packs the staging texture memory identically to how we would fill + // the pack buffer according to the current pack state. + + flushQueuedPackCommand(); + mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); + + return mMemoryBuffer.data() + offset; +} + +void Buffer11::PackStorage11::unmap() +{ + // No-op +} + +void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) +{ + flushQueuedPackCommand(); + mQueuedPackCommand = new PackPixelsParams(params); + + D3D11_TEXTURE2D_DESC textureDesc; + srcTexure->GetDesc(&textureDesc); + + if (mStagingTexture != NULL && + (mTextureFormat != textureDesc.Format || + mTextureSize.width != params.area.width || + mTextureSize.height != params.area.height)) + { + SafeRelease(mStagingTexture); + mTextureSize.width = 0; + mTextureSize.height = 0; + mTextureFormat = DXGI_FORMAT_UNKNOWN; + } + + if (mStagingTexture == NULL) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT hr; + + mTextureSize.width = params.area.width; + mTextureSize.height = params.area.height; + mTextureFormat = textureDesc.Format; + + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = params.area.width; + stagingDesc.Height = params.area.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = mTextureFormat; + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture); + ASSERT(SUCCEEDED(hr)); + } + + if (textureDesc.SampleDesc.Count > 1) + { + UNIMPLEMENTED(); + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + D3D11_BOX srcBox; + srcBox.left = params.area.x; + srcBox.right = params.area.x + params.area.width; + srcBox.top = params.area.y; + srcBox.bottom = params.area.y + params.area.height; + srcBox.front = 0; + srcBox.back = 1; + + // Asynchronous copy + immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox); +} + +void Buffer11::PackStorage11::flushQueuedPackCommand() +{ + ASSERT(mMemoryBuffer.size() > 0); + + if (mQueuedPackCommand) + { + mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); + SafeDelete(mQueuedPackCommand); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h new file mode 100644 index 0000000000..e56be247c4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h @@ -0,0 +1,106 @@ +// +// Copyright 2014 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. +// + +// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBGLESV2_RENDERER_BUFFER11_H_ +#define LIBGLESV2_RENDERER_BUFFER11_H_ + +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ +class Renderer11; + +enum BufferUsage +{ + BUFFER_USAGE_STAGING, + BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, + BUFFER_USAGE_INDEX, + BUFFER_USAGE_PIXEL_UNPACK, + BUFFER_USAGE_PIXEL_PACK, + BUFFER_USAGE_UNIFORM, +}; + +struct PackPixelsParams +{ + PackPixelsParams(); + PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, + const gl::PixelPackState &pack, ptrdiff_t offset); + + gl::Rectangle area; + GLenum format; + GLenum type; + GLuint outputPitch; + gl::Buffer *packBuffer; + gl::PixelPackState pack; + ptrdiff_t offset; +}; + +typedef size_t DataRevision; + +class Buffer11 : public BufferD3D +{ + public: + Buffer11(rx::Renderer11 *renderer); + virtual ~Buffer11(); + + static Buffer11 *makeBuffer11(BufferImpl *buffer); + + ID3D11Buffer *getBuffer(BufferUsage usage); + ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); + bool isMapped() const { return mMappedStorage != NULL; } + void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + + // BufferD3D implementation + virtual size_t getSize() const { return mSize; } + virtual void clear(); + virtual bool supportsDirectBinding() const { return true; } + virtual Renderer* getRenderer(); + + // BufferImpl implementation + virtual void setData(const void* data, size_t size, GLenum usage); + virtual void *getData(); + virtual void setSubData(const void* data, size_t size, size_t offset); + virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + virtual GLvoid* map(size_t offset, size_t length, GLbitfield access); + virtual void unmap(); + virtual void markTransformFeedbackUsage(); + + private: + DISALLOW_COPY_AND_ASSIGN(Buffer11); + + class BufferStorage11; + class NativeBuffer11; + class PackStorage11; + + rx::Renderer11 *mRenderer; + size_t mSize; + + BufferStorage11 *mMappedStorage; + + std::map<BufferUsage, BufferStorage11*> mBufferStorages; + + typedef std::pair<ID3D11Buffer *, ID3D11ShaderResourceView *> BufferSRVPair; + std::map<DXGI_FORMAT, BufferSRVPair> mBufferResourceViews; + + MemoryBuffer mResolvedData; + DataRevision mResolvedDataRevision; + unsigned int mReadUsageCount; + + void markBufferUsage(); + NativeBuffer11 *getStagingBuffer(); + PackStorage11 *getPackStorage(); + + BufferStorage11 *getBufferStorage(BufferUsage usage); + BufferStorage11 *getLatestBufferStorage() const; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp new file mode 100644 index 0000000000..8db5ea27c1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp @@ -0,0 +1,568 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 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. +// + +// Clear11.cpp: Framebuffer clear utility class. + +#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" + +#include "libGLESv2/formatutils.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatps.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintps.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintps.h" + +namespace rx +{ + +template <typename T> +static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color<T> &color, float depth, void *buffer) +{ + d3d11::PositionDepthColorVertex<T> *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex<T>*>(buffer); + + float depthClear = gl::clamp01(depth); + float left = -1.0f; + float right = 1.0f; + float top = -1.0f; + float bottom = 1.0f; + + // Clip the quad coordinates to the scissor if needed + if (scissor != NULL) + { + left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f); + right = std::min(right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f); + top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / float(framebufferSize.height)) * 2.0f - 1.0f); + bottom = std::min(bottom, ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f); + } + + d3d11::SetPositionDepthColorVertex<T>(vertices + 0, left, bottom, depthClear, color); + d3d11::SetPositionDepthColorVertex<T>(vertices + 1, left, top, depthClear, color); + d3d11::SetPositionDepthColorVertex<T>(vertices + 2, right, bottom, depthClear, color); + d3d11::SetPositionDepthColorVertex<T>(vertices + 3, right, top, depthClear, color); +} + +template <unsigned int vsSize, unsigned int psSize> +Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]) +{ + HRESULT result; + + ClearShader shader = { 0 }; + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quadLayout, ArraySize(quadLayout), vsByteCode, vsSize, &shader.inputLayout); + ASSERT(SUCCEEDED(result)); + + result = device->CreateVertexShader(vsByteCode, vsSize, NULL, &shader.vertexShader); + ASSERT(SUCCEEDED(result)); + + result = device->CreatePixelShader(psByteCode, psSize, NULL, &shader.pixelShader); + ASSERT(SUCCEEDED(result)); + + return shader; +} + +Clear11::Clear11(Renderer11 *renderer) + : mRenderer(renderer), mClearBlendStates(StructLessThan<ClearBlendInfo>), mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>), + mVertexBuffer(NULL), mRasterizerState(NULL) +{ + HRESULT result; + ID3D11Device *device = renderer->getDevice(); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex<float>) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); + + D3D11_RASTERIZER_DESC rsDesc; + rsDesc.FillMode = D3D11_FILL_SOLID; + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.FrontCounterClockwise = FALSE; + rsDesc.DepthBias = 0; + rsDesc.DepthBiasClamp = 0.0f; + rsDesc.SlopeScaledDepthBias = 0.0f; + rsDesc.DepthClipEnable = mRenderer->isLevel9(); + rsDesc.ScissorEnable = FALSE; + rsDesc.MultisampleEnable = FALSE; + rsDesc.AntialiasedLineEnable = FALSE; + + result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); + + mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); + if (mRenderer->isLevel9()) { + mUintClearShader = { 0 }; + mIntClearShader = { 0 }; + return; + } + + mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); + mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); +} + +Clear11::~Clear11() +{ + for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++) + { + SafeRelease(i->second); + } + mClearBlendStates.clear(); + + SafeRelease(mFloatClearShader.inputLayout); + SafeRelease(mFloatClearShader.vertexShader); + SafeRelease(mFloatClearShader.pixelShader); + + SafeRelease(mUintClearShader.inputLayout); + SafeRelease(mUintClearShader.vertexShader); + SafeRelease(mUintClearShader.pixelShader); + + SafeRelease(mIntClearShader.inputLayout); + SafeRelease(mIntClearShader.vertexShader); + SafeRelease(mIntClearShader.pixelShader); + + for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) + { + SafeRelease(i->second); + } + mClearDepthStencilStates.clear(); + + SafeRelease(mVertexBuffer); + SafeRelease(mRasterizerState); +} + +void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +{ + // First determine if a scissored clear is needed, this will always require drawing a quad. + // + // Otherwise, iterate over the color buffers which require clearing and determine if they can be + // cleared with ID3D11DeviceContext::ClearRenderTargetView... This requires: + // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer + // render targets as expected but does not work the other way around) + // 2) The format of the render target has no color channels that are currently masked out. + // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. + // + // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView + // by checking if the stencil write mask covers the entire stencil. + // + // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color + // attribute. + + gl::Extents framebufferSize; + if (frameBuffer->getFirstColorbuffer() != NULL) + { + gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); + framebufferSize.width = attachment->getWidth(); + framebufferSize.height = attachment->getHeight(); + framebufferSize.depth = 1; + } + else if (frameBuffer->getDepthOrStencilbuffer() != NULL) + { + gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); + framebufferSize.width = attachment->getWidth(); + framebufferSize.height = attachment->getHeight(); + framebufferSize.depth = 1; + } + else + { + UNREACHABLE(); + return; + } + + if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || + clearParams.scissor.y >= framebufferSize.height || + clearParams.scissor.x + clearParams.scissor.width <= 0 || + clearParams.scissor.y + clearParams.scissor.height <= 0)) + { + // Scissor is enabled and the scissor rectangle is outside the renderbuffer + return; + } + + bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || + clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || + clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); + + std::vector<MaskedRenderTarget> maskedClearRenderTargets; + RenderTarget11* maskedClearDepthStencil = NULL; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment)) + { + gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment); + if (attachment) + { + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(attachment->getRenderTarget()); + if (!renderTarget) + { + ERR("Render target pointer unexpectedly null."); + return; + } + + GLenum internalFormat = attachment->getInternalFormat(); + GLenum actualFormat = attachment->getActualFormat(); + GLenum componentType = gl::GetComponentType(internalFormat); + if (clearParams.colorClearType == GL_FLOAT && + !(componentType == GL_FLOAT || componentType == GL_UNSIGNED_NORMALIZED || componentType == GL_SIGNED_NORMALIZED)) + { + ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" + "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, internalFormat); + } + + GLuint internalRedBits = gl::GetRedBits(internalFormat); + GLuint internalGreenBits = gl::GetGreenBits(internalFormat); + GLuint internalBlueBits = gl::GetBlueBits(internalFormat); + GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat); + + if ((internalRedBits == 0 || !clearParams.colorMaskRed) && + (internalGreenBits == 0 || !clearParams.colorMaskGreen) && + (internalBlueBits == 0 || !clearParams.colorMaskBlue) && + (internalAlphaBits == 0 || !clearParams.colorMaskAlpha)) + { + // Every channel either does not exist in the render target or is masked out + continue; + } + else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT || + (internalRedBits > 0 && !clearParams.colorMaskRed) || + (internalGreenBits > 0 && !clearParams.colorMaskGreen) || + (internalBlueBits > 0 && !clearParams.colorMaskBlue) || + (internalAlphaBits > 0 && !clearParams.colorMaskAlpha)) + { + // A scissored or masked clear is required + MaskedRenderTarget maskAndRt; + bool clearColor = clearParams.clearColor[colorAttachment]; + maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); + maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); + maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); + maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); + maskAndRt.renderTarget = renderTarget; + maskedClearRenderTargets.push_back(maskAndRt); + } + else + { + // ID3D11DeviceContext::ClearRenderTargetView is possible + + ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); + if (!framebufferRTV) + { + ERR("Render target view pointer unexpectedly null."); + return; + } + + // Check if the actual format has a channel that the internal format does not and set them to the + // default values + GLuint actualRedBits = gl::GetRedBits(actualFormat); + GLuint actualGreenBits = gl::GetGreenBits(actualFormat); + GLuint actualBlueBits = gl::GetBlueBits(actualFormat); + GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat); + + const float clearValues[4] = + { + ((internalRedBits == 0 && actualRedBits > 0) ? 0.0f : clearParams.colorFClearValue.red), + ((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), + ((internalBlueBits == 0 && actualBlueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), + ((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + }; + + deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + } + } + } + } + + if (clearParams.clearDepth || clearParams.clearStencil) + { + gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); + if (attachment) + { + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(attachment->getDepthStencil()); + if (!renderTarget) + { + ERR("Depth stencil render target pointer unexpectedly null."); + return; + } + + GLenum actualFormat = attachment->getActualFormat(); + + unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << gl::GetStencilBits(actualFormat)) - 1 : 0; + bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + if (needScissoredClear || needMaskedStencilClear) + { + maskedClearDepthStencil = renderTarget; + } + else + { + ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + ERR("Depth stencil view pointer unexpectedly null."); + return; + } + + UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | + (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); + FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); + UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; + + deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); + } + } + } + + if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) + { + // To clear the render targets and depth stencil in one pass: + // + // Render a quad clipped to the scissor rectangle which draws the clear color and a blend + // state that will perform the required color masking. + // + // The quad's depth is equal to the depth clear value with a depth stencil state that + // will enable or disable depth test/writes if the depth buffer should be cleared or not. + // + // The rasterizer state's stencil is set to always pass or fail based on if the stencil + // should be cleared or not with a stencil write mask of the stencil clear value. + // + // ====================================================================================== + // + // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- + // buffer that is not normalized fixed point or floating point with floating point values + // are undefined so we can just write floats to them and D3D11 will bit cast them to + // integers. + // + // Also, we don't have to worry about attempting to clear a normalized fixed/floating point + // buffer with integer values because there is no gl API call which would allow it, + // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to + // be a compatible clear type. + + // Bind all the render targets which need clearing + ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); + std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size()); + for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) + { + RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; + ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); + if (!rtv) + { + ERR("Render target view unexpectedly null."); + return; + } + + rtvs[i] = rtv; + } + ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; + + ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); + const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + const UINT sampleMask = 0xFFFFFFFF; + + ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); + const UINT stencilClear = clearParams.stencilClearValue & 0xFF; + + // Set the vertices + UINT vertexStride = 0; + const UINT startIdx = 0; + const ClearShader* shader = NULL; + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); + return; + } + + const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; + switch (clearParams.colorClearType) + { + case GL_FLOAT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>); + shader = &mFloatClearShader; + break; + + case GL_UNSIGNED_INT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); + shader = &mUintClearShader; + break; + + case GL_INT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); + shader = &mIntClearShader; + break; + + default: + UNREACHABLE(); + break; + } + + deviceContext->Unmap(mVertexBuffer, 0); + + // Set the viewport to be the same size as the framebuffer + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = framebufferSize.width; + viewport.Height = framebufferSize.height; + viewport.MinDepth = 0; + viewport.MaxDepth = 1; + deviceContext->RSSetViewports(1, &viewport); + + // Apply state + deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); + deviceContext->OMSetDepthStencilState(dsState, stencilClear); + deviceContext->RSSetState(mRasterizerState); + + // Apply shaders + deviceContext->IASetInputLayout(shader->inputLayout); + deviceContext->VSSetShader(shader->vertexShader, NULL, 0); + deviceContext->PSSetShader(shader->pixelShader, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // Apply render targets + deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); + + // Draw the clear quad + deviceContext->Draw(4, 0); + + // Clean up + mRenderer->markAllStateDirty(); + } +} + +ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts) +{ + ClearBlendInfo blendKey = { 0 }; + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + if (i < rts.size()) + { + RenderTarget11 *rt = rts[i].renderTarget; + GLint internalFormat = rt->getInternalFormat(); + + blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && gl::GetRedBits(internalFormat) > 0); + blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && gl::GetGreenBits(internalFormat) > 0); + blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && gl::GetBlueBits(internalFormat) > 0); + blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && gl::GetAlphaBits(internalFormat) > 0); + } + else + { + blendKey.maskChannels[i][0] = false; + blendKey.maskChannels[i][1] = false; + blendKey.maskChannels[i][2] = false; + blendKey.maskChannels[i][3] = false; + } + } + + ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey); + if (i != mClearBlendStates.end()) + { + return i->second; + } + else + { + D3D11_BLEND_DESC blendDesc = { 0 }; + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE; + + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + blendDesc.RenderTarget[i].BlendEnable = FALSE; + blendDesc.RenderTarget[i].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[i][0], + blendKey.maskChannels[i][1], + blendKey.maskChannels[i][2], + blendKey.maskChannels[i][3]); + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11BlendState* blendState = NULL; + HRESULT result = device->CreateBlendState(&blendDesc, &blendState); + if (FAILED(result) || !blendState) + { + ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + return NULL; + } + + mClearBlendStates[blendKey] = blendState; + + return blendState; + } +} + +ID3D11DepthStencilState *Clear11::getDepthStencilState(const gl::ClearParameters &clearParams) +{ + ClearDepthStencilInfo dsKey = { 0 }; + dsKey.clearDepth = clearParams.clearDepth; + dsKey.clearStencil = clearParams.clearStencil; + dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF; + + ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey); + if (i != mClearDepthStencilStates.end()) + { + return i->second; + } + else + { + D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; + dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE; + dsDesc.DepthWriteMask = dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE; + dsDesc.StencilReadMask = 0; + dsDesc.StencilWriteMask = dsKey.stencilWriteMask; + dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DepthStencilState* dsState = NULL; + HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState); + if (FAILED(result) || !dsState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mClearDepthStencilStates[dsKey] = dsState; + + return dsState; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h new file mode 100644 index 0000000000..0cb9a85a6d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h @@ -0,0 +1,83 @@ +// +// Copyright (c) 2013 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. +// + +// Clear11.h: Framebuffer clear utility class. + +#ifndef LIBGLESV2_RENDERER_CLEAR11_H_ +#define LIBGLESV2_RENDERER_CLEAR11_H_ + +#include "libGLESv2/angletypes.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer11; +class RenderTarget11; + +class Clear11 +{ + public: + explicit Clear11(Renderer11 *renderer); + ~Clear11(); + + // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. + void clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + + private: + Renderer11 *mRenderer; + + struct ClearBlendInfo + { + bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + typedef bool (*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); + typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap; + ClearBlendStateMap mClearBlendStates; + + struct MaskedRenderTarget + { + bool colorMask[4]; + RenderTarget11 *renderTarget; + }; + + ID3D11BlendState *getBlendState(const std::vector<MaskedRenderTarget> &rts); + + struct ClearShader + { + ID3D11InputLayout *inputLayout; + ID3D11VertexShader *vertexShader; + ID3D11PixelShader *pixelShader; + }; + ClearShader mFloatClearShader; + ClearShader mUintClearShader; + ClearShader mIntClearShader; + + template <unsigned int vsSize, unsigned int psSize> + static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]); + + struct ClearDepthStencilInfo + { + bool clearDepth; + bool clearStencil; + UINT8 stencilWriteMask; + }; + typedef bool (*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &); + typedef std::map<ClearDepthStencilInfo, ID3D11DepthStencilState*, ClearDepthStencilInfoComparisonFunction> ClearDepthStencilStateMap; + ClearDepthStencilStateMap mClearDepthStencilStates; + + ID3D11DepthStencilState *getDepthStencilState(const gl::ClearParameters &clearParams); + + ID3D11Buffer *mVertexBuffer; + ID3D11RasterizerState *mRasterizerState; +}; + +} + +#endif // LIBGLESV2_RENDERER_CLEAR11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp new file mode 100644 index 0000000000..8698776650 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp @@ -0,0 +1,71 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 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. +// + +// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. + +#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +Fence11::Fence11(rx::Renderer11 *renderer) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Fence11::~Fence11() +{ + SafeRelease(mQuery); +} + +bool Fence11::isSet() const +{ + return mQuery != NULL; +} + +void Fence11::set() +{ + if (!mQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mRenderer->getDeviceContext()->End(mQuery); +} + +bool Fence11::test(bool flushCommandBuffer) +{ + ASSERT(mQuery); + + UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); + HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, getDataFlags); + + if (mRenderer->isDeviceLost()) + { + return gl::error(GL_OUT_OF_MEMORY, true); + } + + ASSERT(result == S_OK || result == S_FALSE); + return (result == S_OK); +} + +bool Fence11::hasError() const +{ + return mRenderer->isDeviceLost(); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h index a5398bca14..50c7621776 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h @@ -21,11 +21,10 @@ class Fence11 : public FenceImpl explicit Fence11(rx::Renderer11 *renderer); virtual ~Fence11(); - GLboolean isFence(); - void setFence(GLenum condition); - GLboolean testFence(); - void finishFence(); - void getFenceiv(GLenum pname, GLint *params); + bool isSet() const; + void set(); + bool test(bool flushCommandBuffer); + bool hasError() const; private: DISALLOW_COPY_AND_ASSIGN(Fence11); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp new file mode 100644 index 0000000000..2165bec305 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp @@ -0,0 +1,460 @@ +#include "precompiled.h" +// +// 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. +// + +// Image11.h: Implements the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" + +#include "libGLESv2/main.h" +#include "common/utilities.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +Image11::Image11() +{ + mStagingTexture = NULL; + mRenderer = NULL; + mDXGIFormat = DXGI_FORMAT_UNKNOWN; +} + +Image11::~Image11() +{ + SafeRelease(mStagingTexture); +} + +Image11 *Image11::makeImage11(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); + return static_cast<rx::Image11*>(img); +} + +void Image11::generateMipmap(Image11 *dest, Image11 *src) +{ + ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); + ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); + ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); + + MipGenerationFunction mipFunction = d3d11::GetMipGenerationFunction(src->getDXGIFormat()); + ASSERT(mipFunction != NULL); + + D3D11_MAPPED_SUBRESOURCE destMapped; + HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped); + if (FAILED(destMapResult)) + { + ERR("Failed to map destination image for mip map generation. HRESULT:0x%X", destMapResult); + return; + } + + D3D11_MAPPED_SUBRESOURCE srcMapped; + HRESULT srcMapResult = src->map(D3D11_MAP_READ, &srcMapped); + if (FAILED(srcMapResult)) + { + ERR("Failed to map source image for mip map generation. HRESULT:0x%X", srcMapResult); + + dest->unmap(); + return; + } + + const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(srcMapped.pData); + uint8_t *destData = reinterpret_cast<uint8_t*>(destMapped.pData); + + mipFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, + destData, destMapped.RowPitch, destMapped.DepthPitch); + + dest->unmap(); + src->unmap(); + + dest->markDirty(); +} + +bool Image11::isDirty() const +{ + // Make sure that this image is marked as dirty even if the staging texture hasn't been created yet + // if initialization is required before use. + return (mDirty && (mStagingTexture || gl_d3d11::RequiresTextureDataInitialization(mInternalFormat))); +} + +bool Image11::copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, 0, width, height, 1); +} + +bool Image11::copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, 0, width, height, 1); +} + +bool Image11::copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +{ + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, zoffset, width, height, depth); +} + +bool Image11::copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height) +{ + TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, arrayLayer, xoffset, yoffset, 0, width, height, 1); +} + +bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) +{ + if (mWidth != width || + mHeight != height || + mInternalFormat != internalformat || + forceRelease) + { + mRenderer = Renderer11::makeRenderer11(renderer); + + mWidth = width; + mHeight = height; + mDepth = depth; + mInternalFormat = internalformat; + mTarget = target; + + // compute the d3d format that will be used + mDXGIFormat = gl_d3d11::GetTexFormat(internalformat); + mActualFormat = d3d11_gl::GetInternalFormat(mDXGIFormat); + mRenderable = gl_d3d11::GetRTVFormat(internalformat) != DXGI_FORMAT_UNKNOWN; + + SafeRelease(mStagingTexture); + mDirty = gl_d3d11::RequiresTextureDataInitialization(mInternalFormat); + + return true; + } + + return false; +} + +DXGI_FORMAT Image11::getDXGIFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); + + return mDXGIFormat; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input) +{ + GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, width, unpackAlignment); + GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, type, width, height, unpackAlignment); + GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat); + + LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, type); + ASSERT(loadFunction != NULL); + + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + if (FAILED(result)) + { + ERR("Could not map image for loading."); + return; + } + + uint8_t* offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch)); + loadFunction(width, height, depth, + reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch, + offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + + unmap(); +} + +void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input) +{ + GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, 1); + GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, height, 1); + + GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat); + GLuint outputBlockWidth = d3d11::GetBlockWidth(mDXGIFormat); + GLuint outputBlockHeight = d3d11::GetBlockHeight(mDXGIFormat); + + ASSERT(xoffset % outputBlockWidth == 0); + ASSERT(yoffset % outputBlockHeight == 0); + + LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, GL_UNSIGNED_BYTE); + ASSERT(loadFunction != NULL); + + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + if (FAILED(result)) + { + ERR("Could not map image for loading."); + return; + } + + uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch + + (xoffset / outputBlockWidth) * outputPixelSize + + zoffset * mappedImage.DepthPitch); + + loadFunction(width, height, depth, + reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch, + offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + + unmap(); +} + +void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); + + if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat) + { + // No conversion needed-- use copyback fastpath + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + { + D3D11_TEXTURE2D_DESC textureDesc; + colorBufferTexture->GetDesc(&textureDesc); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Texture2D* srcTex = NULL; + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); + if (FAILED(result)) + { + ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); + return; + } + + deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); + subresourceIndex = 0; + } + else + { + srcTex = colorBufferTexture; + srcTex->AddRef(); + } + + D3D11_BOX srcBox; + srcBox.left = x; + srcBox.right = x + width; + srcBox.top = y; + srcBox.bottom = y + height; + srcBox.front = 0; + srcBox.back = 1; + + deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox); + + SafeRelease(srcTex); + SafeRelease(colorBufferTexture); + } + } + else + { + // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + if (FAILED(result)) + { + ERR("Failed to map texture for Image11::copy, HRESULT: 0x%X.", result); + return; + } + + // determine the offset coordinate into the destination buffer + GLsizei rowOffset = gl::GetPixelBytes(mActualFormat) * xoffset; + void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; + + GLenum format = gl::GetFormat(mInternalFormat); + GLenum type = gl::GetType(mInternalFormat); + + mRenderer->readPixels(source, x, y, width, height, format, type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + + unmap(); + } +} + +ID3D11Resource *Image11::getStagingTexture() +{ + createStagingTexture(); + + return mStagingTexture; +} + +unsigned int Image11::getStagingSubresource() +{ + createStagingTexture(); + + return mStagingSubresource; +} + +void Image11::createStagingTexture() +{ + if (mStagingTexture) + { + return; + } + + const DXGI_FORMAT dxgiFormat = getDXGIFormat(); + + if (mWidth > 0 && mHeight > 0 && mDepth > 0) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + int lodOffset = 1; + GLsizei width = mWidth; + GLsizei height = mHeight; + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); + + if (mTarget == GL_TEXTURE_3D) + { + ID3D11Texture3D *newTexture = NULL; + + D3D11_TEXTURE3D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.Depth = mDepth; + desc.MipLevels = lodOffset + 1; + desc.Format = dxgiFormat; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (gl_d3d11::RequiresTextureDataInitialization(mInternalFormat)) + { + std::vector<D3D11_SUBRESOURCE_DATA> initialData; + std::vector< std::vector<BYTE> > textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth, + lodOffset + 1, &initialData, &textureData); + + result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture3D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) + { + ID3D11Texture2D *newTexture = NULL; + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = lodOffset + 1; + desc.ArraySize = 1; + desc.Format = dxgiFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (gl_d3d11::RequiresTextureDataInitialization(mInternalFormat)) + { + std::vector<D3D11_SUBRESOURCE_DATA> initialData; + std::vector< std::vector<BYTE> > textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1, + lodOffset + 1, &initialData, &textureData); + + result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture2D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else + { + UNREACHABLE(); + } + } + + mDirty = false; +} + +HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) +{ + createStagingTexture(); + + HRESULT result = E_FAIL; + + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map); + + // this can fail if the device is removed (from TDR) + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else if (SUCCEEDED(result)) + { + mDirty = true; + } + } + + return result; +} + +void Image11::unmap() +{ + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->Unmap(mStagingTexture, mStagingSubresource); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h index 11a6492dc8..7d873a2794 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h @@ -10,7 +10,7 @@ #ifndef LIBGLESV2_RENDERER_IMAGE11_H_ #define LIBGLESV2_RENDERER_IMAGE11_H_ -#include "libGLESv2/renderer/Image.h" +#include "libGLESv2/renderer/d3d/ImageD3D.h" #include "common/debug.h" @@ -26,7 +26,7 @@ class Renderer11; class TextureStorageInterface2D; class TextureStorageInterfaceCube; -class Image11 : public Image +class Image11 : public ImageD3D { public: Image11(); @@ -38,20 +38,21 @@ class Image11 : public Image virtual bool isDirty() const; - virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + virtual bool copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height); - virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); + virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease); - virtual bool isRenderableFormat() const; DXGI_FORMAT getDXGIFormat() const; - virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input); - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input); + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, const void *input); - virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); protected: HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); @@ -60,14 +61,14 @@ class Image11 : public Image private: DISALLOW_COPY_AND_ASSIGN(Image11); - ID3D11Texture2D *getStagingTexture(); + ID3D11Resource *getStagingTexture(); unsigned int getStagingSubresource(); void createStagingTexture(); Renderer11 *mRenderer; DXGI_FORMAT mDXGIFormat; - ID3D11Texture2D *mStagingTexture; + ID3D11Resource *mStagingTexture; unsigned int mStagingSubresource; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp index 44f9976d43..03e4e6611b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -7,8 +7,8 @@ // IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. -#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" namespace rx { @@ -22,20 +22,12 @@ IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) IndexBuffer11::~IndexBuffer11() { - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } + SafeRelease(mBuffer); } bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) { - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } + SafeRelease(mBuffer); updateSerial(); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h index 39a61946ad..e821b7f3d1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ #define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ -#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp index 4940b8c638..3536fafac9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -8,19 +8,35 @@ // InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches // D3D11 input layouts. -#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" #include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "third_party/murmurhash/MurmurHash3.h" namespace rx { +static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS], + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) +{ + for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex]; + + if (translatedAttributes[attributeIndex].active) + { + inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute, + translatedAttribute.currentValueType); + } + } +} + const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) @@ -31,7 +47,7 @@ InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInp mCurrentIL = NULL; for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - mCurrentBuffers[i] = -1; + mCurrentBuffers[i] = NULL; mCurrentVertexStrides[i] = -1; mCurrentVertexOffsets[i] = -1; } @@ -53,7 +69,7 @@ void InputLayoutCache::clear() { for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) { - i->second.inputLayout->Release(); + SafeRelease(i->second.inputLayout); } mInputLayoutMap.clear(); markDirty(); @@ -64,7 +80,7 @@ void InputLayoutCache::markDirty() mCurrentIL = NULL; for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - mCurrentBuffers[i] = -1; + mCurrentBuffers[i] = NULL; mCurrentVertexStrides[i] = -1; mCurrentVertexOffsets[i] = -1; } @@ -84,22 +100,17 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M InputLayoutKey ilKey = { 0 }; - ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL }; - unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - static const char* semanticName = "TEXCOORD"; for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { if (attributes[i].active) { - VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); - BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL; - D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType); + DXGI_FORMAT dxgiFormat = gl_d3d11::GetNativeVertexFormat(vertexFormat); + // Record the type of the associated vertex shader vector in our key // This will prevent mismatched vertex shaders from using the same input layout GLint attributeSize; @@ -107,31 +118,28 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; - ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT; + ilKey.elements[ilKey.elementCount].desc.Format = dxgiFormat; ilKey.elements[ilKey.elementCount].desc.InputSlot = i; ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; ilKey.elementCount++; - - vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX) : vertexBuffer->getBuffer(); - vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial(); - vertexStrides[i] = attributes[i].stride; - vertexOffsets[i] = attributes[i].offset; } } ID3D11InputLayout *inputLayout = NULL; - InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey); - if (i != mInputLayoutMap.end()) + InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey); + if (keyIter != mInputLayoutMap.end()) { - inputLayout = i->second.inputLayout; - i->second.lastUsedTime = mCounter++; + inputLayout = keyIter->second.inputLayout; + keyIter->second.lastUsedTime = mCounter++; } else { - ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); + gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; + GetInputLayout(attributes, shaderInputLayout); + ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutableForInputLayout(shaderInputLayout)); D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; for (unsigned int j = 0; j < ilKey.elementCount; ++j) @@ -159,7 +167,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M leastRecentlyUsed = i; } } - leastRecentlyUsed->second.inputLayout->Release(); + SafeRelease(leastRecentlyUsed->second.inputLayout); mInputLayoutMap.erase(leastRecentlyUsed); } @@ -176,18 +184,45 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M mCurrentIL = inputLayout; } + bool dirtyBuffers = false; + size_t minDiff = gl::MAX_VERTEX_ATTRIBS; + size_t maxDiff = 0; for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] || - vertexOffsets[i] != mCurrentVertexOffsets[i]) + ID3D11Buffer *buffer = NULL; + + if (attributes[i].active) + { + VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); + Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL; + + buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK) + : vertexBuffer->getBuffer(); + } + + UINT vertexStride = attributes[i].stride; + UINT vertexOffset = attributes[i].offset; + + if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] || + vertexOffset != mCurrentVertexOffsets[i]) { - mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]); - mCurrentBuffers[i] = vertexBufferSerials[i]; - mCurrentVertexStrides[i] = vertexStrides[i]; - mCurrentVertexOffsets[i] = vertexOffsets[i]; + dirtyBuffers = true; + minDiff = std::min(minDiff, static_cast<size_t>(i)); + maxDiff = std::max(maxDiff, static_cast<size_t>(i)); + + mCurrentBuffers[i] = buffer; + mCurrentVertexStrides[i] = vertexStride; + mCurrentVertexOffsets[i] = vertexOffset; } } + if (dirtyBuffers) + { + ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); + mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff, + mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff); + } + return GL_NO_ERROR; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h index bb1a8eebcf..5d0ac60537 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h @@ -67,7 +67,7 @@ class InputLayoutCache }; ID3D11InputLayout *mCurrentIL; - unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; + ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp new file mode 100644 index 0000000000..07040342c7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -0,0 +1,253 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 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. +// + +// PixelTransfer11.cpp: +// Implementation for buffer-to-texture and texture-to-buffer copies. +// Used to implement pixel transfers from unpack and to pack buffers. +// + +#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/Context.h" + +// Precompiled shaders +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturevs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturegs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4fps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4ips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4uips.h" + +namespace rx +{ + +PixelTransfer11::PixelTransfer11(Renderer11 *renderer) + : mRenderer(renderer), + mBufferToTextureVS(NULL), + mBufferToTextureGS(NULL), + mParamsConstantBuffer(NULL), + mCopyRasterizerState(NULL), + mCopyDepthStencilState(NULL) +{ + HRESULT result = S_OK; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = FALSE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + + result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState); + ASSERT(SUCCEEDED(result)); + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState); + ASSERT(SUCCEEDED(result)); + + D3D11_BUFFER_DESC constantBufferDesc = { 0 }; + constantBufferDesc.ByteWidth = rx::roundUp<UINT>(sizeof(CopyShaderParams), 32u); + constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDesc.MiscFlags = 0; + constantBufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer"); + + StructZero(&mParamsData); + + // init shaders + if (mRenderer->isLevel9()) + return; + + mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); + mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); + + buildShaderMap(); +} + +PixelTransfer11::~PixelTransfer11() +{ + for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) + { + SafeRelease(shaderMapIt->second); + } + + mBufferToTexturePSMap.clear(); + + SafeRelease(mBufferToTextureVS); + SafeRelease(mBufferToTextureGS); + SafeRelease(mParamsConstantBuffer); + SafeRelease(mCopyRasterizerState); + SafeRelease(mCopyDepthStencilState); +} + +void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, + const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut) +{ + StructZero(parametersOut); + + float texelCenterX = 0.5f / static_cast<float>(destSize.width - 1); + float texelCenterY = 0.5f / static_cast<float>(destSize.height - 1); + + unsigned int bytesPerPixel = gl::GetPixelBytes(internalFormat); + unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment); + unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); + + parametersOut->FirstPixelOffset = offset; + parametersOut->PixelsPerRow = static_cast<unsigned int>(destArea.width); + parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels); + parametersOut->RowsPerSlice = static_cast<unsigned int>(destArea.height); + parametersOut->PositionOffset[0] = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f; + parametersOut->PositionOffset[1] = texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f; + parametersOut->PositionScale[0] = 2.0f / static_cast<float>(destSize.width); + parametersOut->PositionScale[1] = -2.0f / static_cast<float>(destSize.height); +} + +bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + gl::Extents destSize = destRenderTarget->getExtents(); + + if (destArea.x < 0 || destArea.x + destArea.width > destSize.width || + destArea.y < 0 || destArea.y + destArea.height > destSize.height || + destArea.z < 0 || destArea.z + destArea.depth > destSize.depth ) + { + return false; + } + + const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); + + ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); + + ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); + ASSERT(pixelShader); + + // The SRV must be in the proper read format, which may be different from the destination format + // EG: for half float data, we can load full precision floats with implicit conversion + GLenum unsizedFormat = gl::GetFormat(destinationFormat); + GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); + + DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(sourceFormat); + ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); + Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation()); + ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat); + ASSERT(bufferSRV != NULL); + + ID3D11RenderTargetView *textureRTV = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(textureRTV != NULL); + + CopyShaderParams shaderParams; + setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11ShaderResourceView *nullSRV = NULL; + ID3D11Buffer *nullBuffer = NULL; + UINT zero = 0; + + // Are we doing a 2D or 3D copy? + ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); + + deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); + deviceContext->GSSetShader(geometryShader, NULL, 0); + deviceContext->PSSetShader(pixelShader, NULL, 0); + deviceContext->PSSetShaderResources(0, 1, &bufferSRV); + deviceContext->IASetInputLayout(NULL); + deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); + deviceContext->RSSetState(mCopyRasterizerState); + + mRenderer->setOneTimeRenderTarget(textureRTV); + + if (!StructEquals(mParamsData, shaderParams)) + { + d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); + mParamsData = shaderParams; + } + + deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + UINT numPixels = (destArea.width * destArea.height * destArea.depth); + deviceContext->Draw(numPixels, 0); + + // Unbind textures and render targets and vertex buffer + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); + + mRenderer->markAllStateDirty(); + + return true; +} + +void PixelTransfer11::buildShaderMap() +{ + ID3D11Device *device = mRenderer->getDevice(); + + mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps"); + mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps"); + mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps"); +} + +ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const +{ + GLenum componentType = gl::GetComponentType(internalFormat); + + if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) + { + componentType = GL_FLOAT; + } + + auto shaderMapIt = mBufferToTexturePSMap.find(componentType); + return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h new file mode 100644 index 0000000000..2e2fee8f50 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h @@ -0,0 +1,82 @@ +// +// Copyright (c) 2013 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. +// + +// PixelTransfer11.h: +// Buffer-to-Texture and Texture-to-Buffer data transfers. +// Used to implement pixel unpack and pixel pack buffers in ES3. + +#ifndef LIBGLESV2_PIXELTRANSFER11_H_ +#define LIBGLESV2_PIXELTRANSFER11_H_ + +#include "common/platform.h" + +namespace gl +{ + +class Buffer; +struct Box; +struct Extents; +struct PixelUnpackState; + +} + +namespace rx +{ +class Renderer11; +class RenderTarget; + +class PixelTransfer11 +{ + public: + explicit PixelTransfer11(Renderer11 *renderer); + ~PixelTransfer11(); + + static bool supportsBufferToTextureCopy(GLenum internalFormat); + + // unpack: the source buffer is stored in the unpack state, and buffer strides + // offset: the start of the data within the unpack buffer + // destRenderTarget: individual slice/layer of a target texture + // destinationFormat/sourcePixelsType: determines shaders + shader parameters + // destArea: the sub-section of destRenderTarget to copy to + bool copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + private: + + struct CopyShaderParams + { + unsigned int FirstPixelOffset; + unsigned int PixelsPerRow; + unsigned int RowStride; + unsigned int RowsPerSlice; + float PositionOffset[2]; + float PositionScale[2]; + int TexLocationOffset[2]; + int TexLocationScale[2]; + }; + + static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, + const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut); + + void buildShaderMap(); + ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const; + + Renderer11 *mRenderer; + + std::map<GLenum, ID3D11PixelShader *> mBufferToTexturePSMap; + ID3D11VertexShader *mBufferToTextureVS; + ID3D11GeometryShader *mBufferToTextureGS; + ID3D11Buffer *mParamsConstantBuffer; + CopyShaderParams mParamsData; + + ID3D11RasterizerState *mCopyRasterizerState; + ID3D11DepthStencilState *mCopyDepthStencilState; + +}; + +} + +#endif // LIBGLESV2_PIXELTRANSFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp new file mode 100644 index 0000000000..17cf5cad47 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp @@ -0,0 +1,155 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 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. +// + +// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. + +#include "libGLESv2/renderer/d3d/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +static bool checkOcclusionQuery(ID3D11DeviceContext *context, ID3D11Query *query, UINT64 *numPixels) +{ + HRESULT result = context->GetData(query, numPixels, sizeof(UINT64), 0); + return (result == S_OK); +} + +static bool checkStreamOutPrimitivesWritten(ID3D11DeviceContext *context, ID3D11Query *query, UINT64 *numPrimitives) +{ + D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 }; + HRESULT result = context->GetData(query, &soStats, sizeof(D3D11_QUERY_DATA_SO_STATISTICS), 0); + *numPrimitives = soStats.NumPrimitivesWritten; + return (result == S_OK); +} + +Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Query11::~Query11() +{ + SafeRelease(mQuery); +} + +void Query11::begin() +{ + if (mQuery == NULL) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); + queryDesc.MiscFlags = 0; + + if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mRenderer->getDeviceContext()->Begin(mQuery); +} + +void Query11::end() +{ + ASSERT(mQuery); + mRenderer->getDeviceContext()->End(mQuery); + + mStatus = GL_FALSE; + mResult = GL_FALSE; +} + +GLuint Query11::getResult() +{ + if (mQuery != NULL) + { + while (!testQuery()) + { + Sleep(0); + // explicitly check for device loss, some drivers seem to return S_FALSE + // if the device is lost + if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, 0); + } + } + } + + return mResult; +} + +GLboolean Query11::isResultAvailable() +{ + if (mQuery != NULL) + { + testQuery(); + } + + return mStatus; +} + +GLboolean Query11::testQuery() +{ + if (mQuery != NULL && mStatus != GL_TRUE) + { + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + bool queryFinished = false; + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + { + UINT64 numPixels = 0; + queryFinished = checkOcclusionQuery(context, mQuery, &numPixels); + if (queryFinished) + { + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + } + } + break; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + { + UINT64 numPrimitives = 0; + queryFinished = checkStreamOutPrimitivesWritten(context, mQuery, &numPrimitives); + if (queryFinished) + { + mResult = static_cast<GLuint>(numPrimitives); + } + } + break; + + default: + UNREACHABLE(); + break; + } + + if (queryFinished) + { + mStatus = GL_TRUE; + } + else if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + return mStatus; + } + + return GL_TRUE; // prevent blocking when query is null +} + +bool Query11::isStarted() const +{ + return (mQuery != NULL); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h index 0a03de77ca..7a3df46d4f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h @@ -21,10 +21,11 @@ class Query11 : public QueryImpl Query11(rx::Renderer11 *renderer, GLenum type); virtual ~Query11(); - void begin(); - void end(); - GLuint getResult(); - GLboolean isResultAvailable(); + virtual void begin(); + virtual void end(); + virtual GLuint getResult(); + virtual GLboolean isResultAvailable(); + virtual bool isStarted() const; private: DISALLOW_COPY_AND_ASSIGN(Query11); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp index a1c324cd80..b185d97604 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // @@ -8,18 +8,28 @@ // RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render // state objects. -#include "libGLESv2/renderer/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" - +#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/utilities.h" +#include "libGLESv2/FramebufferAttachment.h" + #include "common/debug.h" #include "third_party/murmurhash/MurmurHash3.h" namespace rx { +template <typename mapType> +static void ClearStateMap(mapType &map) +{ + for (typename mapType::iterator i = map.begin(); i != map.end(); i++) + { + SafeRelease(i->second.first); + } + map.clear(); +} + // MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, // ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum // number of unique states of each type an application can create is 4096 @@ -49,29 +59,10 @@ void RenderStateCache::initialize(ID3D11Device *device) void RenderStateCache::clear() { - for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) - { - i->second.first->Release(); - } - mBlendStateCache.clear(); - - for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) - { - i->second.first->Release(); - } - mRasterizerStateCache.clear(); - - for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) - { - i->second.first->Release(); - } - mDepthStencilStateCache.clear(); - - for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) - { - i->second.first->Release(); - } - mSamplerStateCache.clear(); + ClearStateMap(mBlendStateCache); + ClearStateMap(mRasterizerStateCache); + ClearStateMap(mDepthStencilStateCache); + ClearStateMap(mSamplerStateCache); } std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) @@ -79,16 +70,16 @@ std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) static const unsigned int seed = 0xABCDEF98; std::size_t hash = 0; - MurmurHash3_x86_32(&blendState, sizeof(BlendStateKey), seed, &hash); + MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash); return hash; } bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b) { - return memcmp(&a, &b, sizeof(gl::BlendState)) == 0; + return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; } -ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState) +ID3D11BlendState *RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState) { if (!mDevice) { @@ -102,19 +93,18 @@ ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, key.blendState = blendState; for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { - gl::Renderbuffer *renderBuffer = framebuffer->getColorbuffer(i); - if (renderBuffer) + const gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(i); + if (attachment) { if (i > 0) { mrt = true; } - GLenum internalFormat = renderBuffer->getInternalFormat(); - key.rtChannels[i][0] = gl::GetRedSize(internalFormat) > 0; - key.rtChannels[i][1] = gl::GetGreenSize(internalFormat) > 0; - key.rtChannels[i][2] = gl::GetBlueSize(internalFormat) > 0;; - key.rtChannels[i][3] = gl::GetAlphaSize(internalFormat) > 0; + key.rtChannels[i][0] = attachment->getRedSize() > 0; + key.rtChannels[i][1] = attachment->getGreenSize() > 0; + key.rtChannels[i][2] = attachment->getBlueSize() > 0; + key.rtChannels[i][3] = attachment->getAlphaSize() > 0; } else { @@ -125,10 +115,10 @@ ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, } } - BlendStateMap::iterator i = mBlendStateCache.find(key); - if (i != mBlendStateCache.end()) + BlendStateMap::iterator keyIter = mBlendStateCache.find(key); + if (keyIter != mBlendStateCache.end()) { - BlendStateCounterPair &state = i->second; + BlendStateCounterPair &state = keyIter->second; state.second = mCounter++; return state.first; } @@ -147,7 +137,7 @@ ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, leastRecentlyUsed = i; } } - leastRecentlyUsed->second.first->Release(); + SafeRelease(leastRecentlyUsed->second.first); mBlendStateCache.erase(leastRecentlyUsed); } @@ -206,8 +196,7 @@ bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, cons return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; } -ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, - bool scissorEnabled, unsigned int depthSize) +ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled) { if (!mDevice) { @@ -215,15 +204,14 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer return NULL; } - RasterizerStateKey key; + RasterizerStateKey key = { 0 }; key.rasterizerState = rasterState; key.scissorEnabled = scissorEnabled; - key.depthSize = depthSize; - RasterizerStateMap::iterator i = mRasterizerStateCache.find(key); - if (i != mRasterizerStateCache.end()) + RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key); + if (keyIter != mRasterizerStateCache.end()) { - RasterizerStateCounterPair &state = i->second; + RasterizerStateCounterPair &state = keyIter->second; state.second = mCounter++; return state.first; } @@ -242,7 +230,7 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer leastRecentlyUsed = i; } } - leastRecentlyUsed->second.first->Release(); + SafeRelease(leastRecentlyUsed->second.first); mRasterizerStateCache.erase(leastRecentlyUsed); } @@ -258,14 +246,23 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.CullMode = cullMode; rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE; - rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(depthSize)); rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. - rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; rasterDesc.DepthClipEnable = TRUE; rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; rasterDesc.MultisampleEnable = rasterState.multiSample; rasterDesc.AntialiasedLineEnable = FALSE; + if (rasterState.polygonOffsetFill) + { + rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; + rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits; + } + else + { + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBias = 0; + } + ID3D11RasterizerState *dx11RasterizerState = NULL; HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); if (FAILED(result) || !dx11RasterizerState) @@ -302,10 +299,10 @@ ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthS return NULL; } - DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState); - if (i != mDepthStencilStateCache.end()) + DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState); + if (keyIter != mDepthStencilStateCache.end()) { - DepthStencilStateCounterPair &state = i->second; + DepthStencilStateCounterPair &state = keyIter->second; state.second = mCounter++; return state.first; } @@ -324,7 +321,7 @@ ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthS leastRecentlyUsed = i; } } - leastRecentlyUsed->second.first->Release(); + SafeRelease(leastRecentlyUsed->second.first); mDepthStencilStateCache.erase(leastRecentlyUsed); } @@ -380,10 +377,10 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa return NULL; } - SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState); - if (i != mSamplerStateCache.end()) + SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState); + if (keyIter != mSamplerStateCache.end()) { - SamplerStateCounterPair &state = i->second; + SamplerStateCounterPair &state = keyIter->second; state.second = mCounter++; return state.first; } @@ -402,25 +399,25 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa leastRecentlyUsed = i; } } - leastRecentlyUsed->second.first->Release(); + SafeRelease(leastRecentlyUsed->second.first); mSamplerStateCache.erase(leastRecentlyUsed); } D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy); + samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, + samplerState.maxAnisotropy, samplerState.compareMode); samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MipLODBias = static_cast<float>(samplerState.lodOffset); + samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR); + samplerDesc.MipLODBias = 0; samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc); samplerDesc.BorderColor[0] = 0.0f; samplerDesc.BorderColor[1] = 0.0f; samplerDesc.BorderColor[2] = 0.0f; samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset); - samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 - ? gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset) : FLT_MAX; + samplerDesc.MinLOD = samplerState.minLod; + samplerDesc.MaxLOD = samplerState.maxLod; ID3D11SamplerState *dx11SamplerState = NULL; HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h index b4b871a4bd..e6380fbd82 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // @@ -20,6 +20,7 @@ class Framebuffer; namespace rx { +class Renderer11; class RenderStateCache { @@ -30,10 +31,8 @@ class RenderStateCache void initialize(ID3D11Device *device); void clear(); - // Increments refcount on the returned blend state, Release() must be called. - ID3D11BlendState *getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState); - ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState, - bool scissorEnabled, unsigned int depthSize); + ID3D11BlendState *getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState); + ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled); ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState); ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState); @@ -63,7 +62,6 @@ class RenderStateCache { gl::RasterizerState rasterizerState; bool scissorEnabled; - unsigned int depthSize; }; static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp index 3707097aa4..6aa75ae5bd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp @@ -8,26 +8,67 @@ // RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers // retained by Renderbuffers. -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/main.h" namespace rx { -static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view) +static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) +{ + ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource); + if (texture1D) + { + D3D11_TEXTURE1D_DESC texDesc; + texture1D->GetDesc(&texDesc); + SafeRelease(texture1D); + + *mipLevels = texDesc.MipLevels; + *samples = 0; + + return true; + } + + ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource); + if (texture2D) + { + D3D11_TEXTURE2D_DESC texDesc; + texture2D->GetDesc(&texDesc); + SafeRelease(texture2D); + + *mipLevels = texDesc.MipLevels; + *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0; + + return true; + } + + ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(resource); + if (texture3D) + { + D3D11_TEXTURE3D_DESC texDesc; + texture3D->GetDesc(&texDesc); + SafeRelease(texture3D); + + *mipLevels = texDesc.MipLevels; + *samples = 0; + + return true; + } + + return false; +} + +static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; view->GetDesc(&rtvDesc); - D3D11_TEXTURE2D_DESC texDesc; - texture->GetDesc(&texDesc); - unsigned int mipSlice = 0; unsigned int arraySlice = 0; - unsigned int mipLevels = texDesc.MipLevels; switch (rtvDesc.ViewDimension) { @@ -76,20 +117,19 @@ static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11Rende break; } + unsigned int mipLevels, samples; + getTextureProperties(resource, &mipLevels, &samples); + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view) +static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; view->GetDesc(&dsvDesc); - D3D11_TEXTURE2D_DESC texDesc; - texture->GetDesc(&texDesc); - unsigned int mipSlice = 0; unsigned int arraySlice = 0; - unsigned int mipLevels = texDesc.MipLevels; switch (dsvDesc.ViewDimension) { @@ -123,7 +163,7 @@ static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11Depth arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; break; - case D3D11_RTV_DIMENSION_UNKNOWN: + case D3D11_DSV_DIMENSION_UNKNOWN: UNIMPLEMENTED(); break; @@ -132,16 +172,37 @@ static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11Depth break; } + unsigned int mipLevels, samples; + getTextureProperties(resource, &mipLevels, &samples); + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) +RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, + ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) { mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = tex; + + mTexture = resource; + if (mTexture) + { + mTexture->AddRef(); + } + mRenderTarget = rtv; + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + mDepthStencil = NULL; + mShaderResource = srv; + if (mShaderResource) + { + mShaderResource->AddRef(); + } + mSubresourceIndex = 0; if (mRenderTarget && mTexture) @@ -149,26 +210,45 @@ RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, D3D11_RENDER_TARGET_VIEW_DESC desc; mRenderTarget->GetDesc(&desc); - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); + unsigned int mipLevels, samples; + getTextureProperties(mTexture, &mipLevels, &samples); mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); mWidth = width; mHeight = height; - mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; + mDepth = depth; + mSamples = samples; - mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + mInternalFormat = d3d11_gl::GetInternalFormat(desc.Format); + mActualFormat = d3d11_gl::GetInternalFormat(desc.Format); } } -RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) +RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, + ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) { mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = tex; + + mTexture = resource; + if (mTexture) + { + mTexture->AddRef(); + } + mRenderTarget = NULL; + mDepthStencil = dsv; + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + mShaderResource = srv; + if (mShaderResource) + { + mShaderResource->AddRef(); + } + mSubresourceIndex = 0; if (mDepthStencil && mTexture) @@ -176,20 +256,21 @@ RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, D3D11_DEPTH_STENCIL_VIEW_DESC desc; mDepthStencil->GetDesc(&desc); - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); + unsigned int mipLevels, samples; + getTextureProperties(mTexture, &mipLevels, &samples); mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); mWidth = width; mHeight = height; - mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; + mDepth = depth; + mSamples = samples; - mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); + mInternalFormat = d3d11_gl::GetInternalFormat(desc.Format); + mActualFormat = d3d11_gl::GetInternalFormat(desc.Format); } } -RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth) +RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) { mRenderer = Renderer11::makeRenderer11(renderer); mTexture = NULL; @@ -197,9 +278,13 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height mDepthStencil = NULL; mShaderResource = NULL; - DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format); + DXGI_FORMAT texFormat = gl_d3d11::GetTexFormat(internalFormat); + DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(internalFormat); + DXGI_FORMAT rtvFormat = gl_d3d11::GetRTVFormat(internalFormat); + DXGI_FORMAT dsvFormat = gl_d3d11::GetDSVFormat(internalFormat); - int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); + DXGI_FORMAT multisampleFormat = (dsvFormat != DXGI_FORMAT_UNKNOWN ? dsvFormat : rtvFormat); + int supportedSamples = mRenderer->getNearestSupportedSamples(multisampleFormat, samples); if (supportedSamples < 0) { gl::error(GL_OUT_OF_MEMORY); @@ -214,16 +299,35 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height desc.Height = height; desc.MipLevels = 1; desc.ArraySize = 1; - desc.Format = requestedFormat; + desc.Format = texFormat; desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; - desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)); + + // If a rendertarget or depthstencil format exists for this texture format, + // we'll flag it to allow binding that way. Shader resource views are a little + // more complicated. + bool bindRTV = false, bindDSV = false, bindSRV = false; + bindRTV = (rtvFormat != DXGI_FORMAT_UNKNOWN); + bindDSV = (dsvFormat != DXGI_FORMAT_UNKNOWN); + if (srvFormat != DXGI_FORMAT_UNKNOWN) + { + // Multisample targets flagged for binding as depth stencil cannot also be + // flagged for binding as SRV, so make certain not to add the SRV flag for + // these targets. + bindSRV = !(dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); + } + + desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | + (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | + (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + ID3D11Texture2D *texture = NULL; + HRESULT result = device->CreateTexture2D(&desc, NULL, &texture); + mTexture = texture; if (result == E_OUTOFMEMORY) { @@ -232,10 +336,28 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height } ASSERT(SUCCEEDED(result)); - if (depth) + if (bindSRV) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = srvFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(mTexture); + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + } + + if (bindDSV) { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = requestedFormat; + dsvDesc.Format = dsvFormat; dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; dsvDesc.Texture2D.MipSlice = 0; dsvDesc.Flags = 0; @@ -243,82 +365,57 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height if (result == E_OUTOFMEMORY) { - mTexture->Release(); - mTexture = NULL; + SafeRelease(mTexture); + SafeRelease(mShaderResource); gl::error(GL_OUT_OF_MEMORY); + return; } ASSERT(SUCCEEDED(result)); } - else + + if (bindRTV) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = requestedFormat; + rtvDesc.Format = rtvFormat; rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; rtvDesc.Texture2D.MipSlice = 0; result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); if (result == E_OUTOFMEMORY) { - mTexture->Release(); - mTexture = NULL; + SafeRelease(mTexture); + SafeRelease(mShaderResource); + SafeRelease(mDepthStencil); gl::error(GL_OUT_OF_MEMORY); return; } ASSERT(SUCCEEDED(result)); - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = requestedFormat; - srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; - srvDesc.Texture2D.MostDetailedMip = 0; - srvDesc.Texture2D.MipLevels = 1; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); - - if (result == E_OUTOFMEMORY) + if (gl_d3d11::RequiresTextureDataInitialization(internalFormat)) { - mTexture->Release(); - mTexture = NULL; - mRenderTarget->Release(); - mRenderTarget = NULL; - gl::error(GL_OUT_OF_MEMORY); - return; + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + context->ClearRenderTargetView(mRenderTarget, clearValues); } - ASSERT(SUCCEEDED(result)); } } mWidth = width; mHeight = height; - mInternalFormat = format; + mDepth = 1; + mInternalFormat = internalFormat; mSamples = supportedSamples; - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat); + mActualFormat = d3d11_gl::GetInternalFormat(texFormat); mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); } RenderTarget11::~RenderTarget11() { - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mShaderResource) - { - mShaderResource->Release(); - mShaderResource = NULL; - } + SafeRelease(mTexture); + SafeRelease(mRenderTarget); + SafeRelease(mDepthStencil); + SafeRelease(mShaderResource); } RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) @@ -327,7 +424,12 @@ RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) return static_cast<rx::RenderTarget11*>(target); } -ID3D11Texture2D *RenderTarget11::getTexture() const +void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) +{ + // Currently a no-op +} + +ID3D11Resource *RenderTarget11::getTexture() const { return mTexture; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h index 97827f2639..ba9f76e5de 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h @@ -20,14 +20,17 @@ class Renderer11; class RenderTarget11 : public RenderTarget { public: - RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); - RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); - RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth); + // RenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them + RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth); + RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth); + RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples); virtual ~RenderTarget11(); static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); - ID3D11Texture2D *getTexture() const; + virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height); + + ID3D11Resource *getTexture() const; ID3D11RenderTargetView *getRenderTargetView() const; ID3D11DepthStencilView *getDepthStencilView() const; ID3D11ShaderResourceView *getShaderResourceView() const; @@ -38,7 +41,7 @@ class RenderTarget11 : public RenderTarget DISALLOW_COPY_AND_ASSIGN(RenderTarget11); unsigned int mSubresourceIndex; - ID3D11Texture2D *mTexture; + ID3D11Resource *mTexture; ID3D11RenderTargetView *mRenderTarget; ID3D11DepthStencilView *mDepthStencil; ID3D11ShaderResourceView *mShaderResource; @@ -48,4 +51,4 @@ class RenderTarget11 : public RenderTarget } -#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_
\ No newline at end of file +#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp index e70727c65e..17a13f97d6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // @@ -8,43 +8,39 @@ // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. #include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" +#include "common/utilities.h" +#include "common/platform.h" #include "libGLESv2/Buffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/renderer/VertexDataManager.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d11/Fence11.h" - -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h" - -#include "libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h" - +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" +#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" +#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" +#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" #include "libEGL/Display.h" -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) -# include <dxgi1_3.h> -# include <wrl.h> -# include <windows.applicationmodel.core.h> -typedef ABI::Windows::Foundation::IEventHandler<ABI::Windows::ApplicationModel::SuspendingEventArgs *> SuspendEventHandler; +// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process +// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. +#ifndef ANGLE_SKIP_DXGI_1_2_CHECK +#define ANGLE_SKIP_DXGI_1_2_CHECK 0 #endif #ifdef _DEBUG @@ -73,7 +69,10 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 }; -Renderer11::Renderer11(egl::Display *display) : Renderer(display) +Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) + : Renderer(display), + mDc(hDc), + mRequestedDisplay(requestedDisplay) { mVertexDataManager = NULL; mIndexDataManager = NULL; @@ -81,24 +80,10 @@ Renderer11::Renderer11(egl::Display *display) : Renderer(display) mLineLoopIB = NULL; mTriangleFanIB = NULL; - mCopyResourcesInitialized = false; - mCopyVB = NULL; - mCopySampler = NULL; - mCopyIL = NULL; - mCopyVS = NULL; - mCopyRGBAPS = NULL; - mCopyRGBPS = NULL; - mCopyLumPS = NULL; - mCopyLumAlphaPS = NULL; - - mClearResourcesInitialized = false; - mClearVB = NULL; - mClearIL = NULL; - mClearVS = NULL; - mClearSinglePS = NULL; - mClearMultiplePS = NULL; - mClearScissorRS = NULL; - mClearNoScissorRS = NULL; + mBlit = NULL; + mPixelTransfer = NULL; + + mClear = NULL; mSyncQuery = NULL; @@ -117,9 +102,10 @@ Renderer11::Renderer11(egl::Display *display) : Renderer(display) mDriverConstantBufferVS = NULL; mDriverConstantBufferPS = NULL; - mBGRATextureSupport = false; - - mIsGeometryShaderActive = false; + mAppliedVertexShader = NULL; + mAppliedGeometryShader = NULL; + mCurPointGeometryShader = NULL; + mAppliedPixelShader = NULL; } Renderer11::~Renderer11() @@ -139,12 +125,12 @@ Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) EGLint Renderer11::initialize() { - if (!initializeCompiler()) + if (!mCompiler.initialize()) { return EGL_NOT_INITIALIZED; } -#if !defined(ANGLE_OS_WINRT) +#if !defined(ANGLE_PLATFORM_WINRT) mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); @@ -154,7 +140,6 @@ EGLint Renderer11::initialize() return EGL_NOT_INITIALIZED; } - // create the D3D11 device ASSERT(mDevice == NULL); PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); @@ -178,11 +163,17 @@ EGLint Renderer11::initialize() #endif }; + D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE; + if (mRequestedDisplay == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE) + { + driverType = D3D_DRIVER_TYPE_WARP; + } + HRESULT result = S_OK; #ifdef _DEBUG result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, + driverType, NULL, D3D11_CREATE_DEVICE_DEBUG, featureLevels, @@ -201,7 +192,7 @@ EGLint Renderer11::initialize() #endif { result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, + driverType, NULL, 0, featureLevels, @@ -218,7 +209,37 @@ EGLint Renderer11::initialize() } } -#if !defined(ANGLE_OS_WINRT) +#if !ANGLE_SKIP_DXGI_1_2_CHECK && !defined(ANGLE_PLATFORM_WINRT) + // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. + // The easiest way to check is to query for a IDXGIDevice2. + bool requireDXGI1_2 = false; + HWND hwnd = WindowFromDC(mDc); + if (hwnd) + { + DWORD currentProcessId = GetCurrentProcessId(); + DWORD wndProcessId; + GetWindowThreadProcessId(hwnd, &wndProcessId); + requireDXGI1_2 = (currentProcessId != wndProcessId); + } + else + { + requireDXGI1_2 = true; + } + + if (requireDXGI1_2) + { + IDXGIDevice2 *dxgiDevice2 = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); + if (FAILED(result)) + { + ERR("DXGI 1.2 required to present to HWNDs owned by another process.\n"); + return EGL_NOT_INITIALIZED; + } + SafeRelease(dxgiDevice2); + } +#endif + +#if !defined(ANGLE_PLATFORM_WINRT) IDXGIDevice *dxgiDevice = NULL; #else IDXGIDevice1 *dxgiDevice = NULL; @@ -239,7 +260,7 @@ EGLint Renderer11::initialize() return EGL_NOT_INITIALIZED; } - dxgiDevice->Release(); + SafeRelease(dxgiDevice); mDxgiAdapter->GetDesc(&mAdapterDescription); memset(mDescription, 0, sizeof(mDescription)); @@ -270,212 +291,25 @@ EGLint Renderer11::initialize() filter.DenyList.pIDList = hideMessages; infoQueue->AddStorageFilterEntries(&filter); - - infoQueue->Release(); + SafeRelease(infoQueue); } #endif - unsigned int maxSupportedSamples = 0; - unsigned int rtFormatCount = ArraySize(RenderTargetFormats); - unsigned int dsFormatCount = ArraySize(DepthStencilFormats); - for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i) - { - DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount]; - if (format != DXGI_FORMAT_UNKNOWN) - { - UINT formatSupport; - result = mDevice->CheckFormatSupport(format, &formatSupport); - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) - { - MultisampleSupportInfo supportInfo; - - for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++) - { - result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]); - if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0) - { - maxSupportedSamples = std::max(j, maxSupportedSamples); - } - else - { - supportInfo.qualityLevels[j - 1] = 0; - } - } - - mMultisampleSupportMap.insert(std::make_pair(format, supportInfo)); - } - } - } - mMaxSupportedSamples = maxSupportedSamples; - - initializeDevice(); - - // BGRA texture support is optional in feature levels 10 and 10_1 - UINT formatSupport; - result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport); - if (FAILED(result)) - { - ERR("Error checking BGRA format support: 0x%08X", result); - } - else - { - const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET); - mBGRATextureSupport = (formatSupport & flags) == flags; - } - - // Check floating point texture support - static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; - static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET; - static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; - - DXGI_FORMAT float16Formats[] = - { - DXGI_FORMAT_R16_FLOAT, - DXGI_FORMAT_R16G16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - }; - - DXGI_FORMAT float32Formats[] = - { - DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_R32G32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - }; - - mFloat16TextureSupport = true; - mFloat16FilterSupport = true; - mFloat16RenderSupport = true; - for (unsigned int i = 0; i < ArraySize(float16Formats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport))) - { - mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; - mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; - mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; - } - else - { - mFloat16TextureSupport = false; - mFloat16RenderSupport = false; - mFloat16FilterSupport = false; - } - } - - mFloat32TextureSupport = true; - mFloat32FilterSupport = true; - mFloat32RenderSupport = true; - for (unsigned int i = 0; i < ArraySize(float32Formats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport))) - { - mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; - mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; - mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; - } - else - { - mFloat32TextureSupport = false; - mFloat32FilterSupport = false; - mFloat32RenderSupport = false; - } - } - - // Check compressed texture support - const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D; - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport))) - { - mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT1TextureSupport = false; - } - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport))) - { - mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT3TextureSupport = false; - } - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport))) - { - mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT5TextureSupport = false; - } - - // Check depth texture support - DXGI_FORMAT depthTextureFormats[] = - { - DXGI_FORMAT_D16_UNORM, - DXGI_FORMAT_D24_UNORM_S8_UINT, - }; - - static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | - D3D11_FORMAT_SUPPORT_TEXTURE2D; - - mDepthTextureSupport = true; - for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport))) - { - mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags); - } - else - { - mDepthTextureSupport = false; - } - } + mMaxSupportedSamples = 0; -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) - // Monitor when the application suspends so that Trim() can be called - Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::Core::ICoreApplication> application; - result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), - IID_PPV_ARGS(&application)); - if (FAILED(result)) + const d3d11::DXGIFormatSet &dxgiFormats = d3d11::GetAllUsedDXGIFormats(); + for (d3d11::DXGIFormatSet::const_iterator i = dxgiFormats.begin(); i != dxgiFormats.end(); ++i) { - ERR("Error obtaining CoreApplication: 0x%08X", result); - return EGL_NOT_INITIALIZED; + MultisampleSupportInfo support = getMultisampleSupportInfo(*i); + mMultisampleSupportMap.insert(std::make_pair(*i, support)); + mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples); } - EventRegistrationToken cookie; - result = application->add_Suspending(Microsoft::WRL::Callback<SuspendEventHandler>(this, &Renderer11::onSuspend).Get(), &cookie); - if (FAILED(result)) - { - ERR("Error setting suspend callback: 0x%08X", result); - return EGL_NOT_INITIALIZED; - } -#endif + initializeDevice(); return EGL_SUCCESS; } -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) -HRESULT Renderer11::onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *) -{ - if (!mDevice) - return S_OK; - - Microsoft::WRL::ComPtr<IDXGIDevice3> dxgiDevice; - HRESULT result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); - if (FAILED(result)) - { - ERR("Error obtaining DXGIDevice3 on suspend: 0x%08X", result); - return S_OK; - } - - dxgiDevice->Trim(); - - return S_OK; -} -#endif - // do any one-time device initialization // NOTE: this is also needed after a device lost/reset // to reset the scene status and ensure the default states are reset. @@ -488,6 +322,15 @@ void Renderer11::initializeDevice() mVertexDataManager = new VertexDataManager(this); mIndexDataManager = new IndexDataManager(this); + ASSERT(!mBlit); + mBlit = new Blit11(this); + + ASSERT(!mClear); + mClear = new Clear11(this); + + ASSERT(!mPixelTransfer); + mPixelTransfer = new PixelTransfer11(this); + markAllStateDirty(); } @@ -515,18 +358,19 @@ int Renderer11::generateConfigs(ConfigDesc **configDescList) if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) { - UINT formatSupport = 0; - result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport); - depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); + UINT depthStencilSupport = 0; + result = mDevice->CheckFormatSupport(depthStencilFormat, &depthStencilSupport); + depthStencilFormatOK = SUCCEEDED(result) && (depthStencilSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); } if (depthStencilFormatOK) { ConfigDesc newConfig; - newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat); + newConfig.renderTargetFormat = d3d11_gl::GetInternalFormat(renderTargetFormat); + newConfig.depthStencilFormat = d3d11_gl::GetInternalFormat(depthStencilFormat); newConfig.multiSample = 0; // FIXME: enumerate multi-sampling newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast + newConfig.es3Capable = true; (*configDescList)[numConfigs++] = newConfig; } @@ -586,6 +430,23 @@ SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareH return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); } +void Renderer11::generateSwizzle(gl::Texture *texture) +{ + if (texture) + { + TextureStorageInterface *texStorage = texture->getNativeTexture(); + if (texStorage) + { + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); + + storage11->generateSwizzles(texture->getSamplerState().swizzleRed, + texture->getSamplerState().swizzleGreen, + texture->getSamplerState().swizzleBlue, + texture->getSamplerState().swizzleAlpha); + } + } +} + void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) { if (type == gl::SAMPLER_PIXEL) @@ -644,7 +505,6 @@ void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::Samp void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) { ID3D11ShaderResourceView *textureSRV = NULL; - unsigned int serial = 0; bool forceSetTexture = false; if (texture) @@ -653,14 +513,15 @@ void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *textur if (texStorage) { TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); - textureSRV = storage11->getSRV(); + gl::SamplerState samplerState; + texture->getSamplerStateWithNativeOffset(&samplerState); + textureSRV = storage11->getSRV(samplerState); } // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly // missing the shader resource view ASSERT(textureSRV != NULL); - serial = texture->getTextureSerial(); forceSetTexture = texture->hasDirtyImages(); } @@ -672,12 +533,12 @@ void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *textur return; } - if (forceSetTexture || mCurPixelTextureSerials[index] != serial) + if (forceSetTexture || mCurPixelSRVs[index] != textureSRV) { mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); } - mCurPixelTextureSerials[index] = serial; + mCurPixelSRVs[index] = textureSRV; } else if (type == gl::SAMPLER_VERTEX) { @@ -687,22 +548,70 @@ void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *textur return; } - if (forceSetTexture || mCurVertexTextureSerials[index] != serial) + if (forceSetTexture || mCurVertexSRVs[index] != textureSRV) { mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); } - mCurVertexTextureSerials[index] = serial; + mCurVertexSRVs[index] = textureSRV; } else UNREACHABLE(); } +bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) +{ + for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) + { + const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex]; + if (uniformBuffer) + { + Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); + ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + + if (!constantBuffer) + { + return false; + } + + if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial()) + { + mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer); + mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); + } + } + } + + for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) + { + const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex]; + if (uniformBuffer) + { + Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); + ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + + if (!constantBuffer) + { + return false; + } + + if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial()) + { + mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer); + mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); + } + } + } + + return true; +} + void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) { if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) { - ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled, - mCurDepthSize); + ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled); if (!dxRasterState) { ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" @@ -717,12 +626,12 @@ void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) mForceSetRasterState = false; } -void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, +void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, unsigned int sampleMask) { if (mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || - memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 || + memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 || sampleMask != mCurSampleMask) { ID3D11BlendState *dxBlendState = mStateCache.getBlendState(framebuffer, blendState); @@ -766,14 +675,9 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) { - if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - stencilRef != stencilBackRef || - depthStencilState.stencilMask != depthStencilState.stencilBackMask) - { - ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are " - "invalid under WebGL."); - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); + ASSERT(stencilRef == stencilBackRef); + ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); if (!dxDepthStencilState) @@ -782,7 +686,13 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS "setting the default depth stencil state."); } - mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef)); + // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer + // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops + META_ASSERT(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF); + META_ASSERT(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF); + UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu); + + mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); mCurDepthStencilState = depthStencilState; mCurStencilRef = stencilRef; @@ -836,17 +746,14 @@ bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float z actualZFar = 1.0f; } - // Get D3D viewport bounds, which depends on the feature level - const Range& viewportBounds = getViewportBounds(); + const gl::Caps& caps = getRendererCaps(); // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds D3D11_VIEWPORT dxViewport; - dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end); - dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end); - dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension()); - dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension()); - dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX)); - dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY)); + dxViewport.TopLeftX = gl::clamp(actualViewport.x, -static_cast<int>(caps.maxViewportWidth), static_cast<int>(caps.maxViewportWidth)); + dxViewport.TopLeftY = gl::clamp(actualViewport.y, -static_cast<int>(caps.maxViewportHeight), static_cast<int>(caps.maxViewportHeight)); + dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(caps.maxViewportWidth - dxViewport.TopLeftX)); + dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(caps.maxViewportHeight - dxViewport.TopLeftY)); dxViewport.MinDepth = actualZNear; dxViewport.MaxDepth = actualZFar; @@ -904,7 +811,8 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) // emulate fans via rewriting index buffer case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; default: - return gl::error(GL_INVALID_ENUM, false); + UNREACHABLE(); + return false; } if (primitiveTopology != mCurrentPrimitiveTopology) @@ -930,20 +838,13 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(colorAttachment); - if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE) + if (colorbuffer && drawBufferState != GL_NONE) { // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment); - - if (!colorbuffer) - { - ERR("render target pointer unexpectedly null."); - return false; - } - // check for zero-sized default framebuffer, which is a special case. // in this case we do not wish to modify any state and just silently return false. // this will not report any gl error but will cause the calling method to return. @@ -977,59 +878,25 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) missingColorRenderTarget = false; } -#ifdef _DEBUG - // Workaround for Debug SETSHADERRESOURCES_HAZARD D3D11 warnings - for (unsigned int vertexSerialIndex = 0; vertexSerialIndex < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; vertexSerialIndex++) - { - if (colorbuffer->getTextureSerial() != 0 && mCurVertexTextureSerials[vertexSerialIndex] == colorbuffer->getTextureSerial()) - { - setTexture(gl::SAMPLER_VERTEX, vertexSerialIndex, NULL); - } - } - - for (unsigned int pixelSerialIndex = 0; pixelSerialIndex < gl::MAX_TEXTURE_IMAGE_UNITS; pixelSerialIndex++) - { - if (colorbuffer->getTextureSerial() != 0 && mCurPixelTextureSerials[pixelSerialIndex] == colorbuffer->getTextureSerial()) - { - setTexture(gl::SAMPLER_PIXEL, pixelSerialIndex, NULL); - } - } -#endif + // TODO: Detect if this color buffer is already bound as a texture and unbind it first to prevent + // D3D11 warnings. } } // Get the depth stencil render buffer and serials - gl::Renderbuffer *depthStencil = NULL; + gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); unsigned int depthbufferSerial = 0; unsigned int stencilbufferSerial = 0; - if (framebuffer->getDepthbufferType() != GL_NONE) + if (depthStencil) { - depthStencil = framebuffer->getDepthbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - depthbufferSerial = depthStencil->getSerial(); } - else if (framebuffer->getStencilbufferType() != GL_NONE) + else if (framebuffer->getStencilbuffer()) { depthStencil = framebuffer->getStencilbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - stencilbufferSerial = depthStencil->getSerial(); } - // Extract the depth stencil sizes and view - unsigned int depthSize = 0; - unsigned int stencilSize = 0; ID3D11DepthStencilView* framebufferDSV = NULL; if (depthStencil) { @@ -1057,9 +924,6 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) renderTargetHeight = depthStencil->getHeight(); renderTargetFormat = depthStencil->getActualFormat(); } - - depthSize = depthStencil->getDepthSize(); - stencilSize = depthStencil->getStencilSize(); } // Apply the render target and depth stencil @@ -1068,22 +932,20 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) depthbufferSerial != mAppliedDepthbufferSerial || stencilbufferSerial != mAppliedStencilbufferSerial) { - mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV); + mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV); mRenderTargetDesc.width = renderTargetWidth; mRenderTargetDesc.height = renderTargetHeight; mRenderTargetDesc.format = renderTargetFormat; mForceSetViewport = true; mForceSetScissor = true; + mForceSetBlendState = true; - if (!mDepthStencilInitialized || depthSize != mCurDepthSize) + if (!mDepthStencilInitialized) { - mCurDepthSize = depthSize; mForceSetRasterState = true; } - mCurStencilSize = stencilSize; - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) { mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; @@ -1094,13 +956,16 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) mDepthStencilInitialized = true; } + invalidateFramebufferSwizzles(framebuffer); + return true; } -GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) +GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); + GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); if (err != GL_NO_ERROR) { return err; @@ -1115,28 +980,27 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr if (err == GL_NO_ERROR) { - if (indexInfo->storage) - { - if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset) - { - BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); - mDeviceContext->IASetIndexBuffer(storage->getBuffer(BUFFER_USAGE_INDEX), indexBuffer->getIndexFormat(), indexInfo->startOffset); + ID3D11Buffer *buffer = NULL; + DXGI_FORMAT bufferFormat = indexBuffer->getIndexFormat(); - mAppliedIBSerial = 0; - mAppliedStorageIBSerial = storage->getSerial(); - mAppliedIBOffset = indexInfo->startOffset; - } + if (indexInfo->storage) + { + Buffer11 *storage = Buffer11::makeBuffer11(indexInfo->storage); + buffer = storage->getBuffer(BUFFER_USAGE_INDEX); } - else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset) + else { - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + buffer = indexBuffer->getBuffer(); + } - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); + if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset) + { + mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); - mAppliedIBSerial = indexInfo->serial; - mAppliedStorageIBSerial = 0; + mAppliedIB = buffer; + mAppliedIBFormat = bufferFormat; mAppliedIBOffset = indexInfo->startOffset; } } @@ -1144,9 +1008,79 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr return err; } -void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances) +void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) { - if (mode == GL_LINE_LOOP) + ID3D11Buffer* d3dBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + UINT d3dOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + bool requiresUpdate = false; + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + if (transformFeedbackBuffers[i]) + { + Buffer11 *storage = Buffer11::makeBuffer11(transformFeedbackBuffers[i]->getImplementation()); + ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + + d3dBuffers[i] = buffer; + d3dOffsets[i] = (mAppliedTFBuffers[i] != buffer) ? static_cast<UINT>(offsets[i]) : -1; + } + else + { + d3dBuffers[i] = NULL; + d3dOffsets[i] = 0; + } + + if (d3dBuffers[i] != mAppliedTFBuffers[i] || offsets[i] != mAppliedTFOffsets[i]) + { + requiresUpdate = true; + } + } + + if (requiresUpdate) + { + mDeviceContext->SOSetTargets(ArraySize(d3dBuffers), d3dBuffers, d3dOffsets); + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + mAppliedTFBuffers[i] = d3dBuffers[i]; + mAppliedTFOffsets[i] = offsets[i]; + } + } +} + +void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) +{ + if (mode == GL_POINTS && transformFeedbackActive) + { + // Since point sprites are generated with a geometry shader, too many vertices will + // be written if transform feedback is active. To work around this, draw only the points + // with the stream out shader and no pixel shader to feed the stream out buffers and then + // draw again with the point sprite geometry shader to rasterize the point sprites. + + mDeviceContext->PSSetShader(NULL, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + + mDeviceContext->GSSetShader(mCurPointGeometryShader, NULL, 0); + mDeviceContext->PSSetShader(mAppliedPixelShader, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + + mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0); + } + else if (mode == GL_LINE_LOOP) { drawLineLoop(count, GL_NONE, NULL, 0, NULL); } @@ -1164,7 +1098,8 @@ void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances) } } -void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) +void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) { if (mode == GL_LINE_LOOP) { @@ -1268,12 +1203,13 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (type != GL_NONE && elementArrayBuffer) { gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); + BufferImpl *storage = indexBuffer->getImplementation(); intptr_t offset = reinterpret_cast<intptr_t>(indices); indices = static_cast<const GLubyte*>(storage->getData()) + offset; } - const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + // TODO: some level 9 hardware supports 32-bit indices; test and store support instead + const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; if (!mLineLoopIB) { @@ -1291,13 +1227,14 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, // Checked by Renderer11::applyPrimitiveType ASSERT(count >= 0); - if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) + int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); + if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / indexTypeSize)) { ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); return gl::error(GL_OUT_OF_MEMORY); } - const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int); + const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * indexTypeSize; if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, indexType)) { ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); @@ -1324,13 +1261,15 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, return gl::error(GL_OUT_OF_MEMORY); } - if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset) - { - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); + ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + { mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); - mAppliedIBSerial = mLineLoopIB->getSerial(); - mAppliedStorageIBSerial = 0; + mAppliedIB = d3dIndexBuffer; + mAppliedIBFormat = indexFormat; mAppliedIBOffset = indexBufferOffset; } @@ -1343,12 +1282,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic if (type != GL_NONE && elementArrayBuffer) { gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); + BufferImpl *storage = indexBuffer->getImplementation(); intptr_t offset = reinterpret_cast<intptr_t>(indices); indices = static_cast<const GLubyte*>(storage->getData()) + offset; } - const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; if (!mTriangleFanIB) { @@ -1368,13 +1307,14 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic const unsigned int numTris = count - 2; - if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3))) + int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); + if (numTris > (std::numeric_limits<unsigned int>::max() / (indexTypeSize * 3))) { ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); return gl::error(GL_OUT_OF_MEMORY); } - const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); + const unsigned int spaceNeeded = (numTris * 3) * indexTypeSize; if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType)) { ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); @@ -1395,20 +1335,21 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(mappedMemory)); unsigned int indexBufferOffset = offset; - if (!mTriangleFanIB->unmapBuffer()) { ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); return gl::error(GL_OUT_OF_MEMORY); } - if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset) - { - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); + ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + { mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); - mAppliedIBSerial = mTriangleFanIB->getSerial(); - mAppliedStorageIBSerial = 0; + mAppliedIB = d3dIndexBuffer; + mAppliedIBFormat = indexFormat; mAppliedIBOffset = indexBufferOffset; } @@ -1422,54 +1363,73 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic } } -void Renderer11::applyShaders(gl::ProgramBinary *programBinary) +void Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) { - unsigned int programBinarySerial = programBinary->getSerial(); - const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial); + ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); + ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); + ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); + + ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); - if (updateProgramState) + ID3D11PixelShader *pixelShader = NULL; + // Skip pixel shader if we're doing rasterizer discard. + if (!rasterizerDiscard) { - ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); - ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); + pixelShader = (pixelExe ? ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader() : NULL); + } - ID3D11VertexShader *vertexShader = NULL; - if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader(); + ID3D11GeometryShader *geometryShader = NULL; + if (transformFeedbackActive) + { + geometryShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getStreamOutShader() : NULL); + } + else if (mCurRasterState.pointDrawMode) + { + geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); + } - ID3D11PixelShader *pixelShader = NULL; - if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); + bool dirtyUniforms = false; - mDeviceContext->PSSetShader(pixelShader, NULL, 0); + if (vertexShader != mAppliedVertexShader) + { mDeviceContext->VSSetShader(vertexShader, NULL, 0); + mAppliedVertexShader = vertexShader; + dirtyUniforms = true; + } - programBinary->dirtyAllUniforms(); - - mAppliedProgramBinarySerial = programBinarySerial; + if (geometryShader != mAppliedGeometryShader) + { + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + mAppliedGeometryShader = geometryShader; + dirtyUniforms = true; } - // Only use the geometry shader currently for point sprite drawing - const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode); + if (geometryExe && mCurRasterState.pointDrawMode) + { + mCurPointGeometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); + } + else + { + mCurPointGeometryShader = NULL; + } - if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive) + if (pixelShader != mAppliedPixelShader) { - if (usesGeometryShader) - { - ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); - ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); - mDeviceContext->GSSetShader(geometryShader, NULL, 0); - } - else - { - mDeviceContext->GSSetShader(NULL, NULL, 0); - } + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mAppliedPixelShader = pixelShader; + dirtyUniforms = true; + } - mIsGeometryShaderActive = usesGeometryShader; + if (dirtyUniforms) + { + programBinary->dirtyAllUniforms(); } } -void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) +void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) { - ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); - ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable()); + const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms(); unsigned int totalRegisterCountVS = 0; unsigned int totalRegisterCountPS = 0; @@ -1477,25 +1437,30 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra bool vertexUniformsDirty = false; bool pixelUniformsDirty = false; - for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) { - const gl::Uniform *uniform = *uniform_iterator; + const gl::LinkedUniform &uniform = *uniformArray[uniformIndex]; - if (uniform->vsRegisterIndex >= 0) + if (uniform.isReferencedByVertexShader() && !uniform.isSampler()) { - totalRegisterCountVS += uniform->registerCount; - vertexUniformsDirty = vertexUniformsDirty || uniform->dirty; + totalRegisterCountVS += uniform.registerCount; + vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty); } - if (uniform->psRegisterIndex >= 0) + if (uniform.isReferencedByFragmentShader() && !uniform.isSampler()) { - totalRegisterCountPS += uniform->registerCount; - pixelUniformsDirty = pixelUniformsDirty || uniform->dirty; + totalRegisterCountPS += uniform.registerCount; + pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty); } } - ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS); - ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS); + const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programBinary.getVertexUniformStorage()); + const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programBinary.getFragmentUniformStorage()); + ASSERT(vertexUniformStorage); + ASSERT(fragmentUniformStorage); + + ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer(); + ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer(); float (*mapVS)[4] = NULL; float (*mapPS)[4] = NULL; @@ -1504,6 +1469,7 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra { D3D11_MAPPED_SUBRESOURCE map = {0}; HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); mapVS = (float(*)[4])map.pData; } @@ -1512,28 +1478,32 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra { D3D11_MAPPED_SUBRESOURCE map = {0}; HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); mapPS = (float(*)[4])map.pData; } - for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) { - gl::Uniform *uniform = *uniform_iterator; + gl::LinkedUniform *uniform = uniformArray[uniformIndex]; - if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE) + if (!uniform->isSampler()) { - if (uniform->vsRegisterIndex >= 0 && mapVS) + unsigned int componentCount = (4 - uniform->registerElement); + + // we assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would + // overwrite previously written regions of memory. + + if (uniform->isReferencedByVertexShader() && mapVS) { - memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); + memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); } - if (uniform->psRegisterIndex >= 0 && mapPS) + if (uniform->isReferencedByFragmentShader() && mapPS) { - memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); + memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); } } - - uniform->dirty = false; } if (mapVS) @@ -1570,6 +1540,7 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra constantBufferDescription.StructureByteStride = 0; HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); @@ -1586,6 +1557,7 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra constantBufferDescription.StructureByteStride = 0; HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); @@ -1613,271 +1585,8 @@ void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArra void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) { - gl::Renderbuffer *firstRenderbuffer = frameBuffer->getFirstColorbuffer(); - GLenum internalFormat = firstRenderbuffer ? firstRenderbuffer->getInternalFormat() : GL_NONE; - - bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && - ((!clearParams.colorMaskRed && gl::GetRedSize(internalFormat) > 0) || - (!clearParams.colorMaskGreen && gl::GetGreenSize(internalFormat) > 0) || - (!clearParams.colorMaskBlue && gl::GetBlueSize(internalFormat) > 0) || - (!clearParams.colorMaskAlpha && gl::GetAlphaSize(internalFormat) > 0)); - - unsigned int stencilUnmasked = 0x0; - if (frameBuffer->hasStencil()) - { - unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); - stencilUnmasked = (0x1 << stencilSize) - 1; - } - bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && - (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - - bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 || - mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width || - mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height); - - if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear) - { - maskedClear(clearParams, frameBuffer); - } - else - { - if (clearParams.mask & GL_COLOR_BUFFER_BIT) - { - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (frameBuffer->isEnabledColorAttachment(colorAttachment)) - { - gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment); - if (renderbufferObject) - { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget()); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return; - } - - ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); - if (!framebufferRTV) - { - ERR("render target view pointer unexpectedly null."); - return; - } - - GLenum format = renderbufferObject->getInternalFormat(); - - const float clearValues[4] = { (gl::GetRedSize(format) > 0) ? clearParams.colorClearValue.red : 0.0f, - (gl::GetGreenSize(format) > 0) ? clearParams.colorClearValue.green : 0.0f, - (gl::GetBlueSize(format) > 0) ? clearParams.colorClearValue.blue : 0.0f, - (gl::GetAlphaSize(format) > 0) ? clearParams.colorClearValue.alpha : 1.0f }; - mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues); - } - } - } - } - if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT) - { - gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer(); - if (renderbufferObject) - { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil()); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return; - } - - ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - ERR("depth stencil view pointer unexpectedly null."); - return; - } - - UINT clearFlags = 0; - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) - { - clearFlags |= D3D11_CLEAR_DEPTH; - } - if (clearParams.mask & GL_STENCIL_BUFFER_BIT) - { - clearFlags |= D3D11_CLEAR_STENCIL; - } - - float depthClear = gl::clamp01(clearParams.depthClearValue); - UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF; - - mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); - } - } - } -} - -void Renderer11::maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) -{ - HRESULT result; - - if (!mClearResourcesInitialized) - { - ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer"); - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout"); - - result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader"); - - result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)"); - - result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)"); - - D3D11_RASTERIZER_DESC rsScissorDesc; - rsScissorDesc.FillMode = D3D11_FILL_SOLID; - rsScissorDesc.CullMode = D3D11_CULL_NONE; - rsScissorDesc.FrontCounterClockwise = FALSE; - rsScissorDesc.DepthBias = 0; - rsScissorDesc.DepthBiasClamp = 0.0f; - rsScissorDesc.SlopeScaledDepthBias = 0.0f; - rsScissorDesc.DepthClipEnable = FALSE; - rsScissorDesc.ScissorEnable = TRUE; - rsScissorDesc.MultisampleEnable = FALSE; - rsScissorDesc.AntialiasedLineEnable = FALSE; - - result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state"); - - D3D11_RASTERIZER_DESC rsNoScissorDesc; - rsNoScissorDesc.FillMode = D3D11_FILL_SOLID; - rsNoScissorDesc.CullMode = D3D11_CULL_NONE; - rsNoScissorDesc.FrontCounterClockwise = FALSE; - rsNoScissorDesc.DepthBias = 0; - rsNoScissorDesc.DepthBiasClamp = 0.0f; - rsNoScissorDesc.SlopeScaledDepthBias = 0.0f; - rsNoScissorDesc.DepthClipEnable = FALSE; - rsNoScissorDesc.ScissorEnable = FALSE; - rsNoScissorDesc.MultisampleEnable = FALSE; - rsNoScissorDesc.AntialiasedLineEnable = FALSE; - - result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state"); - - mClearResourcesInitialized = true; - } - - // Prepare the depth stencil state to write depth values if the depth should be cleared - // and stencil values if the stencil should be cleared - gl::DepthStencilState glDSState; - glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; - glDSState.depthFunc = GL_ALWAYS; - glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; - glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0; - glDSState.stencilFunc = GL_ALWAYS; - glDSState.stencilMask = 0; - glDSState.stencilFail = GL_REPLACE; - glDSState.stencilPassDepthFail = GL_REPLACE; - glDSState.stencilPassDepthPass = GL_REPLACE; - glDSState.stencilWritemask = clearParams.stencilWriteMask; - glDSState.stencilBackFunc = GL_ALWAYS; - glDSState.stencilBackMask = 0; - glDSState.stencilBackFail = GL_REPLACE; - glDSState.stencilBackPassDepthFail = GL_REPLACE; - glDSState.stencilBackPassDepthPass = GL_REPLACE; - glDSState.stencilBackWritemask = clearParams.stencilWriteMask; - - int stencilClear = clearParams.stencilClearValue & 0x000000FF; - - ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState); - - // Prepare the blend state to use a write mask if the color buffer should be cleared - gl::BlendState glBlendState; - glBlendState.blend = false; - glBlendState.sourceBlendRGB = GL_ONE; - glBlendState.destBlendRGB = GL_ZERO; - glBlendState.sourceBlendAlpha = GL_ONE; - glBlendState.destBlendAlpha = GL_ZERO; - glBlendState.blendEquationRGB = GL_FUNC_ADD; - glBlendState.blendEquationAlpha = GL_FUNC_ADD; - glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false; - glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false; - glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false; - glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false; - glBlendState.sampleAlphaToCoverage = false; - glBlendState.dither = false; - - static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - static const UINT sampleMask = 0xFFFFFFFF; - - ID3D11BlendState *blendState = mStateCache.getBlendState(frameBuffer, glBlendState); - - // Set the vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); - return; - } - - d3d11::PositionDepthColorVertex *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex*>(mappedResource.pData); - - float depthClear = gl::clamp01(clearParams.depthClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue); - - mDeviceContext->Unmap(mClearVB, 0); - - // Apply state - mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); - mDeviceContext->OMSetDepthStencilState(dsState, stencilClear); - mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS); - - // Apply shaders - ID3D11PixelShader *pixelShader = frameBuffer->usingExtendedDrawBuffers() ? mClearMultiplePS : mClearSinglePS; - - mDeviceContext->IASetInputLayout(mClearIL); - mDeviceContext->VSSetShader(mClearVS, NULL, 0); - mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mDeviceContext->GSSetShader(NULL, NULL, 0); - - // Apply vertex buffer - static UINT stride = sizeof(d3d11::PositionDepthColorVertex); - static UINT startIdx = 0; - mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx); - mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - - // Draw the clear quad - mDeviceContext->Draw(4, 0); - - // Clean up - markAllStateDirty(); + mClear->clearFramebuffer(clearParams, frameBuffer); + invalidateFramebufferSwizzles(frameBuffer); } void Renderer11::markAllStateDirty() @@ -1894,12 +1603,12 @@ void Renderer11::markAllStateDirty() for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) { mForceSetVertexSamplerStates[i] = true; - mCurVertexTextureSerials[i] = 0; + mCurVertexSRVs[i] = NULL; } for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) { mForceSetPixelSamplerStates[i] = true; - mCurPixelTextureSerials[i] = 0; + mCurPixelSRVs[i] = NULL; } mForceSetBlendState = true; @@ -1908,16 +1617,32 @@ void Renderer11::markAllStateDirty() mForceSetScissor = true; mForceSetViewport = true; - mAppliedIBSerial = 0; - mAppliedStorageIBSerial = 0; + mAppliedIB = NULL; + mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; mAppliedIBOffset = 0; - mAppliedProgramBinarySerial = 0; + mAppliedVertexShader = NULL; + mAppliedGeometryShader = NULL; + mCurPointGeometryShader = NULL; + mAppliedPixelShader = NULL; + + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + mAppliedTFBuffers[i] = NULL; + mAppliedTFOffsets[i] = 0; + } + memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); mInputLayoutCache.markDirty(); + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++) + { + mCurrentConstantBufferVS[i] = -1; + mCurrentConstantBufferPS[i] = -1; + } + mCurrentVertexConstantBuffer = NULL; mCurrentPixelConstantBuffer = NULL; mCurrentGeometryConstantBuffer = NULL; @@ -1930,39 +1655,13 @@ void Renderer11::releaseDeviceResources() mStateCache.clear(); mInputLayoutCache.clear(); - delete mVertexDataManager; - mVertexDataManager = NULL; - - delete mIndexDataManager; - mIndexDataManager = NULL; - - delete mLineLoopIB; - mLineLoopIB = NULL; - - delete mTriangleFanIB; - mTriangleFanIB = NULL; - - SafeRelease(mCopyVB); - SafeRelease(mCopySampler); - SafeRelease(mCopyIL); - SafeRelease(mCopyIL); - SafeRelease(mCopyVS); - SafeRelease(mCopyRGBAPS); - SafeRelease(mCopyRGBPS); - SafeRelease(mCopyLumPS); - SafeRelease(mCopyLumAlphaPS); - - mCopyResourcesInitialized = false; - - SafeRelease(mClearVB); - SafeRelease(mClearIL); - SafeRelease(mClearVS); - SafeRelease(mClearSinglePS); - SafeRelease(mClearMultiplePS); - SafeRelease(mClearScissorRS); - SafeRelease(mClearNoScissorRS); - - mClearResourcesInitialized = false; + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); + SafeDelete(mTriangleFanIB); + SafeDelete(mBlit); + SafeDelete(mClear); + SafeDelete(mPixelTransfer); SafeRelease(mDriverConstantBufferVS); SafeRelease(mDriverConstantBufferPS); @@ -2058,8 +1757,8 @@ bool Renderer11::testDeviceResettable() return false; } - dummyContext->Release(); - dummyDevice->Release(); + SafeRelease(dummyContext); + SafeRelease(dummyDevice); return true; } @@ -2068,31 +1767,17 @@ void Renderer11::release() { releaseDeviceResources(); - if (mDxgiFactory) - { - mDxgiFactory->Release(); - mDxgiFactory = NULL; - } - - if (mDxgiAdapter) - { - mDxgiAdapter->Release(); - mDxgiAdapter = NULL; - } + SafeRelease(mDxgiFactory); + SafeRelease(mDxgiAdapter); if (mDeviceContext) { mDeviceContext->ClearState(); mDeviceContext->Flush(); - mDeviceContext->Release(); - mDeviceContext = NULL; + SafeRelease(mDeviceContext); } - if (mDevice) - { - mDevice->Release(); - mDevice = NULL; - } + SafeRelease(mDevice); if (mD3d11Module) { @@ -2105,6 +1790,8 @@ void Renderer11::release() FreeLibrary(mDxgiModule); mDxgiModule = NULL; } + + mCompiler.release(); } bool Renderer11::resetDevice() @@ -2152,112 +1839,109 @@ GUID Renderer11::getAdapterIdentifier() const return adapterId; } -bool Renderer11::getBGRATextureSupport() const -{ - return mBGRATextureSupport; -} - -bool Renderer11::getDXT1TextureSupport() -{ - return mDXT1TextureSupport; -} - -bool Renderer11::getDXT3TextureSupport() -{ - return mDXT3TextureSupport; -} - -bool Renderer11::getDXT5TextureSupport() -{ - return mDXT5TextureSupport; -} - -bool Renderer11::getDepthTextureSupport() const +unsigned int Renderer11::getMaxVertexTextureImageUnits() const { - return mDepthTextureSupport; + META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + default: UNREACHABLE(); + return 0; + } } -bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable) +unsigned int Renderer11::getMaxCombinedTextureImageUnits() const { - *renderable = mFloat32RenderSupport; - *filtering = mFloat32FilterSupport; - return mFloat32TextureSupport; + return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); } -bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable) +unsigned int Renderer11::getReservedVertexUniformVectors() const { - *renderable = mFloat16RenderSupport; - *filtering = mFloat16FilterSupport; - return mFloat16TextureSupport; + return 0; // Driver uniforms are stored in a separate constant buffer } -bool Renderer11::getLuminanceTextureSupport() +unsigned int Renderer11::getReservedFragmentUniformVectors() const { - return false; + return 0; // Driver uniforms are stored in a separate constant buffer } -bool Renderer11::getLuminanceAlphaTextureSupport() +unsigned int Renderer11::getMaxVertexUniformVectors() const { - return false; + META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_VERTEX_UNIFORM_VECTORS_D3D11; } -bool Renderer11::getTextureFilterAnisotropySupport() const +unsigned int Renderer11::getMaxFragmentUniformVectors() const { - return true; + META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; } -float Renderer11::getTextureMaxAnisotropy() const +unsigned int Renderer11::getMaxVaryingVectors() const { + META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); + META_ASSERT(D3D11_VS_OUTPUT_REGISTER_COUNT <= D3D11_PS_INPUT_REGISTER_COUNT); + META_ASSERT(D3D10_VS_OUTPUT_REGISTER_COUNT <= D3D10_PS_INPUT_REGISTER_COUNT); switch (mFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: - return D3D11_MAX_MAXANISOTROPY; + return D3D11_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); case D3D_FEATURE_LEVEL_10_0: - return D3D10_MAX_MAXANISOTROPY; + return D3D10_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); case D3D_FEATURE_LEVEL_9_3: + return 10 - getReservedVaryings(); case D3D_FEATURE_LEVEL_9_2: - return 16; case D3D_FEATURE_LEVEL_9_1: - return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + return 8 - getReservedVaryings(); default: UNREACHABLE(); return 0; } } -bool Renderer11::getEventQuerySupport() +unsigned int Renderer11::getMaxVertexShaderUniformBuffers() const { - return true; -} + META_ASSERT(gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT && + gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); -Range Renderer11::getViewportBounds() const -{ switch (mFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: - return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); + return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedVertexUniformBuffers(); case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: - return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); + return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedVertexUniformBuffers(); case D3D_FEATURE_LEVEL_9_3: - return Range(D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: - return Range(D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); + return 0; default: UNREACHABLE(); - return Range(0, 0); + return 0; } } -unsigned int Renderer11::getMaxVertexTextureImageUnits() const +unsigned int Renderer11::getMaxFragmentShaderUniformBuffers() const { - META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + META_ASSERT(gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT && + gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); + switch (mFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers(); case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: - return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; + return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers(); case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: @@ -2267,103 +1951,90 @@ unsigned int Renderer11::getMaxVertexTextureImageUnits() const } } -unsigned int Renderer11::getMaxCombinedTextureImageUnits() const +unsigned int Renderer11::getReservedVertexUniformBuffers() const { - return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); + // we reserve one buffer for the application uniforms, and one for driver uniforms + return 2; } -unsigned int Renderer11::getReservedVertexUniformVectors() const +unsigned int Renderer11::getReservedFragmentUniformBuffers() const { - return 0; // Driver uniforms are stored in a separate constant buffer + // we reserve one buffer for the application uniforms, and one for driver uniforms + return 2; } -unsigned int Renderer11::getReservedFragmentUniformVectors() const +unsigned int Renderer11::getReservedVaryings() const { - return 0; // Driver uniforms are stored in a separate constant buffer + // We potentially reserve varyings for gl_Position, dx_Position, gl_FragCoord and gl_PointSize + return 4; } -unsigned int Renderer11::getMaxVertexUniformVectors() const -{ - META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); - return MAX_VERTEX_UNIFORM_VECTORS_D3D11; -} -unsigned int Renderer11::getMaxFragmentUniformVectors() const +unsigned int Renderer11::getMaxTransformFeedbackBuffers() const { - META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); - return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; -} + META_ASSERT(gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D11_SO_BUFFER_SLOT_COUNT && + gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D10_SO_BUFFER_SLOT_COUNT); -unsigned int Renderer11::getMaxVaryingVectors() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); switch (mFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: - return D3D11_VS_OUTPUT_REGISTER_COUNT; + return D3D11_SO_BUFFER_SLOT_COUNT; case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_SO_BUFFER_SLOT_COUNT; case D3D_FEATURE_LEVEL_10_0: - return D3D10_VS_OUTPUT_REGISTER_COUNT; + return D3D10_SO_BUFFER_SLOT_COUNT; case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: - return 8; + return 0; default: UNREACHABLE(); return 0; } } -bool Renderer11::getNonPower2TextureSupport() const +unsigned int Renderer11::getMaxTransformFeedbackSeparateComponents() const { switch (mFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: + return getMaxTransformFeedbackInterleavedComponents() / getMaxTransformFeedbackBuffers(); case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: - return true; + // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero + // is used. + return 4; case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: - return false; + return 0; default: UNREACHABLE(); - return false; + return 0; } } -bool Renderer11::getOcclusionQuerySupport() const +unsigned int Renderer11::getMaxTransformFeedbackInterleavedComponents() const { - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return true; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - return true; - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } + return (getMaxVaryingVectors() * 4); } -bool Renderer11::getInstancingSupport() const +unsigned int Renderer11::getMaxUniformBufferSize() const { + // Each component is a 4-element vector of 4-byte units (floats) + const unsigned int bytesPerComponent = 4 * sizeof(float); + switch (mFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; case D3D_FEATURE_LEVEL_9_3: - return true; case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: - return false; + return 0; default: UNREACHABLE(); - return false; + return 0; } } @@ -2372,25 +2043,7 @@ bool Renderer11::getShareHandleSupport() const // We only currently support share handles with BGRA surfaces, because // chrome needs BGRA. Once chrome fixes this, we should always support them. // PIX doesn't seem to support using share handles, so disable them. - return getBGRATextureSupport() && !gl::perfActive(); -} - -bool Renderer11::getDerivativeInstructionSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return true; - case D3D_FEATURE_LEVEL_9_3: - return true; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } + return getRendererExtensions().textureFormatBGRA8888 && !gl::perfActive(); } bool Renderer11::getPostSubBufferSupport() const @@ -2399,16 +2052,40 @@ bool Renderer11::getPostSubBufferSupport() const return false; } +int Renderer11::getMaxRecommendedElementsIndices() const +{ + META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); + META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); + + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience. + return std::numeric_limits<GLint>::max(); +} + +int Renderer11::getMaxRecommendedElementsVertices() const +{ + META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); + META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); + + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience. + return std::numeric_limits<GLint>::max(); +} + +bool Renderer11::getSRGBTextureSupport() const +{ + return true; +} + int Renderer11::getMajorShaderModel() const { switch (mFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 (level 9) + case D3D_FEATURE_LEVEL_9_1: + return D3D10_SHADER_MAJOR_VERSION; // 4 default: UNREACHABLE(); return 0; } } @@ -2419,100 +2096,87 @@ int Renderer11::getMinorShaderModel() const { case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_10_0: case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 (level 9) + case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 default: UNREACHABLE(); return 0; } } -float Renderer11::getMaxPointSize() const +int Renderer11::getMinSwapInterval() const { - // choose a reasonable maximum. we enforce this in the shader. - // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size) - return 1024.0f; + return 0; } -int Renderer11::getMaxViewportDimension() const +int Renderer11::getMaxSwapInterval() const { - // Maximum viewport size must be at least as large as the largest render buffer (or larger). - // In our case return the maximum texture size, which is the maximum render buffer size. - META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX); - META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: - return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); - return 0; - } + return 4; } -int Renderer11::getMaxTextureWidth() const +int Renderer11::getMaxSupportedSamples() const { - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } + return mMaxSupportedSamples; } -int Renderer11::getMaxTextureHeight() const +GLsizei Renderer11::getMaxSupportedFormatSamples(GLenum internalFormat) const { - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } + DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat); + MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); + return (iter != mMultisampleSupportMap.end()) ? iter->second.maxSupportedSamples : 0; } -bool Renderer11::get32BitIndexSupport() const +GLsizei Renderer11::getNumSampleCounts(GLenum internalFormat) const { - switch (mFeatureLevel) + unsigned int numCounts = 0; + + // D3D11 supports multisampling for signed and unsigned format, but ES 3.0 does not + GLenum componentType = gl::GetComponentType(internalFormat); + if (componentType != GL_INT && componentType != GL_UNSIGNED_INT) { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; - default: UNREACHABLE(); return false; + DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat); + MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); + + if (iter != mMultisampleSupportMap.end()) + { + const MultisampleSupportInfo& info = iter->second; + for (int i = 0; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) + { + if (info.qualityLevels[i] > 0) + { + numCounts++; + } + } + } } -} -int Renderer11::getMinSwapInterval() const -{ - return 0; + return numCounts; } -int Renderer11::getMaxSwapInterval() const +void Renderer11::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const { - return 4; -} + // D3D11 supports multisampling for signed and unsigned format, but ES 3.0 does not + GLenum componentType = gl::GetComponentType(internalFormat); + if (componentType == GL_INT || componentType == GL_UNSIGNED_INT) + { + return; + } -int Renderer11::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; + DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat); + MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); + + if (iter != mMultisampleSupportMap.end()) + { + const MultisampleSupportInfo& info = iter->second; + int bufPos = 0; + for (int i = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT - 1; i >= 0 && bufPos < bufSize; i--) + { + if (info.qualityLevels[i] > 0) + { + params[bufPos++] = i + 1; + } + } + } } int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const @@ -2538,32 +2202,6 @@ int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requ return -1; } -unsigned int Renderer11::getMaxRenderTargets() const -{ - META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: // return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: // return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1 - // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader - // outputs to multiple RTs that are not bound. - // TODO: Remove pixel shader outputs for render targets that are not bound. - return 1; - default: - UNREACHABLE(); - return 1; - } -} - bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) { if (source && dest) @@ -2571,7 +2209,10 @@ bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStor TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); - mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); + mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); + + dest11->invalidateSwizzleCache(); + return true; } @@ -2585,7 +2226,44 @@ bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSt TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); - mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); + mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); + + dest11->invalidateSwizzleCache(); + + return true; + } + + return false; +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) +{ + if (source && dest) + { + TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source->getStorageInstance()); + TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); + + dest11->invalidateSwizzleCache(); + + return true; + } + + return false; +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) +{ + if (source && dest) + { + TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source->getStorageInstance()); + TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); + + dest11->invalidateSwizzleCache(); + return true; } @@ -2595,7 +2273,7 @@ bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSt bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) { - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (!colorbuffer) { ERR("Failed to retrieve the color buffer from the frame buffer."); @@ -2637,14 +2315,18 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - gl::Rectangle destRect; - destRect.x = xoffset; - destRect.y = yoffset; - destRect.width = sourceRect.width; - destRect.height = sourceRect.height; + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST); - bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), - dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); + storage11->invalidateSwizzleCacheLevel(level); return ret; } @@ -2652,7 +2334,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) { - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (!colorbuffer) { ERR("Failed to retrieve the color buffer from the frame buffer."); @@ -2680,7 +2362,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level)); + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetFace(target, level)); if (!destRenderTarget) { ERR("Failed to retrieve the render target from the destination storage."); @@ -2694,194 +2376,144 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - gl::Rectangle destRect; - destRect.x = xoffset; - destRect.y = yoffset; - destRect.width = sourceRect.width; - destRect.height = sourceRect.height; + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), - dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST); + + storage11->invalidateSwizzleCacheLevel(level); return ret; } -bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, - ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat) +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) { - HRESULT result; - - if (!mCopyResourcesInitialized) + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) { - ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer"); - - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MipLODBias = 0.0f; - samplerDesc.MaxAnisotropy = 0; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = 0.0f; - samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? 0.0f : FLT_MAX; - - result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler"); - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout"); - - result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader"); - - mCopyResourcesInitialized = true; + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); } - // Verify the source and destination area sizes - if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast<int>(sourceWidth) || - sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast<int>(sourceHeight) || - destArea.x < 0 || destArea.x + destArea.width > static_cast<int>(destWidth) || - destArea.y < 0 || destArea.y + destArea.height > static_cast<int>(destHeight)) + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) { - return gl::error(GL_INVALID_VALUE, false); + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); } - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) { - ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); + ERR("Failed to retrieve the render target view from the render target."); return gl::error(GL_OUT_OF_MEMORY, false); } - d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); + if (!storage11) + { + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } - // Create a quad in homogeneous coordinates - float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f; - float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f; - float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f; - float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f; + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset)); + if (!destRenderTarget) + { + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } - float u1 = sourceArea.x / float(sourceWidth); - float v1 = sourceArea.y / float(sourceHeight); - float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth); - float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight); + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } - d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); - d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); - d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); - d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - mDeviceContext->Unmap(mCopyVB, 0); + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); - static UINT stride = sizeof(d3d11::PositionTexCoordVertex); - static UINT startIdx = 0; - mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx); + // Use nearest filtering because source and destination are the same size for the direct + // copy + bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST); - // Apply state - mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); - mDeviceContext->RSSetState(NULL); + storage11->invalidateSwizzleCacheLevel(level); - // Apply shaders - mDeviceContext->IASetInputLayout(mCopyIL); - mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - mDeviceContext->VSSetShader(mCopyVS, NULL, 0); + return ret; +} - ID3D11PixelShader *ps = NULL; - switch(destFormat) +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) { - case GL_RGBA: ps = mCopyRGBAPS; break; - case GL_RGB: ps = mCopyRGBPS; break; - case GL_ALPHA: ps = mCopyRGBAPS; break; - case GL_BGRA_EXT: ps = mCopyRGBAPS; break; - case GL_LUMINANCE: ps = mCopyLumPS; break; - case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break; - default: UNREACHABLE(); ps = NULL; break; + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); } - mDeviceContext->PSSetShader(ps, NULL, 0); - mDeviceContext->GSSetShader(NULL, NULL, 0); - - // Unset the currently bound shader resource to avoid conflicts - static ID3D11ShaderResourceView *const nullSRV = NULL; - mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } - // Apply render target - setOneTimeRenderTarget(dest); + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = destWidth; - viewport.Height = destHeight; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - mDeviceContext->RSSetViewports(1, &viewport); + TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance()); + if (!storage11) + { + SafeRelease(source); + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } - // Apply textures - mDeviceContext->PSSetShaderResources(0, 1, &source); - mDeviceContext->PSSetSamplers(0, 1, &mCopySampler); + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset)); + if (!destRenderTarget) + { + SafeRelease(source); + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } - // Draw the quad - mDeviceContext->Draw(4, 0); + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } - // Unbind textures and render targets and vertex buffer - mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - unapplyRenderTargets(); + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); - UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; - mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + // Use nearest filtering because source and destination are the same size for the direct + // copy + bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST); - markAllStateDirty(); + storage11->invalidateSwizzleCacheLevel(level); - return true; + return ret; } void Renderer11::unapplyRenderTargets() @@ -2895,7 +2527,7 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView rtvArray[0] = renderTargetView; - mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL); + mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL); // Do not preserve the serial for this one-time-use render target for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) @@ -2913,8 +2545,9 @@ RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) { // Note: depth stencil may be NULL for 0 sized surfaces renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), - swapChain11->getDepthStencilTexture(), NULL, - swapChain11->getWidth(), swapChain11->getHeight()); + swapChain11->getDepthStencilTexture(), + swapChain11->getDepthStencilShaderResource(), + swapChain11->getWidth(), swapChain11->getHeight(), 1); } else { @@ -2922,56 +2555,89 @@ RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), swapChain11->getOffscreenTexture(), swapChain11->getRenderTargetShaderResource(), - swapChain11->getWidth(), swapChain11->getHeight()); + swapChain11->getWidth(), swapChain11->getHeight(), 1); } return renderTarget; } -RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) +RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples) { - RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth); + RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples); return renderTarget; } -ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type) +ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers) { ShaderExecutable11 *executable = NULL; + HRESULT result; switch (type) { case rx::SHADER_VERTEX: { - ID3D11VertexShader *vshader = NULL; - HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader); + ID3D11VertexShader *vertexShader = NULL; + ID3D11GeometryShader *streamOutShader = NULL; + + result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); ASSERT(SUCCEEDED(result)); - if (vshader) + if (transformFeedbackVaryings.size() > 0) + { + std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration; + for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) + { + const gl::LinkedVarying &varying = transformFeedbackVaryings[i]; + GLenum transposedType = gl::TransposeMatrixType(varying.type); + + for (size_t j = 0; j < varying.semanticIndexCount; j++) + { + D3D11_SO_DECLARATION_ENTRY entry = { 0 }; + entry.Stream = 0; + entry.SemanticName = varying.semanticName.c_str(); + entry.SemanticIndex = varying.semanticIndex + j; + entry.StartComponent = 0; + entry.ComponentCount = gl::VariableColumnCount(transposedType); + entry.OutputSlot = (separatedOutputBuffers ? i : 0); + soDeclaration.push_back(entry); + } + } + + result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(), + NULL, 0, 0, NULL, &streamOutShader); + ASSERT(SUCCEEDED(result)); + } + + if (vertexShader) { - executable = new ShaderExecutable11(function, length, vshader); + executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); } } break; case rx::SHADER_PIXEL: { - ID3D11PixelShader *pshader = NULL; - HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader); + ID3D11PixelShader *pixelShader = NULL; + + result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); ASSERT(SUCCEEDED(result)); - if (pshader) + if (pixelShader) { - executable = new ShaderExecutable11(function, length, pshader); + executable = new ShaderExecutable11(function, length, pixelShader); } } break; case rx::SHADER_GEOMETRY: { - ID3D11GeometryShader *gshader = NULL; - HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader); + ID3D11GeometryShader *geometryShader = NULL; + + result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); ASSERT(SUCCEEDED(result)); - if (gshader) + if (geometryShader) { - executable = new ShaderExecutable11(function, length, gshader); + executable = new ShaderExecutable11(function, length, geometryShader); } } break; @@ -2983,41 +2649,107 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length return executable; } -ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) +ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround) { - std::string profile; - + const char *profileType = NULL; switch (type) { case rx::SHADER_VERTEX: - profile = "vs_4_0"; + profileType = "vs"; break; case rx::SHADER_PIXEL: - profile = "ps_4_0"; + profileType = "ps"; break; case rx::SHADER_GEOMETRY: - profile = "gs_4_0"; + profileType = "gs"; + break; + default: + UNREACHABLE(); + return NULL; + } + + const char *profileVersion = NULL; + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + profileVersion = "5_0"; + break; + case D3D_FEATURE_LEVEL_10_1: + profileVersion = "4_1"; + break; + case D3D_FEATURE_LEVEL_10_0: + profileVersion = "4_0"; + break; + case D3D_FEATURE_LEVEL_9_3: + profileVersion = "4_0_level_9_3"; + break; + case D3D_FEATURE_LEVEL_9_2: + profileVersion = "4_0_level_9_2"; + break; + case D3D_FEATURE_LEVEL_9_1: + profileVersion = "4_0_level_9_1"; break; default: UNREACHABLE(); return NULL; } - if (mFeatureLevel == D3D_FEATURE_LEVEL_9_3) - profile += "_level_9_3"; - else if (mFeatureLevel == D3D_FEATURE_LEVEL_9_2 || mFeatureLevel == D3D_FEATURE_LEVEL_9_1) - profile += "_level_9_1"; + char profile[32]; + snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion); + + UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0; + + if (gl::perfActive()) + { +#ifndef NDEBUG + flags = D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + flags |= D3DCOMPILE_DEBUG; + + std::string sourcePath = getTempPath(); + std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } + + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. + // Try the default flags first and if compilation fails, try some alternatives. + const UINT extraFlags[] = + { + flags, + flags | D3DCOMPILE_SKIP_VALIDATION, + flags | D3DCOMPILE_SKIP_OPTIMIZATION + }; + + const static char *extraFlagNames[] = + { + "default", + "skip validation", + "skip optimization" + }; - ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile.c_str(), D3DCOMPILE_OPTIMIZATION_LEVEL0, false); + int attempts = ArraySize(extraFlags); + + ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); if (!binary) + { return NULL; + } - ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type); - binary->Release(); + ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type, + transformFeedbackVaryings, separatedOutputBuffers); + SafeRelease(binary); return executable; } +rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize) +{ + return new UniformStorage11(this, storageSize); +} + VertexBuffer *Renderer11::createVertexBuffer() { return new VertexBuffer11(this); @@ -3028,9 +2760,14 @@ IndexBuffer *Renderer11::createIndexBuffer() return new IndexBuffer11(this); } -BufferStorage *Renderer11::createBufferStorage() +BufferImpl *Renderer11::createBuffer() { - return new BufferStorage11(this); + return new Buffer11(this); +} + +VertexArrayImpl *Renderer11::createVertexArray() +{ + return new VertexArray11(this); } QueryImpl *Renderer11::createQuery(GLenum type) @@ -3043,7 +2780,45 @@ FenceImpl *Renderer11::createFence() return new Fence11(this); } -bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) +bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const +{ + ASSERT(getRendererExtensions().pixelBufferObject); + + // sRGB formats do not work with D3D11 buffer SRVs + if (gl::GetColorEncoding(internalFormat) == GL_SRGB) + { + return false; + } + + // We cannot support direct copies to non-color-renderable formats + if (gl_d3d11::GetRTVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + { + return false; + } + + // We skip all 3-channel formats since sometimes format support is missing + if (gl::GetComponentCount(internalFormat) == 3) + { + return false; + } + + // We don't support formats which we can't represent without conversion + if (getNativeTextureFormat(internalFormat) != internalFormat) + { + return false; + } + + return true; +} + +bool Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); + return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); +} + +bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) { ASSERT(colorbuffer != NULL); @@ -3060,8 +2835,8 @@ bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned if (textureResource) { - HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource); - textureResource->Release(); + HRESULT result = textureResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)resource); + SafeRelease(textureResource); if (SUCCEEDED(result)) { @@ -3080,11 +2855,11 @@ bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned } bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil) + const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) { if (blitRenderTarget) { - gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer(); + gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer(); if (!readBuffer) { @@ -3098,7 +2873,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read { if (drawTarget->isEnabledColorAttachment(colorAttachment)) { - gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment); + gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment); if (!drawBuffer) { @@ -3108,7 +2883,8 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); - if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false)) + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, + blitRenderTarget, false, false)) { return false; } @@ -3116,10 +2892,10 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read } } - if (blitDepthStencil) + if (blitDepth || blitStencil) { - gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer(); - gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer(); if (!readBuffer) { @@ -3136,22 +2912,25 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); - if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true)) + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, + false, blitDepth, blitStencil)) { return false; } } + invalidateFramebufferSwizzles(drawTarget); + return true; } -void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) +void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) { ID3D11Texture2D *colorBufferTexture = NULL; unsigned int subresourceIndex = 0; - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) { @@ -3161,11 +2940,18 @@ void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsi area.width = width; area.height = height; - readTextureData(colorBufferTexture, subresourceIndex, area, colorbuffer->getActualFormat(), format, type, outputPitch, - packReverseRowOrder, packAlignment, pixels); + if (pack.pixelBuffer.get() != NULL) + { + rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(pack.pixelBuffer.get()->getImplementation()); + PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels)); + packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); + } + else + { + readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); + } - colorBufferTexture->Release(); - colorBufferTexture = NULL; + SafeRelease(colorBufferTexture); } } @@ -3187,305 +2973,78 @@ TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) return new TextureStorage11_2D(this, swapChain11); } -TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) +TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) { - return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height); + return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels); } -TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) +TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) { - return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size); + return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels); } -static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum sourceGLFormat, GLenum destFormat, GLenum destType) +TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) { - if (sourceFormat == DXGI_FORMAT_A8_UNORM && - destFormat == GL_ALPHA && - destType == GL_UNSIGNED_BYTE) - { - return 1; - } - else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM && - sourceGLFormat == GL_RGBA8_OES && - destFormat == GL_RGBA && - destType == GL_UNSIGNED_BYTE) - { - return 4; - } - else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM && - destFormat == GL_BGRA_EXT && - destType == GL_UNSIGNED_BYTE) - { - return 4; - } - else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT && - sourceGLFormat == GL_RGBA16F_EXT && - destFormat == GL_RGBA && - destType == GL_HALF_FLOAT_OES) - { - return 8; - } - else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT && - destFormat == GL_RGB && - destType == GL_FLOAT) - { - return 12; - } - else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && - sourceGLFormat == GL_RGBA32F_EXT && - destFormat == GL_RGBA && - destType == GL_FLOAT) - { - return 16; - } - else - { - return 0; - } + return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, levels); } -static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, GLenum glFormat, unsigned int x, - unsigned int y, int inputPitch, gl::Color *outColor) +TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) { - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - unsigned int rgba = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch); - outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF); - outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00); - outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000); - - if (gl::GetAlphaSize(glFormat) > 0) - { - outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000); - } - else - { - outColor->alpha = 1.0f; - } - } - break; - - case DXGI_FORMAT_A8_UNORM: - { - outColor->red = 0.0f; - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = *(data + x + y * inputPitch) / 255.0f; - } - break; - - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - outColor->red = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 0); - outColor->green = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 1); - outColor->blue = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 2); - - if (gl::GetAlphaSize(glFormat) > 0) - { - outColor->alpha = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 3); - } - else - { - outColor->alpha = 1.0f; - } - } - break; - - case DXGI_FORMAT_R32G32B32_FLOAT: - { - outColor->red = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 0); - outColor->green = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 1); - outColor->blue = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 2); - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 0)); - outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 1)); - outColor->blue = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 2)); - - if (gl::GetAlphaSize(glFormat) > 0) - { - outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 3)); - } - else - { - outColor->alpha = 1.0f; - } - } - break; - - case DXGI_FORMAT_B8G8R8A8_UNORM: - { - unsigned int bgra = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch); - outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000); - outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF); - outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00); - outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000); - } - break; - - case DXGI_FORMAT_R8_UNORM: - { - outColor->red = *(data + x + y * inputPitch) / 255.0f; - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R8G8_UNORM: - { - unsigned short rg = *reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch); - - outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00); - outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF); - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch)); - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16G16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 0)); - outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 1)); - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; + return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); +} - default: - ERR("ReadPixelColor not implemented for DXGI format %u.", format); - UNIMPLEMENTED(); - break; - } +Texture2DImpl *Renderer11::createTexture2D() +{ + return new TextureD3D_2D(this); } -static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x, - unsigned int y, int outputPitch, void *outData) +TextureCubeImpl *Renderer11::createTextureCube() { - unsigned char* byteData = reinterpret_cast<unsigned char*>(outData); - unsigned short* shortData = reinterpret_cast<unsigned short*>(outData); + return new TextureD3D_Cube(this); +} - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f); - byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f); - byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f); - byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f); - break; +Texture3DImpl *Renderer11::createTexture3D() +{ + return new TextureD3D_3D(this); +} - default: - ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; +Texture2DArrayImpl *Renderer11::createTexture2DArray() +{ + return new TextureD3D_2DArray(this); +} - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.blue + 0.5f); - byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f); - byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.red + 0.5f); - byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f); - break; - - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast<unsigned short>(15 * color.alpha + 0.5f) << 12) | - (static_cast<unsigned short>(15 * color.red + 0.5f) << 8) | - (static_cast<unsigned short>(15 * color.green + 0.5f) << 4) | - (static_cast<unsigned short>(15 * color.blue + 0.5f) << 0); - break; - - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast<unsigned short>( color.alpha + 0.5f) << 15) | - (static_cast<unsigned short>(31 * color.red + 0.5f) << 10) | - (static_cast<unsigned short>(31 * color.green + 0.5f) << 5) | - (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0); - break; - - default: - ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; +void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels) +{ + ASSERT(area.width >= 0); + ASSERT(area.height >= 0); - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_SHORT_5_6_5: - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0) | - (static_cast<unsigned short>(63 * color.green + 0.5f) << 5) | - (static_cast<unsigned short>(31 * color.red + 0.5f) << 11); - break; + D3D11_TEXTURE2D_DESC textureDesc; + texture->GetDesc(&textureDesc); - case GL_UNSIGNED_BYTE: - byteData[3 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f); - byteData[3 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f); - byteData[3 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f); - break; + // Clamp read region to the defined texture boundaries, preventing out of bounds reads + // and reads of uninitialized data. + gl::Rectangle safeArea; + safeArea.x = gl::clamp(area.x, 0, static_cast<int>(textureDesc.Width)); + safeArea.y = gl::clamp(area.y, 0, static_cast<int>(textureDesc.Height)); + safeArea.width = gl::clamp(area.width + std::min(area.x, 0), 0, + static_cast<int>(textureDesc.Width) - safeArea.x); + safeArea.height = gl::clamp(area.height + std::min(area.y, 0), 0, + static_cast<int>(textureDesc.Height) - safeArea.y); - default: - ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; + ASSERT(safeArea.x >= 0 && safeArea.y >= 0); + ASSERT(safeArea.x + safeArea.width <= static_cast<int>(textureDesc.Width)); + ASSERT(safeArea.y + safeArea.height <= static_cast<int>(textureDesc.Height)); - default: - ERR("WritePixelColor not implemented for format 0x%X.", format); - UNIMPLEMENTED(); - break; + if (safeArea.width == 0 || safeArea.height == 0) + { + // no work to do + return; } -} - -void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, - GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, - GLint packAlignment, void *pixels) -{ - D3D11_TEXTURE2D_DESC textureDesc; - texture->GetDesc(&textureDesc); D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = area.width; - stagingDesc.Height = area.height; + stagingDesc.Width = safeArea.width; + stagingDesc.Height = safeArea.height; stagingDesc.MipLevels = 1; stagingDesc.ArraySize = 1; stagingDesc.Format = textureDesc.Format; @@ -3524,7 +3083,7 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou if (FAILED(result)) { ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); - stagingTex->Release(); + SafeRelease(stagingTex); return; } @@ -3538,26 +3097,38 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou } D3D11_BOX srcBox; - srcBox.left = area.x; - srcBox.right = area.x + area.width; - srcBox.top = area.y; - srcBox.bottom = area.y + area.height; - srcBox.front = 0; - srcBox.back = 1; + srcBox.left = static_cast<UINT>(safeArea.x); + srcBox.right = static_cast<UINT>(safeArea.x + safeArea.width); + srcBox.top = static_cast<UINT>(safeArea.y); + srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height); + srcBox.front = 0; + srcBox.back = 1; mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); - srcTex->Release(); - srcTex = NULL; + SafeRelease(srcTex); + + PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); + packPixels(stagingTex, packParams, pixels); + + SafeRelease(stagingTex); +} + +void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, void *pixelsOut) +{ + D3D11_TEXTURE2D_DESC textureDesc; + readTexture->GetDesc(&textureDesc); D3D11_MAPPED_SUBRESOURCE mapping; - mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping); + HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping); + UNUSED_ASSERTION_VARIABLE(hr); + ASSERT(SUCCEEDED(hr)); unsigned char *source; int inputPitch; - if (packReverseRowOrder) + if (params.pack.reverseRowOrder) { - source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (area.height - 1); + source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (params.area.height - 1); inputPitch = -static_cast<int>(mapping.RowPitch); } else @@ -3566,57 +3137,79 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou inputPitch = static_cast<int>(mapping.RowPitch); } - unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, sourceFormat, format, type); - if (fastPixelSize != 0) + GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(textureDesc.Format); + GLenum sourceFormat = gl::GetFormat(sourceInternalFormat); + GLenum sourceType = gl::GetType(sourceInternalFormat); + + GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat); + + if (sourceFormat == params.format && sourceType == params.type) { - unsigned char *dest = static_cast<unsigned char*>(pixels); - for (int j = 0; j < area.height; j++) + unsigned char *dest = static_cast<unsigned char*>(pixelsOut) + params.offset; + for (int y = 0; y < params.area.height; y++) { - memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize); + memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourcePixelSize); } } - else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM && - format == GL_RGBA && - type == GL_UNSIGNED_BYTE) + else { - // Fast path for swapping red with blue - unsigned char *dest = static_cast<unsigned char*>(pixels); + GLenum destInternalFormat = gl::GetSizedInternalFormat(params.format, params.type); + GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat); - for (int j = 0; j < area.height; j++) + ColorCopyFunction fastCopyFunc = d3d11::GetFastCopyFunction(textureDesc.Format, params.format, params.type); + if (fastCopyFunc) { - for (int i = 0; i < area.width; i++) + // Fast copy is possible through some special function + for (int y = 0; y < params.area.height; y++) { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - *(unsigned int*)(dest + 4 * i + j * outputPitch) = - (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red + for (int x = 0; x < params.area.width; x++) + { + void *dest = static_cast<unsigned char*>(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; + void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize; + + fastCopyFunc(src, dest); + } } } - } - else - { - gl::Color pixelColor; - for (int j = 0; j < area.height; j++) + else { - for (int i = 0; i < area.width; i++) + ColorReadFunction readFunc = d3d11::GetColorReadFunction(textureDesc.Format); + ColorWriteFunction writeFunc = gl::GetColorWriteFunction(params.format, params.type); + + unsigned char temp[16]; // Maximum size of any Color<T> type used. + META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) && + sizeof(temp) >= sizeof(gl::ColorUI) && + sizeof(temp) >= sizeof(gl::ColorI)); + + for (int y = 0; y < params.area.height; y++) { - readPixelColor(source, textureDesc.Format, sourceFormat, i, j, inputPitch, &pixelColor); - writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels); + for (int x = 0; x < params.area.width; x++) + { + void *dest = static_cast<unsigned char*>(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; + void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize; + + // readFunc and writeFunc will be using the same type of color, CopyTexImage + // will not allow the copy otherwise. + readFunc(src, temp); + writeFunc(temp, dest); + } } } } - mDeviceContext->Unmap(stagingTex, 0); - - stagingTex->Release(); - stagingTex = NULL; + mDeviceContext->Unmap(readTexture, 0); } -bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, bool wholeBufferCopy) +bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit) { - ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height); + // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, + // it should never be the case that both color and depth/stencil need to be blitted at + // at the same time. + ASSERT(colorBlit != (depthBlit || stencilBlit)); + + bool result = true; RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); if (!drawRenderTarget) @@ -3625,8 +3218,10 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R return gl::error(GL_OUT_OF_MEMORY, false); } - ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture(); + ID3D11Resource *drawTexture = drawRenderTarget11->getTexture(); unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); + ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); + ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); if (!readRenderTarget) @@ -3635,44 +3230,152 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R return gl::error(GL_OUT_OF_MEMORY, false); } - ID3D11Texture2D *readTexture = NULL; + ID3D11Resource *readTexture = NULL; + ID3D11ShaderResourceView *readSRV = NULL; unsigned int readSubresource = 0; if (readRenderTarget->getSamples() > 0) { - readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex()); - readSubresource = 0; + ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture(); + ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(unresolvedResource); + + if (unresolvedTexture) + { + readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); + readSubresource = 0; + + SafeRelease(unresolvedTexture); + + HRESULT hresult = mDevice->CreateShaderResourceView(readTexture, NULL, &readSRV); + if (FAILED(hresult)) + { + SafeRelease(readTexture); + return gl::error(GL_OUT_OF_MEMORY, false); + } + } } else { readTexture = readRenderTarget11->getTexture(); readTexture->AddRef(); readSubresource = readRenderTarget11->getSubresourceIndex(); + readSRV = readRenderTarget11->getShaderResourceView(); + readSRV->AddRef(); } - if (!readTexture) + if (!readTexture || !readSRV) { + SafeRelease(readTexture); + SafeRelease(readSRV); ERR("Failed to retrieve the read render target view from the read render target."); return gl::error(GL_OUT_OF_MEMORY, false); } - D3D11_BOX readBox; - readBox.left = readRect.x; - readBox.right = readRect.x + readRect.width; - readBox.top = readRect.y; - readBox.bottom = readRect.y + readRect.height; - readBox.front = 0; - readBox.back = 1; + gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + + bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); + + bool wholeBufferCopy = !scissorNeeded && + readRect.x == 0 && readRect.width == readSize.width && + readRect.y == 0 && readRect.height == readSize.height && + drawRect.x == 0 && drawRect.width == drawSize.width && + drawRect.y == 0 && drawRect.height == drawSize.height; + + bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; - // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox - // We also require complete framebuffer copies for depth-stencil blit. - D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; + bool flipRequired = readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; - mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0, - readTexture, readSubresource, pSrcBox); + bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || + readRect.y < 0 || readRect.y + readRect.height > readSize.height || + drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || + drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; + + bool hasDepth = gl::GetDepthBits(drawRenderTarget11->getActualFormat()) > 0; + bool hasStencil = gl::GetStencilBits(drawRenderTarget11->getActualFormat()) > 0; + bool partialDSBlit = (hasDepth && depthBlit) != (hasStencil && stencilBlit); + + if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && + !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && + (!(depthBlit || stencilBlit) || wholeBufferCopy)) + { + UINT dstX = drawRect.x; + UINT dstY = drawRect.y; + + D3D11_BOX readBox; + readBox.left = readRect.x; + readBox.right = readRect.x + readRect.width; + readBox.top = readRect.y; + readBox.bottom = readRect.y + readRect.height; + readBox.front = 0; + readBox.back = 1; + + if (scissorNeeded) + { + // drawRect is guaranteed to have positive width and height because stretchRequired is false. + ASSERT(drawRect.width >= 0 || drawRect.height >= 0); + + if (drawRect.x < scissor->x) + { + dstX = scissor->x; + readBox.left += (scissor->x - drawRect.x); + } + if (drawRect.y < scissor->y) + { + dstY = scissor->y; + readBox.top += (scissor->y - drawRect.y); + } + if (drawRect.x + drawRect.width > scissor->x + scissor->width) + { + readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width)); + } + if (drawRect.y + drawRect.height > scissor->y + scissor->height) + { + readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height)); + } + } + + // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox + // We also require complete framebuffer copies for depth-stencil blit. + D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; + + mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0, + readTexture, readSubresource, pSrcBox); + result = true; + } + else + { + gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1); + gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1); + + if (depthBlit && stencilBlit) + { + result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor); + } + else if (depthBlit) + { + result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize, + scissor); + } + else if (stencilBlit) + { + result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor); + } + else + { + GLenum format = gl::GetFormat(drawRenderTarget->getInternalFormat()); + result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, + scissor, format, filter); + } + } SafeRelease(readTexture); + SafeRelease(readSRV); - return true; + return result; } ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) @@ -3713,6 +3416,47 @@ ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, } } +void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel) +{ + ASSERT(attachment->isTexture()); + TextureStorage *texStorage = attachment->getTextureStorage(); + if (texStorage) + { + TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); + if (!texStorage11) + { + ERR("texture storage pointer unexpectedly null."); + return; + } + + texStorage11->invalidateSwizzleCacheLevel(mipLevel); + } +} + +void Renderer11::invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer) +{ + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(colorAttachment); + if (attachment && attachment->isTexture()) + { + invalidateFBOAttachmentSwizzles(attachment, attachment->mipLevel()); + } + } + + gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthbuffer(); + if (depthAttachment && depthAttachment->isTexture()) + { + invalidateFBOAttachmentSwizzles(depthAttachment, depthAttachment->mipLevel()); + } + + gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilbuffer(); + if (stencilAttachment && stencilAttachment->isTexture()) + { + invalidateFBOAttachmentSwizzles(stencilAttachment, stencilAttachment->mipLevel()); + } +} + bool Renderer11::getLUID(LUID *adapterLuid) const { adapterLuid->HighPart = 0; @@ -3733,4 +3477,51 @@ bool Renderer11::getLUID(LUID *adapterLuid) const return true; } +GLenum Renderer11::getNativeTextureFormat(GLenum internalFormat) const +{ + return d3d11_gl::GetInternalFormat(gl_d3d11::GetTexFormat(internalFormat)); +} + +rx::VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const +{ + return gl_d3d11::GetVertexConversionType(vertexFormat); +} + +GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const +{ + return d3d11::GetComponentType(gl_d3d11::GetNativeVertexFormat(vertexFormat)); +} + +Renderer11::MultisampleSupportInfo Renderer11::getMultisampleSupportInfo(DXGI_FORMAT format) +{ + MultisampleSupportInfo supportInfo = { 0 }; + + UINT formatSupport; + HRESULT result; + + result = mDevice->CheckFormatSupport(format, &formatSupport); + if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) + { + for (unsigned int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) + { + result = mDevice->CheckMultisampleQualityLevels(format, i, &supportInfo.qualityLevels[i - 1]); + if (SUCCEEDED(result) && supportInfo.qualityLevels[i - 1] > 0) + { + supportInfo.maxSupportedSamples = std::max(supportInfo.maxSupportedSamples, i); + } + else + { + supportInfo.qualityLevels[i - 1] = 0; + } + } + } + + return supportInfo; +} + +void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +{ + d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h index 773fc26db1..a31f15ee64 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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,27 +11,17 @@ #include "common/angleutils.h" #include "libGLESv2/angletypes.h" -#include "libGLESv2/mathutil.h" +#include "common/mathutil.h" #include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d/HLSLCompiler.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" #include "libGLESv2/renderer/RenderTarget.h" -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) -struct IInspectable; -namespace ABI { - namespace Windows { - namespace ApplicationModel { - struct ISuspendingEventArgs; - } - } -} -#endif - namespace gl { -class Renderbuffer; +class FramebufferAttachment; } namespace rx @@ -40,6 +30,10 @@ namespace rx class VertexDataManager; class IndexDataManager; class StreamingIndexBufferInterface; +class Blit11; +class Clear11; +class PixelTransfer11; +struct PackPixelsParams; enum { @@ -50,7 +44,7 @@ enum class Renderer11 : public Renderer { public: - Renderer11(egl::Display *display); + Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay); virtual ~Renderer11(); static Renderer11 *makeRenderer11(Renderer *renderer); @@ -65,11 +59,14 @@ class Renderer11 : public Renderer virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + virtual void generateSwizzle(gl::Texture *texture); virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); + virtual bool setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); + virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, unsigned int sampleMask); virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW); @@ -80,13 +77,17 @@ class Renderer11 : public Renderer virtual bool applyPrimitiveType(GLenum mode, GLsizei count); virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary); - virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); + virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); + virtual void applyUniforms(const gl::ProgramBinary &programBinary); + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + GLint first, GLsizei count, GLsizei instances); virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]); - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); @@ -98,20 +99,10 @@ class Renderer11 : public Renderer virtual bool testDeviceLost(bool notify); virtual bool testDeviceResettable(); - // Renderer capabilities virtual DWORD getAdapterVendor() const; virtual std::string getRendererDescription() const; virtual GUID getAdapterIdentifier() const; - virtual bool getBGRATextureSupport() const; - virtual bool getDXT1TextureSupport(); - virtual bool getDXT3TextureSupport(); - virtual bool getDXT5TextureSupport(); - virtual bool getEventQuerySupport(); - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); - virtual bool getLuminanceTextureSupport(); - virtual bool getLuminanceAlphaTextureSupport(); virtual unsigned int getMaxVertexTextureImageUnits() const; virtual unsigned int getMaxCombinedTextureImageUnits() const; virtual unsigned int getReservedVertexUniformVectors() const; @@ -119,66 +110,86 @@ class Renderer11 : public Renderer virtual unsigned int getMaxVertexUniformVectors() const; virtual unsigned int getMaxFragmentUniformVectors() const; virtual unsigned int getMaxVaryingVectors() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual bool getTextureFilterAnisotropySupport() const; - virtual float getTextureMaxAnisotropy() const; + virtual unsigned int getMaxVertexShaderUniformBuffers() const; + virtual unsigned int getMaxFragmentShaderUniformBuffers() const; + virtual unsigned int getReservedVertexUniformBuffers() const; + virtual unsigned int getReservedFragmentUniformBuffers() const; + unsigned int getReservedVaryings() const; + virtual unsigned int getMaxTransformFeedbackBuffers() const; + virtual unsigned int getMaxTransformFeedbackSeparateComponents() const; + virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const; + virtual unsigned int getMaxUniformBufferSize() const; virtual bool getShareHandleSupport() const; - virtual bool getDerivativeInstructionSupport() const; virtual bool getPostSubBufferSupport() const; + virtual int getMaxRecommendedElementsIndices() const; + virtual int getMaxRecommendedElementsVertices() const; + virtual bool getSRGBTextureSupport() const; virtual int getMajorShaderModel() const; - virtual float getMaxPointSize() const; - virtual int getMaxViewportDimension() const; - virtual int getMaxTextureWidth() const; - virtual int getMaxTextureHeight() const; - virtual bool get32BitIndexSupport() const; virtual int getMinSwapInterval() const; virtual int getMaxSwapInterval() const; virtual GLsizei getMaxSupportedSamples() const; + virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; + virtual GLsizei getNumSampleCounts(GLenum internalFormat) const; + virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const; int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const; - virtual unsigned int getMaxRenderTargets() const; - // Pixel operations virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); + virtual bool copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source); + virtual bool copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source); virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - - bool copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, - ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat); + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level); + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level); virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil); - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); + const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); + virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels); // RenderTarget creation virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); // Shader operations - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround); + virtual UniformStorage *createUniformStorage(size_t storageSize); // Image operations virtual Image *createImage(); virtual void generateMipmap(Image *dest, Image *source); virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + + // Texture creation + virtual Texture2DImpl *createTexture2D(); + virtual TextureCubeImpl *createTextureCube(); + virtual Texture3DImpl *createTexture3D(); + virtual Texture2DArrayImpl *createTexture2DArray(); // Buffer creation + virtual BufferImpl *createBuffer(); virtual VertexBuffer *createVertexBuffer(); virtual IndexBuffer *createIndexBuffer(); - virtual BufferStorage *createBufferStorage(); + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray(); // Query and Fence creation virtual QueryImpl *createQuery(GLenum type); @@ -188,37 +199,50 @@ class Renderer11 : public Renderer ID3D11Device *getDevice() { return mDevice; } ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; - D3D_FEATURE_LEVEL getFeatureLevel() { return mFeatureLevel; } + bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; } + + Blit11 *getBlitter() { return mBlit; } - bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; + virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + bool getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); void unapplyRenderTargets(); void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); + void packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, void *pixelsOut); virtual bool getLUID(LUID *adapterLuid) const; + virtual GLenum getNativeTextureFormat(GLenum internalFormat) const; + virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; + virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; private: DISALLOW_COPY_AND_ASSIGN(Renderer11); + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const; + void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); - void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, - GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, - GLint packAlignment, void *pixels); - - void maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); - rx::Range getViewportBounds() const; + void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels); - bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, bool wholeBufferCopy); + bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) - HRESULT onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *); -#endif + static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel); + static void invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer); HMODULE mD3d11Module; HMODULE mDxgiModule; + EGLNativeDisplayType mDc; + EGLint mRequestedDisplay; + + HLSLCompiler mCompiler; bool mDeviceLost; @@ -229,28 +253,15 @@ class Renderer11 : public Renderer RenderStateCache mStateCache; - // Support flags - bool mFloat16TextureSupport; - bool mFloat16FilterSupport; - bool mFloat16RenderSupport; - - bool mFloat32TextureSupport; - bool mFloat32FilterSupport; - bool mFloat32RenderSupport; - - bool mDXT1TextureSupport; - bool mDXT3TextureSupport; - bool mDXT5TextureSupport; - - bool mDepthTextureSupport; - // Multisample format support struct MultisampleSupportInfo { unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; + unsigned int maxSupportedSamples; }; + MultisampleSupportInfo getMultisampleSupportInfo(DXGI_FORMAT format); - typedef std::unordered_map<DXGI_FORMAT, MultisampleSupportInfo, std::hash<int> > MultisampleSupportMap; + typedef std::unordered_map<DXGI_FORMAT, MultisampleSupportInfo> MultisampleSupportMap; MultisampleSupportMap mMultisampleSupportMap; unsigned int mMaxSupportedSamples; @@ -262,8 +273,6 @@ class Renderer11 : public Renderer bool mDepthStencilInitialized; bool mRenderTargetDescInitialized; rx::RenderTarget::Desc mRenderTargetDesc; - unsigned int mCurDepthSize; - unsigned int mCurStencilSize; // Currently applied sampler states bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; @@ -273,13 +282,13 @@ class Renderer11 : public Renderer gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; // Currently applied textures - unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; + ID3D11ShaderResourceView *mCurVertexSRVs[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + ID3D11ShaderResourceView *mCurPixelSRVs[gl::MAX_TEXTURE_IMAGE_UNITS]; // Currently applied blend state bool mForceSetBlendState; gl::BlendState mCurBlendState; - gl::Color mCurBlendColor; + gl::ColorF mCurBlendColor; unsigned int mCurSampleMask; // Currently applied rasterizer state @@ -306,22 +315,32 @@ class Renderer11 : public Renderer // Currently applied primitive topology D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; - unsigned int mAppliedIBSerial; - unsigned int mAppliedStorageIBSerial; + // Currently applied index buffer + ID3D11Buffer *mAppliedIB; + DXGI_FORMAT mAppliedIBFormat; unsigned int mAppliedIBOffset; - unsigned int mAppliedProgramBinarySerial; - bool mIsGeometryShaderActive; + // Currently applied transform feedback buffers + ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + + // Currently applied shaders + ID3D11VertexShader *mAppliedVertexShader; + ID3D11GeometryShader *mAppliedGeometryShader; + ID3D11GeometryShader *mCurPointGeometryShader; + ID3D11PixelShader *mAppliedPixelShader; dx_VertexConstants mVertexConstants; dx_VertexConstants mAppliedVertexConstants; ID3D11Buffer *mDriverConstantBufferVS; ID3D11Buffer *mCurrentVertexConstantBuffer; + unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; dx_PixelConstants mPixelConstants; dx_PixelConstants mAppliedPixelConstants; ID3D11Buffer *mDriverConstantBufferPS; ID3D11Buffer *mCurrentPixelConstantBuffer; + unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; ID3D11Buffer *mCurrentGeometryConstantBuffer; @@ -334,25 +353,11 @@ class Renderer11 : public Renderer StreamingIndexBufferInterface *mTriangleFanIB; // Texture copy resources - bool mCopyResourcesInitialized; - ID3D11Buffer *mCopyVB; - ID3D11SamplerState *mCopySampler; - ID3D11InputLayout *mCopyIL; - ID3D11VertexShader *mCopyVS; - ID3D11PixelShader *mCopyRGBAPS; - ID3D11PixelShader *mCopyRGBPS; - ID3D11PixelShader *mCopyLumPS; - ID3D11PixelShader *mCopyLumAlphaPS; + Blit11 *mBlit; + PixelTransfer11 *mPixelTransfer; // Masked clear resources - bool mClearResourcesInitialized; - ID3D11Buffer *mClearVB; - ID3D11InputLayout *mClearIL; - ID3D11VertexShader *mClearVS; - ID3D11PixelShader *mClearSinglePS; - ID3D11PixelShader *mClearMultiplePS; - ID3D11RasterizerState *mClearScissorRS; - ID3D11RasterizerState *mClearNoScissorRS; + Clear11 *mClear; // Sync query ID3D11Query *mSyncQuery; @@ -364,9 +369,6 @@ class Renderer11 : public Renderer DXGI_ADAPTER_DESC mAdapterDescription; char mDescription[128]; IDXGIFactory *mDxgiFactory; - - // Cached device caps - bool mBGRATextureSupport; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp index 2e455e3af5..5a7c987494 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // @@ -8,9 +8,9 @@ // ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader // executable implementation details. -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" -#include "common/debug.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" namespace rx { @@ -21,18 +21,16 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D mPixelExecutable = executable; mVertexExecutable = NULL; mGeometryExecutable = NULL; - - mConstantBuffer = NULL; + mStreamOutExecutable = NULL; } -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable) +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut) : ShaderExecutable(function, length) { mVertexExecutable = executable; mPixelExecutable = NULL; mGeometryExecutable = NULL; - - mConstantBuffer = NULL; + mStreamOutExecutable = streamOut; } ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) @@ -41,29 +39,15 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D mGeometryExecutable = executable; mVertexExecutable = NULL; mPixelExecutable = NULL; - - mConstantBuffer = NULL; + mStreamOutExecutable = NULL; } ShaderExecutable11::~ShaderExecutable11() { - if (mVertexExecutable) - { - mVertexExecutable->Release(); - } - if (mPixelExecutable) - { - mPixelExecutable->Release(); - } - if (mGeometryExecutable) - { - mGeometryExecutable->Release(); - } - - if (mConstantBuffer) - { - mConstantBuffer->Release(); - } + SafeRelease(mVertexExecutable); + SafeRelease(mPixelExecutable); + SafeRelease(mGeometryExecutable); + SafeRelease(mStreamOutExecutable); } ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable) @@ -87,23 +71,42 @@ ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const return mGeometryExecutable; } -ID3D11Buffer *ShaderExecutable11::getConstantBuffer(ID3D11Device *device, unsigned int registerCount) +ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const { - if (!mConstantBuffer && registerCount > 0) + return mStreamOutExecutable; +} + +UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) + : UniformStorage(initialSize), + mConstantBuffer(NULL) +{ + ID3D11Device *d3d11Device = renderer->getDevice(); + + if (initialSize > 0) { D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = registerCount * sizeof(float[4]); + constantBufferDescription.ByteWidth = initialSize; constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; constantBufferDescription.MiscFlags = 0; constantBufferDescription.StructureByteStride = 0; - HRESULT result = device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); + HRESULT result = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); } +} - return mConstantBuffer; +UniformStorage11::~UniformStorage11() +{ + SafeRelease(mConstantBuffer); } -}
\ No newline at end of file +const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorage *uniformStorage) +{ + ASSERT(HAS_DYNAMIC_TYPE(const UniformStorage11*, uniformStorage)); + return static_cast<const UniformStorage11*>(uniformStorage); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h index c6ec1cf7d2..74a1e03915 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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,12 +14,14 @@ namespace rx { +class Renderer11; +class UniformStorage11; class ShaderExecutable11 : public ShaderExecutable { public: ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); - ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable); + ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut); ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); virtual ~ShaderExecutable11(); @@ -29,8 +31,7 @@ class ShaderExecutable11 : public ShaderExecutable ID3D11PixelShader *getPixelShader() const; ID3D11VertexShader *getVertexShader() const; ID3D11GeometryShader *getGeometryShader() const; - - ID3D11Buffer *getConstantBuffer(ID3D11Device *device, unsigned int registerCount); + ID3D11GeometryShader *getStreamOutShader() const; private: DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11); @@ -38,7 +39,20 @@ class ShaderExecutable11 : public ShaderExecutable ID3D11PixelShader *mPixelExecutable; ID3D11VertexShader *mVertexExecutable; ID3D11GeometryShader *mGeometryExecutable; + ID3D11GeometryShader *mStreamOutExecutable; +}; + +class UniformStorage11 : public UniformStorage +{ + public: + UniformStorage11(Renderer11 *renderer, size_t initialSize); + virtual ~UniformStorage11(); + + static const UniformStorage11 *makeUniformStorage11(const UniformStorage *uniformStorage); + ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } + + private: ID3D11Buffer *mConstantBuffer; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp index bd97d5cff5..0341df10f9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp @@ -1,19 +1,20 @@ #include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. -#include "libGLESv2/renderer/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h" +#include "common/platform.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" namespace rx { @@ -30,6 +31,7 @@ SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDL mOffscreenSRView = NULL; mDepthStencilTexture = NULL; mDepthStencilDSView = NULL; + mDepthStencilSRView = NULL; mQuadVB = NULL; mPassThroughSampler = NULL; mPassThroughIL = NULL; @@ -37,6 +39,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDL mPassThroughPS = NULL; mWidth = -1; mHeight = -1; + mViewportWidth = -1; + mViewportHeight = -1; mSwapInterval = 0; mAppCreatedShareHandle = mShareHandle != NULL; mPassThroughResourcesInit = false; @@ -57,6 +61,7 @@ void SwapChain11::release() SafeRelease(mOffscreenSRView); SafeRelease(mDepthStencilTexture); SafeRelease(mDepthStencilDSView); + SafeRelease(mDepthStencilSRView); SafeRelease(mQuadVB); SafeRelease(mPassThroughSampler); SafeRelease(mPassThroughIL); @@ -76,6 +81,7 @@ void SwapChain11::releaseOffscreenTexture() SafeRelease(mOffscreenSRView); SafeRelease(mDepthStencilTexture); SafeRelease(mDepthStencilDSView); + SafeRelease(mDepthStencilSRView); } EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) @@ -88,6 +94,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei ASSERT(backbufferWidth >= 1); ASSERT(backbufferHeight >= 1); +#if !defined(ANGLE_PLATFORM_WINRT) // Preserve the render target content ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; if (previousOffscreenTexture) @@ -96,6 +103,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } const int previousWidth = mWidth; const int previousHeight = mHeight; +#endif releaseOffscreenTexture(); @@ -114,7 +122,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); - tempResource11->Release(); + SafeRelease(tempResource11); if (FAILED(result)) { @@ -129,7 +137,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei if (offscreenTextureDesc.Width != (UINT)backbufferWidth || offscreenTextureDesc.Height != (UINT)backbufferHeight - || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat) + || offscreenTextureDesc.Format != gl_d3d11::GetTexFormat(mBackBufferFormat) || offscreenTextureDesc.MipLevels != 1 || offscreenTextureDesc.ArraySize != 1) { @@ -145,7 +153,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; offscreenTextureDesc.Width = backbufferWidth; offscreenTextureDesc.Height = backbufferHeight; - offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); + offscreenTextureDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat); offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; offscreenTextureDesc.SampleDesc.Count = 1; @@ -172,7 +180,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } } - d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture"); + d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture"); // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client if (useSharedResource) @@ -188,7 +196,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei else { result = offscreenTextureResource->GetSharedHandle(&mShareHandle); - offscreenTextureResource->Release(); + SafeRelease(offscreenTextureResource); if (FAILED(result)) { @@ -198,32 +206,43 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } } } - - HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView); + + D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; + offscreenRTVDesc.Format = gl_d3d11::GetRTVFormat(mBackBufferFormat); + offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + offscreenRTVDesc.Texture2D.MipSlice = 0; + + HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target"); + d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); + + D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; + offscreenSRVDesc.Format = gl_d3d11::GetSRVFormat(mBackBufferFormat); + offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + offscreenSRVDesc.Texture2D.MostDetailedMip = 0; + offscreenSRVDesc.Texture2D.MipLevels = -1; - result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView); + result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource"); + d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); if (mDepthBufferFormat != GL_NONE) { - D3D11_TEXTURE2D_DESC depthStencilDesc = {0}; - depthStencilDesc.Width = backbufferWidth; - depthStencilDesc.Height = backbufferHeight; - depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat); - depthStencilDesc.MipLevels = 1; - depthStencilDesc.ArraySize = 1; - depthStencilDesc.SampleDesc.Count = 1; - depthStencilDesc.SampleDesc.Quality = 0; - depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; - depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - depthStencilDesc.CPUAccessFlags = 0; - depthStencilDesc.MiscFlags = 0; - - result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture); + D3D11_TEXTURE2D_DESC depthStencilTextureDesc; + depthStencilTextureDesc.Width = backbufferWidth; + depthStencilTextureDesc.Height = backbufferHeight; + depthStencilTextureDesc.Format = gl_d3d11::GetTexFormat(mDepthBufferFormat); + depthStencilTextureDesc.MipLevels = 1; + depthStencilTextureDesc.ArraySize = 1; + depthStencilTextureDesc.SampleDesc.Count = 1; + depthStencilTextureDesc.SampleDesc.Quality = 0; + depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; + depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + depthStencilTextureDesc.CPUAccessFlags = 0; + depthStencilTextureDesc.MiscFlags = 0; + + result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); if (FAILED(result)) { ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); @@ -238,16 +257,37 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei return EGL_BAD_ALLOC; } } - d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture"); + d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture"); + + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; + depthStencilDesc.Format = gl_d3d11::GetDSVFormat(mDepthBufferFormat); + depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilDesc.Flags = 0; + depthStencilDesc.Texture2D.MipSlice = 0; + + result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); + + D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; + depthStencilSRVDesc.Format = gl_d3d11::GetSRVFormat(mDepthBufferFormat); + depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; + depthStencilSRVDesc.Texture2D.MipLevels = -1; - result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView); + result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView); ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view"); + d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource"); } mWidth = backbufferWidth; mHeight = backbufferHeight; +#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP + mViewportWidth = backbufferWidth; + mViewportHeight = backbufferHeight; +#endif +#if !defined(ANGLE_PLATFORM_WINRT) if (previousOffscreenTexture != NULL) { D3D11_BOX sourceBox = {0}; @@ -262,13 +302,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei const int yoffset = std::max(mHeight - previousHeight, 0); deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); - previousOffscreenTexture->Release(); + SafeRelease(previousOffscreenTexture); if (mSwapChain) { - swapRect(0, 0, mWidth, mHeight); + swapRect(0, 0, mWidth, mHeight, SWAP_NORMAL); } } +#endif return EGL_SUCCESS; } @@ -295,8 +336,15 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) SafeRelease(mBackBufferRTView); // Resize swap chain - DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); + HRESULT result; +#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP // Windows phone swap chain is never resized, only the texture is +#if !defined(ANGLE_PLATFORM_WINRT) + const int bufferCount = 1; +#else + const int bufferCount = 2; +#endif + DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::GetTexFormat(mBackBufferFormat); + result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); if (FAILED(result)) { @@ -312,7 +360,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) return EGL_BAD_ALLOC; } } - +#endif result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); ASSERT(SUCCEEDED(result)); if (SUCCEEDED(result)) @@ -361,49 +409,56 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap if (mWindow) { -#if !defined(ANGLE_OS_WINRT) IDXGIFactory *factory = mRenderer->getDxgiFactory(); - +#if !defined(ANGLE_PLATFORM_WINRT) DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; - swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); swapChainDesc.BufferDesc.Width = backbufferWidth; swapChainDesc.BufferDesc.Height = backbufferHeight; - swapChainDesc.BufferCount = 2; - swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; - swapChainDesc.Windowed = TRUE; + swapChainDesc.BufferDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat); + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 1; swapChainDesc.OutputWindow = mWindow; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapChainDesc.Flags = 0; + + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); #else - IDXGIFactory2 *factory; - HRESULT result = mRenderer->getDxgiFactory()->QueryInterface(IID_PPV_ARGS(&factory)); + IDXGIFactory2 *factory2; + HRESULT result = factory->QueryInterface(IID_PPV_ARGS(&factory2)); ASSERT(SUCCEEDED(result)); DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; - swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - swapChainDesc.Width = backbufferWidth; - swapChainDesc.Height = backbufferHeight; + swapChainDesc.Width = 0; + swapChainDesc.Height = 0; + swapChainDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat); + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.Stereo = FALSE; -#if !defined(ANGLE_OS_WINPHONE) + swapChainDesc.Flags = 0; +#if WINAPI_FAMILY==WINAPI_FAMILY_PC_APP + swapChainDesc.Scaling = DXGI_SCALING_NONE; swapChainDesc.BufferCount = 2; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; -#else +#elif WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP swapChainDesc.BufferCount = 1; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; #endif -#endif - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.Flags = 0; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; -#if !defined(ANGLE_OS_WINRT) - HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); -#else IDXGISwapChain1 *swapChain; - result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); + result = factory2->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); mSwapChain = swapChain; + HRESULT hr = swapChain->GetDesc1(&swapChainDesc); + ASSERT(SUCCEEDED(hr)); + mViewportWidth = swapChainDesc.Width; + mViewportHeight = swapChainDesc.Height; #endif if (FAILED(result)) @@ -415,28 +470,10 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap { return EGL_CONTEXT_LOST; } -#if !defined(ANGLE_OS_WINRT) else { - // We cannot create a swap chain for an HWND that is owned by a different process on some versions of - // windows - DWORD currentProcessId = GetCurrentProcessId(); - DWORD wndProcessId; - GetWindowThreadProcessId(mWindow, &wndProcessId); - - if (currentProcessId != wndProcessId) - { - ERR("Could not create swap chain, window owned by different process"); - return EGL_BAD_NATIVE_WINDOW; - } - else - { - return EGL_BAD_ALLOC; - } + return EGL_BAD_ALLOC; } -#else - return EGL_BAD_ALLOC; -#endif } result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); @@ -505,21 +542,21 @@ void SwapChain11::initPassThroughResources() { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL); + result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); - result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS); + result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); - result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS); + result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); } // parameters should be validated/clamped by caller -EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) { if (!mSwapChain) { @@ -550,10 +587,13 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); - d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); - d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); - d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); - d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); + const int rotateL = flags & SWAP_ROTATE_90; + const int rotateR = flags & SWAP_ROTATE_270; + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2); deviceContext->Unmap(mQuadVB, 0); @@ -583,8 +623,8 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = mWidth; - viewport.Height = mHeight; + viewport.Width = mViewportWidth; + viewport.Height = mViewportHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); @@ -605,6 +645,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) if (result == DXGI_ERROR_DEVICE_REMOVED) { HRESULT removedReason = device->GetDeviceRemovedReason(); + UNUSED_TRACE_VARIABLE(removedReason); ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); return EGL_CONTEXT_LOST; } @@ -628,61 +669,33 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return EGL_SUCCESS; } -// Increments refcount on texture. -// caller must Release() the returned texture ID3D11Texture2D *SwapChain11::getOffscreenTexture() { - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - return mOffscreenTexture; } -// Increments refcount on view. -// caller must Release() the returned view ID3D11RenderTargetView *SwapChain11::getRenderTarget() { - if (mOffscreenRTView) - { - mOffscreenRTView->AddRef(); - } - return mOffscreenRTView; } -// Increments refcount on view. -// caller must Release() the returned view ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() { - if (mOffscreenSRView) - { - mOffscreenSRView->AddRef(); - } - return mOffscreenSRView; } -// Increments refcount on view. -// caller must Release() the returned view ID3D11DepthStencilView *SwapChain11::getDepthStencil() { - if (mDepthStencilDSView) - { - mDepthStencilDSView->AddRef(); - } - return mDepthStencilDSView; } -ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource() { - if (mDepthStencilTexture) - { - mDepthStencilTexture->AddRef(); - } + return mDepthStencilSRView; +} +ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +{ return mDepthStencilTexture; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h index 2a030c839d..b30b78568a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h @@ -25,7 +25,7 @@ class SwapChain11 : public SwapChain EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags); virtual void recreate(); virtual ID3D11Texture2D *getOffscreenTexture(); @@ -34,6 +34,7 @@ class SwapChain11 : public SwapChain virtual ID3D11Texture2D *getDepthStencilTexture(); virtual ID3D11DepthStencilView *getDepthStencil(); + virtual ID3D11ShaderResourceView *getDepthStencilShaderResource(); EGLint getWidth() const { return mWidth; } EGLint getHeight() const { return mHeight; } @@ -51,6 +52,8 @@ class SwapChain11 : public SwapChain Renderer11 *mRenderer; EGLint mHeight; EGLint mWidth; + EGLint mViewportWidth; + EGLint mViewportHeight; bool mAppCreatedShareHandle; unsigned int mSwapInterval; bool mPassThroughResourcesInit; @@ -66,6 +69,7 @@ class SwapChain11 : public SwapChain ID3D11Texture2D *mDepthStencilTexture; ID3D11DepthStencilView *mDepthStencilDSView; + ID3D11ShaderResourceView *mDepthStencilSRView; ID3D11Buffer *mQuadVB; ID3D11SamplerState *mPassThroughSampler; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp new file mode 100644 index 0000000000..00b81b7c92 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp @@ -0,0 +1,1559 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2014 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. +// + +// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" + +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" + +#include "common/utilities.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +TextureStorage11::SwizzleCacheValue::SwizzleCacheValue() + : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE) +{ +} + +TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha) + : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha) +{ +} + +bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const +{ + return swizzleRed == other.swizzleRed && + swizzleGreen == other.swizzleGreen && + swizzleBlue == other.swizzleBlue && + swizzleAlpha == other.swizzleAlpha; +} + +bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const +{ + return !(*this == other); +} + +TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) + : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle) +{ +} + +bool TextureStorage11::SRVKey::operator==(const SRVKey &rhs) const +{ + return baseLevel == rhs.baseLevel && + mipLevels == rhs.mipLevels && + swizzle == rhs.swizzle; +} + +TextureStorage11::SRVCache::~SRVCache() +{ + for (size_t i = 0; i < cache.size(); i++) + { + SafeRelease(cache[i].srv); + } +} + +ID3D11ShaderResourceView *TextureStorage11::SRVCache::find(const SRVKey &key) const +{ + for (size_t i = 0; i < cache.size(); i++) + { + if (cache[i].key == key) + { + return cache[i].srv; + } + } + + return NULL; +} + +ID3D11ShaderResourceView *TextureStorage11::SRVCache::add(const SRVKey &key, ID3D11ShaderResourceView *srv) +{ + SRVPair pair = {key, srv}; + cache.push_back(pair); + + return srv; +} + +TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) + : mBindFlags(bindFlags), + mTopLevel(0), + mMipLevels(0), + mTextureFormat(DXGI_FORMAT_UNKNOWN), + mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), + mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), + mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), + mTextureWidth(0), + mTextureHeight(0), + mTextureDepth(0) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mLevelSRVs[i] = NULL; + } +} + +TextureStorage11::~TextureStorage11() +{ + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mLevelSRVs[level]); + } +} + +TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); + return static_cast<TextureStorage11*>(storage); +} + +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget) +{ + UINT bindFlags = 0; + + if (gl_d3d11::GetSRVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + { + bindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + if (gl_d3d11::GetDSVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + { + bindFlags |= D3D11_BIND_DEPTH_STENCIL; + } + if (gl_d3d11::GetRTVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN && renderTarget) + { + bindFlags |= D3D11_BIND_RENDER_TARGET; + } + + return bindFlags; +} + +UINT TextureStorage11::getBindFlags() const +{ + return mBindFlags; +} + +int TextureStorage11::getTopLevel() const +{ + return mTopLevel; +} + +bool TextureStorage11::isRenderTarget() const +{ + return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; +} + +bool TextureStorage11::isManaged() const +{ + return false; +} + +int TextureStorage11::getLevelCount() const +{ + return mMipLevels - mTopLevel; +} + +int TextureStorage11::getLevelWidth(int mipLevel) const +{ + return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1); +} + +int TextureStorage11::getLevelHeight(int mipLevel) const +{ + return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1); +} + +int TextureStorage11::getLevelDepth(int mipLevel) const +{ + return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1); +} + +UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const +{ + UINT index = 0; + if (getResource()) + { + index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels); + } + return index; +} + +ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState) +{ + bool swizzleRequired = samplerState.swizzleRequired(); + bool mipmapping = IsMipmapFiltered(samplerState); + unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1; + + // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) + mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel); + + if (swizzleRequired) + { + verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha); + } + + SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired); + ID3D11ShaderResourceView *srv = srvCache.find(key); + + if(srv) + { + return srv; + } + + DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); + ID3D11Resource *texture = swizzleRequired ? getSwizzleTexture() : getResource(); + + srv = createSRV(samplerState.baseLevel, mipLevels, format, texture); + + return srvCache.add(key, srv); +} + +ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mLevelSRVs[mipLevel]) + { + mLevelSRVs[mipLevel] = createSRV(mipLevel, 1, mShaderResourceFormat, getResource()); + } + + return mLevelSRVs[mipLevel]; + } + else + { + return NULL; + } +} + +void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +{ + SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + for (int level = 0; level < getLevelCount(); level++) + { + // Check if the swizzle for this level is out of date + if (mSwizzleCache[level] != swizzleTarget) + { + // Need to re-render the swizzle for this level + ID3D11ShaderResourceView *sourceSRV = getSRVLevel(level); + ID3D11RenderTargetView *destRTV = getSwizzleRenderTarget(level); + + gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + + Blit11 *blitter = mRenderer->getBlitter(); + + if (blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha)) + { + mSwizzleCache[level] = swizzleTarget; + } + else + { + ERR("Failed to swizzle texture."); + } + } + } +} + +void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) +{ + if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache)) + { + // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a + // valid swizzle combination + mSwizzleCache[mipLevel] = SwizzleCacheValue(); + } +} + +void TextureStorage11::invalidateSwizzleCache() +{ + for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++) + { + invalidateSwizzleCacheLevel(mipLevel); + } +} + +bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, + int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth) +{ + if (srcTexture) + { + invalidateSwizzleCacheLevel(level); + + gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth); + + bool fullCopy = copyArea.x == 0 && + copyArea.y == 0 && + copyArea.z == 0 && + copyArea.width == texSize.width && + copyArea.height == texSize.height && + copyArea.depth == texSize.depth; + + ID3D11Resource *dstTexture = getResource(); + unsigned int dstSubresource = getSubresourceIndex(level + mTopLevel, layerTarget); + + ASSERT(dstTexture); + + if (!fullCopy && (d3d11::GetDepthBits(mTextureFormat) > 0 || d3d11::GetStencilBits(mTextureFormat) > 0)) + { + // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead + Blit11 *blitter = mRenderer->getBlitter(); + + return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, + dstTexture, dstSubresource, copyArea, texSize, + NULL); + } + else + { + D3D11_BOX srcBox; + srcBox.left = copyArea.x; + srcBox.top = copyArea.y; + srcBox.right = copyArea.x + roundUp((unsigned int)width, d3d11::GetBlockWidth(mTextureFormat)); + srcBox.bottom = copyArea.y + roundUp((unsigned int)height, d3d11::GetBlockHeight(mTextureFormat)); + srcBox.front = copyArea.z; + srcBox.back = copyArea.z + copyArea.depth; + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, + srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); + return true; + } + } + + return false; +} + +void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) +{ + if (source && dest) + { + ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); + ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); + + if (sourceSRV && destRTV) + { + gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); + gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); + + gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth()); + gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); + + Blit11 *blitter = mRenderer->getBlitter(); + + blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, + gl::GetFormat(source->getInternalFormat()), GL_LINEAR); + } + } +} + +void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +{ + SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + for (unsigned int level = 0; level < mMipLevels; level++) + { + ASSERT(mSwizzleCache[level] == swizzleTarget); + } +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) +{ + mTexture = swapchain->getOffscreenTexture(); + mTexture->AddRef(); + mSwizzleTexture = NULL; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + mSwizzleRenderTargets[i] = NULL; + } + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + mMipLevels = texDesc.MipLevels; + mTextureFormat = texDesc.Format; + mTextureWidth = texDesc.Width; + mTextureHeight = texDesc.Height; + mTextureDepth = 1; + + ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srv->GetDesc(&srvDesc); + mShaderResourceFormat = srvDesc.Format; + + ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + offscreenRTV->GetDesc(&rtvDesc); + mRenderTargetFormat = rtvDesc.Format; + + GLenum internalFormat = d3d11_gl::GetInternalFormat(mTextureFormat); + mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalFormat); + mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalFormat); + mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalFormat); + + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + mSwizzleRenderTargets[i] = NULL; + } + + mTextureFormat = gl_d3d11::GetTexFormat(internalformat); + mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); + mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); + mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); + mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); + mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); + mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat); + + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0) + { + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; // Compressed texture size constraints? + desc.Height = height; + desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0); + desc.ArraySize = 1; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + gl::error(GL_OUT_OF_MEMORY); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = 1; + } + } +} + +TextureStorage11_2D::~TextureStorage11_2D() +{ + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + SafeDelete(mRenderTarget[i]); + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); + return static_cast<TextureStorage11_2D*>(storage); +} + +ID3D11Resource *TextureStorage11_2D::getResource() const +{ + return mTexture; +} + +RenderTarget *TextureStorage11_2D::getRenderTarget(int level) +{ + if (level >= 0 && level < getLevelCount()) + { + if (!mRenderTarget[level]) + { + ID3D11ShaderResourceView *srv = getSRVLevel(level); + if (!srv) + { + return NULL; + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = mTopLevel + level; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv; + HRESULT result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTarget[level]; + } + else + { + return NULL; + } +} + +ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2D.MipLevels = mipLevels; + + ID3D11ShaderResourceView *SRV = NULL; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + + return SRV; +} + +void TextureStorage11_2D::generateMipmap(int level) +{ + invalidateSwizzleCacheLevel(level); + + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + + generateMipmapLayer(source, dest); +} + +ID3D11Resource *TextureStorage11_2D::getSwizzleTexture() +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 1; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleTexture; +} + +ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = getSwizzleTexture(); + if (!swizzleTexture) + { + return NULL; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +unsigned int TextureStorage11_2D::getTextureLevelDepth(int mipLevel) const +{ + return 1; +} + +TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mSwizzleRenderTargets[level] = NULL; + for (unsigned int face = 0; face < 6; face++) + { + mRenderTarget[face][level] = NULL; + } + } + + mTextureFormat = gl_d3d11::GetTexFormat(internalformat); + mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); + mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); + mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); + mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); + mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); + mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat); + + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (size > 0) + { + // adjust size if needed for compressed textures + int height = size; + d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = size; + desc.Height = size; + desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); + desc.ArraySize = 6; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = 1; + } + } +} + +TextureStorage11_Cube::~TextureStorage11_Cube() +{ + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mSwizzleRenderTargets[level]); + for (unsigned int face = 0; face < 6; face++) + { + SafeDelete(mRenderTarget[face][level]); + } + } +} + +TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); + return static_cast<TextureStorage11_Cube*>(storage); +} + +ID3D11Resource *TextureStorage11_Cube::getResource() const +{ + return mTexture; +} + +RenderTarget *TextureStorage11_Cube::getRenderTargetFace(GLenum faceTarget, int level) +{ + if (level >= 0 && level < getLevelCount()) + { + int faceIndex = TextureD3D_Cube::targetToIndex(faceTarget); + if (!mRenderTarget[faceIndex][level]) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = faceIndex; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Flags = 0; + dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; + dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; + dsvDesc.Texture2DArray.ArraySize = 1; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTarget[faceIndex][level]; + } + else + { + return NULL; + } +} + +ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + + // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures + bool unnormalizedInteger = (d3d11::GetComponentType(mTextureFormat) == GL_INT || + d3d11::GetComponentType(mTextureFormat) == GL_UNSIGNED_INT); + + if(unnormalizedInteger) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = 6; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = mipLevels; + srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; + } + + ID3D11ShaderResourceView *SRV = NULL; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + + return SRV; +} + +void TextureStorage11_Cube::generateMipmap(int faceIndex, int level) +{ + invalidateSwizzleCacheLevel(level); + + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level)); + + generateMipmapLayer(source, dest); +} + +ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture() +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 6; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleTexture; +} + +ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = getSwizzleTexture(); + if (!swizzleTexture) + { + return NULL; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = 6; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +unsigned int TextureStorage11_Cube::getTextureLevelDepth(int mipLevel) const +{ + return 6; +} + +TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mLevelRenderTargets[i] = NULL; + mSwizzleRenderTargets[i] = NULL; + } + + mTextureFormat = gl_d3d11::GetTexFormat(internalformat); + mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); + mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); + mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); + mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); + mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); + mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat); + + // If the width, height or depth are not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0 && depth > 0) + { + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.Depth = depth; + desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); + desc.Format = mTextureFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + gl::error(GL_OUT_OF_MEMORY); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = desc.Depth; + } + } +} + +TextureStorage11_3D::~TextureStorage11_3D() +{ + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++) + { + SafeDelete(i->second); + } + mLevelLayerRenderTargets.clear(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + SafeDelete(mLevelRenderTargets[i]); + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage)); + return static_cast<TextureStorage11_3D*>(storage); +} + +ID3D11Resource *TextureStorage11_3D::getResource() const +{ + return mTexture; +} + +ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + srvDesc.Texture3D.MostDetailedMip = baseLevel; + srvDesc.Texture3D.MipLevels = mipLevels; + + ID3D11ShaderResourceView *SRV = NULL; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + + return SRV; +} + +RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mLevelRenderTargets[mipLevel]) + { + ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel); + if (!srv) + { + return NULL; + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = -1; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel)); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + else + { + UNREACHABLE(); + } + } + + return mLevelRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + LevelLayerKey key(mipLevel, layer); + if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + // TODO, what kind of SRV is expected here? + ID3D11ShaderResourceView *srv = NULL; + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = layer; + rtvDesc.Texture3D.WSize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } + } + + return mLevelLayerRenderTargets[key]; + } + else + { + return NULL; + } +} + +void TextureStorage11_3D::generateMipmap(int level) +{ + invalidateSwizzleCacheLevel(level); + + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + + generateMipmapLayer(source, dest); +} + +ID3D11Resource *TextureStorage11_3D::getSwizzleTexture() +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = mSwizzleTextureFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture3D*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleTexture; +} + +ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = getSwizzleTexture(); + if (!swizzleTexture) + { + return NULL; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = -1; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +unsigned int TextureStorage11_3D::getTextureLevelDepth(int mipLevel) const +{ + return std::max(mTextureDepth >> mipLevel, 1U); +} + + +TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mSwizzleRenderTargets[level] = NULL; + } + + mTextureFormat = gl_d3d11::GetTexFormat(internalformat); + mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); + mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); + mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); + mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); + mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); + mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat); + + // if the width, height or depth is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0 && depth > 0) + { + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); + desc.ArraySize = depth; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + gl::error(GL_OUT_OF_MEMORY); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = desc.ArraySize; + } + } +} + +TextureStorage11_2DArray::~TextureStorage11_2DArray() +{ + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mSwizzleRenderTargets[level]); + } + + for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++) + { + SafeDelete(i->second); + } + mRenderTargets.clear(); +} + +TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage)); + return static_cast<TextureStorage11_2DArray*>(storage); +} + +ID3D11Resource *TextureStorage11_2DArray::getResource() const +{ + return mTexture; +} + +ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2DArray.MipLevels = mipLevels; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = mTextureDepth; + + ID3D11ShaderResourceView *SRV = NULL; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + + return SRV; +} + +RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + LevelLayerKey key(mipLevel, layer); + if (mRenderTargets.find(key) == mRenderTargets.end()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = layer; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = layer; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTargets[key]; + } + else + { + return NULL; + } +} + +void TextureStorage11_2DArray::generateMipmap(int level) +{ + invalidateSwizzleCacheLevel(level); + for (unsigned int layer = 0; layer < mTextureDepth; layer++) + { + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer)); + + generateMipmapLayer(source, dest); + } +} + +ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture() +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleTexture; +} + +ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = getSwizzleTexture(); + if (!swizzleTexture) + { + return NULL; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = mTextureDepth; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +unsigned int TextureStorage11_2DArray::getTextureLevelDepth(int mipLevel) const +{ + return mTextureDepth; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h new file mode 100644 index 0000000000..6be7bac8e2 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h @@ -0,0 +1,278 @@ +// +// Copyright (c) 2012-2013 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. +// + +// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ + +#include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" + +namespace rx +{ +class RenderTarget; +class RenderTarget11; +class Renderer; +class Renderer11; +class SwapChain11; + +class TextureStorage11 : public TextureStorage +{ + public: + virtual ~TextureStorage11(); + + static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); + + static DWORD GetTextureBindFlags(GLenum internalFormat, bool renderTarget); + + UINT getBindFlags() const; + + virtual ID3D11Resource *getResource() const = 0; + virtual ID3D11ShaderResourceView *getSRV(const gl::SamplerState &samplerState); + virtual RenderTarget *getRenderTarget(int level) { return NULL; } + virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level) { return NULL; } + virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer) { return NULL; } + + virtual void generateMipmap(int level) {}; + virtual void generateMipmap(int face, int level) {}; + + virtual int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int getLevelCount() const; + UINT getSubresourceIndex(int mipLevel, int layerTarget) const; + + void generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + void invalidateSwizzleCacheLevel(int mipLevel); + void invalidateSwizzleCache(); + + bool updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, int level, + int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth); + + protected: + TextureStorage11(Renderer *renderer, UINT bindFlags); + void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); + int getLevelWidth(int mipLevel) const; + int getLevelHeight(int mipLevel) const; + int getLevelDepth(int mipLevel) const; + + virtual ID3D11Resource *getSwizzleTexture() = 0; + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel) = 0; + ID3D11ShaderResourceView *getSRVLevel(int mipLevel); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) = 0; + + void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const = 0; + + Renderer11 *mRenderer; + int mTopLevel; + unsigned int mMipLevels; + + DXGI_FORMAT mTextureFormat; + DXGI_FORMAT mShaderResourceFormat; + DXGI_FORMAT mRenderTargetFormat; + DXGI_FORMAT mDepthStencilFormat; + DXGI_FORMAT mSwizzleTextureFormat; + DXGI_FORMAT mSwizzleShaderResourceFormat; + DXGI_FORMAT mSwizzleRenderTargetFormat; + unsigned int mTextureWidth; + unsigned int mTextureHeight; + unsigned int mTextureDepth; + + struct SwizzleCacheValue + { + GLenum swizzleRed; + GLenum swizzleGreen; + GLenum swizzleBlue; + GLenum swizzleAlpha; + + SwizzleCacheValue(); + SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha); + + bool operator ==(const SwizzleCacheValue &other) const; + bool operator !=(const SwizzleCacheValue &other) const; + }; + SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + struct SRVKey + { + SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false); + + bool operator==(const SRVKey &rhs) const; + + int baseLevel; + int mipLevels; + bool swizzle; + }; + + struct SRVPair + { + SRVKey key; + ID3D11ShaderResourceView *srv; + }; + + struct SRVCache + { + ~SRVCache(); + + ID3D11ShaderResourceView *find(const SRVKey &key) const; + ID3D11ShaderResourceView *add(const SRVKey &key, ID3D11ShaderResourceView *srv); + + std::vector<SRVPair> cache; + }; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11); + + const UINT mBindFlags; + + SRVCache srvCache; + ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_2D : public TextureStorage11 +{ + public: + TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain); + TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual ~TextureStorage11_2D(); + + static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); + + virtual ID3D11Resource *getResource() const; + virtual RenderTarget *getRenderTarget(int level); + + virtual void generateMipmap(int level); + + protected: + virtual ID3D11Resource *getSwizzleTexture(); + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + + ID3D11Texture2D *mTexture; + RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_Cube : public TextureStorage11 +{ + public: + TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels); + virtual ~TextureStorage11_Cube(); + + static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); + + virtual ID3D11Resource *getResource() const; + virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level); + + virtual void generateMipmap(int faceIndex, int level); + + protected: + virtual ID3D11Resource *getSwizzleTexture(); + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + + ID3D11Texture2D *mTexture; + RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_3D : public TextureStorage11 +{ + public: + TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorage11_3D(); + + static TextureStorage11_3D *makeTextureStorage11_3D(TextureStorage *storage); + + virtual ID3D11Resource *getResource() const; + virtual RenderTarget *getRenderTarget(int mipLevel); + virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer); + + virtual void generateMipmap(int level); + + protected: + virtual ID3D11Resource *getSwizzleTexture(); + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + + typedef std::pair<int, int> LevelLayerKey; + typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap; + RenderTargetMap mLevelLayerRenderTargets; + + RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + ID3D11Texture3D *mTexture; + ID3D11Texture3D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_2DArray : public TextureStorage11 +{ + public: + TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorage11_2DArray(); + + static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage); + + virtual ID3D11Resource *getResource() const; + virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer); + + virtual void generateMipmap(int level); + + protected: + virtual ID3D11Resource *getSwizzleTexture(); + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + + typedef std::pair<int, int> LevelLayerKey; + typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap; + RenderTargetMap mRenderTargets; + + ID3D11Texture2D *mTexture; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h new file mode 100644 index 0000000000..590cb9f05a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h @@ -0,0 +1,42 @@ +// +// Copyright 2014 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. +// + +// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAY11_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAY11_H_ + +#include "libGLESv2/renderer/VertexArrayImpl.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ +class Renderer11; + +class VertexArray11 : public VertexArrayImpl +{ + public: + VertexArray11(rx::Renderer11 *renderer) + : VertexArrayImpl(), + mRenderer(renderer) + { + } + virtual ~VertexArray11() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } + virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } + virtual void enableAttribute(size_t idx, bool enabledState) { } + + private: + DISALLOW_COPY_AND_ASSIGN(VertexArray11); + + rx::Renderer11 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp new file mode 100644 index 0000000000..2f47ec0a67 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -0,0 +1,223 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 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. +// + +// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. + +#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" + +namespace rx +{ + +VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +VertexBuffer11::~VertexBuffer11() +{ + SafeRelease(mBuffer); +} + +bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) +{ + SafeRelease(mBuffer); + + updateSerial(); + + if (size > 0) + { + ID3D11Device* dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = size; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return false; + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return true; +} + +VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); + return static_cast<VertexBuffer11*>(vetexBuffer); +} + +bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) +{ + if (mBuffer) + { + gl::Buffer *buffer = attrib.buffer.get(); + int inputStride = ComputeVertexAttributeStride(attrib); + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + char* output = reinterpret_cast<char*>(mappedResource.pData) + offset; + + const char *input = NULL; + if (attrib.enabled) + { + if (buffer) + { + Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation()); + input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.offset); + } + else + { + input = static_cast<const char*>(attrib.pointer); + } + } + else + { + input = reinterpret_cast<const char*>(currentValue.FloatValues); + } + + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } + + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + VertexCopyFunction conversionFunc = gl_d3d11::GetVertexCopyFunction(vertexFormat); + ASSERT(conversionFunc != NULL); + conversionFunc(input, inputStride, count, output); + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances, unsigned int *outSpaceRequired) const +{ + unsigned int elementCount = 0; + if (attrib.enabled) + { + if (instances == 0 || attrib.divisor == 0) + { + elementCount = count; + } + else + { + if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.divisor - 1)) + { + // Round up + elementCount = rx::roundUp(static_cast<unsigned int>(instances), attrib.divisor); + } + else + { + elementCount = instances / attrib.divisor; + } + } + + gl::VertexFormat vertexFormat(attrib); + unsigned int elementSize = static_cast<unsigned int>(gl_d3d11::GetVertexElementSize(vertexFormat)); + if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } + } + else + { + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return true; + } +} + +unsigned int VertexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +bool VertexBuffer11::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return true; + } +} + +bool VertexBuffer11::discard() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +ID3D11Buffer *VertexBuffer11::getBuffer() const +{ + return mBuffer; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h index eceb426e82..c2a5aa7afd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ #define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ -#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/d3d/VertexBuffer.h" namespace rx { @@ -25,22 +25,16 @@ class VertexBuffer11 : public VertexBuffer static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int offset); - virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset); virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; - virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; - virtual unsigned int getBufferSize() const; virtual bool setBufferSize(unsigned int size); virtual bool discard(); - unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; - DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const; - ID3D11Buffer *getBuffer() const; private: @@ -51,22 +45,6 @@ class VertexBuffer11 : public VertexBuffer ID3D11Buffer *mBuffer; unsigned int mBufferSize; bool mDynamicUsage; - - typedef void (*VertexConversionFunction)(const void *, unsigned int, unsigned int, void *); - struct VertexConverter - { - VertexConversionFunction conversionFunc; - bool identity; - DXGI_FORMAT dxgiFormat; - unsigned int outputElementSize; - }; - - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - // This table is used to generate mAttributeTypes. - static const VertexConverter mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] - - static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute); }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp new file mode 100644 index 0000000000..c991fd4991 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp @@ -0,0 +1,1458 @@ +#include "precompiled.h" +// +// Copyright (c) 2013-2014 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. +// + +// formatutils11.cpp: Queries for GL image formats and their translations to D3D11 +// formats. + +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/generatemip.h" +#include "libGLESv2/renderer/loadimage.h" +#include "libGLESv2/renderer/copyimage.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/copyvertex.h" + +namespace rx +{ + +struct D3D11FormatInfo +{ + DXGI_FORMAT mTexFormat; + DXGI_FORMAT mSRVFormat; + DXGI_FORMAT mRTVFormat; + DXGI_FORMAT mDSVFormat; + + D3D11FormatInfo() + : mTexFormat(DXGI_FORMAT_UNKNOWN), mDSVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN) + { } + + D3D11FormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) + : mTexFormat(texFormat), mDSVFormat(dsvFormat), mRTVFormat(rtvFormat), mSRVFormat(srvFormat) + { } +}; + +// For sized GL internal formats, there is only one corresponding D3D11 format. This map type allows +// querying for the DXGI texture formats to use for textures, SRVs, RTVs and DSVs given a GL internal +// format. +typedef std::pair<GLenum, D3D11FormatInfo> D3D11ES3FormatPair; +typedef std::map<GLenum, D3D11FormatInfo> D3D11ES3FormatMap; + +static D3D11ES3FormatMap BuildD3D11FormatMap() +{ + D3D11ES3FormatMap map; + + // | GL internal format | | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + map.insert(D3D11ES3FormatPair(GL_NONE, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R8, D3D11FormatInfo(DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R8_SNORM, D3D11FormatInfo(DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG8, D3D11FormatInfo(DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG8_SNORM, D3D11FormatInfo(DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB8, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB8_SNORM, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB565, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA4, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB5_A1, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA8, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA8_SNORM, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB10_A2, D3D11FormatInfo(DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB10_A2UI, D3D11FormatInfo(DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_SRGB8, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_SRGB8_ALPHA8, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R16F, D3D11FormatInfo(DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG16F, D3D11FormatInfo(DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB16F, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA16F, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R32F, D3D11FormatInfo(DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG32F, D3D11FormatInfo(DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB32F, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA32F, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R11F_G11F_B10F, D3D11FormatInfo(DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB9_E5, D3D11FormatInfo(DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R8I, D3D11FormatInfo(DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R8UI, D3D11FormatInfo(DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R16I, D3D11FormatInfo(DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R16UI, D3D11FormatInfo(DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R32I, D3D11FormatInfo(DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_R32UI, D3D11FormatInfo(DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG8I, D3D11FormatInfo(DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG8UI, D3D11FormatInfo(DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG16I, D3D11FormatInfo(DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG16UI, D3D11FormatInfo(DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG32I, D3D11FormatInfo(DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RG32UI, D3D11FormatInfo(DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB8I, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB8UI, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB16I, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB16UI, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB32I, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB32UI, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA8I, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA8UI, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA16I, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA16UI, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA32I, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA32UI, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN))); + + // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format? + map.insert(D3D11ES3FormatPair(GL_ALPHA, D3D11FormatInfo(DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_LUMINANCE, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGB, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_RGBA, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_BGRA_EXT, D3D11FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + + // From GL_EXT_texture_storage + // | GL internal format | | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + map.insert(D3D11ES3FormatPair(GL_ALPHA8_EXT, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_LUMINANCE8_EXT, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_ALPHA32F_EXT, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_LUMINANCE32F_EXT, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_ALPHA16F_EXT, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_LUMINANCE16F_EXT, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_BGRA8_EXT, D3D11FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_BGRA4_ANGLEX, D3D11FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); + map.insert(D3D11ES3FormatPair(GL_BGR5_A1_ANGLEX, D3D11FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); + + // Depth stencil formats + map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT16, D3D11FormatInfo(DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM ))); + map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT24, D3D11FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); + map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT32F, D3D11FormatInfo(DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT ))); + map.insert(D3D11ES3FormatPair(GL_DEPTH24_STENCIL8, D3D11FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); + map.insert(D3D11ES3FormatPair(GL_DEPTH32F_STENCIL8, D3D11FormatInfo(DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT))); + map.insert(D3D11ES3FormatPair(GL_STENCIL_INDEX8, D3D11FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); + + // From GL_ANGLE_depth_texture + // Since D3D11 doesn't have a D32_UNORM format, use D24S8 which has comparable precision and matches the ES3 format. + map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT32_OES, D3D11FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); + + // Compressed formats, From ES 3.0.1 spec, table 3.16 + // | GL internal format | | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_R11_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SIGNED_R11_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RG11_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SIGNED_RG11_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB8_ETC2, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_ETC2, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA8_ETC2_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + + // From GL_EXT_texture_compression_dxt1 + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D11FormatInfo(DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D11FormatInfo(DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + + // From GL_ANGLE_texture_compression_dxt3 + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D11FormatInfo(DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + + // From GL_ANGLE_texture_compression_dxt5 + map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D11FormatInfo(DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + + return map; +} + +static bool GetD3D11FormatInfo(GLenum internalFormat, D3D11FormatInfo *outFormatInfo) +{ + static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); + D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + if (outFormatInfo) + { + *outFormatInfo = iter->second; + } + return true; + } + else + { + return false; + } +} + +// ES3 image loading functions vary based on the internal format and data type given, +// this map type determines the loading function from the internal format and type supplied +// to glTex*Image*D and the destination DXGI_FORMAT. Source formats and types are taken from +// Tables 3.2 and 3.3 of the ES 3 spec. +typedef std::pair<GLenum, GLenum> InternalFormatTypePair; +typedef std::pair<InternalFormatTypePair, LoadImageFunction> D3D11LoadFunctionPair; +typedef std::map<InternalFormatTypePair, LoadImageFunction> D3D11LoadFunctionMap; + +static void UnimplementedLoadFunction(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNIMPLEMENTED(); +} + +static void UnreachableLoadFunction(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters. +static inline void insertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type, + LoadImageFunction loadFunc) +{ + map->insert(D3D11LoadFunctionPair(InternalFormatTypePair(internalFormat, type), loadFunc)); +} + +D3D11LoadFunctionMap buildD3D11LoadFunctionMap() +{ + D3D11LoadFunctionMap map; + + // | Internal format | Type | Load function | + insertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> ); + insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> ); + insertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> ); + insertLoadFunction(&map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> ); + insertLoadFunction(&map, GL_RGBA8_SNORM, GL_BYTE, LoadToNative<GLbyte, 4> ); + insertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, LoadRGBA4ToRGBA8 ); + insertLoadFunction(&map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative<GLuint, 1> ); + insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, LoadRGB5A1ToRGBA8 ); + insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_INT_2_10_10_10_REV, LoadRGB10A2ToRGBA8 ); + insertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT, LoadToNative<GLhalf, 4> ); + insertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT_OES, LoadToNative<GLhalf, 4> ); + insertLoadFunction(&map, GL_RGBA32F, GL_FLOAT, LoadToNative<GLfloat, 4> ); + insertLoadFunction(&map, GL_RGBA16F, GL_FLOAT, Load32FTo16F<4> ); + insertLoadFunction(&map, GL_RGBA8UI, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> ); + insertLoadFunction(&map, GL_RGBA8I, GL_BYTE, LoadToNative<GLbyte, 4> ); + insertLoadFunction(&map, GL_RGBA16UI, GL_UNSIGNED_SHORT, LoadToNative<GLushort, 4> ); + insertLoadFunction(&map, GL_RGBA16I, GL_SHORT, LoadToNative<GLshort, 4> ); + insertLoadFunction(&map, GL_RGBA32UI, GL_UNSIGNED_INT, LoadToNative<GLuint, 4> ); + insertLoadFunction(&map, GL_RGBA32I, GL_INT, LoadToNative<GLint, 4> ); + insertLoadFunction(&map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative<GLuint, 1> ); + insertLoadFunction(&map, GL_RGB8, GL_UNSIGNED_BYTE, LoadToNative3To4<GLubyte, 0xFF> ); + insertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_BYTE, LoadToNative3To4<GLubyte, 0xFF> ); + insertLoadFunction(&map, GL_SRGB8, GL_UNSIGNED_BYTE, LoadToNative3To4<GLubyte, 0xFF> ); + insertLoadFunction(&map, GL_RGB8_SNORM, GL_BYTE, LoadToNative3To4<GLbyte, 0x7F> ); + insertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, LoadR5G6B5ToRGBA8 ); + insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, LoadToNative<GLuint, 1> ); + insertLoadFunction(&map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, LoadToNative<GLuint, 1> ); + insertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT, LoadToNative3To4<GLhalf, gl::Float16One>); + insertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT_OES, LoadToNative3To4<GLhalf, gl::Float16One>); + insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT, LoadRGB16FToRG11B10F ); + insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT_OES, LoadRGB16FToRG11B10F ); + insertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT, LoadRGB16FToRGB9E5 ); + insertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT_OES, LoadRGB16FToRGB9E5 ); + insertLoadFunction(&map, GL_RGB32F, GL_FLOAT, LoadToNative3To4<GLfloat, gl::Float32One>); + insertLoadFunction(&map, GL_RGB16F, GL_FLOAT, LoadRGB32FToRGBA16F ); + insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_FLOAT, LoadRGB32FToRG11B10F ); + insertLoadFunction(&map, GL_RGB9_E5, GL_FLOAT, LoadRGB32FToRGB9E5 ); + insertLoadFunction(&map, GL_RGB8UI, GL_UNSIGNED_BYTE, LoadToNative3To4<GLubyte, 0x01> ); + insertLoadFunction(&map, GL_RGB8I, GL_BYTE, LoadToNative3To4<GLbyte, 0x01> ); + insertLoadFunction(&map, GL_RGB16UI, GL_UNSIGNED_SHORT, LoadToNative3To4<GLushort, 0x0001> ); + insertLoadFunction(&map, GL_RGB16I, GL_SHORT, LoadToNative3To4<GLshort, 0x0001> ); + insertLoadFunction(&map, GL_RGB32UI, GL_UNSIGNED_INT, LoadToNative3To4<GLuint, 0x00000001> ); + insertLoadFunction(&map, GL_RGB32I, GL_INT, LoadToNative3To4<GLint, 0x00000001> ); + insertLoadFunction(&map, GL_RG8, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 2> ); + insertLoadFunction(&map, GL_RG8_SNORM, GL_BYTE, LoadToNative<GLbyte, 2> ); + insertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT, LoadToNative<GLhalf, 2> ); + insertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT_OES, LoadToNative<GLhalf, 2> ); + insertLoadFunction(&map, GL_RG32F, GL_FLOAT, LoadToNative<GLfloat, 2> ); + insertLoadFunction(&map, GL_RG16F, GL_FLOAT, Load32FTo16F<2> ); + insertLoadFunction(&map, GL_RG8UI, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 2> ); + insertLoadFunction(&map, GL_RG8I, GL_BYTE, LoadToNative<GLbyte, 2> ); + insertLoadFunction(&map, GL_RG16UI, GL_UNSIGNED_SHORT, LoadToNative<GLushort, 2> ); + insertLoadFunction(&map, GL_RG16I, GL_SHORT, LoadToNative<GLshort, 2> ); + insertLoadFunction(&map, GL_RG32UI, GL_UNSIGNED_INT, LoadToNative<GLuint, 2> ); + insertLoadFunction(&map, GL_RG32I, GL_INT, LoadToNative<GLint, 2> ); + insertLoadFunction(&map, GL_R8, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 1> ); + insertLoadFunction(&map, GL_R8_SNORM, GL_BYTE, LoadToNative<GLbyte, 1> ); + insertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT, LoadToNative<GLhalf, 1> ); + insertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT_OES, LoadToNative<GLhalf, 1> ); + insertLoadFunction(&map, GL_R32F, GL_FLOAT, LoadToNative<GLfloat, 1> ); + insertLoadFunction(&map, GL_R16F, GL_FLOAT, Load32FTo16F<1> ); + insertLoadFunction(&map, GL_R8UI, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 1> ); + insertLoadFunction(&map, GL_R8I, GL_BYTE, LoadToNative<GLbyte, 1> ); + insertLoadFunction(&map, GL_R16UI, GL_UNSIGNED_SHORT, LoadToNative<GLushort, 1> ); + insertLoadFunction(&map, GL_R16I, GL_SHORT, LoadToNative<GLshort, 1> ); + insertLoadFunction(&map, GL_R32UI, GL_UNSIGNED_INT, LoadToNative<GLuint, 1> ); + insertLoadFunction(&map, GL_R32I, GL_INT, LoadToNative<GLint, 1> ); + insertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, LoadToNative<GLushort, 1> ); + insertLoadFunction(&map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + insertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_INT, LoadR32ToR16 ); + insertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT, LoadToNative<GLfloat, 1> ); + insertLoadFunction(&map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, LoadR32ToR24G8 ); + insertLoadFunction(&map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, LoadToNative<GLuint, 2> ); + + // Unsized formats + // Load functions are unreachable because they are converted to sized internal formats based on + // the format and type before loading takes place. + insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_RGB, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + + // From GL_OES_texture_float + insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, LoadLA32FToRGBA32F ); + insertLoadFunction(&map, GL_LUMINANCE, GL_FLOAT, LoadL32FToRGBA32F ); + insertLoadFunction(&map, GL_ALPHA, GL_FLOAT, LoadA32FToRGBA32F ); + + // From GL_OES_texture_half_float + insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT, LoadL16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); + insertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT, LoadA16FToRGBA16F ); + insertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); + + // From GL_EXT_texture_storage + insertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToBGRA8 ); + insertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 ); + insertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 ); + insertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F ); + insertLoadFunction(&map, GL_LUMINANCE32F_EXT, GL_FLOAT, LoadL32FToRGBA32F ); + insertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT, LoadLA32FToRGBA32F ); + insertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT, LoadA16FToRGBA16F ); + insertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT, LoadL16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); + + // From GL_ANGLE_depth_texture + insertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + + // From GL_EXT_texture_format_BGRA8888 + insertLoadFunction(&map, GL_BGRA8_EXT, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> ); + insertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, LoadRGBA4ToRGBA8 ); + insertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> ); + insertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, LoadRGB5A1ToRGBA8 ); + insertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 4> ); + + // Compressed formats + // From ES 3.0.1 spec, table 3.16 + // | Internal format | Type | Load function | + insertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + + // From GL_EXT_texture_compression_dxt1 + insertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); + insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); + + // From GL_ANGLE_texture_compression_dxt3 + insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + + // From GL_ANGLE_texture_compression_dxt5 + insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + + return map; +} + +// A map to determine the pixel size and mipmap generation function of a given DXGI format +struct DXGIFormatInfo +{ + GLuint mPixelBits; + GLuint mBlockWidth; + GLuint mBlockHeight; + GLenum mComponentType; + + MipGenerationFunction mMipGenerationFunction; + ColorReadFunction mColorReadFunction; + + DXGIFormatInfo() + : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mComponentType(GL_NONE), mMipGenerationFunction(NULL), + mColorReadFunction(NULL) + { } + + DXGIFormatInfo(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, GLenum componentType, + MipGenerationFunction mipFunc, ColorReadFunction readFunc) + : mPixelBits(pixelBits), mBlockWidth(blockWidth), mBlockHeight(blockHeight), mComponentType(componentType), + mMipGenerationFunction(mipFunc), mColorReadFunction(readFunc) + { } +}; + +typedef std::map<DXGI_FORMAT, DXGIFormatInfo> DXGIFormatInfoMap; + +void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, + GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc) +{ + map->insert(std::make_pair(dxgiFormat, DXGIFormatInfo(pixelBits, blockWidth, blockHeight, componentType, mipFunc, readFunc))); +} + +static DXGIFormatInfoMap BuildDXGIFormatInfoMap() +{ + DXGIFormatInfoMap map; + + // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function + AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL); + + AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<A8>, ReadColor<A8, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8>, ReadColor<R8, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8>, ReadColor<R8G8, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat>); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8S>, ReadColor<R8S, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8G8S>, ReadColor<R8G8S, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8G8B8A8S>, ReadColor<R8G8B8A8S, GLfloat>); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8>, ReadColor<R8, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16>, ReadColor<R16, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32>, ReadColor<R32, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8G8>, ReadColor<R8G8, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16G16>, ReadColor<R16G16, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32>, ReadColor<R32G32, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32B32>, ReadColor<R32G32B32, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16G16B16A16>, ReadColor<R16G16B16A16, GLuint>); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32B32A32>, ReadColor<R32G32B32A32, GLuint>); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip<R8S>, ReadColor<R8S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip<R16S>, ReadColor<R16S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip<R32S>, ReadColor<R32S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip<R8G8S>, ReadColor<R8G8S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip<R16G16S>, ReadColor<R16G16S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip<R32G32S>, ReadColor<R32G32S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip<R32G32B32S>, ReadColor<R32G32B32S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip<R8G8B8A8S>, ReadColor<R8G8B8A8S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip<R16G16B16A16S>, ReadColor<R16G16B16A16S, GLint>); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip<R32G32B32A32S>, ReadColor<R32G32B32A32S, GLint>); + + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R10G10B10A2>, ReadColor<R10G10B10A2, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R10G10B10A2>, ReadColor<R10G10B10A2, GLuint>); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip<R16F>, ReadColor<R16F, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>); + + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R32F>, ReadColor<R32F, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>); + + AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip<R9G9B9E5>, ReadColor<R9G9B9E5, GLfloat>); + AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R11G11B10F>, ReadColor<R11G11B10F, GLfloat>); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL); + + AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + + // Useful formats for vertex buffers + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + + return map; +} + +typedef std::map<DXGI_FORMAT, GLenum> DXGIToESFormatMap; + +inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value) +{ + map->insert(std::make_pair(key, value)); +} + +static DXGIToESFormatMap BuildDXGIToESFormatMap() +{ + DXGIToESFormatMap map; + + AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE); + + AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8); + AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2); + AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5); + AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + + return map; +} + +static const DXGIToESFormatMap &GetDXGIToESFormatMap() +{ + static const DXGIToESFormatMap map = BuildDXGIToESFormatMap(); + return map; +} + +static const DXGIFormatInfoMap &GetDXGIFormatInfoMap() +{ + static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap(); + return infoMap; +} + +static bool GetDXGIFormatInfo(DXGI_FORMAT format, DXGIFormatInfo *outFormatInfo) +{ + const DXGIFormatInfoMap &infoMap = GetDXGIFormatInfoMap(); + DXGIFormatInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + if (outFormatInfo) + { + *outFormatInfo = iter->second; + } + return true; + } + else + { + return false; + } +} + +static d3d11::DXGIFormatSet BuildAllDXGIFormatSet() +{ + d3d11::DXGIFormatSet set; + + const DXGIFormatInfoMap &infoMap = GetDXGIFormatInfoMap(); + for (DXGIFormatInfoMap::const_iterator i = infoMap.begin(); i != infoMap.end(); ++i) + { + set.insert(i->first); + } + + return set; +} + +struct D3D11FastCopyFormat +{ + DXGI_FORMAT mSourceFormat; + GLenum mDestFormat; + GLenum mDestType; + + D3D11FastCopyFormat(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) + : mSourceFormat(sourceFormat), mDestFormat(destFormat), mDestType(destType) + { } + + bool operator<(const D3D11FastCopyFormat& other) const + { + return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; + } +}; + +typedef std::map<D3D11FastCopyFormat, ColorCopyFunction> D3D11FastCopyMap; +typedef std::pair<D3D11FastCopyFormat, ColorCopyFunction> D3D11FastCopyPair; + +static D3D11FastCopyMap BuildFastCopyMap() +{ + D3D11FastCopyMap map; + + map.insert(D3D11FastCopyPair(D3D11FastCopyFormat(DXGI_FORMAT_B8G8R8A8_UNORM, GL_RGBA, GL_UNSIGNED_BYTE), CopyBGRAUByteToRGBAUByte)); + + return map; +} + +struct DXGIDepthStencilInfo +{ + unsigned int mDepthBits; + unsigned int mDepthOffset; + unsigned int mStencilBits; + unsigned int mStencilOffset; + + DXGIDepthStencilInfo() + : mDepthBits(0), mDepthOffset(0), mStencilBits(0), mStencilOffset(0) + { } + + DXGIDepthStencilInfo(unsigned int depthBits, unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset) + : mDepthBits(depthBits), mDepthOffset(depthOffset), mStencilBits(stencilBits), mStencilOffset(stencilOffset) + { } +}; + +typedef std::map<DXGI_FORMAT, DXGIDepthStencilInfo> DepthStencilInfoMap; +typedef std::pair<DXGI_FORMAT, DXGIDepthStencilInfo> DepthStencilInfoPair; + +static DepthStencilInfoMap BuildDepthStencilInfoMap() +{ + DepthStencilInfoMap map; + + map.insert(DepthStencilInfoPair(DXGI_FORMAT_R16_TYPELESS, DXGIDepthStencilInfo(16, 0, 0, 0))); + map.insert(DepthStencilInfoPair(DXGI_FORMAT_R16_UNORM, DXGIDepthStencilInfo(16, 0, 0, 0))); + map.insert(DepthStencilInfoPair(DXGI_FORMAT_D16_UNORM, DXGIDepthStencilInfo(16, 0, 0, 0))); + + map.insert(DepthStencilInfoPair(DXGI_FORMAT_R24G8_TYPELESS, DXGIDepthStencilInfo(24, 0, 8, 24))); + map.insert(DepthStencilInfoPair(DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGIDepthStencilInfo(24, 0, 8, 24))); + map.insert(DepthStencilInfoPair(DXGI_FORMAT_D24_UNORM_S8_UINT, DXGIDepthStencilInfo(24, 0, 8, 24))); + + map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_TYPELESS, DXGIDepthStencilInfo(32, 0, 0, 0))); + map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_FLOAT, DXGIDepthStencilInfo(32, 0, 0, 0))); + map.insert(DepthStencilInfoPair(DXGI_FORMAT_D32_FLOAT, DXGIDepthStencilInfo(32, 0, 0, 0))); + + map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32G8X24_TYPELESS, DXGIDepthStencilInfo(32, 0, 8, 32))); + map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGIDepthStencilInfo(32, 0, 8, 32))); + map.insert(DepthStencilInfoPair(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGIDepthStencilInfo(32, 0, 8, 32))); + + return map; +} + +static const DepthStencilInfoMap &GetDepthStencilInfoMap() +{ + static const DepthStencilInfoMap infoMap = BuildDepthStencilInfoMap(); + return infoMap; +} + +bool GetDepthStencilInfo(DXGI_FORMAT format, DXGIDepthStencilInfo *outDepthStencilInfo) +{ + const DepthStencilInfoMap& infoMap = GetDepthStencilInfoMap(); + DepthStencilInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + if (outDepthStencilInfo) + { + *outDepthStencilInfo = iter->second; + } + return true; + } + else + { + return false; + } +} + +struct SwizzleSizeType +{ + unsigned int mMaxComponentSize; + GLenum mComponentType; + + SwizzleSizeType() + : mMaxComponentSize(0), mComponentType(GL_NONE) + { } + + SwizzleSizeType(unsigned int maxComponentSize, GLenum componentType) + : mMaxComponentSize(maxComponentSize), mComponentType(componentType) + { } + + bool operator<(const SwizzleSizeType& other) const + { + return (mMaxComponentSize != other.mMaxComponentSize) ? (mMaxComponentSize < other.mMaxComponentSize) + : (mComponentType < other.mComponentType); + } +}; + +struct SwizzleFormatInfo +{ + DXGI_FORMAT mTexFormat; + DXGI_FORMAT mSRVFormat; + DXGI_FORMAT mRTVFormat; + + SwizzleFormatInfo() + : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN) + { } + + SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat) + : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) + { } +}; + +typedef std::map<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoMap; +typedef std::pair<SwizzleSizeType, SwizzleFormatInfo> SwizzleInfoPair; + +static SwizzleInfoMap BuildSwizzleInfoMap() +{ + SwizzleInfoMap map; + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM))); + map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM ))); + + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT ))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT ))); + + return map; +} +typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitializerPair; +typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitializerMap; + +static InternalFormatInitializerMap BuildInternalFormatInitializerMap() +{ + InternalFormatInitializerMap map; + + map.insert(InternalFormatInitializerPair(GL_RGB8, Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF> )); + map.insert(InternalFormatInitializerPair(GL_RGB565, Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF> )); + map.insert(InternalFormatInitializerPair(GL_SRGB8, Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF> )); + map.insert(InternalFormatInitializerPair(GL_RGB16F, Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>)); + map.insert(InternalFormatInitializerPair(GL_RGB32F, Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>)); + map.insert(InternalFormatInitializerPair(GL_RGB8UI, Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01> )); + map.insert(InternalFormatInitializerPair(GL_RGB8I, Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01> )); + map.insert(InternalFormatInitializerPair(GL_RGB16UI, Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001> )); + map.insert(InternalFormatInitializerPair(GL_RGB16I, Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001> )); + map.insert(InternalFormatInitializerPair(GL_RGB32UI, Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001> )); + map.insert(InternalFormatInitializerPair(GL_RGB32I, Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001> )); + + return map; +} + +static const SwizzleInfoMap &GetSwizzleInfoMap() +{ + static const SwizzleInfoMap map = BuildSwizzleInfoMap(); + return map; +} + +static const SwizzleFormatInfo GetSwizzleFormatInfo(GLenum internalFormat) +{ + // Get the maximum sized component + unsigned int maxBits = 1; + + if (gl::IsFormatCompressed(internalFormat)) + { + unsigned int compressedBitsPerBlock = gl::GetPixelBytes(internalFormat) * 8; + unsigned int blockSize = gl::GetCompressedBlockWidth(internalFormat) * + gl::GetCompressedBlockHeight(internalFormat); + maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); + } + else + { + maxBits = std::max(maxBits, gl::GetAlphaBits( internalFormat)); + maxBits = std::max(maxBits, gl::GetRedBits( internalFormat)); + maxBits = std::max(maxBits, gl::GetGreenBits( internalFormat)); + maxBits = std::max(maxBits, gl::GetBlueBits( internalFormat)); + maxBits = std::max(maxBits, gl::GetLuminanceBits(internalFormat)); + maxBits = std::max(maxBits, gl::GetDepthBits( internalFormat)); + } + + maxBits = roundUp(maxBits, 8U); + + GLenum componentType = gl::GetComponentType(internalFormat); + + const SwizzleInfoMap &map = GetSwizzleInfoMap(); + SwizzleInfoMap::const_iterator iter = map.find(SwizzleSizeType(maxBits, componentType)); + + if (iter != map.end()) + { + return iter->second; + } + else + { + UNREACHABLE(); + static const SwizzleFormatInfo defaultFormatInfo; + return defaultFormatInfo; + } +} + +static const InternalFormatInitializerMap &GetInternalFormatInitializerMap() +{ + static const InternalFormatInitializerMap map = BuildInternalFormatInitializerMap(); + return map; +} + +namespace d3d11 +{ + +MipGenerationFunction GetMipGenerationFunction(DXGI_FORMAT format) +{ + DXGIFormatInfo formatInfo; + if (GetDXGIFormatInfo(format, &formatInfo)) + { + return formatInfo.mMipGenerationFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +LoadImageFunction GetImageLoadFunction(GLenum internalFormat, GLenum type) +{ + static const D3D11LoadFunctionMap loadImageMap = buildD3D11LoadFunctionMap(); + D3D11LoadFunctionMap::const_iterator iter = loadImageMap.find(InternalFormatTypePair(internalFormat, type)); + if (iter != loadImageMap.end()) + { + return iter->second; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +GLuint GetFormatPixelBytes(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mPixelBits / 8; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockWidth(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mBlockWidth; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockHeight(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mBlockHeight; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLenum GetComponentType(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mComponentType; + } + else + { + UNREACHABLE(); + return GL_NONE; + } +} + +GLuint GetDepthBits(DXGI_FORMAT format) +{ + DXGIDepthStencilInfo dxgiDSInfo; + if (GetDepthStencilInfo(format, &dxgiDSInfo)) + { + return dxgiDSInfo.mDepthBits; + } + else + { + // Since the depth stencil info map does not contain all used DXGI formats, + // we should not assert that the format exists + return 0; + } +} + +GLuint GetDepthOffset(DXGI_FORMAT format) +{ + DXGIDepthStencilInfo dxgiDSInfo; + if (GetDepthStencilInfo(format, &dxgiDSInfo)) + { + return dxgiDSInfo.mDepthOffset; + } + else + { + // Since the depth stencil info map does not contain all used DXGI formats, + // we should not assert that the format exists + return 0; + } +} + +GLuint GetStencilBits(DXGI_FORMAT format) +{ + DXGIDepthStencilInfo dxgiDSInfo; + if (GetDepthStencilInfo(format, &dxgiDSInfo)) + { + return dxgiDSInfo.mStencilBits; + } + else + { + // Since the depth stencil info map does not contain all used DXGI formats, + // we should not assert that the format exists + return 0; + } +} + +GLuint GetStencilOffset(DXGI_FORMAT format) +{ + DXGIDepthStencilInfo dxgiDSInfo; + if (GetDepthStencilInfo(format, &dxgiDSInfo)) + { + return dxgiDSInfo.mStencilOffset; + } + else + { + // Since the depth stencil info map does not contain all used DXGI formats, + // we should not assert that the format exists + return 0; + } +} + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + int upsampleCount = 0; + + GLsizei blockWidth = dxgiFormatInfo.mBlockWidth; + GLsizei blockHeight = dxgiFormatInfo.mBlockHeight; + + // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. + if (isImage || *requestWidth < blockWidth || *requestHeight < blockHeight) + { + while (*requestWidth % blockWidth != 0 || *requestHeight % blockHeight != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + *levelOffset = upsampleCount; + } + else + { + UNREACHABLE(); + } +} + +const DXGIFormatSet &GetAllUsedDXGIFormats() +{ + static DXGIFormatSet formatSet = BuildAllDXGIFormatSet(); + return formatSet; +} + +ColorReadFunction GetColorReadFunction(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mColorReadFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +ColorCopyFunction GetFastCopyFunction(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) +{ + static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap(); + D3D11FastCopyMap::const_iterator iter = fastCopyMap.find(D3D11FastCopyFormat(sourceFormat, destFormat, destType)); + return (iter != fastCopyMap.end()) ? iter->second : NULL; +} + +} + +namespace gl_d3d11 +{ + +DXGI_FORMAT GetTexFormat(GLenum internalFormat) +{ + D3D11FormatInfo d3d11FormatInfo; + if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) + { + return d3d11FormatInfo.mTexFormat; + } + else + { + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +DXGI_FORMAT GetSRVFormat(GLenum internalFormat) +{ + D3D11FormatInfo d3d11FormatInfo; + if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) + { + return d3d11FormatInfo.mSRVFormat; + } + else + { + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +DXGI_FORMAT GetRTVFormat(GLenum internalFormat) +{ + D3D11FormatInfo d3d11FormatInfo; + if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) + { + return d3d11FormatInfo.mRTVFormat; + } + else + { + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +DXGI_FORMAT GetDSVFormat(GLenum internalFormat) +{ + D3D11FormatInfo d3d11FormatInfo; + if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) + { + return d3d11FormatInfo.mDSVFormat; + } + else + { + return DXGI_FORMAT_UNKNOWN; + } +} + +// Given a GL internal format, this function returns the DSV format if it is depth- or stencil-renderable, +// the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. +DXGI_FORMAT GetRenderableFormat(GLenum internalFormat) +{ + DXGI_FORMAT targetFormat = GetDSVFormat(internalFormat); + if (targetFormat == DXGI_FORMAT_UNKNOWN) + targetFormat = GetRTVFormat(internalFormat); + if (targetFormat == DXGI_FORMAT_UNKNOWN) + targetFormat = GetTexFormat(internalFormat); + + return targetFormat; +} + +DXGI_FORMAT GetSwizzleTexFormat(GLint internalFormat) +{ + if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4) + { + const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat); + return swizzleInfo.mTexFormat; + } + else + { + return GetTexFormat(internalFormat); + } +} + +DXGI_FORMAT GetSwizzleSRVFormat(GLint internalFormat) +{ + if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4) + { + const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat); + return swizzleInfo.mSRVFormat; + } + else + { + return GetSRVFormat(internalFormat); + } +} + +DXGI_FORMAT GetSwizzleRTVFormat(GLint internalFormat) +{ + if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4) + { + const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat); + return swizzleInfo.mRTVFormat; + } + else + { + return GetRTVFormat(internalFormat); + } +} + +bool RequiresTextureDataInitialization(GLint internalFormat) +{ + const InternalFormatInitializerMap &map = GetInternalFormatInitializerMap(); + return map.find(internalFormat) != map.end(); +} + +InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat) +{ + const InternalFormatInitializerMap &map = GetInternalFormatInitializerMap(); + InternalFormatInitializerMap::const_iterator iter = map.find(internalFormat); + if (iter != map.end()) + { + return iter->second; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +struct D3D11VertexFormatInfo +{ + rx::VertexConversionType mConversionType; + DXGI_FORMAT mNativeFormat; + VertexCopyFunction mCopyFunction; + + D3D11VertexFormatInfo() + : mConversionType(VERTEX_CONVERT_NONE), + mNativeFormat(DXGI_FORMAT_UNKNOWN), + mCopyFunction(NULL) + {} + + D3D11VertexFormatInfo(VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) + : mConversionType(conversionType), + mNativeFormat(nativeFormat), + mCopyFunction(copyFunction) + {} +}; + +typedef std::map<gl::VertexFormat, D3D11VertexFormatInfo> D3D11VertexFormatInfoMap; + +typedef std::pair<gl::VertexFormat, D3D11VertexFormatInfo> D3D11VertexFormatPair; + +static void addVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLboolean normalized, GLuint componentCount, + VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) +{ + gl::VertexFormat inputFormat(inputType, normalized, componentCount, false); + map->insert(D3D11VertexFormatPair(inputFormat, D3D11VertexFormatInfo(conversionType, nativeFormat, copyFunction))); +} + +static void addIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLuint componentCount, + VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) +{ + gl::VertexFormat inputFormat(inputType, GL_FALSE, componentCount, true); + map->insert(D3D11VertexFormatPair(inputFormat, D3D11VertexFormatInfo(conversionType, nativeFormat, copyFunction))); +} + +static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() +{ + D3D11VertexFormatInfoMap map; + + // TODO: column legend + + // + // Float formats + // + + // GL_BYTE -- un-normalized + addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, ©VertexData<GLbyte, 1, 0>); + addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, ©VertexData<GLbyte, 2, 0>); + addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData<GLbyte, 3, 1>); + addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData<GLbyte, 4, 0>); + + // GL_BYTE -- normalized + addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, ©VertexData<GLbyte, 1, 0>); + addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, ©VertexData<GLbyte, 2, 0>); + addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, ©VertexData<GLbyte, 3, INT8_MAX>); + addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, ©VertexData<GLbyte, 4, 0>); + + // GL_UNSIGNED_BYTE -- un-normalized + addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, ©VertexData<GLubyte, 1, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, ©VertexData<GLubyte, 2, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData<GLubyte, 3, 1>); + addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData<GLubyte, 4, 0>); + + // GL_UNSIGNED_BYTE -- normalized + addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, ©VertexData<GLubyte, 1, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, ©VertexData<GLubyte, 2, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, ©VertexData<GLubyte, 3, UINT8_MAX>); + addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, ©VertexData<GLubyte, 4, 0>); + + // GL_SHORT -- un-normalized + addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, ©VertexData<GLshort, 1, 0>); + addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, ©VertexData<GLshort, 2, 0>); + addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData<GLshort, 4, 1>); + addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData<GLshort, 4, 0>); + + // GL_SHORT -- normalized + addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, ©VertexData<GLshort, 1, 0>); + addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, ©VertexData<GLshort, 2, 0>); + addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, ©VertexData<GLshort, 3, INT16_MAX>); + addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, ©VertexData<GLshort, 4, 0>); + + // GL_UNSIGNED_SHORT -- un-normalized + addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, ©VertexData<GLushort, 1, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, ©VertexData<GLushort, 2, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData<GLushort, 3, 1>); + addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData<GLushort, 4, 0>); + + // GL_UNSIGNED_SHORT -- normalized + addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, ©VertexData<GLushort, 1, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, ©VertexData<GLushort, 2, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, ©VertexData<GLushort, 3, UINT16_MAX>); + addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, ©VertexData<GLushort, 4, 0>); + + // GL_INT -- un-normalized + addVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, ©VertexData<GLint, 1, 0>); + addVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, ©VertexData<GLint, 2, 0>); + addVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, ©VertexData<GLint, 3, 0>); + addVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData<GLint, 4, 0>); + + // GL_INT -- normalized + addVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, ©ToFloatVertexData<GLint, 1, true>); + addVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, ©ToFloatVertexData<GLint, 2, true>); + addVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©ToFloatVertexData<GLint, 3, true>); + addVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©ToFloatVertexData<GLint, 4, true>); + + // GL_UNSIGNED_INT -- un-normalized + addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, ©VertexData<GLuint, 1, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, ©VertexData<GLuint, 2, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, ©VertexData<GLuint, 3, 0>); + addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, ©VertexData<GLuint, 4, 0>); + + // GL_UNSIGNED_INT -- normalized + addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, ©ToFloatVertexData<GLuint, 1, true>); + addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, ©ToFloatVertexData<GLuint, 2, true>); + addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©ToFloatVertexData<GLuint, 3, true>); + addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, ©ToFloatVertexData<GLuint, 4, true>); + + // GL_FIXED + addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, ©FixedVertexData<1>); + addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, ©FixedVertexData<2>); + addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©FixedVertexData<3>); + addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©FixedVertexData<4>); + + // GL_HALF_FLOAT + addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, ©VertexData<GLhalf, 1, 0>); + addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, ©VertexData<GLhalf, 2, 0>); + addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, ©VertexData<GLhalf, 3, gl::Float16One>); + addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, ©VertexData<GLhalf, 4, 0>); + + // GL_FLOAT + addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, ©VertexData<GLfloat, 1, 0>); + addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, ©VertexData<GLfloat, 2, 0>); + addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, ©VertexData<GLfloat, 3, 0>); + addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, ©VertexData<GLfloat, 4, 0>); + + // GL_INT_2_10_10_10_REV + addVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©PackedVertexData<true, false, true>); + addVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©PackedVertexData<true, true, true>); + + // GL_UNSIGNED_INT_2_10_10_10_REV + addVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©PackedVertexData<false, false, true>); + addVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, ©PackedUnsignedVertexData); + + // + // Integer Formats + // + + // GL_BYTE + addIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, ©VertexData<GLbyte, 1, 0>); + addIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, ©VertexData<GLbyte, 2, 0>); + addIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData<GLbyte, 3, 1>); + addIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData<GLbyte, 4, 0>); + + // GL_UNSIGNED_BYTE + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, ©VertexData<GLubyte, 1, 0>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, ©VertexData<GLubyte, 2, 0>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData<GLubyte, 3, 1>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData<GLubyte, 4, 0>); + + // GL_SHORT + addIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, ©VertexData<GLshort, 1, 0>); + addIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, ©VertexData<GLshort, 2, 0>); + addIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData<GLshort, 3, 1>); + addIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData<GLshort, 4, 0>); + + // GL_UNSIGNED_SHORT + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, ©VertexData<GLushort, 1, 0>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, ©VertexData<GLushort, 2, 0>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData<GLushort, 3, 1>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData<GLushort, 4, 0>); + + // GL_INT + addIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, ©VertexData<GLint, 1, 0>); + addIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, ©VertexData<GLint, 2, 0>); + addIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, ©VertexData<GLint, 3, 0>); + addIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData<GLint, 4, 0>); + + // GL_UNSIGNED_INT + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, ©VertexData<GLuint, 1, 0>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, ©VertexData<GLuint, 2, 0>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, ©VertexData<GLuint, 3, 0>); + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData<GLuint, 4, 0>); + + // GL_INT_2_10_10_10_REV + addIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, ©PackedVertexData<true, true, false>); + + // GL_UNSIGNED_INT_2_10_10_10_REV + addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, ©PackedUnsignedVertexData); + + return map; +} + +static bool GetD3D11VertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D11VertexFormatInfo *outVertexFormatInfo) +{ + static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap(); + + D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat); + if (iter != vertexFormatMap.end()) + { + if (outVertexFormatInfo) + { + *outVertexFormatInfo = iter->second; + } + return true; + } + else + { + return false; + } +} + +VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat) +{ + D3D11VertexFormatInfo vertexFormatInfo; + if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) + { + return vertexFormatInfo.mCopyFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat) +{ + D3D11VertexFormatInfo vertexFormatInfo; + if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) + { + // FIXME: should not need a client version, and is not a pixel! + return d3d11::GetFormatPixelBytes(vertexFormatInfo.mNativeFormat); + } + else + { + UNREACHABLE(); + return 0; + } +} + +rx::VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat) +{ + D3D11VertexFormatInfo vertexFormatInfo; + if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) + { + return vertexFormatInfo.mConversionType; + } + else + { + UNREACHABLE(); + return VERTEX_CONVERT_NONE; + } +} + +DXGI_FORMAT GetNativeVertexFormat(const gl::VertexFormat &vertexFormat) +{ + D3D11VertexFormatInfo vertexFormatInfo; + if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) + { + return vertexFormatInfo.mNativeFormat; + } + else + { + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +} + +namespace d3d11_gl +{ + +GLenum GetInternalFormat(DXGI_FORMAT format) +{ + const DXGIToESFormatMap &formatMap = GetDXGIToESFormatMap(); + DXGIToESFormatMap::const_iterator iter = formatMap.find(format); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + UNREACHABLE(); + return GL_NONE; + } +} + +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h new file mode 100644 index 0000000000..d77fccfe9c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2013-2014 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. +// + +// formatutils11.h: Queries for GL image formats and their translations to D3D11 +// formats. + +#ifndef LIBGLESV2_RENDERER_FORMATUTILS11_H_ +#define LIBGLESV2_RENDERER_FORMATUTILS11_H_ + +#include "libGLESv2/formatutils.h" + +namespace rx +{ + +class Renderer; + +namespace d3d11 +{ + +typedef std::set<DXGI_FORMAT> DXGIFormatSet; + +MipGenerationFunction GetMipGenerationFunction(DXGI_FORMAT format); +LoadImageFunction GetImageLoadFunction(GLenum internalFormat, GLenum type); + +GLuint GetFormatPixelBytes(DXGI_FORMAT format); +GLuint GetBlockWidth(DXGI_FORMAT format); +GLuint GetBlockHeight(DXGI_FORMAT format); +GLenum GetComponentType(DXGI_FORMAT format); + +GLuint GetDepthBits(DXGI_FORMAT format); +GLuint GetDepthOffset(DXGI_FORMAT format); +GLuint GetStencilBits(DXGI_FORMAT format); +GLuint GetStencilOffset(DXGI_FORMAT format); + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +const DXGIFormatSet &GetAllUsedDXGIFormats(); + +ColorReadFunction GetColorReadFunction(DXGI_FORMAT format); +ColorCopyFunction GetFastCopyFunction(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType); + +} + +namespace gl_d3d11 +{ + +DXGI_FORMAT GetTexFormat(GLenum internalFormat); +DXGI_FORMAT GetSRVFormat(GLenum internalFormat); +DXGI_FORMAT GetRTVFormat(GLenum internalFormat); +DXGI_FORMAT GetDSVFormat(GLenum internalFormat); +DXGI_FORMAT GetRenderableFormat(GLenum internalFormat); + +DXGI_FORMAT GetSwizzleTexFormat(GLint internalFormat); +DXGI_FORMAT GetSwizzleSRVFormat(GLint internalFormat); +DXGI_FORMAT GetSwizzleRTVFormat(GLint internalFormat); + +bool RequiresTextureDataInitialization(GLint internalFormat); +InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat); + +VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat); +size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat); +VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat); +DXGI_FORMAT GetNativeVertexFormat(const gl::VertexFormat &vertexFormat); + +} + +namespace d3d11_gl +{ + +GLenum GetInternalFormat(DXGI_FORMAT format); + +} + +} + +#endif // LIBGLESV2_RENDERER_FORMATUTILS11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp new file mode 100644 index 0000000000..d3d135fe5b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp @@ -0,0 +1,634 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2014 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. +// + +// renderer11_utils.cpp: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "common/debug.h" + +namespace rx +{ + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) +{ + D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; + + switch (glBlend) + { + case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break; + case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break; + case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break; + case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) +{ + D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; + + switch (glBlendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break; + case GL_MIN: d3dBlendOp = D3D11_BLEND_OP_MIN; break; + case GL_MAX: d3dBlendOp = D3D11_BLEND_OP_MAX; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + UINT8 mask = 0; + if (red) + { + mask |= D3D11_COLOR_WRITE_ENABLE_RED; + } + if (green) + { + mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + } + if (blue) + { + mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + } + if (alpha) + { + mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + } + return mask; +} + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) +{ + D3D11_CULL_MODE cull = D3D11_CULL_NONE; + + if (cullEnabled) + { + switch (cullMode) + { + case GL_FRONT: cull = D3D11_CULL_FRONT; break; + case GL_BACK: cull = D3D11_CULL_BACK; break; + case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break; + default: UNREACHABLE(); + } + } + else + { + cull = D3D11_CULL_NONE; + } + + return cull; +} + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) +{ + D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; + switch (comparison) + { + case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break; + case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break; + case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break; + case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break; + case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break; + case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break; + case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break; + case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) +{ + return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; +} + +UINT8 ConvertStencilMask(GLuint stencilmask) +{ + return static_cast<UINT8>(stencilmask); +} + +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) +{ + D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break; + case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break; + case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode) +{ + bool comparison = comparisonMode != GL_NONE; + + if (maxAnisotropy > 1.0f) + { + return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison)); + } + else + { + D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; + D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; + switch (minFilter) + { + case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break; + case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break; + default: UNREACHABLE(); + } + + D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; + switch (magFilter) + { + case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break; + default: UNREACHABLE(); + } + + return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, static_cast<D3D11_COMPARISON_FUNC>(comparison)); + } +} + +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) +{ + switch (wrap) + { + case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP; + case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP; + case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR; + default: UNREACHABLE(); + } + + return D3D11_TEXTURE_ADDRESS_WRAP; +} + +D3D11_QUERY ConvertQueryType(GLenum queryType) +{ + switch (queryType) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS; + default: UNREACHABLE(); return D3D11_QUERY_EVENT; + } +} + +} + + +namespace d3d11_gl +{ + +static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11Device *device) +{ + gl::TextureCaps textureCaps; + + DXGI_FORMAT textureFormat = gl_d3d11::GetTexFormat(internalFormat); + DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(internalFormat); + DXGI_FORMAT rtvFormat = gl_d3d11::GetRTVFormat(internalFormat); + DXGI_FORMAT dsvFormat = gl_d3d11::GetDSVFormat(internalFormat); + DXGI_FORMAT renderFormat = gl_d3d11::GetRenderableFormat(internalFormat); + + UINT formatSupport; + if (SUCCEEDED(device->CheckFormatSupport(textureFormat, &formatSupport))) + { + if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0) + { + textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); + } + else + { + textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0) && + ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) != 0) && + ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) != 0); + } + } + + if (SUCCEEDED(device->CheckFormatSupport(renderFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0)) + { + for (size_t sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount++) + { + UINT qualityCount = 0; + if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount, &qualityCount)) && + qualityCount > 0) + { + textureCaps.sampleCounts.insert(sampleCount); + } + } + } + + textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(srvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0; + textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(rtvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) || + (SUCCEEDED(device->CheckFormatSupport(dsvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0)); + + return textureCaps; +} + +static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_MAX_MAXANISOTROPY; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return 16; + + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + + default: UNREACHABLE(); return 0; + } +} + +static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return true; + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return true; + + default: UNREACHABLE(); return false; + } +} + +static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: return true; + + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model + // ps_2_x is required for the ddx (and other derivative functions). + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level + // 9.3 supports shader model ps_2_x. + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: return true; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + + // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 1; /* D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; */ + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX; + + // No constants for D3D9 viewport size limits, use the maximum texture sizes + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +{ + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, device); + textureCapsMap->insert(*internalFormat, textureCaps); + } + + D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel(); + + // GL core feature limits + caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max()); + caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel); + caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel); + caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel); + caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel); + + // Unimplemented, set to minimum required + caps->maxLODBias = 2.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Maximum draw buffers and color attachments are the same, max color attachments could eventually be + // increased to 16 + caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel); + caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel); + + // D3D11 has the same limit for viewport width and height + caps->maxViewportWidth = GetMaximumViewportSize(featureLevel); + caps->maxViewportHeight = caps->maxViewportWidth; + + // Choose a reasonable maximum, enforced in the shader. + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = 1024.0f; + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = true; + extensions->packedDepthStencil = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = true; + extensions->mapBuffer = true; + extensions->mapBufferRange = true; + extensions->textureNPOT = GetNPOTTextureSupport(featureLevel); + extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1; + extensions->textureStorage = true; + extensions->textureFilterAnisotropic = true; + extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel); + extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel); + extensions->fence = GetEventQuerySupport(featureLevel); + extensions->timerQuery = false; // Unimplemented + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = true; + extensions->framebufferMultisample = true; + extensions->instancedArrays = GetInstancingSupport(featureLevel); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); + extensions->shaderTextureLOD = true; + extensions->fragDepth = true; + extensions->textureUsage = true; // This could be false since it has no effect in D3D11 + extensions->translatedShaderSource = true; +} + +} + +namespace d3d11 +{ + +void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, + GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData, + std::vector< std::vector<BYTE> > *outData) +{ + InitializeTextureDataFunction initializeFunc = gl_d3d11::GetTextureDataInitializationFunction(internalFormat); + DXGI_FORMAT dxgiFormat = gl_d3d11::GetTexFormat(internalFormat); + + outSubresourceData->resize(mipLevels); + outData->resize(mipLevels); + + for (unsigned int i = 0; i < mipLevels; i++) + { + unsigned int mipWidth = std::max(width >> i, 1U); + unsigned int mipHeight = std::max(height >> i, 1U); + unsigned int mipDepth = std::max(depth >> i, 1U); + + unsigned int rowWidth = d3d11::GetFormatPixelBytes(dxgiFormat) * mipWidth; + unsigned int imageSize = rowWidth * height; + + outData->at(i).resize(rowWidth * mipHeight * mipDepth); + initializeFunc(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); + + outSubresourceData->at(i).pSysMem = outData->at(i).data(); + outSubresourceData->at(i).SysMemPitch = rowWidth; + outSubresourceData->at(i).SysMemSlicePitch = imageSize; + } +} + +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) +{ + vertex->x = x; + vertex->y = y; + vertex->u = u; + vertex->v = v; +} + +void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s) +{ + vertex->x = x; + vertex->y = y; + vertex->l = layer; + vertex->u = u; + vertex->v = v; + vertex->s = s; +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) +{ +#if defined(_DEBUG) + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); +#else + return S_OK; +#endif +} + +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h new file mode 100644 index 0000000000..4de9bfa86d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h @@ -0,0 +1,173 @@ +// +// Copyright (c) 2012-2014 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. +// + +// renderer11_utils.h: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H +#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H + +#include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" + +namespace rx +{ + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); +UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); +UINT8 ConvertStencilMask(GLuint stencilmask); +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode); +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); + +D3D11_QUERY ConvertQueryType(GLenum queryType); + +} + +namespace d3d11_gl +{ + +void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); + +} + +namespace d3d11 +{ + +void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, + GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData, + std::vector< std::vector<BYTE> > *outData); + +struct PositionTexCoordVertex +{ + float x, y; + float u, v; +}; +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); + +struct PositionLayerTexCoord3DVertex +{ + float x, y; + unsigned int l; + float u, v, s; +}; +void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s); + +template <typename T> +struct PositionDepthColorVertex +{ + float x, y, z; + T r, g, b, a; +}; + +template <typename T> +void SetPositionDepthColorVertex(PositionDepthColorVertex<T>* vertex, float x, float y, float z, + const gl::Color<T> &color) +{ + vertex->x = x; + vertex->y = y; + vertex->z = z; + vertex->r = color.red; + vertex->g = color.green; + vertex->b = color.blue; + vertex->a = color.alpha; +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + +template <typename outType> +outType* DynamicCastComObject(IUnknown* object) +{ + outType *outObject = NULL; + HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast<void**>(&outObject)); + if (SUCCEEDED(result)) + { + return outObject; + } + else + { + SafeRelease(outObject); + return NULL; + } +} + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case DXGI_ERROR_DEVICE_HUNG: + case DXGI_ERROR_DEVICE_REMOVED: + case DXGI_ERROR_DEVICE_RESET: + case DXGI_ERROR_DRIVER_INTERNAL_ERROR: + case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: + return true; + default: + return false; + } +} + +template <unsigned int N> +inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11VertexShader *vs = NULL; + HRESULT result = device->CreateVertexShader(byteCode, N, NULL, &vs); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(vs, name); + return vs; +} + +template <unsigned int N> +inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11GeometryShader *gs = NULL; + HRESULT result = device->CreateGeometryShader(byteCode, N, NULL, &gs); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(gs, name); + return gs; +} + +template <unsigned int N> +inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11PixelShader *ps = NULL; + HRESULT result = device->CreatePixelShader(byteCode, N, NULL, &ps); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(ps, name); + return ps; +} + +// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to +// represent an entire buffer. +template <class T> +inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value) +{ + D3D11_MAPPED_SUBRESOURCE mappedResource; + context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + + memcpy(mappedResource.pData, &value, sizeof(T)); + + context->Unmap(constantBuffer, 0); +} + +} + +} + +#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl new file mode 100644 index 0000000000..20e6623a30 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl @@ -0,0 +1,76 @@ +Buffer<float4> Buffer4F : register(t0); +Buffer<int4> Buffer4I : register(t0); +Buffer<uint4> Buffer4UI : register(t0); + +struct VS_OUTPUT +{ + float4 position : SV_Position; + uint index : TEXCOORD0; + uint slice : LAYER; +}; + +struct GS_OUTPUT +{ + float4 position : SV_Position; + uint index : TEXCOORD0; + uint slice : SV_RenderTargetArrayIndex; +}; + +cbuffer BufferCopyParams : register(b0) +{ + uint FirstPixelOffset; + uint PixelsPerRow; + uint RowStride; + uint RowsPerSlice; + float2 PositionOffset; + float2 PositionScale; + int2 TexLocationOffset; + int2 TexLocationScale; +} + +void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex) +{ + uint PixelsPerSlice = PixelsPerRow * RowsPerSlice; + uint SliceStride = RowStride * RowsPerSlice; + + uint slice = vertexID / PixelsPerSlice; + uint sliceOffset = slice * PixelsPerSlice; + uint row = (vertexID - sliceOffset) / PixelsPerRow; + uint col = vertexID - sliceOffset - (row * PixelsPerRow); + + float2 coords = float2(float(col), float(row)); + + outVertex.position = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f); + outVertex.index = FirstPixelOffset + slice * SliceStride + row * RowStride + col; + outVertex.slice = slice; +} + +void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex) +{ + ComputePositionAndIndex(vertexID, outVertex); +} + +[maxvertexcount(1)] +void GS_BufferToTexture(point VS_OUTPUT inVertex[1], inout PointStream<GS_OUTPUT> outStream) +{ + GS_OUTPUT outVertex; + outVertex.position = inVertex[0].position; + outVertex.index = inVertex[0].index; + outVertex.slice = inVertex[0].slice; + outStream.Append(outVertex); +} + +float4 PS_BufferToTexture_4F(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4F.Load(inIndex); +} + +int4 PS_BufferToTexture_4I(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4I.Load(inIndex); +} + +uint4 PS_BufferToTexture_4UI(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4UI.Load(inIndex); +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl new file mode 100644 index 0000000000..b4cf38076e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl @@ -0,0 +1,106 @@ +// Assume we are in SM4+, which has 8 color outputs + +void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputFloat +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; +#if SM4 + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float4 color7 : SV_TARGET7; +#endif +}; + +PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputFloat outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; +#if SM4 + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; +#endif + return outColor; +} + + +void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputUint +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + uint4 color5 : SV_TARGET5; + uint4 color6 : SV_TARGET6; + uint4 color7 : SV_TARGET7; +}; + +PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR) +{ + PS_OutputUint outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} + + +void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out int4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputSint +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + int4 color5 : SV_TARGET5; + int4 color6 : SV_TARGET6; + int4 color7 : SV_TARGET7; +}; + +PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR) +{ + PS_OutputSint outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl new file mode 100644 index 0000000000..8671c39fb7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl @@ -0,0 +1,111 @@ +Texture2D<float4> TextureF : register(t0); +Texture2D<uint4> TextureUI : register(t0); +Texture2D<int4> TextureI : register(t0); + +SamplerState Sampler : register(s0); + +void VS_Passthrough2D( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0, + out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0) +{ + outPosition = float4(inPosition, 0.0f, 1.0f); + outTexCoord = inTexCoord; +} + +float PS_PassthroughDepth2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_DEPTH +{ + return TextureF.Sample(Sampler, inTexCoord).r; +} + +float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, inTexCoord).rgba; +} + +uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return TextureUI.Load(int3(size * inTexCoord, 0)).rgba; +} + +int4 PS_PassthroughRGBA2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return TextureI.Load(int3(size * inTexCoord, 0)).rgba; +} + +float4 PS_PassthroughRGB2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rgb, 1.0f); +} + +uint4 PS_PassthroughRGB2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rgb, 0); +} + +int4 PS_PassthroughRGB2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).rgb, 0); +} + +float4 PS_PassthroughRG2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rg, 0.0f, 1.0f); +} + +uint4 PS_PassthroughRG2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); +} + +int4 PS_PassthroughRG2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); +} + +float4 PS_PassthroughR2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).r, 0.0f, 0.0f, 1.0f); +} + +uint4 PS_PassthroughR2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); +} + +int4 PS_PassthroughR2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); +} + +float4 PS_PassthroughLum2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, inTexCoord).rrra; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl new file mode 100644 index 0000000000..c23c9032ec --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl @@ -0,0 +1,146 @@ +Texture3D<float4> TextureF : register(t0); +Texture3D<uint4> TextureUI : register(t0); +Texture3D<int4> TextureI : register(t0); + +SamplerState Sampler : register(s0); + +struct VS_INPUT +{ + float2 Position : POSITION; + uint Layer : LAYER; + float3 TexCoord : TEXCOORD; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + uint Layer : LAYER; + float3 TexCoord : TEXCOORD; +}; + +struct GS_OUTPUT +{ + float4 Position : SV_POSITION; + uint Layer : SV_RENDERTARGETARRAYINDEX; + float3 TexCoord : TEXCOORD; +}; + +VS_OUTPUT VS_Passthrough3D(VS_INPUT input) +{ + VS_OUTPUT output; + + output.Position = float4(input.Position, 0.0f, 1.0f); + output.Layer = input.Layer; + output.TexCoord = input.TexCoord; + + return output; +} + +[maxvertexcount(3)] +void GS_Passthrough3D(triangle VS_OUTPUT input[3], inout TriangleStream<GS_OUTPUT> outputStream) +{ + GS_OUTPUT output; + + for (int i = 0; i < 3; i++) + { + output.Position = input[i].Position; + output.Layer = input[i].Layer; + output.TexCoord = input[i].TexCoord; + + outputStream.Append(output); + } +} + +float4 PS_PassthroughRGBA3D(GS_OUTPUT input) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, input.TexCoord).rgba; +} + +uint4 PS_PassthroughRGBA3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return TextureUI.Load(int4(size * input.TexCoord, 0)).rgba; +} + +int4 PS_PassthroughRGBA3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return TextureI.Load(int4(size * input.TexCoord, 0)).rgba; +} + +float4 PS_PassthroughRGB3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rgb, 1.0f); +} + +uint4 PS_PassthroughRGB3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rgb, 0); +} + +int4 PS_PassthroughRGB3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rgb, 0); +} + +float4 PS_PassthroughRG3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rg, 0.0f, 1.0f); +} + +uint4 PS_PassthroughRG3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); +} + +int4 PS_PassthroughRG3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); +} + +float4 PS_PassthroughR3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).r, 0.0f, 0.0f, 1.0f); +} + +uint4 PS_PassthroughR3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); +} + +int4 PS_PassthroughR3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); +} + +float4 PS_PassthroughLum3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha3D(GS_OUTPUT input) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, input.TexCoord).rrra; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl new file mode 100644 index 0000000000..505e222137 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl @@ -0,0 +1,99 @@ +Texture2D<float4> TextureF2D : register(t0); +Texture2D<uint4> TextureUI2D : register(t0); +Texture2D<int4> TextureI2D : register(t0); + +Texture3D<float4> TextureF3D : register(t0); +Texture3D<uint4> TextureUI3D : register(t0); +Texture3D<int4> TextureI3D : register(t0); + +Texture2DArray<float4> TextureF2DArray : register(t0); +Texture2DArray<uint4> TextureUI2DArray : register(t0); +Texture2DArray<int4> TextureI2DArray : register(t0); + +SamplerState Sampler : register(s0); + +cbuffer SwizzleProperties : register(b0) +{ + uint4 SwizzleIndices : packoffset(c0); +} + +float4 SwizzleLookup(in float4 sample) +{ + float lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return float4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +int4 SwizzleLookup(in int4 sample) +{ + int lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return int4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +uint4 SwizzleLookup(in uint4 sample) +{ + uint lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return uint4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +float4 PS_SwizzleF2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF2D.Sample(Sampler, inTexCoord)); +} + +int4 PS_SwizzleI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI2D.GetDimensions(size.x, size.y); + + return SwizzleLookup(TextureI2D.Load(int3(size * inTexCoord, 0))); +} + +uint4 PS_SwizzleUI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI2D.GetDimensions(size.x, size.y); + + return SwizzleLookup(TextureUI2D.Load(int3(size * inTexCoord, 0))); +} + +float4 PS_SwizzleF3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF3D.Sample(Sampler, inTexCoord)); +} + +int4 PS_SwizzleI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureI3D.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureI3D.Load(int4(size * inTexCoord, 0))); +} + +uint4 PS_SwizzleUI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureUI3D.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureUI3D.Load(int4(size * inTexCoord, 0))); +} + +float4 PS_SwizzleF2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF2DArray.Sample(Sampler, float3(inTexCoord.xy, inLayer))); +} + +int4 PS_SwizzleI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureI2DArray.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); +} + +uint4 PS_SwizzleUI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureUI2DArray.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureUI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp index d73df6418d..f486e5a4cc 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp @@ -5,70 +5,68 @@ // found in the LICENSE file. // -// Blit.cpp: Surface copy utility class. +// Blit9.cpp: Surface copy utility class. -#include "libGLESv2/renderer/d3d9/Blit.h" +#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/FramebufferAttachment.h" namespace { -#include "libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" const BYTE* const g_shaderCode[] = { - g_vs20_standardvs, - g_vs20_flipyvs, - g_ps20_passthroughps, - g_ps20_luminanceps, - g_ps20_componentmaskps + g_vs20_VS_standard, + g_vs20_VS_flipy, + g_ps20_PS_passthrough, + g_ps20_PS_luminance, + g_ps20_PS_componentmask }; const size_t g_shaderSize[] = { - sizeof(g_vs20_standardvs), - sizeof(g_vs20_flipyvs), - sizeof(g_ps20_passthroughps), - sizeof(g_ps20_luminanceps), - sizeof(g_ps20_componentmaskps) + sizeof(g_vs20_VS_standard), + sizeof(g_vs20_VS_flipy), + sizeof(g_ps20_PS_passthrough), + sizeof(g_ps20_PS_luminance), + sizeof(g_ps20_PS_componentmask) }; } namespace rx { -Blit::Blit(rx::Renderer9 *renderer) +Blit9::Blit9(rx::Renderer9 *renderer) : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL) { initGeometry(); memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); } -Blit::~Blit() +Blit9::~Blit9() { - if (mSavedStateBlock) mSavedStateBlock->Release(); - if (mQuadVertexBuffer) mQuadVertexBuffer->Release(); - if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release(); + SafeRelease(mSavedStateBlock); + SafeRelease(mQuadVertexBuffer); + SafeRelease(mQuadVertexDeclaration); for (int i = 0; i < SHADER_COUNT; i++) { - if (mCompiledShaders[i]) - { - mCompiledShaders[i]->Release(); - } + SafeRelease(mCompiledShaders[i]); } } -void Blit::initGeometry() +void Blit9::initGeometry() { static const float quad[] = { @@ -116,7 +114,7 @@ void Blit::initGeometry() } template <class D3DShaderType> -bool Blit::setShader(ShaderId source, const char *profile, +bool Blit9::setShader(ShaderId source, const char *profile, D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length), HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) { @@ -154,17 +152,17 @@ bool Blit::setShader(ShaderId source, const char *profile, return true; } -bool Blit::setVertexShader(ShaderId shader) +bool Blit9::setVertexShader(ShaderId shader) { return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); } -bool Blit::setPixelShader(ShaderId shader) +bool Blit9::setPixelShader(ShaderId shader) { return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); } -RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const +RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const { D3DSURFACE_DESC desc; surface->GetDesc(&desc); @@ -178,7 +176,7 @@ RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const return rect; } -bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) { IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source)); if (!texture) @@ -204,18 +202,18 @@ bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) render(); - texture->Release(); + SafeRelease(texture); restoreState(); return true; } -bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) { RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *source = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); if (colorbuffer) { @@ -240,18 +238,18 @@ bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum des if (destSurface) { result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - destSurface->Release(); + SafeRelease(destSurface); } - source->Release(); + SafeRelease(source); return result; } -bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) { RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *source = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); if (colorbuffer) { @@ -276,14 +274,14 @@ bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum des if (destSurface) { result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - destSurface->Release(); + SafeRelease(destSurface); } - source->Release(); + SafeRelease(source); return result; } -bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) { if (!dest) { @@ -316,7 +314,7 @@ bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFo return true; } -bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) { IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); if (!texture) @@ -339,14 +337,14 @@ bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLen render(); } - texture->Release(); + SafeRelease(texture); restoreState(); return true; } -bool Blit::setFormatConvertShaders(GLenum destFormat) +bool Blit9::setFormatConvertShaders(GLenum destFormat) { bool okay = setVertexShader(SHADER_VS_STANDARD); @@ -356,6 +354,8 @@ bool Blit::setFormatConvertShaders(GLenum destFormat) case GL_RGBA: case GL_BGRA_EXT: case GL_RGB: + case GL_RG_EXT: + case GL_RED_EXT: case GL_ALPHA: okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK); break; @@ -375,41 +375,99 @@ bool Blit::setFormatConvertShaders(GLenum destFormat) // The meaning of this constant depends on the shader that was selected. // See the shader assembly code above for details. - float psConst0[4] = { 0, 0, 0, 0 }; + // Allocate one array for both registers and split it into two float4's. + float psConst[8] = { 0 }; + float *multConst = &psConst[0]; + float *addConst = &psConst[4]; switch (destFormat) { default: UNREACHABLE(); case GL_RGBA: case GL_BGRA_EXT: - psConst0[X] = 1; - psConst0[Z] = 1; + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 1; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; break; case GL_RGB: - psConst0[X] = 1; - psConst0[W] = 1; + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 1; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_RG_EXT: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_RED_EXT: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; break; case GL_ALPHA: - psConst0[Z] = 1; + multConst[X] = 0; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; break; case GL_LUMINANCE: - psConst0[Y] = 1; + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; break; case GL_LUMINANCE_ALPHA: - psConst0[X] = 1; + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; break; } - mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); + mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2); return true; } -IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) +IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) { if (!surface) { @@ -437,26 +495,26 @@ IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - texture->Release(); + SafeRelease(texture); return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); } mRenderer->endScene(); result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); - textureSurface->Release(); + SafeRelease(textureSurface); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - texture->Release(); + SafeRelease(texture); return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); } return texture; } -void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) +void Blit9::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) { IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -473,7 +531,7 @@ void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) device->SetVertexShaderConstantF(0, halfPixelAdjust, 1); } -void Blit::setCommonBlitState() +void Blit9::setCommonBlitState() { IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -503,7 +561,7 @@ void Blit::setCommonBlitState() } } -void Blit::render() +void Blit9::render() { IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -514,7 +572,7 @@ void Blit::render() hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); } -void Blit::saveState() +void Blit9::saveState() { IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -530,12 +588,12 @@ void Blit::saveState() setCommonBlitState(); - static const float dummyConst[4] = { 0, 0, 0, 0 }; + static const float dummyConst[8] = { 0 }; device->SetVertexShader(NULL); - device->SetVertexShaderConstantF(0, dummyConst, 1); + device->SetVertexShaderConstantF(0, dummyConst, 2); device->SetPixelShader(NULL); - device->SetPixelShaderConstantF(0, dummyConst, 1); + device->SetPixelShaderConstantF(0, dummyConst, 2); D3DVIEWPORT9 dummyVp; dummyVp.X = 0; @@ -566,23 +624,15 @@ void Blit::saveState() } } -void Blit::restoreState() +void Blit9::restoreState() { IDirect3DDevice9 *device = mRenderer->getDevice(); device->SetDepthStencilSurface(mSavedDepthStencil); - if (mSavedDepthStencil != NULL) - { - mSavedDepthStencil->Release(); - mSavedDepthStencil = NULL; - } + SafeRelease(mSavedDepthStencil); device->SetRenderTarget(0, mSavedRenderTarget); - if (mSavedRenderTarget != NULL) - { - mSavedRenderTarget->Release(); - mSavedRenderTarget = NULL; - } + SafeRelease(mSavedRenderTarget); ASSERT(mSavedStateBlock != NULL); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h index 3718028e66..3635bca932 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h @@ -4,10 +4,10 @@ // found in the LICENSE file. // -// Blit.cpp: Surface copy utility class. +// Blit9.cpp: Surface copy utility class. -#ifndef LIBGLESV2_BLIT_H_ -#define LIBGLESV2_BLIT_H_ +#ifndef LIBGLESV2_BLIT9_H_ +#define LIBGLESV2_BLIT9_H_ #include "common/angleutils.h" @@ -22,11 +22,11 @@ class Renderer9; class TextureStorageInterface2D; class TextureStorageInterfaceCube; -class Blit +class Blit9 { public: - explicit Blit(Renderer9 *renderer); - ~Blit(); + explicit Blit9(Renderer9 *renderer); + ~Blit9(); // Copy from source surface to dest surface. // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) @@ -87,8 +87,8 @@ class Blit IDirect3DSurface9 *mSavedRenderTarget; IDirect3DSurface9 *mSavedDepthStencil; - DISALLOW_COPY_AND_ASSIGN(Blit); + DISALLOW_COPY_AND_ASSIGN(Blit9); }; } -#endif // LIBGLESV2_BLIT_H_ +#endif // LIBGLESV2_BLIT9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp new file mode 100644 index 0000000000..347bde0c65 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp @@ -0,0 +1,126 @@ +#include "precompiled.h" +// +// Copyright 2014 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. +// + +// Buffer9.cpp Defines the Buffer9 class. + +#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +Buffer9::Buffer9(rx::Renderer9 *renderer) + : BufferD3D(), + mRenderer(renderer), + mSize(0) +{ + +} + +Buffer9::~Buffer9() +{ + +} + +Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Buffer9*, buffer)); + return static_cast<Buffer9*>(buffer); +} + +void Buffer9::clear() +{ + mSize = 0; +} + +void Buffer9::setData(const void* data, size_t size, GLenum usage) +{ + if (size > mMemory.size()) + { + if (!mMemory.resize(size)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mSize = size; + if (data) + { + memcpy(mMemory.data(), data, size); + } + + mIndexRangeCache.clear(); + + invalidateStaticData(); + + if (usage == GL_STATIC_DRAW) + { + initializeStaticData(); + } +} + +void *Buffer9::getData() +{ + return mMemory.data(); +} + +void Buffer9::setSubData(const void* data, size_t size, size_t offset) +{ + if (offset + size > mMemory.size()) + { + if (!mMemory.resize(offset + size)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mSize = std::max(mSize, offset + size); + if (data) + { + memcpy(mMemory.data() + offset, data, size); + } + + mIndexRangeCache.invalidateRange(offset, size); + + invalidateStaticData(); +} + +void Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + Buffer9* sourceBuffer = makeBuffer9(source); + if (sourceBuffer) + { + memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); + } + + invalidateStaticData(); +} + +// We do not suppot buffer mapping in D3D9 +GLvoid* Buffer9::map(size_t offset, size_t length, GLbitfield access) +{ + UNREACHABLE(); + return NULL; +} + +void Buffer9::unmap() +{ + UNREACHABLE(); +} + +void Buffer9::markTransformFeedbackUsage() +{ + UNREACHABLE(); +} + +Renderer* Buffer9::getRenderer() +{ + return mRenderer; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h new file mode 100644 index 0000000000..ec25ec30c9 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h @@ -0,0 +1,53 @@ +// +// Copyright 2014 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. +// + +// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBGLESV2_RENDERER_BUFFER9_H_ +#define LIBGLESV2_RENDERER_BUFFER9_H_ + +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ +class Renderer9; + +class Buffer9 : public BufferD3D +{ + public: + Buffer9(rx::Renderer9 *renderer); + virtual ~Buffer9(); + + static Buffer9 *makeBuffer9(BufferImpl *buffer); + + // BufferD3D implementation + virtual size_t getSize() const { return mSize; } + virtual void clear(); + virtual bool supportsDirectBinding() const { return false; } + virtual Renderer* getRenderer(); + + // BufferImpl implementation + virtual void setData(const void* data, size_t size, GLenum usage); + virtual void *getData(); + virtual void setSubData(const void* data, size_t size, size_t offset); + virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + virtual GLvoid* map(size_t offset, size_t length, GLbitfield access); + virtual void unmap(); + virtual void markTransformFeedbackUsage(); + + private: + DISALLOW_COPY_AND_ASSIGN(Buffer9); + + rx::Renderer9 *mRenderer; + MemoryBuffer mMemory; + size_t mSize; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp new file mode 100644 index 0000000000..d2437cadf3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp @@ -0,0 +1,73 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 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. +// + +// Fence9.cpp: Defines the rx::Fence9 class. + +#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +Fence9::Fence9(rx::Renderer9 *renderer) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Fence9::~Fence9() +{ + SafeRelease(mQuery); +} + +bool Fence9::isSet() const +{ + return mQuery != NULL; +} + +void Fence9::set() +{ + if (!mQuery) + { + mQuery = mRenderer->allocateEventQuery(); + if (!mQuery) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); +} + +bool Fence9::test(bool flushCommandBuffer) +{ + ASSERT(mQuery); + + DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0); + HRESULT result = mQuery->GetData(NULL, 0, getDataFlags); + + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY, true); + } + + ASSERT(result == S_OK || result == S_FALSE); + + return (result == S_OK); +} + +bool Fence9::hasError() const +{ + return mRenderer->isDeviceLost(); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h index 9f17641e51..e923a2178c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h @@ -21,11 +21,10 @@ class Fence9 : public FenceImpl explicit Fence9(rx::Renderer9 *renderer); virtual ~Fence9(); - GLboolean isFence(); - void setFence(GLenum condition); - GLboolean testFence(); - void finishFence(); - void getFenceiv(GLenum pname, GLint *params); + bool isSet() const; + void set(); + bool test(bool flushCommandBuffer); + bool hasError() const; private: DISALLOW_COPY_AND_ASSIGN(Fence9); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp index cd12d8cc9e..e237c3b6e1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp @@ -1,3 +1,4 @@ + #include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. @@ -8,17 +9,18 @@ // Image9.cpp: Implements the rx::Image9 class, which acts as the interface to // the actual underlying surfaces of a Texture. -#include "libGLESv2/renderer/d3d9/Image9.h" +#include "libGLESv2/renderer/d3d/d3d9/Image9.h" #include "libGLESv2/main.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/generatemip.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" namespace rx { @@ -34,10 +36,7 @@ Image9::Image9() Image9::~Image9() { - if (mSurface) - { - mSurface->Release(); - } + SafeRelease(mSurface); } void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) @@ -54,6 +53,9 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); + MipGenerationFunction mipFunction = d3d9::GetMipGenerationFunction(sourceDesc.Format); + ASSERT(mipFunction != NULL); + D3DLOCKED_RECT sourceLocked = {0}; result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); ASSERT(SUCCEEDED(result)); @@ -62,37 +64,17 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour result = destSurface->LockRect(&destLocked, NULL, 0); ASSERT(SUCCEEDED(result)); - const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(sourceLocked.pBits); - unsigned char *destData = reinterpret_cast<unsigned char*>(destLocked.pBits); + const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits); + uint8_t *destData = reinterpret_cast<uint8_t*>(destLocked.pBits); if (sourceData && destData) { - switch (sourceDesc.Format) - { - case D3DFMT_L8: - GenerateMip<L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A8L8: - GenerateMip<A8L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - GenerateMip<A8R8G8B8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A16B16G16R16F: - GenerateMip<A16B16G16R16F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A32B32G32R32F: - GenerateMip<A32B32G32R32F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - default: - UNREACHABLE(); - break; - } - - destSurface->UnlockRect(); - sourceSurface->UnlockRect(); + mipFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, + destData, destLocked.Pitch, 0); } + + destSurface->UnlockRect(); + sourceSurface->UnlockRect(); } Image9 *Image9::makeImage9(Image *img) @@ -126,8 +108,10 @@ void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *so D3DSURFACE_DESC desc; source->GetDesc(&desc); - int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height; - int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width); + int blockHeight = d3d9::GetBlockHeight(desc.Format); + int rows = desc.Height / blockHeight; + + int bytes = d3d9::GetBlockSize(desc.Format, desc.Width, blockHeight); ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); for(int i = 0; i < rows; i++) @@ -141,10 +125,17 @@ void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *so else UNREACHABLE(); } -bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) +bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) { + // 3D textures are not supported by the D3D9 backend. + ASSERT(depth <= 1); + + // Only 2D and cube texture are supported by the D3D9 backend. + ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP); + if (mWidth != width || mHeight != height || + mDepth != depth || mInternalFormat != internalformat || forceRelease) { @@ -152,16 +143,16 @@ bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei widt mWidth = width; mHeight = height; + mDepth = depth; mInternalFormat = internalformat; + // compute the d3d format that will be used - mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat); - mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat); + mD3DFormat = gl_d3d9::GetTextureFormat(internalformat); + mActualFormat = d3d9_gl::GetInternalFormat(mD3DFormat); + mRenderable = gl_d3d9::GetRenderFormat(internalformat) != D3DFMT_UNKNOWN; - if (mSurface) - { - mSurface->Release(); - mSurface = NULL; - } + SafeRelease(mSurface); + mDirty = gl_d3d9::RequiresTextureDataInitialization(mInternalFormat); return true; } @@ -180,14 +171,13 @@ void Image9::createSurface() IDirect3DSurface9 *newSurface = NULL; const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; const D3DFORMAT d3dFormat = getD3DFormat(); - ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures if (mWidth != 0 && mHeight != 0) { int levelToFetch = 0; GLsizei requestWidth = mWidth; GLsizei requestHeight = mHeight; - gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch); + d3d9::MakeValidSize(true, d3dFormat, &requestWidth, &requestHeight, &levelToFetch); IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -202,7 +192,27 @@ void Image9::createSurface() } newTexture->GetSurfaceLevel(levelToFetch, &newSurface); - newTexture->Release(); + SafeRelease(newTexture); + + if (gl_d3d9::RequiresTextureDataInitialization(mInternalFormat)) + { + InitializeTextureDataFunction initializeFunc = gl_d3d9::GetTextureDataInitializationFunction(mInternalFormat); + + RECT entireRect; + entireRect.left = 0; + entireRect.right = mWidth; + entireRect.top = 0; + entireRect.bottom = mHeight; + + D3DLOCKED_RECT lockedRect; + result = newSurface->LockRect(&lockedRect, &entireRect, 0); + ASSERT(SUCCEEDED(result)); + + initializeFunc(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits), lockedRect.Pitch, 0); + + result = newSurface->UnlockRect(); + ASSERT(SUCCEEDED(result)); + } } mSurface = newSurface; @@ -232,15 +242,11 @@ void Image9::unlock() if (mSurface) { HRESULT result = mSurface->UnlockRect(); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); } } -bool Image9::isRenderableFormat() const -{ - return TextureStorage9::IsTextureFormatRenderable(getD3DFormat()); -} - D3DFORMAT Image9::getD3DFormat() const { // this should only happen if the image hasn't been redefined first @@ -250,6 +256,13 @@ D3DFORMAT Image9::getD3DFormat() const return mD3DFormat; } +bool Image9::isDirty() const +{ + // Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet + // if initialization is required before use. + return (mSurface || gl_d3d9::RequiresTextureDataInitialization(mInternalFormat)) && mDirty; +} + IDirect3DSurface9 *Image9::getSurface() { createSurface(); @@ -280,7 +293,7 @@ void Image9::setManagedSurface(IDirect3DSurface9 *surface) if (mSurface) { copyLockableSurfaces(surface, mSurface); - mSurface->Release(); + SafeRelease(mSurface); } mSurface = surface; @@ -288,22 +301,38 @@ void Image9::setManagedSurface(IDirect3DSurface9 *surface) } } -bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image9::copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { ASSERT(getSurface() != NULL); TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); - return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height); + return copyToSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height); } -bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image9::copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { ASSERT(getSurface() != NULL); TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); - return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height); + return copyToSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height); +} + +bool Image9::copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +{ + // 3D textures are not supported by the D3D9 backend. + UNREACHABLE(); + return false; } -bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image9::copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) { + // 2D array textures are not supported by the D3D9 backend. + UNREACHABLE(); + return false; +} + +bool Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + ASSERT(width > 0 && height > 0); + if (!destSurface) return false; @@ -334,26 +363,35 @@ bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint copyLockableSurfaces(surf, sourceSurface); result = device->UpdateSurface(surf, &rect, destSurface, &point); ASSERT(SUCCEEDED(result)); - surf->Release(); + SafeRelease(surf); } } else { // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); } } - destSurface->Release(); + SafeRelease(destSurface); return true; } // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input // into the target pixel rectangle. -void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) +void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input) { + // 3D textures are not supported by the D3D9 backend. + ASSERT(zoffset == 0 && depth == 1); + + GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, width, unpackAlignment); + + LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat); + ASSERT(loadFunction != NULL); + RECT lockRect = { xoffset, yoffset, @@ -367,100 +405,30 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heigh return; } - - GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); - - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: -#if defined(__SSE2__) - if (gl::supportsSSE2()) - { - loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else -#endif - { - loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_LUMINANCE8_EXT: - loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8); - break; - case GL_ALPHA32F_EXT: - loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE32F_EXT: - loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_ALPHA16F_EXT: - loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE16F_EXT: - loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE8_ALPHA8_EXT: - loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8); - break; - case GL_LUMINANCE_ALPHA32F_EXT: - loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE_ALPHA16F_EXT: - loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB8_OES: - loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB565: - loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA8_OES: -#if defined(__SSE2__) - if (gl::supportsSSE2()) - { - loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else -#endif - { - loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_RGBA4: - loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB5_A1: - loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_BGRA8_EXT: - loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D - case GL_RGB32F_EXT: - loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB16F_EXT: - loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA32F_EXT: - loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA16F_EXT: - loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - default: UNREACHABLE(); - } + loadFunction(width, height, depth, + reinterpret_cast<const uint8_t*>(input), inputRowPitch, 0, + reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0); unlock(); } -void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, +void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, const void *input) { - ASSERT(xoffset % 4 == 0); - ASSERT(yoffset % 4 == 0); + // 3D textures are not supported by the D3D9 backend. + ASSERT(zoffset == 0 && depth == 1); + + GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, 1); + GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, height, 1); + + ASSERT(xoffset % d3d9::GetBlockWidth(mD3DFormat) == 0); + ASSERT(yoffset % d3d9::GetBlockHeight(mD3DFormat) == 0); - RECT lockRect = { + LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat); + ASSERT(loadFunction != NULL); + + RECT lockRect = + { xoffset, yoffset, xoffset + width, yoffset + height }; @@ -472,23 +440,22 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLs return; } - GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); - GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); - int rows = inputSize / inputPitch; - for (int i = 0; i < rows; ++i) - { - memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); - } + loadFunction(width, height, depth, + reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch, + reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0); unlock(); } // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { + // ES3.0 only behaviour to copy into a 3d texture + ASSERT(zoffset == 0); + RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *surface = NULL; - gl::Renderbuffer *colorbuffer = source->getColorbuffer(0); + gl::FramebufferAttachment *colorbuffer = source->getColorbuffer(0); if (colorbuffer) { @@ -517,7 +484,7 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, if (FAILED(result)) { ERR("Could not create matching destination surface."); - surface->Release(); + SafeRelease(surface); return gl::error(GL_OUT_OF_MEMORY); } @@ -526,8 +493,8 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, if (FAILED(result)) { ERR("GetRenderTargetData unexpectedly failed."); - renderTargetData->Release(); - surface->Release(); + SafeRelease(renderTargetData); + SafeRelease(surface); return gl::error(GL_OUT_OF_MEMORY); } @@ -540,8 +507,8 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, if (FAILED(result)) { ERR("Failed to lock the source surface (rectangle might be invalid)."); - renderTargetData->Release(); - surface->Release(); + SafeRelease(renderTargetData); + SafeRelease(surface); return gl::error(GL_OUT_OF_MEMORY); } @@ -552,8 +519,8 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, { ERR("Failed to lock the destination surface (rectangle might be invalid)."); renderTargetData->UnlockRect(); - renderTargetData->Release(); - surface->Release(); + SafeRelease(renderTargetData); + SafeRelease(surface); return gl::error(GL_OUT_OF_MEMORY); } @@ -727,8 +694,8 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, unlock(); renderTargetData->UnlockRect(); - renderTargetData->Release(); - surface->Release(); + SafeRelease(renderTargetData); + SafeRelease(surface); mDirty = true; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h index 2fbbca3124..2d1536f24b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // @@ -10,7 +10,7 @@ #ifndef LIBGLESV2_RENDERER_IMAGE9_H_ #define LIBGLESV2_RENDERER_IMAGE9_H_ -#include "libGLESv2/renderer/Image.h" +#include "libGLESv2/renderer/d3d/ImageD3D.h" #include "common/debug.h" namespace gl @@ -25,7 +25,7 @@ class Renderer9; class TextureStorageInterface2D; class TextureStorageInterfaceCube; -class Image9 : public Image +class Image9 : public ImageD3D { public: Image9(); @@ -37,32 +37,33 @@ class Image9 : public Image static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); - virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); + virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease); - virtual bool isRenderableFormat() const; D3DFORMAT getD3DFormat() const; - virtual bool isDirty() const {return mSurface && mDirty;} + virtual bool isDirty() const; IDirect3DSurface9 *getSurface(); virtual void setManagedSurface(TextureStorageInterface2D *storage, int level); virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level); - virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input); - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + virtual bool copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + virtual bool copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height); + + virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input); + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, const void *input); - virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset,GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); private: DISALLOW_COPY_AND_ASSIGN(Image9); void createSurface(); void setManagedSurface(IDirect3DSurface9 *surface); - bool updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + bool copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); void unlock(); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp index 7cb5d13a18..472e6981a8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -1,14 +1,14 @@ #include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // // Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. -#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" namespace rx { @@ -23,20 +23,12 @@ IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) IndexBuffer9::~IndexBuffer9() { - if (mIndexBuffer) - { - mIndexBuffer->Release(); - mIndexBuffer = NULL; - } + SafeRelease(mIndexBuffer); } bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) { - if (mIndexBuffer) - { - mIndexBuffer->Release(); - mIndexBuffer = NULL; - } + SafeRelease(mIndexBuffer); updateSerial(); @@ -49,7 +41,7 @@ bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dy } else if (indexType == GL_UNSIGNED_INT) { - if (mRenderer->get32BitIndexSupport()) + if (mRenderer->getRendererExtensions().elementIndexUint) { format = D3DFMT_INDEX32; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h index 6801867532..cfc20e1c64 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ #define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ -#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/d3d/IndexBuffer.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp index 72781cbc39..3c6f1d0d43 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp @@ -8,10 +8,10 @@ // Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. -#include "libGLESv2/renderer/d3d9/Query9.h" +#include "libGLESv2/renderer/d3d/d3d9/Query9.h" #include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" namespace rx { @@ -24,11 +24,7 @@ Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type) Query9::~Query9() { - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } + SafeRelease(mQuery); } void Query9::begin() @@ -42,17 +38,16 @@ void Query9::begin() } HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); } void Query9::end() { - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(mQuery); HRESULT result = mQuery->Issue(D3DISSUE_END); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); mStatus = GL_FALSE; @@ -122,4 +117,9 @@ GLboolean Query9::testQuery() return GL_TRUE; // prevent blocking when query is null } +bool Query9::isStarted() const +{ + return (mQuery != NULL); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h index 47eef89336..62906230c4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h @@ -21,10 +21,11 @@ class Query9 : public QueryImpl Query9(rx::Renderer9 *renderer, GLenum type); virtual ~Query9(); - void begin(); - void end(); - GLuint getResult(); - GLboolean isResultAvailable(); + virtual void begin(); + virtual void end(); + virtual GLuint getResult(); + virtual GLboolean isResultAvailable(); + virtual bool isStarted() const; private: DISALLOW_COPY_AND_ASSIGN(Query9); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp new file mode 100644 index 0000000000..49bd9b4000 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp @@ -0,0 +1,139 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2014 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. +// + +// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 +// pointers retained by renderbuffers. + +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. +RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) +{ + mRenderer = Renderer9::makeRenderer9(renderer); + mRenderTarget = surface; + + if (mRenderTarget) + { + D3DSURFACE_DESC description; + mRenderTarget->GetDesc(&description); + + mWidth = description.Width; + mHeight = description.Height; + mDepth = 1; + + mInternalFormat = d3d9_gl::GetInternalFormat(description.Format); + mActualFormat = d3d9_gl::GetInternalFormat(description.Format); + mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType); + } +} + +RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) +{ + mRenderer = Renderer9::makeRenderer9(renderer); + mRenderTarget = NULL; + + D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat); + int supportedSamples = mRenderer->getNearestSupportedSamples(renderFormat, samples); + + if (supportedSamples == -1) + { + gl::error(GL_OUT_OF_MEMORY); + + return; + } + + HRESULT result = D3DERR_INVALIDCALL; + + if (width > 0 && height > 0) + { + IDirect3DDevice9 *device = mRenderer->getDevice(); + + bool requiresInitialization = false; + + if (gl::GetDepthBits(internalFormat) > 0 || + gl::GetStencilBits(internalFormat) > 0) + { + result = device->CreateDepthStencilSurface(width, height, renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &mRenderTarget, NULL); + } + else + { + requiresInitialization = gl_d3d9::RequiresTextureDataInitialization(internalFormat); + + result = device->CreateRenderTarget(width, height, renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &mRenderTarget, NULL); + } + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + + return; + } + + ASSERT(SUCCEEDED(result)); + + if (requiresInitialization) + { + // This format requires that the data be initialized before the render target can be used + // Unfortunately this requires a Get call on the d3d device but it is far better than having + // to mark the render target as lockable and copy data to the gpu. + IDirect3DSurface9 *prevRenderTarget = NULL; + device->GetRenderTarget(0, &prevRenderTarget); + device->SetRenderTarget(0, mRenderTarget); + device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); + device->SetRenderTarget(0, prevRenderTarget); + } + } + + mWidth = width; + mHeight = height; + mDepth = 1; + mInternalFormat = internalFormat; + mSamples = supportedSamples; + mActualFormat = d3d9_gl::GetInternalFormat(renderFormat); +} + +RenderTarget9::~RenderTarget9() +{ + SafeRelease(mRenderTarget); +} + +RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); + return static_cast<rx::RenderTarget9*>(target); +} + +void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) +{ + // Currently a no-op +} + +IDirect3DSurface9 *RenderTarget9::getSurface() +{ + // Caller is responsible for releasing the returned surface reference. + // TODO: remove the AddRef to match RenderTarget11 + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h index faf8ad1c6d..68d7adb49e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h @@ -21,10 +21,13 @@ class RenderTarget9 : public RenderTarget { public: RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface); - RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); + RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples); virtual ~RenderTarget9(); static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); + + virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height); + IDirect3DSurface9 *getSurface(); private: diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp index 97a10d64bf..491c27a6ab 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp @@ -1,32 +1,39 @@ #include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. +#include "common/utilities.h" + #include "libGLESv2/main.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" -#include "libGLESv2/renderer/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/Image9.h" -#include "libGLESv2/renderer/d3d9/Blit.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d9/BufferStorage9.h" -#include "libGLESv2/renderer/d3d9/Query9.h" -#include "libGLESv2/renderer/d3d9/Fence9.h" +#include "libGLESv2/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d/d3d9/Image9.h" +#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Query9.h" +#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexArray9.h" +#include "libGLESv2/angletypes.h" #include "libEGL/Display.h" @@ -43,6 +50,13 @@ #define ANGLE_ENABLE_D3D9EX 1 #endif // !defined(ANGLE_ENABLE_D3D9EX) +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); + namespace rx { static const D3DFORMAT RenderTargetFormats[] = @@ -80,7 +94,9 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 }; -Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice) +Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) + : Renderer(display), + mDc(hDc) { mD3d9Module = NULL; @@ -117,6 +133,10 @@ Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Rend mNullColorbufferCache[i].height = 0; mNullColorbufferCache[i].buffer = NULL; } + + mAppliedVertexShader = NULL; + mAppliedPixelShader = NULL; + mAppliedProgramSerial = 0; } Renderer9::~Renderer9() @@ -130,10 +150,10 @@ Renderer9::~Renderer9() } } - deinitialize(); + release(); } -void Renderer9::deinitialize() +void Renderer9::release() { releaseDeviceResources(); @@ -142,22 +162,15 @@ void Renderer9::deinitialize() SafeRelease(mD3d9); SafeRelease(mD3d9Ex); + mCompiler.release(); + if (mDeviceWindow) { DestroyWindow(mDeviceWindow); mDeviceWindow = NULL; } - if (mD3d9Module) - { - mD3d9Module = NULL; - } - - while (!mMultiSampleSupport.empty()) - { - delete [] mMultiSampleSupport.begin()->second; - mMultiSampleSupport.erase(mMultiSampleSupport.begin()); - } + mD3d9Module = NULL; } Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) @@ -168,21 +181,13 @@ Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) EGLint Renderer9::initialize() { - if (!initializeCompiler()) + if (!mCompiler.initialize()) { return EGL_NOT_INITIALIZED; } - if (mSoftwareDevice) - { - TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader"); - mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); - } - else - { - TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); - mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); - } + TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); + mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); if (mD3d9Module == NULL) { @@ -251,7 +256,7 @@ EGLint Renderer9::initialize() } // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. - // This is required by Texture2D::convertToRenderTarget. + // This is required by Texture2D::ensureRenderTarget. if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) { ERR("Renderer does not support stretctrect from textures!\n"); @@ -263,15 +268,6 @@ EGLint Renderer9::initialize() mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); } - // ATI cards on XP have problems with non-power-of-two textures. - mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && - !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD); - - // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec - mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2)); - mMinSwapInterval = 4; mMaxSwapInterval = 0; @@ -301,48 +297,17 @@ EGLint Renderer9::initialize() mMaxSwapInterval = std::max(mMaxSwapInterval, 4); } - int max = 0; - { - TRACE_EVENT0("gpu", "getMultiSampleSupport"); - for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i) - { - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - getMultiSampleSupport(RenderTargetFormats[i], multisampleArray); - mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) - { - max = j; - } - } - } - } + mMaxSupportedSamples = 0; + const d3d9::D3DFormatSet &d3d9Formats = d3d9::GetAllUsedD3DFormats(); + for (d3d9::D3DFormatSet::const_iterator i = d3d9Formats.begin(); i != d3d9Formats.end(); ++i) { - TRACE_EVENT0("gpu", "getMultiSampleSupport2"); - for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i) - { - if (DepthStencilFormats[i] == D3DFMT_UNKNOWN) - continue; - - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - getMultiSampleSupport(DepthStencilFormats[i], multisampleArray); - mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) - { - max = j; - } - } - } + TRACE_EVENT0("gpu", "getMultiSampleSupport"); + MultisampleSupportInfo support = getMultiSampleSupport(*i); + mMultiSampleSupport[*i] = support; + mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples); } - mMaxSupportedSamples = max; - static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); static const TCHAR className[] = TEXT("STATIC"); @@ -378,7 +343,7 @@ EGLint Renderer9::initialize() if (mD3d9Ex) { TRACE_EVENT0("gpu", "mDevice_QueryInterface"); - result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); + result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx); ASSERT(SUCCEEDED(result)); } @@ -388,36 +353,6 @@ EGLint Renderer9::initialize() mPixelShaderCache.initialize(mDevice); } - // Check occlusion query support - IDirect3DQuery9 *occlusionQuery = NULL; - { - TRACE_EVENT0("gpu", "device_CreateQuery"); - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) - { - occlusionQuery->Release(); - mOcclusionQuerySupport = true; - } - else - { - mOcclusionQuerySupport = false; - } - } - - // Check event query support - IDirect3DQuery9 *eventQuery = NULL; - { - TRACE_EVENT0("gpu", "device_CreateQuery2"); - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) - { - eventQuery->Release(); - mEventQuerySupport = true; - } - else - { - mEventQuerySupport = false; - } - } - D3DDISPLAYMODE currentDisplayMode; mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); @@ -428,72 +363,10 @@ EGLint Renderer9::initialize() SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); - // Check depth texture support - // we use INTZ for depth textures in Direct3D9 - // we also want NULL texture support to ensure the we can make depth-only FBOs - // see http://aras-p.info/texts/D3D9GPUHacks.html - mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL)); - - // Check 32 bit floating point texture support - mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - - mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - - if (!mFloat32FilterSupport && !mFloat32RenderSupport) - { - mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - } - else - { - mFloat32TextureSupport = true; - } - - // Check 16 bit floating point texture support - mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - - mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - - if (!mFloat16FilterSupport && !mFloat16RenderSupport) - { - mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - } - else - { - mFloat16TextureSupport = true; - } - - // Check DXT texture support - mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); - mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); - mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)); - - // Check luminance[alpha] texture support - mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); - mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); - initializeDevice(); + d3d9::InitializeVertexTranslations(this); + return EGL_SUCCESS; } @@ -520,7 +393,7 @@ void Renderer9::initializeDevice() mSceneStarted = false; ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); - mBlit = new Blit(this); + mBlit = new Blit9(this); mVertexDataManager = new rx::VertexDataManager(this); mIndexDataManager = new rx::IndexDataManager(this); } @@ -585,10 +458,11 @@ int Renderer9::generateConfigs(ConfigDesc **configDescList) if (SUCCEEDED(result)) { ConfigDesc newConfig; - newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat); + newConfig.renderTargetFormat = d3d9_gl::GetInternalFormat(renderTargetFormat); + newConfig.depthStencilFormat = d3d9_gl::GetInternalFormat(depthStencilFormat); newConfig.multiSample = 0; // FIXME: enumerate multi-sampling newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat); + newConfig.es3Capable = false; (*configDescList)[numConfigs++] = newConfig; } @@ -681,6 +555,7 @@ IDirect3DQuery9* Renderer9::allocateEventQuery() if (mEventQueryPool.empty()) { HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); } else @@ -696,7 +571,7 @@ void Renderer9::freeEventQuery(IDirect3DQuery9* query) { if (mEventQueryPool.size() > 1000) { - query->Release(); + SafeRelease(query); } else { @@ -736,9 +611,14 @@ IndexBuffer *Renderer9::createIndexBuffer() return new IndexBuffer9(this); } -BufferStorage *Renderer9::createBufferStorage() +BufferImpl *Renderer9::createBuffer() { - return new BufferStorage9(); + return new Buffer9(this); +} + +VertexArrayImpl *Renderer9::createVertexArray() +{ + return new VertexArray9(this); } QueryImpl *Renderer9::createQuery(GLenum type) @@ -751,6 +631,26 @@ FenceImpl *Renderer9::createFence() return new Fence9(this); } +bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const +{ + // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. + return false; +} + +bool Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. + UNREACHABLE(); + return false; +} + +void Renderer9::generateSwizzle(gl::Texture *texture) +{ + // Swizzled textures are not available in ES2 or D3D9 + UNREACHABLE(); +} + void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) { bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; @@ -769,8 +669,8 @@ void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::Sampl gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset); - if (mSupportsTextureFilterAnisotropy) + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.baseLevel); + if (getRendererExtensions().textureFilterAnisotropic) { mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); } @@ -814,6 +714,12 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture appliedSerials[index] = serial; } +bool Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[]) +{ + // No effect in ES2/D3D9 + return true; +} + void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) { bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; @@ -852,10 +758,11 @@ void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) mForceSetRasterState = false; } -void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) +void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) { bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; - bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0; + bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0; bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; if (blendStateChanged || blendColorChanged) @@ -906,6 +813,9 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState FIXME("Sample alpha to coverage is unimplemented."); } + gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); + GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; + // Set the color mask bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; // Apparently some ATI cards have a bug where a draw with a zero color @@ -914,8 +824,10 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState // drawing is done. // http://code.google.com/p/angleproject/issues/detail?id=169 - DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, - blendState.colorMaskBlue, blendState.colorMaskAlpha); + DWORD colorMask = gl_d3d9::ConvertColorMask(gl::GetRedBits(internalFormat) > 0 && blendState.colorMaskRed, + gl::GetGreenBits(internalFormat) > 0 && blendState.colorMaskGreen, + gl::GetBlueBits(internalFormat) > 0 && blendState.colorMaskBlue, + gl::GetAlphaBits(internalFormat) > 0 && blendState.colorMaskAlpha); if (colorMask == 0 && !zeroColorMaskAllowed) { // Enable green channel, but set blending so nothing will be drawn. @@ -984,13 +896,10 @@ void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilSt const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; - if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - stencilRef != stencilBackRef || - depthStencilState.stencilMask != depthStencilState.stencilBackMask) - { - ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); - return gl::error(GL_INVALID_OPERATION); - } + + ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); + ASSERT(stencilRef == stencilBackRef); + ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); // get the maximum size of the stencil ref unsigned int maxStencil = (1 << mCurStencilSize) - 1; @@ -1188,14 +1097,15 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) mPrimitiveCount = count - 2; break; default: - return gl::error(GL_INVALID_ENUM, false); + UNREACHABLE(); + return false; } return mPrimitiveCount > 0; } -gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) +gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer) { if (!depthbuffer) { @@ -1218,7 +1128,8 @@ gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) } } - gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); + gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); + gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(nullRenderbuffer); // add nullbuffer to the cache NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; @@ -1243,29 +1154,25 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) { // if there is no color attachment we must synthesize a NULL colorattachment // to keep the D3D runtime happy. This should only be possible if depth texturing. - gl::Renderbuffer *renderbufferObject = NULL; - if (framebuffer->getColorbufferType(0) != GL_NONE) + gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0); + if (!attachment) { - renderbufferObject = framebuffer->getColorbuffer(0); + attachment = getNullColorbuffer(framebuffer->getDepthbuffer()); } - else - { - renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer()); - } - if (!renderbufferObject) + if (!attachment) { ERR("unable to locate renderbuffer for FBO."); return false; } bool renderTargetChanged = false; - unsigned int renderTargetSerial = renderbufferObject->getSerial(); + unsigned int renderTargetSerial = attachment->getSerial(); if (renderTargetSerial != mAppliedRenderTargetSerial) { // Apply the render target on the device IDirect3DSurface9 *renderTargetSurface = NULL; - RenderTarget *renderTarget = renderbufferObject->getRenderTarget(); + RenderTarget *renderTarget = attachment->getRenderTarget(); if (renderTarget) { renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); @@ -1278,35 +1185,22 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) } mDevice->SetRenderTarget(0, renderTargetSurface); - renderTargetSurface->Release(); + SafeRelease(renderTargetSurface); mAppliedRenderTargetSerial = renderTargetSerial; renderTargetChanged = true; } - gl::Renderbuffer *depthStencil = NULL; + gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); unsigned int depthbufferSerial = 0; unsigned int stencilbufferSerial = 0; - if (framebuffer->getDepthbufferType() != GL_NONE) + if (depthStencil) { - depthStencil = framebuffer->getDepthbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - depthbufferSerial = depthStencil->getSerial(); } - else if (framebuffer->getStencilbufferType() != GL_NONE) + else if (framebuffer->getStencilbuffer()) { depthStencil = framebuffer->getStencilbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - stencilbufferSerial = depthStencil->getSerial(); } @@ -1335,7 +1229,7 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) } mDevice->SetDepthStencilSurface(depthStencilSurface); - depthStencilSurface->Release(); + SafeRelease(depthStencilSurface); depthSize = depthStencil->getDepthSize(); stencilSize = depthStencil->getStencilSize(); @@ -1366,25 +1260,27 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) { mForceSetScissor = true; mForceSetViewport = true; + mForceSetBlendState = true; - mRenderTargetDesc.width = renderbufferObject->getWidth(); - mRenderTargetDesc.height = renderbufferObject->getHeight(); - mRenderTargetDesc.format = renderbufferObject->getActualFormat(); + mRenderTargetDesc.width = attachment->getWidth(); + mRenderTargetDesc.height = attachment->getHeight(); + mRenderTargetDesc.format = attachment->getActualFormat(); mRenderTargetDescInitialized = true; } return true; } -GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) +GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); + GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); if (err != GL_NO_ERROR) { return err; } - + return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); } @@ -1410,10 +1306,17 @@ GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArr return err; } -void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances) +void Renderer9::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) { + UNREACHABLE(); +} + +void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) +{ + ASSERT(!transformFeedbackActive); + startScene(); - + if (mode == GL_LINE_LOOP) { drawLineLoop(count, GL_NONE, NULL, 0, NULL); @@ -1448,7 +1351,8 @@ void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances) } } -void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) +void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) { startScene(); @@ -1476,14 +1380,14 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (type != GL_NONE && elementArrayBuffer) { gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); + BufferImpl *storage = indexBuffer->getImplementation(); intptr_t offset = reinterpret_cast<intptr_t>(indices); indices = static_cast<const GLubyte*>(storage->getData()) + offset; } unsigned int startIndex = 0; - if (get32BitIndexSupport()) + if (getRendererExtensions().elementIndexUint) { if (!mLineLoopIB) { @@ -1498,15 +1402,15 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } } + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int))) { ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); return gl::error(GL_OUT_OF_MEMORY); } - // Checked by Renderer9::applyPrimitiveType - ASSERT(count >= 0); - const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int); if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) { @@ -1674,7 +1578,7 @@ void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indi if (elementArrayBuffer) { - BufferStorage *storage = elementArrayBuffer->getStorage(); + BufferImpl *storage = elementArrayBuffer->getImplementation(); intptr_t offset = reinterpret_cast<intptr_t>(indices); indices = static_cast<const GLubyte*>(storage->getData()) + offset; } @@ -1688,34 +1592,51 @@ void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indi } } -void Renderer9::applyShaders(gl::ProgramBinary *programBinary) +void Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) { - unsigned int programBinarySerial = programBinary->getSerial(); - if (programBinarySerial != mAppliedProgramBinarySerial) - { - ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); - ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); + ASSERT(!transformFeedbackActive); + ASSERT(!rasterizerDiscard); - IDirect3DVertexShader9 *vertexShader = NULL; - if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader(); + ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); + ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); - IDirect3DPixelShader9 *pixelShader = NULL; - if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader(); + IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); + IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); - mDevice->SetPixelShader(pixelShader); + if (vertexShader != mAppliedVertexShader) + { mDevice->SetVertexShader(vertexShader); + mAppliedVertexShader = vertexShader; + } + + if (pixelShader != mAppliedPixelShader) + { + mDevice->SetPixelShader(pixelShader); + mAppliedPixelShader = pixelShader; + } + + // D3D9 has a quirk where creating multiple shaders with the same content + // can return the same shader pointer. Because GL programs store different data + // per-program, checking the program serial guarantees we upload fresh + // uniform data even if our shader pointers are the same. + // https://code.google.com/p/angleproject/issues/detail?id=661 + unsigned int programSerial = programBinary->getSerial(); + if (programSerial != mAppliedProgramSerial) + { programBinary->dirtyAllUniforms(); mDxUniformsDirty = true; - - mAppliedProgramBinarySerial = programBinarySerial; + mAppliedProgramSerial = programSerial; } } -void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) +void Renderer9::applyUniforms(const gl::ProgramBinary &programBinary) { - for (std::vector<gl::Uniform*>::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub) + const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms(); + + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) { - gl::Uniform *targetUniform = *ub; + gl::LinkedUniform *targetUniform = uniformArray[uniformIndex]; if (targetUniform->dirty) { @@ -1751,8 +1672,6 @@ void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray default: UNREACHABLE(); } - - targetUniform->dirty = false; } } @@ -1765,20 +1684,20 @@ void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray } } -void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v) +void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v) { - if (targetUniform->psRegisterIndex >= 0) + if (targetUniform->isReferencedByFragmentShader()) { mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); } - if (targetUniform->vsRegisterIndex >= 0) + if (targetUniform->isReferencedByVertexShader()) { mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); } } -void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v) +void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v) { ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; @@ -1794,7 +1713,7 @@ void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v) applyUniformnfv(targetUniform, (GLfloat*)vector); } -void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v) +void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v) { ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; @@ -1812,27 +1731,68 @@ void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v) void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) { - D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha), - gl::unorm<8>(clearParams.colorClearValue.red), - gl::unorm<8>(clearParams.colorClearValue.green), - gl::unorm<8>(clearParams.colorClearValue.blue)); + if (clearParams.colorClearType != GL_FLOAT) + { + // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0 + UNREACHABLE(); + return; + } + + bool clearColor = clearParams.clearColor[0]; + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + if (clearParams.clearColor[i] != clearColor) + { + // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0 + UNREACHABLE(); + return; + } + } + float depth = gl::clamp01(clearParams.depthClearValue); - int stencil = clearParams.stencilClearValue & 0x000000FF; + DWORD stencil = clearParams.stencilClearValue & 0x000000FF; unsigned int stencilUnmasked = 0x0; - if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil()) + if (clearParams.clearStencil && frameBuffer->hasStencil()) { - unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); + unsigned int stencilSize = gl::GetStencilBits(frameBuffer->getStencilbuffer()->getActualFormat()); stencilUnmasked = (0x1 << stencilSize) - 1; } - bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; - - const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && + const bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && - !(clearParams.colorMaskRed && clearParams.colorMaskGreen && - clearParams.colorMaskBlue && alphaUnmasked); + + bool needMaskedColorClear = false; + D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); + if (clearColor) + { + gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); + GLenum internalFormat = attachment->getInternalFormat(); + GLenum actualFormat = attachment->getActualFormat(); + + GLuint internalRedBits = gl::GetRedBits(internalFormat); + GLuint internalGreenBits = gl::GetGreenBits(internalFormat); + GLuint internalBlueBits = gl::GetBlueBits(internalFormat); + GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat); + + GLuint actualRedBits = gl::GetRedBits(actualFormat); + GLuint actualGreenBits = gl::GetGreenBits(actualFormat); + GLuint actualBlueBits = gl::GetBlueBits(actualFormat); + GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat); + + color = D3DCOLOR_ARGB(gl::unorm<8>((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + gl::unorm<8>((internalRedBits == 0 && actualRedBits > 0) ? 0.0f : clearParams.colorFClearValue.red), + gl::unorm<8>((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), + gl::unorm<8>((internalBlueBits == 0 && actualBlueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); + + if ((internalRedBits > 0 && !clearParams.colorMaskRed) || + (internalGreenBits > 0 && !clearParams.colorMaskGreen) || + (internalBlueBits > 0 && !clearParams.colorMaskBlue) || + (internalAlphaBits > 0 && !clearParams.colorMaskAlpha)) + { + needMaskedColorClear = true; + } + } if (needMaskedColorClear || needMaskedStencilClear) { @@ -1893,7 +1853,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - if (clearParams.mask & GL_COLOR_BUFFER_BIT) + if (clearColor) { mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, @@ -1906,7 +1866,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); } - if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT)) + if (stencilUnmasked != 0x0 && clearParams.clearStencil) { mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); @@ -1962,7 +1922,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f startScene(); mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) + if (clearParams.clearDepth) { mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); @@ -1974,18 +1934,18 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f mMaskedClearSavedState->Apply(); } } - else if (clearParams.mask) + else if (clearColor || clearParams.clearDepth || clearParams.clearStencil) { DWORD dxClearFlags = 0; - if (clearParams.mask & GL_COLOR_BUFFER_BIT) + if (clearColor) { dxClearFlags |= D3DCLEAR_TARGET; } - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) + if (clearParams.clearDepth) { dxClearFlags |= D3DCLEAR_ZBUFFER; } - if (clearParams.mask & GL_STENCIL_BUFFER_BIT) + if (clearParams.clearStencil) { dxClearFlags |= D3DCLEAR_STENCIL; } @@ -2020,7 +1980,9 @@ void Renderer9::markAllStateDirty() } mAppliedIBSerial = 0; - mAppliedProgramBinarySerial = 0; + mAppliedVertexShader = NULL; + mAppliedPixelShader = NULL; + mAppliedProgramSerial = 0; mDxUniformsDirty = true; mVertexDeclarationCache.markStateDirty(); @@ -2028,11 +1990,11 @@ void Renderer9::markAllStateDirty() void Renderer9::releaseDeviceResources() { - while (!mEventQueryPool.empty()) + for (size_t i = 0; i < mEventQueryPool.size(); i++) { - mEventQueryPool.back()->Release(); - mEventQueryPool.pop_back(); + SafeRelease(mEventQueryPool[i]); } + mEventQueryPool.clear(); SafeRelease(mMaskedClearSavedState); @@ -2048,10 +2010,8 @@ void Renderer9::releaseDeviceResources() { SafeDelete(mNullColorbufferCache[i].buffer); } - } - void Renderer9::notifyDeviceLost() { mDeviceLost = true; @@ -2221,7 +2181,7 @@ bool Renderer9::resetRemovedDevice() // The hardware adapter has been removed. Application must destroy the device, do enumeration of // adapters and create another Direct3D device. If application continues rendering without // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. - deinitialize(); + release(); return (initialize() == EGL_SUCCESS); } @@ -2255,84 +2215,30 @@ GUID Renderer9::getAdapterIdentifier() const return mAdapterIdentifier.DeviceIdentifier; } -void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) -{ - for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) - { - HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, - TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); - - multiSampleArray[multiSampleIndex] = SUCCEEDED(result); - } -} - -bool Renderer9::getBGRATextureSupport() const -{ - // DirectX 9 always supports BGRA - return true; -} - -bool Renderer9::getDXT1TextureSupport() -{ - return mDXT1TextureSupport; -} - -bool Renderer9::getDXT3TextureSupport() -{ - return mDXT3TextureSupport; -} - -bool Renderer9::getDXT5TextureSupport() +Renderer9::MultisampleSupportInfo Renderer9::getMultiSampleSupport(D3DFORMAT format) { - return mDXT5TextureSupport; -} - -bool Renderer9::getDepthTextureSupport() const -{ - return mDepthTextureSupport; -} - -bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable) -{ - *filtering = mFloat32FilterSupport; - *renderable = mFloat32RenderSupport; - return mFloat32TextureSupport; -} - -bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable) -{ - *filtering = mFloat16FilterSupport; - *renderable = mFloat16RenderSupport; - return mFloat16TextureSupport; -} - -bool Renderer9::getLuminanceTextureSupport() -{ - return mLuminanceTextureSupport; -} + MultisampleSupportInfo support = { 0 }; -bool Renderer9::getLuminanceAlphaTextureSupport() -{ - return mLuminanceAlphaTextureSupport; -} - -bool Renderer9::getTextureFilterAnisotropySupport() const -{ - return mSupportsTextureFilterAnisotropy; -} - -float Renderer9::getTextureMaxAnisotropy() const -{ - if (mSupportsTextureFilterAnisotropy) + for (unsigned int multiSampleIndex = 0; multiSampleIndex < ArraySize(support.supportedSamples); multiSampleIndex++) { - return static_cast<float>(mDeviceCaps.MaxAnisotropy); + HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, TRUE, + (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); + + if (SUCCEEDED(result)) + { + support.supportedSamples[multiSampleIndex] = true; + if (multiSampleIndex != D3DMULTISAMPLE_NONMASKABLE) + { + support.maxSupportedSamples = std::max(support.maxSupportedSamples, multiSampleIndex); + } + } + else + { + support.supportedSamples[multiSampleIndex] = false; + } } - return 1.0f; -} -bool Renderer9::getEventQuerySupport() -{ - return mEventQuerySupport; + return support; } unsigned int Renderer9::getMaxVertexTextureImageUnits() const @@ -2373,68 +2279,79 @@ unsigned int Renderer9::getMaxVaryingVectors() const return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; } -bool Renderer9::getNonPower2TextureSupport() const +unsigned int Renderer9::getMaxVertexShaderUniformBuffers() const { - return mSupportsNonPower2Textures; + return 0; } -bool Renderer9::getOcclusionQuerySupport() const +unsigned int Renderer9::getMaxFragmentShaderUniformBuffers() const { - return mOcclusionQuerySupport; + return 0; } -bool Renderer9::getInstancingSupport() const +unsigned int Renderer9::getReservedVertexUniformBuffers() const { - return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); + return 0; } -bool Renderer9::getShareHandleSupport() const +unsigned int Renderer9::getReservedFragmentUniformBuffers() const { - // PIX doesn't seem to support using share handles, so disable them. - return (mD3d9Ex != NULL) && !gl::perfActive(); + return 0; } -bool Renderer9::getDerivativeInstructionSupport() const +unsigned int Renderer9::getMaxTransformFeedbackBuffers() const { - return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; + return 0; } -bool Renderer9::getPostSubBufferSupport() const +unsigned int Renderer9::getMaxTransformFeedbackSeparateComponents() const { - return true; + return 0; } -int Renderer9::getMajorShaderModel() const +unsigned int Renderer9::getMaxTransformFeedbackInterleavedComponents() const { - return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); + return 0; +} + +unsigned int Renderer9::getMaxUniformBufferSize() const +{ + return 0; } -float Renderer9::getMaxPointSize() const +bool Renderer9::getShareHandleSupport() const +{ + // PIX doesn't seem to support using share handles, so disable them. + return (mD3d9Ex != NULL) && !gl::perfActive(); +} + +bool Renderer9::getPostSubBufferSupport() const { - // Point size clamped at 1.0f for SM2 - return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f; + return true; } -int Renderer9::getMaxViewportDimension() const +int Renderer9::getMaxRecommendedElementsIndices() const { - int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()), - (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); - return maxTextureDimension; + // ES3 only + UNREACHABLE(); + return 0; } -int Renderer9::getMaxTextureWidth() const +int Renderer9::getMaxRecommendedElementsVertices() const { - return (int)mDeviceCaps.MaxTextureWidth; + // ES3 only + UNREACHABLE(); + return 0; } -int Renderer9::getMaxTextureHeight() const +bool Renderer9::getSRGBTextureSupport() const { - return (int)mDeviceCaps.MaxTextureHeight; + return false; } -bool Renderer9::get32BitIndexSupport() const +int Renderer9::getMajorShaderModel() const { - return mDeviceCaps.MaxVertexIndex >= (1 << 16); + return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); } DWORD Renderer9::getCapsDeclTypes() const @@ -2457,6 +2374,53 @@ int Renderer9::getMaxSupportedSamples() const return mMaxSupportedSamples; } +GLsizei Renderer9::getMaxSupportedFormatSamples(GLenum internalFormat) const +{ + D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat); + MultisampleSupportMap::const_iterator itr = mMultiSampleSupport.find(format); + return (itr != mMultiSampleSupport.end()) ? mMaxSupportedSamples : 0; +} + +GLsizei Renderer9::getNumSampleCounts(GLenum internalFormat) const +{ + D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat); + MultisampleSupportMap::const_iterator iter = mMultiSampleSupport.find(format); + + unsigned int numCounts = 0; + if (iter != mMultiSampleSupport.end()) + { + const MultisampleSupportInfo& info = iter->second; + for (int i = 0; i < D3DMULTISAMPLE_16_SAMPLES; i++) + { + if (i != D3DMULTISAMPLE_NONMASKABLE && info.supportedSamples[i]) + { + numCounts++; + } + } + } + + return numCounts; +} + +void Renderer9::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const +{ + D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat); + MultisampleSupportMap::const_iterator iter = mMultiSampleSupport.find(format); + + if (iter != mMultiSampleSupport.end()) + { + const MultisampleSupportInfo& info = iter->second; + int bufPos = 0; + for (int i = D3DMULTISAMPLE_16_SAMPLES; i >= 0 && bufPos < bufSize; i--) + { + if (i != D3DMULTISAMPLE_NONMASKABLE && info.supportedSamples[i]) + { + params[bufPos++] = i; + } + } + } +} + int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const { if (requested == 0) @@ -2464,7 +2428,7 @@ int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const return requested; } - std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format); + MultisampleSupportMap::const_iterator itr = mMultiSampleSupport.find(format); if (itr == mMultiSampleSupport.end()) { if (format == D3DFMT_UNKNOWN) @@ -2472,9 +2436,9 @@ int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const return -1; } - for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) + for (unsigned int i = requested; i < ArraySize(itr->second.supportedSamples); ++i) { - if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) + if (itr->second.supportedSamples[i] && i != D3DMULTISAMPLE_NONMASKABLE) { return i; } @@ -2483,59 +2447,6 @@ int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const return -1; } -unsigned int Renderer9::getMaxRenderTargets() const -{ - // we do not support MRT in d3d9 - return 1; -} - -D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat) -{ - switch (internalformat) - { - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - return D3DFMT_INTZ; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return D3DFMT_DXT1; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - return D3DFMT_DXT3; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return D3DFMT_DXT5; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return D3DFMT_A32B32G32R32F; - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - return D3DFMT_A16B16G16R16F; - case GL_LUMINANCE8_EXT: - if (getLuminanceTextureSupport()) - { - return D3DFMT_L8; - } - break; - case GL_LUMINANCE8_ALPHA8_EXT: - if (getLuminanceAlphaTextureSupport()) - { - return D3DFMT_A8L8; - } - break; - case GL_RGB8_OES: - case GL_RGB565: - return D3DFMT_X8R8G8B8; - } - - return D3DFMT_A8R8G8B8; -} - bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) { bool result = false; @@ -2545,19 +2456,21 @@ bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStora TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance()); TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance()); - int levels = source9->levelCount(); + int levels = source9->getLevelCount(); for (int i = 0; i < levels; ++i) { IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); - + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); - if (srcSurf) srcSurf->Release(); - if (dstSurf) dstSurf->Release(); + SafeRelease(srcSurf); + SafeRelease(dstSurf); if (!result) + { return false; + } } } @@ -2572,7 +2485,7 @@ bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSto { TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance()); TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance()); - int levels = source9->levelCount(); + int levels = source9->getLevelCount(); for (int f = 0; f < 6; f++) { for (int i = 0; i < levels; i++) @@ -2582,11 +2495,13 @@ bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSto result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); - if (srcSurf) srcSurf->Release(); - if (dstSurf) dstSurf->Release(); + SafeRelease(srcSurf); + SafeRelease(dstSurf); if (!result) + { return false; + } } } } @@ -2594,6 +2509,20 @@ bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSto return result; } +bool Renderer9::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) +{ + // 3D textures are not available in the D3D9 backend. + UNREACHABLE(); + return false; +} + +bool Renderer9::copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) +{ + // 2D array textures are not supported by the D3D9 backend. + UNREACHABLE(); + return false; +} + D3DPOOL Renderer9::getBufferPool(DWORD usage) const { if (mD3d9Ex != NULL) @@ -2635,15 +2564,33 @@ bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sou return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); } +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) +{ + // 3D textures are not available in the D3D9 backend. + UNREACHABLE(); + return false; +} + +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) +{ + // 2D array textures are not available in the D3D9 backend. + UNREACHABLE(); + return false; +} + bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil) + const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) { + ASSERT(filter == GL_NEAREST); + endScene(); if (blitRenderTarget) { - gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0); - gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0); + gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0); + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0); RenderTarget9 *readRenderTarget = NULL; RenderTarget9 *drawRenderTarget = NULL; IDirect3DSurface9* readSurface = NULL; @@ -2673,6 +2620,9 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & return gl::error(GL_OUT_OF_MEMORY, false); } + gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + RECT srcRect; srcRect.left = readRect.x; srcRect.right = readRect.x + readRect.width; @@ -2685,10 +2635,79 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & dstRect.top = drawRect.y; dstRect.bottom = drawRect.y + drawRect.height; + // Clip the rectangles to the scissor rectangle + if (scissor) + { + if (dstRect.left < scissor->x) + { + srcRect.left += (scissor->x - dstRect.left); + dstRect.left = scissor->x; + } + if (dstRect.top < scissor->y) + { + srcRect.top += (scissor->y - dstRect.top); + dstRect.top = scissor->y; + } + if (dstRect.right > scissor->x + scissor->width) + { + srcRect.right -= (dstRect.right - (scissor->x + scissor->width)); + dstRect.right = scissor->x + scissor->width; + } + if (dstRect.bottom > scissor->y + scissor->height) + { + srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height)); + dstRect.bottom = scissor->y + scissor->height; + } + } + + // Clip the rectangles to the destination size + if (dstRect.left < 0) + { + srcRect.left += -dstRect.left; + dstRect.left = 0; + } + if (dstRect.right > dstSize.width) + { + srcRect.right -= (dstRect.right - dstSize.width); + dstRect.right = dstSize.width; + } + if (dstRect.top < 0) + { + srcRect.top += -dstRect.top; + dstRect.top = 0; + } + if (dstRect.bottom > dstSize.height) + { + srcRect.bottom -= (dstRect.bottom - dstSize.height); + dstRect.bottom = dstSize.height; + } + + // Clip the rectangles to the source size + if (srcRect.left < 0) + { + dstRect.left += -srcRect.left; + srcRect.left = 0; + } + if (srcRect.right > srcSize.width) + { + dstRect.right -= (srcRect.right - srcSize.width); + srcRect.right = srcSize.width; + } + if (srcRect.top < 0) + { + dstRect.top += -srcRect.top; + srcRect.top = 0; + } + if (srcRect.bottom > srcSize.height) + { + dstRect.bottom -= (srcRect.bottom - srcSize.height); + srcRect.bottom = srcSize.height; + } + HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); - readSurface->Release(); - drawSurface->Release(); + SafeRelease(readSurface); + SafeRelease(drawSurface); if (FAILED(result)) { @@ -2697,10 +2716,10 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & } } - if (blitDepthStencil) + if (blitDepth || blitStencil) { - gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); - gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); RenderTarget9 *readDepthStencil = NULL; RenderTarget9 *drawDepthStencil = NULL; IDirect3DSurface9* readSurface = NULL; @@ -2732,8 +2751,8 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); - readSurface->Release(); - drawSurface->Release(); + SafeRelease(readSurface); + SafeRelease(drawSurface); if (FAILED(result)) { @@ -2745,18 +2764,20 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & return true; } -void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) +void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) { + ASSERT(pack.pixelBuffer.get() == NULL); + RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *surface = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); if (colorbuffer) { renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); } - + if (renderTarget) { surface = renderTarget->getSurface(); @@ -2774,13 +2795,13 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) { UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target - surface->Release(); + SafeRelease(surface); return gl::error(GL_OUT_OF_MEMORY); } HRESULT result; IDirect3DSurface9 *systemSurface = NULL; - bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() && + bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && getShareHandleSupport() && 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) @@ -2802,18 +2823,17 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - surface->Release(); + SafeRelease(surface); return gl::error(GL_OUT_OF_MEMORY); } } result = mDevice->GetRenderTargetData(surface, systemSurface); - surface->Release(); - surface = NULL; + SafeRelease(surface); if (FAILED(result)) { - systemSurface->Release(); + SafeRelease(systemSurface); // It turns out that D3D will sometimes produce more error // codes than those documented. @@ -2832,7 +2852,7 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz if (directToPixels) { - systemSurface->Release(); + SafeRelease(systemSurface); return; } @@ -2848,17 +2868,14 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz if (FAILED(result)) { UNREACHABLE(); - systemSurface->Release(); + SafeRelease(systemSurface); return; // No sensible error to generate } - unsigned char *dest = (unsigned char*)pixels; - unsigned short *dest16 = (unsigned short*)pixels; - unsigned char *source; int inputPitch; - if (packReverseRowOrder) + if (pack.reverseRowOrder) { source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); inputPitch = -lock.Pitch; @@ -2869,231 +2886,67 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz inputPitch = lock.Pitch; } - unsigned int fastPixelSize = 0; + GLenum sourceInternalFormat = d3d9_gl::GetInternalFormat(desc.Format); + GLenum sourceFormat = gl::GetFormat(sourceInternalFormat); + GLenum sourceType = gl::GetType(sourceInternalFormat); - if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_BYTE) - { - fastPixelSize = 4; - } - else if ((desc.Format == D3DFMT_A4R4G4B4 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) || - (desc.Format == D3DFMT_A1R5G5B5 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)) - { - fastPixelSize = 2; - } - else if (desc.Format == D3DFMT_A16B16G16R16F && - format == GL_RGBA && - type == GL_HALF_FLOAT_OES) - { - fastPixelSize = 8; - } - else if (desc.Format == D3DFMT_A32B32G32R32F && - format == GL_RGBA && - type == GL_FLOAT) - { - fastPixelSize = 16; - } + GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat); - for (int j = 0; j < rect.bottom - rect.top; j++) + if (sourceFormat == format && sourceType == type) { - if (fastPixelSize != 0) + // Direct copy possible + unsigned char *dest = static_cast<unsigned char*>(pixels); + for (int y = 0; y < rect.bottom - rect.top; y++) { - // Fast path for formats which require no translation: - // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE - // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT - // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT - // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES - // D3DFMT_A32B32G32R32F to RGBA/FLOAT - // - // Note that buffers with no alpha go through the slow path below. - memcpy(dest + j * outputPitch, - source + j * inputPitch, - (rect.right - rect.left) * fastPixelSize); - continue; - } - else if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_RGBA && - type == GL_UNSIGNED_BYTE) - { - // Fast path for swapping red with blue - for (int i = 0; i < rect.right - rect.left; i++) - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - *(unsigned int*)(dest + 4 * i + j * outputPitch) = - (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red - } - continue; + memcpy(dest + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourcePixelSize); } + } + else + { + GLenum destInternalFormat = gl::GetSizedInternalFormat(format, type); + GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat); + GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat); - for (int i = 0; i < rect.right - rect.left; i++) + ColorCopyFunction fastCopyFunc = d3d9::GetFastCopyFunction(desc.Format, format, type); + if (fastCopyFunc) { - float r; - float g; - float b; - float a; - - switch (desc.Format) + // Fast copy is possible through some special function + for (int y = 0; y < rect.bottom - rect.top; y++) { - case D3DFMT_R5G6B5: - { - unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = 1.0f; - b = (rgb & 0x001F) * (1.0f / 0x001F); - g = (rgb & 0x07E0) * (1.0f / 0x07E0); - r = (rgb & 0xF800) * (1.0f / 0xF800); - } - break; - case D3DFMT_A1R5G5B5: - { - unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = (argb & 0x8000) ? 1.0f : 0.0f; - b = (argb & 0x001F) * (1.0f / 0x001F); - g = (argb & 0x03E0) * (1.0f / 0x03E0); - r = (argb & 0x7C00) * (1.0f / 0x7C00); - } - break; - case D3DFMT_A8R8G8B8: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xFF000000) * (1.0f / 0xFF000000); - b = (argb & 0x000000FF) * (1.0f / 0x000000FF); - g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_X8R8G8B8: - { - unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = 1.0f; - b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); - g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_A2R10G10B10: + for (int x = 0; x < rect.right - rect.left; x++) { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); + void *dest = static_cast<unsigned char*>(pixels) + y * outputPitch + x * destPixelSize; + void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize; - a = (argb & 0xC0000000) * (1.0f / 0xC0000000); - b = (argb & 0x000003FF) * (1.0f / 0x000003FF); - g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); - r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); + fastCopyFunc(src, dest); } - break; - case D3DFMT_A32B32G32R32F: - { - // float formats in D3D are stored rgba, rather than the other way round - 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: - { - // float formats in D3D are stored rgba, rather than the other way round - r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0)); - g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1)); - b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2)); - a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3)); - } - break; - default: - UNIMPLEMENTED(); // FIXME - UNREACHABLE(); - return; } + } + else + { + ColorReadFunction readFunc = d3d9::GetColorReadFunction(desc.Format); + ColorWriteFunction writeFunc = gl::GetColorWriteFunction(format, type); + + gl::ColorF temp; - switch (format) + for (int y = 0; y < rect.bottom - rect.top; y++) { - case GL_RGBA: - switch (type) + for (int x = 0; x < rect.right - rect.left; x++) { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - default: UNREACHABLE(); - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(15 * a + 0.5f) << 12)| - ((unsigned short)(15 * r + 0.5f) << 8) | - ((unsigned short)(15 * g + 0.5f) << 4) | - ((unsigned short)(15 * b + 0.5f) << 0); - break; - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)( a + 0.5f) << 15) | - ((unsigned short)(31 * r + 0.5f) << 10) | - ((unsigned short)(31 * g + 0.5f) << 5) | - ((unsigned short)(31 * b + 0.5f) << 0); - break; - default: UNREACHABLE(); - } - break; - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_SHORT_5_6_5: - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(31 * b + 0.5f) << 0) | - ((unsigned short)(63 * g + 0.5f) << 5) | - ((unsigned short)(31 * r + 0.5f) << 11); - break; - case GL_UNSIGNED_BYTE: - dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - break; - default: UNREACHABLE(); + void *dest = reinterpret_cast<unsigned char*>(pixels) + y * outputPitch + x * destPixelSize; + void *src = source + y * inputPitch + x * sourcePixelSize; + + // readFunc and writeFunc will be using the same type of color, CopyTexImage + // will not allow the copy otherwise. + readFunc(src, &temp); + writeFunc(&temp, dest); } - break; - default: UNREACHABLE(); } } } systemSurface->UnlockRect(); - - systemSurface->Release(); + SafeRelease(systemSurface); } RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) @@ -3114,14 +2967,19 @@ RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) return renderTarget; } -RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) +RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples) { RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); return renderTarget; } -ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type) +ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers) { + // Transform feedback is not supported in ES2 or D3D9 + ASSERT(transformFeedbackVaryings.size() == 0); + ShaderExecutable9 *executable = NULL; switch (type) @@ -3152,8 +3010,13 @@ ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, return executable; } -ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) +ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround) { + // Transform feedback is not supported in ES2 or D3D9 + ASSERT(transformFeedbackVaryings.size() == 0); + const char *profile = NULL; switch (type) @@ -3169,20 +3032,67 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha return NULL; } - // ANGLE issue 486: - // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization - UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL); + UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; + + if (workaround == ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION) + { + flags = D3DCOMPILE_SKIP_OPTIMIZATION; + } + else if (workaround == ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION) + { + flags = D3DCOMPILE_OPTIMIZATION_LEVEL3; + } + else ASSERT(workaround == ANGLE_D3D_WORKAROUND_NONE); + + if (gl::perfActive()) + { +#ifndef NDEBUG + flags = D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + flags |= D3DCOMPILE_DEBUG; + + std::string sourcePath = getTempPath(); + std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } + + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. + // Try the default flags first and if compilation fails, try some alternatives. + const UINT extraFlags[] = + { + flags, + flags | D3DCOMPILE_AVOID_FLOW_CONTROL, + flags | D3DCOMPILE_PREFER_FLOW_CONTROL + }; - ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true); + const static char *extraFlagNames[] = + { + "default", + "avoid flow control", + "prefer flow control" + }; + + int attempts = ArraySize(extraFlags); + + ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); if (!binary) + { return NULL; + } - ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type); - binary->Release(); + ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, + transformFeedbackVaryings, separatedOutputBuffers); + SafeRelease(binary); return executable; } +rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize) +{ + return new UniformStorage(storageSize); +} + bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) { return mBlit->boxFilter(source, dest); @@ -3223,7 +3133,7 @@ bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *s { Image9::copyLockableSurfaces(surf, source); result = mDevice->UpdateSurface(surf, NULL, dest, NULL); - surf->Release(); + SafeRelease(surf); } } else @@ -3260,14 +3170,50 @@ TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) return new TextureStorage9_2D(this, swapChain9); } -TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) +TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) { - return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height); + return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); } -TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) +TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) { - return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size); + return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels); +} + +TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + // 3D textures are not supported by the D3D9 backend. + UNREACHABLE(); + + return NULL; +} + +TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + // 2D array textures are not supported by the D3D9 backend. + UNREACHABLE(); + + return NULL; +} + +Texture2DImpl *Renderer9::createTexture2D() +{ + return new TextureD3D_2D(this); +} + +TextureCubeImpl *Renderer9::createTextureCube() +{ + return new TextureD3D_Cube(this); +} + +Texture3DImpl *Renderer9::createTexture3D() +{ + return new TextureD3D_3D(this); +} + +Texture2DArrayImpl *Renderer9::createTexture2DArray() +{ + return new TextureD3D_2DArray(this); } bool Renderer9::getLUID(LUID *adapterLuid) const @@ -3284,4 +3230,25 @@ bool Renderer9::getLUID(LUID *adapterLuid) const return false; } +GLenum Renderer9::getNativeTextureFormat(GLenum internalFormat) const +{ + return d3d9_gl::GetInternalFormat(gl_d3d9::GetTextureFormat(internalFormat)); +} + +rx::VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const +{ + return d3d9::GetVertexConversionType(vertexFormat); +} + +GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const +{ + D3DDECLTYPE declType = d3d9::GetNativeVertexFormat(vertexFormat); + return d3d9::GetDeclTypeComponentType(declType); +} + +void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +{ + d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h index 24fd2bdd84..070623c9db 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // @@ -10,15 +10,16 @@ #define LIBGLESV2_RENDERER_RENDERER9_H_ #include "common/angleutils.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/renderer/ShaderCache.h" -#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" +#include "common/mathutil.h" +#include "libGLESv2/renderer/d3d/HLSLCompiler.h" +#include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/RenderTarget.h" namespace gl { -class Renderbuffer; +class FramebufferAttachment; } namespace rx @@ -27,11 +28,12 @@ class VertexDataManager; class IndexDataManager; class StreamingIndexBufferInterface; struct TranslatedAttribute; +class Blit9; class Renderer9 : public Renderer { public: - Renderer9(egl::Display *display, HDC hDc, bool softwareDevice); + Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay); virtual ~Renderer9(); static Renderer9 *makeRenderer9(Renderer *renderer); @@ -57,22 +59,14 @@ class Renderer9 : public Renderer IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); -#if 0 - void *createTexture2D(); - void *createTextureCube(); - void *createQuery(); - void *createIndexBuffer(); - void *createVertexbuffer(); - - // state setup - void applyShaders(); - void applyConstants(); -#endif + virtual void generateSwizzle(gl::Texture *texture); virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); + virtual bool setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); + virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, + virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, unsigned int sampleMask); virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW); @@ -82,14 +76,19 @@ class Renderer9 : public Renderer bool ignoreViewport); virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary); - virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); + virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); + virtual void applyUniforms(const gl::ProgramBinary &programBinary); virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + GLint first, GLsizei count, GLsizei instances); virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]); + + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); @@ -101,21 +100,11 @@ class Renderer9 : public Renderer virtual bool testDeviceLost(bool notify); virtual bool testDeviceResettable(); - // Renderer capabilities IDirect3DDevice9 *getDevice() { return mDevice; } virtual DWORD getAdapterVendor() const; virtual std::string getRendererDescription() const; virtual GUID getAdapterIdentifier() const; - virtual bool getBGRATextureSupport() const; - virtual bool getDXT1TextureSupport(); - virtual bool getDXT3TextureSupport(); - virtual bool getDXT5TextureSupport(); - virtual bool getEventQuerySupport(); - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); - virtual bool getLuminanceTextureSupport(); - virtual bool getLuminanceAlphaTextureSupport(); virtual unsigned int getMaxVertexTextureImageUnits() const; virtual unsigned int getMaxCombinedTextureImageUnits() const; virtual unsigned int getReservedVertexUniformVectors() const; @@ -123,93 +112,122 @@ class Renderer9 : public Renderer virtual unsigned int getMaxVertexUniformVectors() const; virtual unsigned int getMaxFragmentUniformVectors() const; virtual unsigned int getMaxVaryingVectors() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual bool getTextureFilterAnisotropySupport() const; - virtual float getTextureMaxAnisotropy() const; + virtual unsigned int getMaxVertexShaderUniformBuffers() const; + virtual unsigned int getMaxFragmentShaderUniformBuffers() const; + virtual unsigned int getReservedVertexUniformBuffers() const; + virtual unsigned int getReservedFragmentUniformBuffers() const; + virtual unsigned int getMaxTransformFeedbackBuffers() const; + virtual unsigned int getMaxTransformFeedbackSeparateComponents() const; + virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const; + virtual unsigned int getMaxUniformBufferSize() const; virtual bool getShareHandleSupport() const; - virtual bool getDerivativeInstructionSupport() const; virtual bool getPostSubBufferSupport() const; + virtual int getMaxRecommendedElementsIndices() const; + virtual int getMaxRecommendedElementsVertices() const; + virtual bool getSRGBTextureSupport() const; virtual int getMajorShaderModel() const; - virtual float getMaxPointSize() const; - virtual int getMaxViewportDimension() const; - virtual int getMaxTextureWidth() const; - virtual int getMaxTextureHeight() const; - virtual bool get32BitIndexSupport() const; DWORD getCapsDeclTypes() const; virtual int getMinSwapInterval() const; virtual int getMaxSwapInterval() const; virtual GLsizei getMaxSupportedSamples() const; + virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; + virtual GLsizei getNumSampleCounts(GLenum internalFormat) const; + virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const; int getNearestSupportedSamples(D3DFORMAT format, int requested) const; - - virtual unsigned int getMaxRenderTargets() const; - - D3DFORMAT ConvertTextureInternalFormat(GLint internalformat); // Pixel operations virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); + virtual bool copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source); + virtual bool copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source); virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level); + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level); virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil); - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); + const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); + virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels); // RenderTarget creation virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); // Shader operations - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector<gl::LinkedVarying> &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround); + virtual UniformStorage *createUniformStorage(size_t storageSize); // Image operations virtual Image *createImage(); virtual void generateMipmap(Image *dest, Image *source); virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + + // Texture creation + virtual Texture2DImpl *createTexture2D(); + virtual TextureCubeImpl *createTextureCube(); + virtual Texture3DImpl *createTexture3D(); + virtual Texture2DArrayImpl *createTexture2DArray(); // Buffer creation + virtual BufferImpl *createBuffer(); virtual VertexBuffer *createVertexBuffer(); virtual IndexBuffer *createIndexBuffer(); - virtual BufferStorage *createBufferStorage(); + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray(); // Query and Fence creation virtual QueryImpl *createQuery(GLenum type); virtual FenceImpl *createFence(); + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; + virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + // D3D9-renderer specific methods bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); D3DPOOL getTexturePool(DWORD usage) const; virtual bool getLUID(LUID *adapterLuid) const; + virtual GLenum getNativeTextureFormat(GLenum internalFormat) const; + virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; + virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; private: DISALLOW_COPY_AND_ASSIGN(Renderer9); - void deinitialize(); + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const; - void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v); - void applyUniformniv(gl::Uniform *targetUniform, const GLint *v); - void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v); + void release(); + + void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v); + void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v); + void applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v); void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); - gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer); + gl::FramebufferAttachment *getNullColorbuffer(gl::FramebufferAttachment *depthbuffer); D3DPOOL getBufferPool(DWORD usage) const; @@ -226,13 +244,14 @@ class Renderer9 : public Renderer UINT mAdapter; D3DDEVTYPE mDeviceType; - bool mSoftwareDevice; // FIXME: Deprecate IDirect3D9 *mD3d9; // Always valid after successful initialization. IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. IDirect3DDevice9 *mDevice; IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. - Blit *mBlit; + HLSLCompiler mCompiler; + + Blit9 *mBlit; HWND mDeviceWindow; @@ -245,34 +264,21 @@ class Renderer9 : public Renderer GLsizei mRepeatDraw; bool mSceneStarted; - bool mSupportsNonPower2Textures; - bool mSupportsTextureFilterAnisotropy; int mMinSwapInterval; int mMaxSwapInterval; - bool mOcclusionQuerySupport; - bool mEventQuerySupport; bool mVertexTextureSupport; - bool mDepthTextureSupport; - - bool mFloat32TextureSupport; - bool mFloat32FilterSupport; - bool mFloat32RenderSupport; - - bool mFloat16TextureSupport; - bool mFloat16FilterSupport; - bool mFloat16RenderSupport; - - bool mDXT1TextureSupport; - bool mDXT3TextureSupport; - bool mDXT5TextureSupport; - - bool mLuminanceTextureSupport; - bool mLuminanceAlphaTextureSupport; + struct MultisampleSupportInfo + { + bool supportedSamples[D3DMULTISAMPLE_16_SAMPLES + 1]; + unsigned int maxSupportedSamples; + }; + typedef std::map<D3DFORMAT, MultisampleSupportInfo> MultisampleSupportMap; + MultisampleSupportMap mMultiSampleSupport; + unsigned int mMaxSupportedSamples; - std::map<D3DFORMAT, bool *> mMultiSampleSupport; - GLsizei mMaxSupportedSamples; + MultisampleSupportInfo getMultiSampleSupport(D3DFORMAT format); // current render target states unsigned int mAppliedRenderTargetSerial; @@ -308,7 +314,7 @@ class Renderer9 : public Renderer bool mForceSetBlendState; gl::BlendState mCurBlendState; - gl::Color mCurBlendColor; + gl::ColorF mCurBlendColor; GLuint mCurSampleMask; // Currently applied sampler states @@ -323,8 +329,10 @@ class Renderer9 : public Renderer unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; unsigned int mAppliedIBSerial; - unsigned int mAppliedProgramBinarySerial; - + IDirect3DVertexShader9 *mAppliedVertexShader; + IDirect3DPixelShader9 *mAppliedPixelShader; + unsigned int mAppliedProgramSerial; + rx::dx_VertexConstants mVertexConstants; rx::dx_PixelConstants mPixelConstants; bool mDxUniformsDirty; @@ -346,7 +354,7 @@ class Renderer9 : public Renderer UINT lruCount; int width; int height; - gl::Renderbuffer *buffer; + gl::FramebufferAttachment *buffer; } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; UINT mMaxNullColorbufferLRU; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h index 4391ac271a..a03528c9b5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h @@ -53,7 +53,7 @@ class ShaderCache // Random eviction policy. if (mMap.size() >= kMaxMapSize) { - mMap.begin()->second->Release(); + SafeRelease(mMap.begin()->second); mMap.erase(mMap.begin()); } @@ -67,7 +67,7 @@ class ShaderCache { for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) { - it->second->Release(); + SafeRelease(it->second); } mMap.clear(); @@ -88,15 +88,7 @@ class ShaderCache return mDevice->CreatePixelShader(function, shader); } -#ifndef HASH_MAP -# ifdef _MSC_VER -# define HASH_MAP stdext::hash_map -# else -# define HASH_MAP std::unordered_map -# endif -#endif - - typedef HASH_MAP<std::string, ShaderObject*> Map; + typedef std::unordered_map<std::string, ShaderObject*> Map; Map mMap; IDirect3DDevice9 *mDevice; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp index 5decf9664d..c10ddbf6ce 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -8,7 +8,7 @@ // ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader // executable implementation details. -#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" +#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" #include "common/debug.h" @@ -31,14 +31,8 @@ ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirec ShaderExecutable9::~ShaderExecutable9() { - if (mVertexExecutable) - { - mVertexExecutable->Release(); - } - if (mPixelExecutable) - { - mPixelExecutable->Release(); - } + SafeRelease(mVertexExecutable); + SafeRelease(mPixelExecutable); } ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h index fa1e6c2844..fa1e6c2844 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp index dd8895d18d..c6567b635f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp @@ -1,15 +1,16 @@ #include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // // SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. -#include "libGLESv2/renderer/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" namespace rx { @@ -35,38 +36,16 @@ SwapChain9::~SwapChain9() void SwapChain9::release() { - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } + SafeRelease(mSwapChain); + SafeRelease(mBackBuffer); + SafeRelease(mDepthStencil); + SafeRelease(mRenderTarget); + SafeRelease(mOffscreenTexture); if (mWindow) + { mShareHandle = NULL; + } } static DWORD convertInterval(EGLint interval) @@ -111,29 +90,10 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI // Release specific resources to free up memory for the new render target, while the // old render target still exists for the purpose of preserving its contents. - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } + SafeRelease(mSwapChain); + SafeRelease(mBackBuffer); + SafeRelease(mOffscreenTexture); + SafeRelease(mDepthStencil); HANDLE *pShareHandle = NULL; if (!mWindow && mRenderer->getShareHandleSupport()) @@ -142,8 +102,8 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI } result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT, - &mOffscreenTexture, pShareHandle); + gl_d3d9::GetTextureFormat(mBackBufferFormat), + D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); if (FAILED(result)) { ERR("Could not create offscreen texture: %08lX", result); @@ -187,15 +147,15 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); ASSERT(SUCCEEDED(result)); - oldRenderTarget->Release(); + SafeRelease(oldRenderTarget); } if (mWindow) { D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat); + presentParameters.AutoDepthStencilFormat = gl_d3d9::GetRenderFormat(mDepthBufferFormat); presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat); + presentParameters.BackBufferFormat = gl_d3d9::GetRenderFormat(mBackBufferFormat); presentParameters.EnableAutoDepthStencil = FALSE; presentParameters.Flags = 0; presentParameters.hDeviceWindow = mWindow; @@ -247,7 +207,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI if (mDepthBufferFormat != GL_NONE) { result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, - gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat), + gl_d3d9::GetRenderFormat(mDepthBufferFormat), D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); if (FAILED(result)) @@ -276,7 +236,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI } // parameters should be validated/clamped by caller -EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint) { if (!mSwapChain) { @@ -356,6 +316,14 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return EGL_BAD_ALLOC; } + // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is + // in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation. The + // device appears to be ok after emitting this error so simply return a failure to swap. + if (result == 0x88760873) + { + return EGL_BAD_MATCH; + } + // http://crbug.com/313210 // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific // device removed bug with lost contexts when reinstalling drivers. @@ -370,6 +338,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) // Increments refcount on surface. // caller must Release() the returned surface +// TODO: remove the AddRef to match SwapChain11 IDirect3DSurface9 *SwapChain9::getRenderTarget() { if (mRenderTarget) @@ -382,6 +351,7 @@ IDirect3DSurface9 *SwapChain9::getRenderTarget() // Increments refcount on surface. // caller must Release() the returned surface +// TODO: remove the AddRef to match SwapChain11 IDirect3DSurface9 *SwapChain9::getDepthStencil() { if (mDepthStencil) @@ -394,6 +364,7 @@ IDirect3DSurface9 *SwapChain9::getDepthStencil() // Increments refcount on texture. // caller must Release() the returned texture +// TODO: remove the AddRef to match SwapChain11 IDirect3DTexture9 *SwapChain9::getOffscreenTexture() { if (mOffscreenTexture) @@ -434,10 +405,10 @@ void SwapChain9::recreate() return; } - mSwapChain->Release(); + SafeRelease(mSwapChain); mSwapChain = newSwapChain; - mBackBuffer->Release(); + SafeRelease(mBackBuffer); result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); ASSERT(SUCCEEDED(result)); } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h index 16a62bd86f..4d756f80d1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h @@ -25,7 +25,7 @@ class SwapChain9 : public SwapChain EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint); virtual void recreate(); virtual IDirect3DSurface9 *getRenderTarget(); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp index 2486a9a5bf..b065ee80fe 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 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. // @@ -10,17 +10,19 @@ // D3D9 texture. #include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/Texture.h" namespace rx { TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) - : mLodOffset(0), + : mTopLevel(0), mRenderer(Renderer9::makeRenderer9(renderer)), mD3DUsage(usage), mD3DPool(mRenderer->getTexturePool(usage)) @@ -37,46 +39,23 @@ TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) return static_cast<TextureStorage9*>(storage); } -DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable) +DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget) { DWORD d3dusage = 0; - if (d3dfmt == D3DFMT_INTZ) + if (gl::GetDepthBits(internalformat) > 0 || + gl::GetStencilBits(internalformat) > 0) { d3dusage |= D3DUSAGE_DEPTHSTENCIL; } - else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) + else if (renderTarget && (gl_d3d9::GetRenderFormat(internalformat) != D3DFMT_UNKNOWN)) { d3dusage |= D3DUSAGE_RENDERTARGET; } + return d3dusage; } -bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return true; - } - 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; -} bool TextureStorage9::isRenderTarget() const { @@ -98,17 +77,18 @@ DWORD TextureStorage9::getUsage() const return mD3DUsage; } -int TextureStorage9::getLodOffset() const +int TextureStorage9::getTopLevel() const { - return mLodOffset; + return mTopLevel; } -int TextureStorage9::levelCount() +int TextureStorage9::getLevelCount() const { - return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0; + return getBaseTexture() ? (getBaseTexture()->GetLevelCount() - getTopLevel()) : 0; } -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) + : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) { IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); mTexture = surfaceTexture; @@ -117,8 +97,8 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain initializeRenderTarget(); } -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) - : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { mTexture = NULL; mRenderTarget = NULL; @@ -127,9 +107,11 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum in if (width > 0 && height > 0) { IDirect3DDevice9 *device = mRenderer->getDevice(); - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); - HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), - mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); + D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat); + d3d9::MakeValidSize(false, format, &width, &height, &mTopLevel); + UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; + + HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); if (FAILED(result)) { @@ -143,12 +125,8 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum in TextureStorage9_2D::~TextureStorage9_2D() { - if (mTexture) - { - mTexture->Release(); - } - - delete mRenderTarget; + SafeRelease(mTexture); + SafeDelete(mRenderTarget); } TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage) @@ -165,11 +143,12 @@ IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) if (mTexture) { - HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface); + HRESULT result = mTexture->GetSurfaceLevel(level + mTopLevel, &surface); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level + mLodOffset != 0 && isManaged() && dirty) + if (level + mTopLevel != 0 && isManaged() && dirty) { mTexture->AddDirtyRect(NULL); } @@ -178,7 +157,7 @@ IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) return surface; } -RenderTarget *TextureStorage9_2D::getRenderTarget() +RenderTarget *TextureStorage9_2D::getRenderTarget(int level) { return mRenderTarget; } @@ -193,8 +172,8 @@ void TextureStorage9_2D::generateMipmap(int level) mRenderer->boxFilter(upper, lower); } - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); + SafeRelease(upper); + SafeRelease(lower); } IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const @@ -214,8 +193,8 @@ void TextureStorage9_2D::initializeRenderTarget() } } -TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) - : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) +TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { mTexture = NULL; for (int i = 0; i < 6; ++i) @@ -229,9 +208,11 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenu { IDirect3DDevice9 *device = mRenderer->getDevice(); int height = size; - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); - HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), - mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); + D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat); + d3d9::MakeValidSize(false, format, &size, &height, &mTopLevel); + UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; + + HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); if (FAILED(result)) { @@ -245,14 +226,11 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenu TextureStorage9_Cube::~TextureStorage9_Cube() { - if (mTexture) - { - mTexture->Release(); - } + SafeRelease(mTexture); for (int i = 0; i < 6; ++i) { - delete mRenderTarget[i]; + SafeDelete(mRenderTarget[i]); } } @@ -271,7 +249,8 @@ IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, in if (mTexture) { D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); - HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface); + HRESULT result = mTexture->GetCubeMapSurface(face, level + mTopLevel, &surface); + UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); // With managed textures the driver needs to be informed of updates to the lower mipmap levels @@ -284,23 +263,23 @@ IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, in return surface; } -RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget) +RenderTarget *TextureStorage9_Cube::getRenderTargetFace(GLenum faceTarget, int level) { - return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)]; + return mRenderTarget[TextureD3D_Cube::targetToIndex(faceTarget)]; } -void TextureStorage9_Cube::generateMipmap(int face, int level) +void TextureStorage9_Cube::generateMipmap(int faceIndex, int level) { - IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false); - IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true); + IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1, false); + IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, true); if (upper != NULL && lower != NULL) { mRenderer->boxFilter(upper, lower); } - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); + SafeRelease(upper); + SafeRelease(lower); } IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h index 86f551a131..cc7c155d34 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2013 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,7 +11,7 @@ #ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ #define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ -#include "libGLESv2/renderer/TextureStorage.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" #include "common/debug.h" namespace rx @@ -20,37 +20,37 @@ class Renderer9; class SwapChain9; class RenderTarget; class RenderTarget9; -class Blit; class TextureStorage9 : public TextureStorage { public: - TextureStorage9(Renderer *renderer, DWORD usage); virtual ~TextureStorage9(); static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); - static DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable); - static bool IsTextureFormatRenderable(D3DFORMAT format); + static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget); D3DPOOL getPool() const; DWORD getUsage() const; virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; - virtual RenderTarget *getRenderTarget() { return NULL; } - virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return NULL; } + virtual RenderTarget *getRenderTarget(int level) { return NULL; } + virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level) { return NULL; } + virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer) { return NULL; } virtual void generateMipmap(int level) {}; virtual void generateMipmap(int face, int level) {}; - virtual int getLodOffset() const; + virtual int getTopLevel() const; virtual bool isRenderTarget() const; virtual bool isManaged() const; - virtual int levelCount(); + virtual int getLevelCount() const; protected: - int mLodOffset; + int mTopLevel; Renderer9 *mRenderer; + TextureStorage9(Renderer *renderer, DWORD usage); + private: DISALLOW_COPY_AND_ASSIGN(TextureStorage9); @@ -62,13 +62,13 @@ class TextureStorage9_2D : public TextureStorage9 { public: TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain); - TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); virtual ~TextureStorage9_2D(); static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); - virtual RenderTarget *getRenderTarget(); + virtual RenderTarget *getRenderTarget(int level); virtual IDirect3DBaseTexture9 *getBaseTexture() const; virtual void generateMipmap(int level); @@ -84,15 +84,15 @@ class TextureStorage9_2D : public TextureStorage9 class TextureStorage9_Cube : public TextureStorage9 { public: - TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels); virtual ~TextureStorage9_Cube(); static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); - virtual RenderTarget *getRenderTarget(GLenum faceTarget); + virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level); virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmap(int face, int level); + virtual void generateMipmap(int faceIndex, int level); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h new file mode 100644 index 0000000000..66a6c64d81 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h @@ -0,0 +1,43 @@ +// +// Copyright 2014 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. +// + +// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAY9_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAY9_H_ + +#include "libGLESv2/renderer/VertexArrayImpl.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ +class Renderer9; + +class VertexArray9 : public VertexArrayImpl +{ + public: + VertexArray9(rx::Renderer9 *renderer) + : VertexArrayImpl(), + mRenderer(renderer) + { + } + + virtual ~VertexArray9() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } + virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } + virtual void enableAttribute(size_t idx, bool enabledState) { } + + private: + DISALLOW_COPY_AND_ASSIGN(VertexArray9); + + rx::Renderer9 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp new file mode 100644 index 0000000000..d260640dbe --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -0,0 +1,252 @@ +#include "precompiled.h" +// +// 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. +// + +// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. + +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/vertexconversion.h" +#include "libGLESv2/renderer/BufferImpl.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" + +#include "libGLESv2/Buffer.h" + +namespace rx +{ + +VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) +{ + mVertexBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +VertexBuffer9::~VertexBuffer9() +{ + SafeRelease(mVertexBuffer); +} + +bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) +{ + SafeRelease(mVertexBuffer); + + updateSerial(); + + if (size > 0) + { + DWORD flags = D3DUSAGE_WRITEONLY; + if (dynamicUsage) + { + flags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", size); + return false; + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return true; +} + +VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); + return static_cast<VertexBuffer9*>(vertexBuffer); +} + +bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) +{ + if (mVertexBuffer) + { + gl::Buffer *buffer = attrib.buffer.get(); + + int inputStride = gl::ComputeVertexAttributeStride(attrib); + int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); + + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + + unsigned int mapSize; + if (!spaceRequired(attrib, count, instances, &mapSize)) + { + return false; + } + + HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return false; + } + + const char *input = NULL; + if (attrib.enabled) + { + if (buffer) + { + BufferImpl *storage = buffer->getImplementation(); + input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.offset); + } + else + { + input = static_cast<const char*>(attrib.pointer); + } + } + else + { + input = reinterpret_cast<const char*>(currentValue.FloatValues); + } + + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } + + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + bool needsConversion = (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0; + + if (!needsConversion && inputStride == elementSize) + { + size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride); + memcpy(mapPtr, input, copySize); + } + else + { + VertexCopyFunction copyFunction = d3d9::GetVertexCopyFunction(vertexFormat); + copyFunction(input, inputStride, count, mapPtr); + } + + mVertexBuffer->Unlock(); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const +{ + return spaceRequired(attrib, count, instances, outSpaceRequired); +} + +unsigned int VertexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +bool VertexBuffer9::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return true; + } +} + +bool VertexBuffer9::discard() +{ + if (mVertexBuffer) + { + void *dummy; + HRESULT result; + + result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + ERR("Discard lock failed with error 0x%08x", result); + return false; + } + + result = mVertexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Discard unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const +{ + return mVertexBuffer; +} + +bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) +{ + gl::VertexFormat vertexFormat(attrib, GL_FLOAT); + unsigned int elementSize = d3d9::GetVertexElementSize(vertexFormat); + + if (attrib.enabled) + { + unsigned int elementCount = 0; + if (instances == 0 || attrib.divisor == 0) + { + elementCount = count; + } + else + { + if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.divisor - 1)) + { + // Round up + elementCount = (static_cast<unsigned int>(instances) + (attrib.divisor - 1)) / attrib.divisor; + } + else + { + elementCount = static_cast<unsigned int>(instances) / attrib.divisor; + } + } + + if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } + } + else + { + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return true; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h new file mode 100644 index 0000000000..fc4b6b6d26 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h @@ -0,0 +1,54 @@ +// +// 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. +// + +// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ + +#include "libGLESv2/renderer/d3d/VertexBuffer.h" + +namespace rx +{ +class Renderer9; + +class VertexBuffer9 : public VertexBuffer +{ + public: + explicit VertexBuffer9(rx::Renderer9 *const renderer); + virtual ~VertexBuffer9(); + + virtual bool initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset); + + virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; + + virtual unsigned int getBufferSize() const; + virtual bool setBufferSize(unsigned int size); + virtual bool discard(); + + IDirect3DVertexBuffer9 *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); + + rx::Renderer9 *const mRenderer; + + IDirect3DVertexBuffer9 *mVertexBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired); +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp index e5c8a14232..303d8ad299 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -8,9 +8,10 @@ // VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. #include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" namespace rx { @@ -36,10 +37,7 @@ VertexDeclarationCache::~VertexDeclarationCache() { for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) { - if (mVertexDeclCache[i].vertexDeclaration) - { - mVertexDeclCache[i].vertexDeclaration->Release(); - } + SafeRelease(mVertexDeclCache[i].vertexDeclaration); } } @@ -134,9 +132,11 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl mAppliedVBs[stream].offset = attributes[i].offset; } + gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT); + element->Stream = stream; element->Offset = 0; - element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4; + element->Type = d3d9::GetNativeVertexFormat(vertexFormat); element->Method = D3DDECLMETHOD_DEFAULT; element->Usage = D3DDECLUSAGE_TEXCOORD; element->UsageIndex = programBinary->getSemanticIndex(i); @@ -188,8 +188,7 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl if (lastCache->vertexDeclaration != NULL) { - lastCache->vertexDeclaration->Release(); - lastCache->vertexDeclaration = NULL; + SafeRelease(lastCache->vertexDeclaration); // mLastSetVDecl is set to the replacement, so we don't have to worry // about it. } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h index 3fc024a9ba..004e28df4f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -9,7 +9,7 @@ #ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ #define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ -#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp new file mode 100644 index 0000000000..f5d1da62b3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp @@ -0,0 +1,820 @@ +#include "precompiled.h" +// +// Copyright (c) 2013-2014 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. +// + +// formatutils9.cpp: Queries for GL image formats and their translations to D3D9 +// formats. + +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/generatemip.h" +#include "libGLESv2/renderer/loadimage.h" +#include "libGLESv2/renderer/copyimage.h" +#include "libGLESv2/renderer/vertexconversion.h" + +namespace rx +{ + +// Each GL internal format corresponds to one D3D format and data loading function. +// Due to not all formats being available all the time, some of the function/format types are wrapped +// in templates that perform format support queries on a Renderer9 object which is supplied +// when requesting the function or format. + +typedef bool(*FallbackPredicateFunction)(); + +template <FallbackPredicateFunction pred, LoadImageFunction prefered, LoadImageFunction fallback> +static void FallbackLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + if (pred()) + { + prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } + else + { + fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } +} + +static void UnreachableLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); + +struct D3D9FormatInfo +{ + D3DFORMAT mTexFormat; + D3DFORMAT mRenderFormat; + LoadImageFunction mLoadFunction; + + D3D9FormatInfo() + : mTexFormat(D3DFMT_NULL), mRenderFormat(D3DFMT_NULL), mLoadFunction(NULL) + { } + + D3D9FormatInfo(D3DFORMAT textureFormat, D3DFORMAT renderFormat, LoadImageFunction loadFunc) + : mTexFormat(textureFormat), mRenderFormat(renderFormat), mLoadFunction(loadFunc) + { } +}; + +typedef std::pair<GLenum, D3D9FormatInfo> D3D9FormatPair; +typedef std::map<GLenum, D3D9FormatInfo> D3D9FormatMap; + +static D3D9FormatMap BuildD3D9FormatMap() +{ + D3D9FormatMap map; + + // | Internal format | Texture format | Render format | Load function | + map.insert(D3D9FormatPair(GL_NONE, D3D9FormatInfo(D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ))); + + map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT16, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ))); + map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT32_OES, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D32, UnreachableLoad ))); + map.insert(D3D9FormatPair(GL_DEPTH24_STENCIL8_OES, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ))); + map.insert(D3D9FormatPair(GL_STENCIL_INDEX8, D3D9FormatInfo(D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ))); // TODO: What's the texture format? + + map.insert(D3D9FormatPair(GL_RGBA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative<GLfloat, 4> ))); + map.insert(D3D9FormatPair(GL_RGB32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4<GLfloat, gl::Float32One>))); + map.insert(D3D9FormatPair(GL_RG32F_EXT, D3D9FormatInfo(D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative<GLfloat, 2> ))); + map.insert(D3D9FormatPair(GL_R32F_EXT, D3D9FormatInfo(D3DFMT_R32F, D3DFMT_R32F, LoadToNative<GLfloat, 1> ))); + map.insert(D3D9FormatPair(GL_ALPHA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F ))); + map.insert(D3D9FormatPair(GL_LUMINANCE32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F ))); + map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F ))); + + map.insert(D3D9FormatPair(GL_RGBA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative<GLhalf, 4> ))); + map.insert(D3D9FormatPair(GL_RGB16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4<GLhalf, gl::Float16One> ))); + map.insert(D3D9FormatPair(GL_RG16F_EXT, D3D9FormatInfo(D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative<GLhalf, 2> ))); + map.insert(D3D9FormatPair(GL_R16F_EXT, D3D9FormatInfo(D3DFMT_R16F, D3DFMT_R16F, LoadToNative<GLhalf, 1> ))); + map.insert(D3D9FormatPair(GL_ALPHA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F ))); + map.insert(D3D9FormatPair(GL_LUMINANCE16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F ))); + map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F ))); + + map.insert(D3D9FormatPair(GL_ALPHA8_EXT, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad<gl::supportsSSE2, LoadA8ToBGRA8_SSE2, LoadA8ToBGRA8>))); + + map.insert(D3D9FormatPair(GL_RGB8_OES, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 ))); + map.insert(D3D9FormatPair(GL_RGB565, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 ))); + map.insert(D3D9FormatPair(GL_RGBA8_OES, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad<gl::supportsSSE2, LoadRGBA8ToBGRA8_SSE2, LoadRGBA8ToBGRA8>))); + map.insert(D3D9FormatPair(GL_RGBA4, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 ))); + map.insert(D3D9FormatPair(GL_RGB5_A1, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 ))); + map.insert(D3D9FormatPair(GL_R8_EXT, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 ))); + map.insert(D3D9FormatPair(GL_RG8_EXT, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 ))); + + map.insert(D3D9FormatPair(GL_BGRA8_EXT, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative<GLubyte, 4> ))); + map.insert(D3D9FormatPair(GL_BGRA4_ANGLEX, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ))); + map.insert(D3D9FormatPair(GL_BGR5_A1_ANGLEX, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ))); + + map.insert(D3D9FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D9FormatInfo(D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ))); + map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D9FormatInfo(D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ))); + map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D9FormatInfo(D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ))); + map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D9FormatInfo(D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ))); + + // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and + // then changing the format and loading function appropriately. + map.insert(D3D9FormatPair(GL_LUMINANCE8_EXT, D3D9FormatInfo(D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 1> ))); + map.insert(D3D9FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D9FormatInfo(D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 2> ))); + + return map; +} + +static bool GetD3D9FormatInfo(GLenum internalFormat, D3D9FormatInfo *outFormatInfo) +{ + static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); + D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + if (outFormatInfo) + { + *outFormatInfo = iter->second; + } + return true; + } + else + { + return false; + } +} + +// A map to determine the pixel size and mip generation function of a given D3D format +struct D3DFormatInfo +{ + GLuint mPixelBits; + GLuint mBlockWidth; + GLuint mBlockHeight; + GLenum mInternalFormat; + + MipGenerationFunction mMipGenerationFunction; + ColorReadFunction mColorReadFunction; + + D3DFormatInfo() + : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mInternalFormat(GL_NONE), mMipGenerationFunction(NULL), + mColorReadFunction(NULL) + { } + + D3DFormatInfo(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, GLenum internalFormat, + MipGenerationFunction mipFunc, ColorReadFunction readFunc) + : mPixelBits(pixelBits), mBlockWidth(blockWidth), mBlockHeight(blockHeight), mInternalFormat(internalFormat), + mMipGenerationFunction(mipFunc), mColorReadFunction(readFunc) + { } +}; + +typedef std::pair<D3DFORMAT, D3DFormatInfo> D3D9FormatInfoPair; +typedef std::map<D3DFORMAT, D3DFormatInfo> D3D9FormatInfoMap; + +static D3D9FormatInfoMap BuildD3D9FormatInfoMap() +{ + D3D9FormatInfoMap map; + + // | D3DFORMAT | | S |W |H | Internal format | Mip generation function | Color read function | + map.insert(D3D9FormatInfoPair(D3DFMT_NULL, D3DFormatInfo( 0, 0, 0, GL_NONE, NULL, NULL ))); + map.insert(D3D9FormatInfoPair(D3DFMT_UNKNOWN, D3DFormatInfo( 0, 0, 0, GL_NONE, NULL, NULL ))); + + map.insert(D3D9FormatInfoPair(D3DFMT_L8, D3DFormatInfo( 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_A8, D3DFormatInfo( 8, 1, 1, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_A8L8, D3DFormatInfo( 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_A4R4G4B4, D3DFormatInfo( 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip<B4G4R4A4>, ReadColor<B4G4R4A4, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_A1R5G5B5, D3DFormatInfo( 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip<B5G5R5A1>, ReadColor<B5G5R5A1, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_R5G6B5, D3DFormatInfo( 16, 1, 1, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_X8R8G8B8, D3DFormatInfo( 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_A8R8G8B8, D3DFormatInfo( 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_R16F, D3DFormatInfo( 16, 1, 1, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_G16R16F, D3DFormatInfo( 32, 1, 1, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_A16B16G16R16F, D3DFormatInfo( 64, 1, 1, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>))); + map.insert(D3D9FormatInfoPair(D3DFMT_R32F, D3DFormatInfo( 32, 1, 1, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_G32R32F, D3DFormatInfo( 64, 1, 1, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> ))); + map.insert(D3D9FormatInfoPair(D3DFMT_A32B32G32R32F, D3DFormatInfo(128, 1, 1, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>))); + + map.insert(D3D9FormatInfoPair(D3DFMT_D16, D3DFormatInfo( 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ))); + map.insert(D3D9FormatInfoPair(D3DFMT_D24S8, D3DFormatInfo( 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ))); + map.insert(D3D9FormatInfoPair(D3DFMT_D24X8, D3DFormatInfo( 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ))); + map.insert(D3D9FormatInfoPair(D3DFMT_D32, D3DFormatInfo( 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL ))); + + map.insert(D3D9FormatInfoPair(D3DFMT_INTZ, D3DFormatInfo( 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ))); + + map.insert(D3D9FormatInfoPair(D3DFMT_DXT1, D3DFormatInfo( 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ))); + map.insert(D3D9FormatInfoPair(D3DFMT_DXT3, D3DFormatInfo(128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ))); + map.insert(D3D9FormatInfoPair(D3DFMT_DXT5, D3DFormatInfo(128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ))); + + return map; +} + +static const D3D9FormatInfoMap &GetD3D9FormatInfoMap() +{ + static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); + return infoMap; +} + +static bool GetD3D9FormatInfo(D3DFORMAT format, D3DFormatInfo *outFormatInfo) +{ + const D3D9FormatInfoMap &infoMap = GetD3D9FormatInfoMap(); + D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + if (outFormatInfo) + { + *outFormatInfo = iter->second; + } + return true; + } + else + { + return false; + } +} +static d3d9::D3DFormatSet BuildAllD3DFormatSet() +{ + d3d9::D3DFormatSet set; + + const D3D9FormatInfoMap &infoMap = GetD3D9FormatInfoMap(); + for (D3D9FormatInfoMap::const_iterator i = infoMap.begin(); i != infoMap.end(); ++i) + { + set.insert(i->first); + } + + return set; +} + +struct D3D9FastCopyFormat +{ + D3DFORMAT mSourceFormat; + GLenum mDestFormat; + GLenum mDestType; + + D3D9FastCopyFormat(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType) + : mSourceFormat(sourceFormat), mDestFormat(destFormat), mDestType(destType) + { } + + bool operator<(const D3D9FastCopyFormat& other) const + { + return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; + } +}; + +typedef std::map<D3D9FastCopyFormat, ColorCopyFunction> D3D9FastCopyMap; +typedef std::pair<D3D9FastCopyFormat, ColorCopyFunction> D3D9FastCopyPair; + +static D3D9FastCopyMap BuildFastCopyMap() +{ + D3D9FastCopyMap map; + + map.insert(D3D9FastCopyPair(D3D9FastCopyFormat(D3DFMT_A8R8G8B8, GL_RGBA, GL_UNSIGNED_BYTE), CopyBGRAUByteToRGBAUByte)); + + return map; +} + +typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair; +typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap; + +static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() +{ + InternalFormatInitialzerMap map; + + map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>)); + map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>)); + + return map; +} + +static const InternalFormatInitialzerMap &GetInternalFormatInitialzerMap() +{ + static const InternalFormatInitialzerMap map = BuildInternalFormatInitialzerMap(); + return map; +} + +namespace d3d9 +{ + +MipGenerationFunction GetMipGenerationFunction(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mMipGenerationFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +LoadImageFunction GetImageLoadFunction(GLenum internalFormat) +{ + D3D9FormatInfo d3d9FormatInfo; + if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) + { + return d3d9FormatInfo.mLoadFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +GLuint GetFormatPixelBytes(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mPixelBits / 8; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockWidth(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mBlockWidth; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockHeight(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mBlockHeight; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockSize(D3DFORMAT format, GLuint width, GLuint height) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + GLuint numBlocksWide = (width + d3dFormatInfo.mBlockWidth - 1) / d3dFormatInfo.mBlockWidth; + GLuint numBlocksHight = (height + d3dFormatInfo.mBlockHeight - 1) / d3dFormatInfo.mBlockHeight; + + return (d3dFormatInfo.mPixelBits * numBlocksWide * numBlocksHight) / 8; + } + else + { + UNREACHABLE(); + return 0; + } +} + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + int upsampleCount = 0; + + GLsizei blockWidth = d3dFormatInfo.mBlockWidth; + GLsizei blockHeight = d3dFormatInfo.mBlockHeight; + + // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. + if (isImage || *requestWidth < blockWidth || *requestHeight < blockHeight) + { + while (*requestWidth % blockWidth != 0 || *requestHeight % blockHeight != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + *levelOffset = upsampleCount; + } +} + +const D3DFormatSet &GetAllUsedD3DFormats() +{ + static const D3DFormatSet formatSet = BuildAllD3DFormatSet(); + return formatSet; +} + +ColorReadFunction GetColorReadFunction(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mColorReadFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType) +{ + static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap(); + D3D9FastCopyMap::const_iterator iter = fastCopyMap.find(D3D9FastCopyFormat(sourceFormat, destFormat, destType)); + return (iter != fastCopyMap.end()) ? iter->second : NULL; +} + +GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) +{ + switch (declType) + { + case D3DDECLTYPE_FLOAT1: return GL_FLOAT; + case D3DDECLTYPE_FLOAT2: return GL_FLOAT; + case D3DDECLTYPE_FLOAT3: return GL_FLOAT; + case D3DDECLTYPE_FLOAT4: return GL_FLOAT; + case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT; + case D3DDECLTYPE_SHORT2: return GL_INT; + case D3DDECLTYPE_SHORT4: return GL_INT; + case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED; + default: UNREACHABLE(); return GL_NONE; + } +} + +// Attribute format conversion +enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + +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; +}; + +struct TranslationDescription +{ + DWORD capsFlag; + FormatConverter preferredConversion; + FormatConverter fallbackConversion; +}; + +static unsigned int typeIndex(GLenum type); +static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); + +bool mTranslationsInitialized = false; +FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + +// 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> : NoWiden<size> { }; +template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { }; +template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { }; +template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { }; +template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { }; +template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : 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 : 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> : Normalize<typename GLToCType<fromType>::type> { }; + +// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. +template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { }; +template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 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> : NormalizedDefaultValues<T> { }; +template <class T> struct DefaultVertexValuesStage2<T, false> : 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> : 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 + : 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 }; +}; + +// Initialize 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 TranslationDescription 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 InitializeVertexTranslations(const rx::Renderer9 *renderer) +{ + DWORD declTypes = renderer->getCapsDeclTypes(); + + 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) + { + mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; + } + else + { + mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; + } + } + } + } +} + +unsigned int typeIndex(GLenum type) +{ + 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; + } +} + +const FormatConverter &formatConverter(const gl::VertexFormat &vertexFormat) +{ + // Pure integer attributes only supported in ES3.0 + ASSERT(!vertexFormat.mPureInteger); + return mFormatConverters[typeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; +} + +VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat) +{ + return formatConverter(vertexFormat).convertArray; +} + +size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat) +{ + return formatConverter(vertexFormat).outputElementSize; +} + +VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat) +{ + return (formatConverter(vertexFormat).identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU); +} + +D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat) +{ + return formatConverter(vertexFormat).d3dDeclType; +} + +} + +namespace gl_d3d9 +{ + +D3DFORMAT GetTextureFormat(GLenum internalFormat) +{ + D3D9FormatInfo d3d9FormatInfo; + if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) + { + return d3d9FormatInfo.mTexFormat; + } + else + { + return D3DFMT_UNKNOWN; + } +} + +D3DFORMAT GetRenderFormat(GLenum internalFormat) +{ + D3D9FormatInfo d3d9FormatInfo; + if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) + { + return d3d9FormatInfo.mRenderFormat; + } + else + { + return D3DFMT_UNKNOWN; + } +} + +D3DMULTISAMPLE_TYPE GetMultisampleType(GLsizei samples) +{ + return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE; +} + +bool RequiresTextureDataInitialization(GLint internalFormat) +{ + const InternalFormatInitialzerMap &map = GetInternalFormatInitialzerMap(); + return map.find(internalFormat) != map.end(); +} + +InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat) +{ + const InternalFormatInitialzerMap &map = GetInternalFormatInitialzerMap(); + InternalFormatInitialzerMap::const_iterator iter = map.find(internalFormat); + if (iter != map.end()) + { + return iter->second; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +} + +namespace d3d9_gl +{ + +GLenum GetInternalFormat(D3DFORMAT format) +{ + static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); + D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + return iter->second.mInternalFormat; + } + else + { + UNREACHABLE(); + return GL_NONE; + } +} + +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) +{ + return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0; +} + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) +{ + GLenum internalFormat = d3d9_gl::GetInternalFormat(d3dformat); + GLenum convertedFormat = gl::GetFormat(internalFormat); + return convertedFormat == format; +} + +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h new file mode 100644 index 0000000000..26388794e0 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h @@ -0,0 +1,77 @@ +// +// Copyright (c) 2013-2014 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. +// + +// formatutils9.h: Queries for GL image formats and their translations to D3D9 +// formats. + +#ifndef LIBGLESV2_RENDERER_FORMATUTILS9_H_ +#define LIBGLESV2_RENDERER_FORMATUTILS9_H_ + +#include "libGLESv2/formatutils.h" + +namespace rx +{ + +class Renderer9; + +namespace d3d9 +{ + +typedef std::set<D3DFORMAT> D3DFormatSet; + +MipGenerationFunction GetMipGenerationFunction(D3DFORMAT format); +LoadImageFunction GetImageLoadFunction(GLenum internalFormat); + +GLuint GetFormatPixelBytes(D3DFORMAT format); +GLuint GetBlockWidth(D3DFORMAT format); +GLuint GetBlockHeight(D3DFORMAT format); +GLuint GetBlockSize(D3DFORMAT format, GLuint width, GLuint height); + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +const D3DFormatSet &GetAllUsedD3DFormats(); + +ColorReadFunction GetColorReadFunction(D3DFORMAT format); +ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType); + +VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat); +size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat); +VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat); +D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat); + +GLenum GetDeclTypeComponentType(D3DDECLTYPE declType); +int GetDeclTypeComponentCount(D3DDECLTYPE declType); +bool IsDeclTypeNormalized(D3DDECLTYPE declType); + +void InitializeVertexTranslations(const rx::Renderer9 *renderer); + +} + +namespace gl_d3d9 +{ + +D3DFORMAT GetTextureFormat(GLenum internalForma); +D3DFORMAT GetRenderFormat(GLenum internalFormat); + +D3DMULTISAMPLE_TYPE GetMultisampleType(GLsizei samples); + +bool RequiresTextureDataInitialization(GLint internalFormat); +InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat); + +} + +namespace d3d9_gl +{ + +GLenum GetInternalFormat(D3DFORMAT format); +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); + +} + +} + +#endif // LIBGLESV2_RENDERER_FORMATUTILS9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp new file mode 100644 index 0000000000..68e5378fbb --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp @@ -0,0 +1,409 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2014 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. +// + +// renderer9_utils.cpp: Conversion functions and other utility routines +// specific to the D3D9 renderer. + +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/formatutils.h" +#include "common/mathutil.h" +#include "libGLESv2/Context.h" + +#include "common/debug.h" + +#include "third_party/systeminfo/SystemInfo.h" + +namespace rx +{ + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison) +{ + D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; + switch (comparison) + { + case GL_NEVER: d3dComp = D3DCMP_NEVER; break; + case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; + case GL_LESS: d3dComp = D3DCMP_LESS; break; + case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; + case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; + case GL_GREATER: d3dComp = D3DCMP_GREATER; break; + case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; + case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3DCOLOR ConvertColor(gl::ColorF color) +{ + return D3DCOLOR_RGBA(gl::unorm<8>(color.red), + gl::unorm<8>(color.green), + gl::unorm<8>(color.blue), + gl::unorm<8>(color.alpha)); +} + +D3DBLEND ConvertBlendFunc(GLenum blend) +{ + D3DBLEND d3dBlend = D3DBLEND_ZERO; + + switch (blend) + { + case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; + case GL_ONE: d3dBlend = D3DBLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; + case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; + case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3DBLENDOP ConvertBlendOp(GLenum blendOp) +{ + D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; + + switch (blendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; + case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break; + case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) +{ + D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; + case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; + case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) +{ + D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; + + switch (wrap) + { + case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; + case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; + case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; + default: UNREACHABLE(); + } + + return d3dWrap; +} + +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) +{ + D3DCULL cull = D3DCULL_CCW; + switch (cullFace) + { + case GL_FRONT: + cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); + break; + case GL_BACK: + cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); + break; + case GL_FRONT_AND_BACK: + cull = D3DCULL_NONE; // culling will be handled during draw + break; + default: UNREACHABLE(); + } + + return cull; +} + +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) +{ + D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; + + 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_POSITIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + face = D3DCUBEMAP_FACE_NEGATIVE_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) | + (green ? D3DCOLORWRITEENABLE_GREEN : 0) | + (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | + (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); +} + +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) +{ + if (maxAnisotropy > 1.0f) + { + return D3DTEXF_ANISOTROPIC; + } + + D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; + switch (magFilter) + { + case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; + case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; + default: UNREACHABLE(); + } + + return d3dMagFilter; +} + +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) +{ + switch (minFilter) + { + case GL_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + default: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + UNREACHABLE(); + } + + if (maxAnisotropy > 1.0f) + { + *d3dMinFilter = D3DTEXF_ANISOTROPIC; + } +} + +} + +namespace d3d9_gl +{ + +static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType, + UINT adapter, D3DFORMAT adapterFormat) +{ + gl::TextureCaps textureCaps; + + D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat); + if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0) + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, renderFormat)); + textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, renderFormat)); + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, renderFormat)) || + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, renderFormat)); + } + else + { + D3DFORMAT textureFormat = gl_d3d9::GetTextureFormat(internalFormat); + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, textureFormat)) && + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, textureFormat)); + textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, textureFormat)); + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, textureFormat)) || + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, textureFormat)); + } + + textureCaps.sampleCounts.insert(1); + for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) + { + D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); + + HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, renderFormat, TRUE, multisampleType, NULL); + if (SUCCEEDED(result)) + { + textureCaps.sampleCounts.insert(i); + } + } + + return textureCaps; +} + +void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +{ + D3DCAPS9 deviceCaps; + if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps))) + { + // Can't continue with out device caps + return; + } + + D3DDISPLAYMODE currentDisplayMode; + d3d9->GetAdapterDisplayMode(adapter, ¤tDisplayMode); + + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter, + currentDisplayMode.Format); + textureCapsMap->insert(*internalFormat, textureCaps); + } + + // GL core feature limits + caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max()); + + // 3D textures are unimplemented in D3D9 + caps->max3DTextureSize = 1; + + // Only one limit in GL, use the minimum dimension + caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight); + + // D3D treats cube maps as a special case of 2D textures + caps->maxCubeMapTextureSize = caps->max2DTextureSize; + + // Array textures are not available in D3D9 + caps->maxArrayTextureLayers = 1; + + // ES3-only feature + caps->maxLODBias = 0.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Draw buffers are not supported in D3D9 + caps->maxDrawBuffers = 1; + caps->maxColorAttachments = 1; + + // No specific limits on viewport size, maximum 2D texture size is equivalent + caps->maxViewportWidth = caps->max2DTextureSize; + caps->maxViewportHeight = caps->maxViewportWidth; + + // Point size is clamped to 1.0f when the shader model is less than 3 + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f); + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16); + extensions->packedDepthStencil = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = false; + extensions->mapBuffer = false; + extensions->mapBufferRange = false; + + // ATI cards on XP have problems with non-power-of-two textures. + D3DADAPTER_IDENTIFIER9 adapterId = { 0 }; + if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId))) + { + extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && + !(isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); + } + else + { + extensions->textureNPOT = false; + } + + extensions->drawBuffers = false; + extensions->textureStorage = true; + + // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec + extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2; + extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy); + + // Check occlusion query support by trying to create one + IDirect3DQuery9 *occlusionQuery = NULL; + extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery; + SafeRelease(occlusionQuery); + + // Check event query support by trying to create one + IDirect3DQuery9 *eventQuery = NULL; + extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery; + SafeRelease(eventQuery); + + extensions->timerQuery = false; // Unimplemented + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = true; + extensions->framebufferMultisample = true; + extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; + extensions->shaderTextureLOD = true; + extensions->fragDepth = true; + extensions->textureUsage = true; + extensions->translatedShaderSource = true; + extensions->colorBufferFloat = false; +} + +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h index bf6cdf1ea6..7f3c65d3e0 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // @@ -10,16 +10,17 @@ #ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H #define LIBGLESV2_RENDERER_RENDERER9_UTILS_H -#include "libGLESv2/utilities.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); +namespace rx +{ namespace gl_d3d9 { D3DCMPFUNC ConvertComparison(GLenum comparison); -D3DCOLOR ConvertColor(gl::Color color); +D3DCOLOR ConvertColor(gl::ColorF color); D3DBLEND ConvertBlendFunc(GLenum blend); D3DBLENDOP ConvertBlendOp(GLenum blendOp); D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); @@ -29,31 +30,19 @@ D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); -D3DFORMAT ConvertRenderbufferFormat(GLenum format); -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); } namespace d3d9_gl { -GLuint GetAlphaSize(D3DFORMAT colorFormat); -GLuint GetStencilSize(D3DFORMAT stencilFormat); - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); -GLenum ConvertBackBufferFormat(D3DFORMAT format); -GLenum ConvertDepthStencilFormat(D3DFORMAT format); -GLenum ConvertRenderTargetFormat(D3DFORMAT format); -GLenum GetEquivalentFormat(D3DFORMAT format); +void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); } namespace d3d9 { -bool IsCompressedFormat(D3DFORMAT format); -size_t ComputeRowSize(D3DFORMAT format, unsigned int width); inline bool isDeviceLostError(HRESULT errorCode) { @@ -71,4 +60,6 @@ inline bool isDeviceLostError(HRESULT errorCode) } +} + #endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps new file mode 100644 index 0000000000..eb43eb3e7a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps @@ -0,0 +1,33 @@ +// +// 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. +// + +sampler2D tex : s0; + +uniform float4 mult : c0; +uniform float4 add : c1; + +// Passthrough Pixel Shader +// Outputs texture 0 sampled at texcoord 0. +float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR +{ + return tex2D(tex, texcoord.xy); +}; + +// Luminance Conversion Pixel Shader +// Performs a mad operation using the LA data from the texture with mult.xw and add.xw. +// Returns data in the form of llla +float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR +{ + return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy; +}; + +// RGB/A Component Mask Pixel Shader +// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw. +// Returns data in the form of rgba +float4 PS_componentmask(float4 texcoord : TEXCOORD0) : COLOR +{ + return tex2D(tex, texcoord.xy) * mult + add; +}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs index 3a36980b93..3bd611ba5d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs @@ -17,7 +17,7 @@ uniform float4 halfPixelSize : c0; // Outputs the homogenous position as-is. // Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right. // C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0. -VS_OUTPUT standardvs(in float4 position : POSITION) +VS_OUTPUT VS_standard(in float4 position : POSITION) { VS_OUTPUT Out; @@ -32,7 +32,7 @@ VS_OUTPUT standardvs(in float4 position : POSITION) // Outputs the homogenous position as-is. // Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right. // C0.XY must be the half-pixel width and height. C0.ZW must be 0. -VS_OUTPUT flipyvs(in float4 position : POSITION) +VS_OUTPUT VS_flipy(in float4 position : POSITION) { VS_OUTPUT Out; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp deleted file mode 100644 index 31d5b8b886..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp +++ /dev/null @@ -1,366 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 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. -// - -// BufferStorage11.cpp Defines the BufferStorage11 class. - -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -namespace rx -{ - -BufferStorage11::BufferStorage11(Renderer11 *renderer) -{ - mRenderer = renderer; - - mStagingBuffer = NULL; - mStagingBufferSize = 0; - - mSize = 0; - - mResolvedData = NULL; - mResolvedDataSize = 0; - mResolvedDataValid = false; - - mReadUsageCount = 0; - mWriteUsageCount = 0; -} - -BufferStorage11::~BufferStorage11() -{ - SafeRelease(mStagingBuffer); - - if (mResolvedData) - { - free(mResolvedData); - mResolvedData = NULL; - } - - for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++) - { - SafeDelete(it->second); - } -} - -BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); - return static_cast<BufferStorage11*>(bufferStorage); -} - -void *BufferStorage11::getData() -{ - ASSERT(mStagingBuffer); - - if (!mResolvedDataValid) - { - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - HRESULT result; - - if (!mResolvedData || mResolvedDataSize < mStagingBufferSize) - { - free(mResolvedData); - mResolvedData = malloc(mSize); - mResolvedDataSize = mSize; - } - - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); - } - - memcpy(mResolvedData, mappedResource.pData, mSize); - - context->Unmap(mStagingBuffer, 0); - - mResolvedDataValid = true; - } - - mReadUsageCount = 0; - - return mResolvedData; -} - -void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset) -{ - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - HRESULT result; - - const unsigned int requiredStagingBufferSize = size + offset; - const bool createStagingBuffer = !mStagingBuffer || mStagingBufferSize < requiredStagingBufferSize; - - if (createStagingBuffer) - { - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = requiredStagingBufferSize; - bufferDesc.Usage = D3D11_USAGE_STAGING; - bufferDesc.BindFlags = 0; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - HRESULT result; - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - ID3D11Buffer *newStagingBuffer; - - if (data && offset == 0) - { - D3D11_SUBRESOURCE_DATA initialData; - initialData.pSysMem = data; - initialData.SysMemPitch = requiredStagingBufferSize; - initialData.SysMemSlicePitch = 0; - - result = device->CreateBuffer(&bufferDesc, &initialData, &newStagingBuffer); - } - else - { - result = device->CreateBuffer(&bufferDesc, NULL, &newStagingBuffer); - } - - if (FAILED(result)) - { - mStagingBufferSize = 0; - return gl::error(GL_OUT_OF_MEMORY); - } - - mStagingBufferSize = requiredStagingBufferSize; - - if (mStagingBuffer && offset > 0) - { - // If offset is greater than zero and the buffer is non-null, need to preserve the data from - // the old buffer up to offset - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = std::min(offset, requiredStagingBufferSize); - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(newStagingBuffer, 0, 0, 0, 0, mStagingBuffer, 0, &srcBox); - } - - SafeRelease(mStagingBuffer); - mStagingBuffer = newStagingBuffer; - } - - if (data && (offset != 0 || !createStagingBuffer)) - { - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset; - memcpy(offsetBufferPointer, data, size); - - context->Unmap(mStagingBuffer, 0); - } - - for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++) - { - it->second->markDirty(); - } - - mSize = std::max(mSize, requiredStagingBufferSize); - mWriteUsageCount = 0; - - mResolvedDataValid = false; -} - -void BufferStorage11::copyData(BufferStorage* sourceStorage, unsigned int size, - unsigned int sourceOffset, unsigned int destOffset) -{ - BufferStorage11* source = makeBufferStorage11(sourceStorage); - if (source) - { - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_BOX srcBox; - srcBox.left = sourceOffset; - srcBox.right = sourceOffset + size; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - ASSERT(mStagingBuffer && source->mStagingBuffer); - context->CopySubresourceRegion(mStagingBuffer, 0, destOffset, 0, 0, source->mStagingBuffer, 0, &srcBox); - } -} - -void BufferStorage11::clear() -{ - mResolvedDataValid = false; - mSize = 0; -} - -unsigned int BufferStorage11::getSize() const -{ - return mSize; -} - -bool BufferStorage11::supportsDirectBinding() const -{ - return true; -} - -void BufferStorage11::markBufferUsage() -{ - mReadUsageCount++; - mWriteUsageCount++; - - const unsigned int usageLimit = 5; - - if (mReadUsageCount > usageLimit && mResolvedData) - { - free(mResolvedData); - mResolvedData = NULL; - mResolvedDataSize = 0; - mResolvedDataValid = false; - } -} - -ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage) -{ - markBufferUsage(); - - DirectBufferStorage11 *directBuffer = NULL; - - auto directBufferIt = mDirectBuffers.find(usage); - if (directBufferIt != mDirectBuffers.end()) - { - directBuffer = directBufferIt->second; - } - - if (directBuffer) - { - if (directBuffer->isDirty()) - { - // if updateFromStagingBuffer returns true, the D3D buffer has been recreated - // and we should update our serial - if (directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0)) - { - updateSerial(); - } - } - } - else - { - // buffer is not allocated, create it - directBuffer = new DirectBufferStorage11(mRenderer, usage); - directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0); - - mDirectBuffers.insert(std::make_pair(usage, directBuffer)); - updateSerial(); - } - - return directBuffer->getD3DBuffer(); -} - -DirectBufferStorage11::DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage) - : mRenderer(renderer), - mUsage(usage), - mDirectBuffer(NULL), - mBufferSize(0), - mDirty(false) -{ -} - -DirectBufferStorage11::~DirectBufferStorage11() -{ - SafeRelease(mDirectBuffer); -} - -BufferUsage DirectBufferStorage11::getUsage() const -{ - return mUsage; -} - -// Returns true if it recreates the direct buffer -bool DirectBufferStorage11::updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset) -{ - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - // unused for now - ASSERT(offset == 0); - - unsigned int requiredBufferSize = size + offset; - bool createBuffer = !mDirectBuffer || mBufferSize < requiredBufferSize; - - // (Re)initialize D3D buffer if needed - if (createBuffer) - { - D3D11_BUFFER_DESC bufferDesc; - fillBufferDesc(&bufferDesc, mRenderer, mUsage, requiredBufferSize); - - ID3D11Buffer *newBuffer; - HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); - - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY, false); - } - - // No longer need the old buffer - SafeRelease(mDirectBuffer); - mDirectBuffer = newBuffer; - - mBufferSize = bufferDesc.ByteWidth; - } - - // Copy data via staging buffer - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = size; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(mDirectBuffer, 0, offset, 0, 0, stagingBuffer, 0, &srcBox); - - mDirty = false; - - return createBuffer; -} - -void DirectBufferStorage11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize) -{ - bufferDesc->ByteWidth = bufferSize; - bufferDesc->MiscFlags = 0; - bufferDesc->StructureByteStride = 0; - - switch (usage) - { - case BUFFER_USAGE_VERTEX: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_INDEX: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc->CPUAccessFlags = 0; - break; - - default: - UNREACHABLE(); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h deleted file mode 100644 index a6afafe1b4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright (c) 2013 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. -// - -// BufferStorage11.h Defines the BufferStorage11 class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ -class Renderer; -class Renderer11; -class DirectBufferStorage11; - -enum BufferUsage -{ - BUFFER_USAGE_VERTEX, - BUFFER_USAGE_INDEX, -}; - -class BufferStorage11 : public BufferStorage -{ - public: - explicit BufferStorage11(Renderer11 *renderer); - virtual ~BufferStorage11(); - - static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage); - - virtual void *getData(); - virtual void setData(const void* data, unsigned int size, unsigned int offset); - virtual void copyData(BufferStorage* sourceStorage, unsigned int size, - unsigned int sourceOffset, unsigned int destOffset); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; - - ID3D11Buffer *getBuffer(BufferUsage usage); - - private: - Renderer11 *mRenderer; - - ID3D11Buffer *mStagingBuffer; - unsigned int mStagingBufferSize; - - std::map<BufferUsage, DirectBufferStorage11*> mDirectBuffers; - - unsigned int mSize; - - void *mResolvedData; - unsigned int mResolvedDataSize; - bool mResolvedDataValid; - - unsigned int mReadUsageCount; - unsigned int mWriteUsageCount; - - void markBufferUsage(); -}; - -// Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points -// - vertex buffers -// - index buffers -class DirectBufferStorage11 -{ - public: - DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage); - ~DirectBufferStorage11(); - - BufferUsage getUsage() const; - bool updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset); - - ID3D11Buffer *getD3DBuffer() { return mDirectBuffer; } - bool isDirty() const { return mDirty; } - void markDirty() { mDirty = true; } - - private: - Renderer11 *mRenderer; - const BufferUsage mUsage; - ID3D11Buffer *mDirectBuffer; - size_t mBufferSize; - bool mDirty; - - static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize); -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp deleted file mode 100644 index 2a7d4d43ef..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 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. -// - -// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. - -#include "libGLESv2/renderer/d3d11/Fence11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -namespace rx -{ - -Fence11::Fence11(rx::Renderer11 *renderer) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Fence11::~Fence11() -{ - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } -} - -GLboolean Fence11::isFence() -{ - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return mQuery != NULL; -} - -void Fence11::setFence(GLenum condition) -{ - if (!mQuery) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - - if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mRenderer->getDeviceContext()->End(mQuery); - - setCondition(condition); - setStatus(GL_FALSE); -} - -GLboolean Fence11::testFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } - - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0); - - if (mRenderer->isDeviceLost()) - { - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - return getStatus(); -} - -void Fence11::finishFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - while (!testFence()) - { - Sleep(0); - } -} - -void Fence11::getFenceiv(GLenum pname, GLint *params) -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV - // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - if (getStatus()) - { - params[0] = GL_TRUE; - return; - } - - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); - - if (mRenderer->isDeviceLost()) - { - params[0] = GL_TRUE; - return gl::error(GL_OUT_OF_MEMORY); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - params[0] = getStatus(); - - break; - } - case GL_FENCE_CONDITION_NV: - params[0] = getCondition(); - break; - default: - return gl::error(GL_INVALID_ENUM); - break; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp deleted file mode 100644 index 5d039a35e8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp +++ /dev/null @@ -1,498 +0,0 @@ -#include "precompiled.h" -// -// 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. -// - -// Image11.h: Implements the rx::Image11 class, which acts as the interface to -// the actual underlying resources of a Texture - -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/generatemip.h" - -namespace rx -{ - -Image11::Image11() -{ - mStagingTexture = NULL; - mRenderer = NULL; - mDXGIFormat = DXGI_FORMAT_UNKNOWN; -} - -Image11::~Image11() -{ - if (mStagingTexture) - { - mStagingTexture->Release(); - } -} - -Image11 *Image11::makeImage11(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); - return static_cast<rx::Image11*>(img); -} - -void Image11::generateMipmap(Image11 *dest, Image11 *src) -{ - ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); - ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); - ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); - - D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped; - dest->map(D3D11_MAP_WRITE, &destMapped); - src->map(D3D11_MAP_READ, &srcMapped); - - const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData); - unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData); - - if (sourceData && destData) - { - switch (src->getDXGIFormat()) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM: - GenerateMip<R8G8B8A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_A8_UNORM: - GenerateMip<A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R8_UNORM: - GenerateMip<R8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32B32A32_FLOAT: - GenerateMip<A32B32G32R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32B32_FLOAT: - GenerateMip<R32G32B32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16G16B16A16_FLOAT: - GenerateMip<A16B16G16R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R8G8_UNORM: - GenerateMip<R8G8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16_FLOAT: - GenerateMip<R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16G16_FLOAT: - GenerateMip<R16G16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32_FLOAT: - GenerateMip<R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32_FLOAT: - GenerateMip<R32G32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - default: - UNREACHABLE(); - break; - } - - dest->unmap(); - src->unmap(); - } - - dest->markDirty(); -} - -static bool FormatRequiresInitialization(DXGI_FORMAT dxgiFormat, GLenum internalFormat) -{ - return (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(internalFormat) == 0) || - (dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(internalFormat) == 0); -} - -bool Image11::isDirty() const -{ - return ((mStagingTexture || FormatRequiresInitialization(mDXGIFormat, mInternalFormat)) && mDirty); -} - -bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height); -} - -bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height); -} - -bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) -{ - if (mWidth != width || - mHeight != height || - mInternalFormat != internalformat || - forceRelease) - { - mRenderer = Renderer11::makeRenderer11(renderer); - - mWidth = width; - mHeight = height; - mInternalFormat = internalformat; - // compute the d3d format that will be used - mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat); - - if (mStagingTexture) - { - mStagingTexture->Release(); - mStagingTexture = NULL; - } - - return true; - } - - return false; -} - -bool Image11::isRenderableFormat() const -{ - return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat); -} - -DXGI_FORMAT Image11::getDXGIFormat() const -{ - // this should only happen if the image hasn't been redefined first - // which would be a bug by the caller - ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); - - return mDXGIFormat; -} - -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the target pixel rectangle. -void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) -{ - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) - { - ERR("Could not map image for loading."); - return; - } - - GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); - size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8; - void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize)); - - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: - if (mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0) - loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - else - loadAlphaDataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE8_EXT: - loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); - break; - case GL_ALPHA32F_EXT: - loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE32F_EXT: - loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_ALPHA16F_EXT: - loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE16F_EXT: - loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE8_ALPHA8_EXT: - loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); - break; - case GL_LUMINANCE_ALPHA32F_EXT: - loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE_ALPHA16F_EXT: - loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB8_OES: - loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB565: - loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA8_OES: - loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA4: - loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB5_A1: - loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_BGRA8_EXT: - loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB32F_EXT: - loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB16F_EXT: - loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA32F_EXT: - loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA16F_EXT: - loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - default: UNREACHABLE(); - } - - unmap(); -} - -void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input) -{ - ASSERT(xoffset % 4 == 0); - ASSERT(yoffset % 4 == 0); - - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) - { - ERR("Could not map image for loading."); - return; - } - - // Size computation assumes a 4x4 block compressed texture format - size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8; - void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize)); - - GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); - GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); - int rows = inputSize / inputPitch; - for (int i = 0; i < rows; ++i) - { - memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); - } - - unmap(); -} - -void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - gl::Renderbuffer *colorbuffer = source->getReadColorbuffer(); - - if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat) - { - // No conversion needed-- use copyback fastpath - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; - - if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) - { - D3D11_TEXTURE2D_DESC textureDesc; - colorBufferTexture->GetDesc(&textureDesc); - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - ID3D11Texture2D* srcTex = NULL; - if (textureDesc.SampleDesc.Count > 1) - { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); - if (FAILED(result)) - { - ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); - return; - } - - deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); - subresourceIndex = 0; - } - else - { - srcTex = colorBufferTexture; - srcTex->AddRef(); - } - - D3D11_BOX srcBox; - srcBox.left = x; - srcBox.right = x + width; - srcBox.top = y; - srcBox.bottom = y + height; - srcBox.front = 0; - srcBox.back = 1; - - deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox); - - srcTex->Release(); - colorBufferTexture->Release(); - } - } - else - { - // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - - // determine the offset coordinate into the destination buffer - GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset; - void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset; - - mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat), - gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset); - - unmap(); - } -} - -ID3D11Texture2D *Image11::getStagingTexture() -{ - createStagingTexture(); - - return mStagingTexture; -} - -unsigned int Image11::getStagingSubresource() -{ - createStagingTexture(); - - return mStagingSubresource; -} - -template <typename T, size_t N> -static void setDefaultData(ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, UINT subresource, - GLsizei width, GLsizei height, const T (&defaultData)[N]) -{ - D3D11_MAPPED_SUBRESOURCE map; - deviceContext->Map(texture, subresource, D3D11_MAP_WRITE, 0, &map); - - unsigned char* ptr = reinterpret_cast<unsigned char*>(map.pData); - size_t pixelSize = sizeof(T) * N; - - for (GLsizei y = 0; y < height; y++) - { - for (GLsizei x = 0; x < width; x++) - { - memcpy(ptr + (y * map.RowPitch) + (x * pixelSize), defaultData, pixelSize); - } - } - - deviceContext->Unmap(texture, subresource); -} - -void Image11::createStagingTexture() -{ - if (mStagingTexture) - { - return; - } - - ID3D11Texture2D *newTexture = NULL; - int lodOffset = 1; - const DXGI_FORMAT dxgiFormat = getDXGIFormat(); - ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures - - if (mWidth != 0 && mHeight != 0) - { - GLsizei width = mWidth; - GLsizei height = mHeight; - - // adjust size if needed for compressed textures - gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset); - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = lodOffset + 1; - desc.ArraySize = 1; - desc.Format = dxgiFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture); - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mStagingTexture = newTexture; - mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); - mDirty = false; - - if (mDXGIFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(mInternalFormat) == 0) - { - unsigned char defaultPixel[4] = { 0, 0, 0, 255 }; - setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel); - } - else if (mDXGIFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(mInternalFormat) == 0) - { - float defaultPixel[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel); - } -} - -HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) -{ - createStagingTexture(); - - HRESULT result = E_FAIL; - - if (mStagingTexture) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map); - - // this can fail if the device is removed (from TDR) - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - } - else if (SUCCEEDED(result)) - { - mDirty = true; - } - } - - return result; -} - -void Image11::unmap() -{ - if (mStagingTexture) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - deviceContext->Unmap(mStagingTexture, mStagingSubresource); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp deleted file mode 100644 index 24c0330a1e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 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. -// - -// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. - -#include "libGLESv2/renderer/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Query11::~Query11() -{ - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } -} - -void Query11::begin() -{ - if (mQuery == NULL) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_OCCLUSION; - queryDesc.MiscFlags = 0; - - if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mRenderer->getDeviceContext()->Begin(mQuery); -} - -void Query11::end() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - mRenderer->getDeviceContext()->End(mQuery); - - mStatus = GL_FALSE; - mResult = GL_FALSE; -} - -GLuint Query11::getResult() -{ - if (mQuery != NULL) - { - while (!testQuery()) - { - Sleep(0); - // explicitly check for device loss, some drivers seem to return S_FALSE - // if the device is lost - if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } - } - } - - return mResult; -} - -GLboolean Query11::isResultAvailable() -{ - if (mQuery != NULL) - { - testQuery(); - } - - return mStatus; -} - -GLboolean Query11::testQuery() -{ - if (mQuery != NULL && mStatus != GL_TRUE) - { - UINT64 numPixels = 0; - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0); - if (result == S_OK) - { - mStatus = GL_TRUE; - - switch (getType()) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; - break; - default: - UNREACHABLE(); - } - } - else if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - return mStatus; - } - - return GL_TRUE; // prevent blocking when query is null -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp deleted file mode 100644 index 0c981ac503..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp +++ /dev/null @@ -1,667 +0,0 @@ -#include "precompiled.h" -// -// 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. -// - -// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived -// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. - -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" - -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" - -#include "libGLESv2/utilities.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) - : mBindFlags(bindFlags), - mLodOffset(0), - mMipLevels(0), - mTexture(NULL), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), - mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), - mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), - mSRV(NULL), - mTextureWidth(0), - mTextureHeight(0) -{ - mRenderer = Renderer11::makeRenderer11(renderer); -} - -TextureStorage11::~TextureStorage11() -{ -} - -TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); - return static_cast<TextureStorage11*>(storage); -} - -DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable) -{ - UINT bindFlags = D3D11_BIND_SHADER_RESOURCE; - - if (d3d11::IsDepthStencilFormat(format)) - { - bindFlags |= D3D11_BIND_DEPTH_STENCIL; - } - else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) - { - bindFlags |= D3D11_BIND_RENDER_TARGET; - } - return bindFlags; -} - -bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) -{ - switch(format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_R8_UNORM: - case DXGI_FORMAT_R8G8_UNORM: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_R16G16_FLOAT: - return true; - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices - return false; - default: - UNREACHABLE(); - return false; - } -} - -UINT TextureStorage11::getBindFlags() const -{ - return mBindFlags; -} - -ID3D11Texture2D *TextureStorage11::getBaseTexture() const -{ - return mTexture; -} - -int TextureStorage11::getLodOffset() const -{ - return mLodOffset; -} - -bool TextureStorage11::isRenderTarget() const -{ - return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; -} - -bool TextureStorage11::isManaged() const -{ - return false; -} - -int TextureStorage11::levelCount() -{ - int levels = 0; - if (getBaseTexture()) - { - levels = mMipLevels - getLodOffset(); - } - return levels; -} - -UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex) -{ - UINT index = 0; - if (getBaseTexture()) - { - index = D3D11CalcSubresource(level, faceIndex, mMipLevels); - } - return index; -} - -bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource, - int level, int face, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height) -{ - if (srcTexture) - { - // Round up the width and height to the nearest multiple of dimension alignment - unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat); - width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment; - height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment; - - D3D11_BOX srcBox; - srcBox.left = xoffset; - srcBox.top = yoffset; - srcBox.right = xoffset + width; - srcBox.bottom = yoffset + height; - srcBox.front = 0; - srcBox.back = 1; - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - ASSERT(getBaseTexture()); - context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face), - xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox); - return true; - } - - return false; -} - -void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) -{ - if (source && dest) - { - ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); - ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); - - if (sourceSRV && destRTV) - { - gl::Rectangle sourceArea; - sourceArea.x = 0; - sourceArea.y = 0; - sourceArea.width = source->getWidth(); - sourceArea.height = source->getHeight(); - - gl::Rectangle destArea; - destArea.x = 0; - destArea.y = 0; - destArea.width = dest->getWidth(); - destArea.height = dest->getHeight(); - - mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), - destRTV, destArea, dest->getWidth(), dest->getHeight(), - GL_RGBA); - } - } -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) -{ - mTexture = swapchain->getOffscreenTexture(); - mSRV = swapchain->getRenderTargetShaderResource(); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mRenderTarget[i] = NULL; - } - - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - mMipLevels = texDesc.MipLevels; - mTextureFormat = texDesc.Format; - mTextureWidth = texDesc.Width; - mTextureHeight = texDesc.Height; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - mSRV->GetDesc(&srvDesc); - mShaderResourceFormat = srvDesc.Format; - - ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - offscreenRTV->GetDesc(&rtvDesc); - mRenderTargetFormat = rtvDesc.Format; - offscreenRTV->Release(); - - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) - : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) -{ - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mRenderTarget[i] = NULL; - } - - DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); - if (d3d11::IsDepthStencilFormat(convertedFormat)) - { - mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); - mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); - mDepthStencilFormat = convertedFormat; - mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; - } - else - { - mTextureFormat = convertedFormat; - mShaderResourceFormat = convertedFormat; - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - mRenderTargetFormat = convertedFormat; - } - - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - // adjust size if needed for compressed textures - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; // Compressed texture size constraints? - desc.Height = height; - desc.MipLevels = mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? ((levels > 0) ? levels + mLodOffset : 0) : 1; - desc.ArraySize = 1; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - gl::error(GL_OUT_OF_MEMORY); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - } - } -} - -TextureStorage11_2D::~TextureStorage11_2D() -{ - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mSRV) - { - mSRV->Release(); - mSRV = NULL; - } - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - delete mRenderTarget[i]; - mRenderTarget[i] = NULL; - } -} - -TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); - return static_cast<TextureStorage11_2D*>(storage); -} - -RenderTarget *TextureStorage11_2D::getRenderTarget(int level) -{ - if (level >= 0 && level < static_cast<int>(mMipLevels)) - { - if (!mRenderTarget[level]) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MostDetailedMip = level; - srvDesc.Texture2D.MipLevels = level ? 1 : -1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); - } - ASSERT(SUCCEEDED(result)); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = level; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = level; - dsvDesc.Flags = 0; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else - { - UNREACHABLE(); - } - } - - return mRenderTarget[level]; - } - else - { - return NULL; - } -} - -ID3D11ShaderResourceView *TextureStorage11_2D::getSRV() -{ - if (!mSRV) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); - srvDesc.Texture2D.MostDetailedMip = 0; - - HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL)); - } - ASSERT(SUCCEEDED(result)); - } - - return mSRV; -} - -void TextureStorage11_2D::generateMipmap(int level) -{ - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); - - generateMipmapLayer(source, dest); -} - -TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) - : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) -{ - for (unsigned int i = 0; i < 6; i++) - { - for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) - { - mRenderTarget[i][j] = NULL; - } - } - - DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); - if (d3d11::IsDepthStencilFormat(convertedFormat)) - { - mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); - mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); - mDepthStencilFormat = convertedFormat; - mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; - } - else - { - mTextureFormat = convertedFormat; - mShaderResourceFormat = convertedFormat; - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - mRenderTargetFormat = convertedFormat; - } - - // if the size is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (size > 0) - { - // adjust size if needed for compressed textures - int height = size; - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = size; - desc.Height = size; - desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; - desc.ArraySize = 6; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - } - } -} - -TextureStorage11_Cube::~TextureStorage11_Cube() -{ - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mSRV) - { - mSRV->Release(); - mSRV = NULL; - } - - for (unsigned int i = 0; i < 6; i++) - { - for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) - { - delete mRenderTarget[i][j]; - mRenderTarget[i][j] = NULL; - } - } -} - -TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); - return static_cast<TextureStorage11_Cube*>(storage); -} - -RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level) -{ - unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget); - if (level >= 0 && level < static_cast<int>(mMipLevels)) - { - if (!mRenderTarget[faceIdx][level]) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube - srvDesc.Texture2DArray.MostDetailedMip = level; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = faceIdx; - srvDesc.Texture2DArray.ArraySize = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); - } - ASSERT(SUCCEEDED(result)); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = level; - rtvDesc.Texture2DArray.FirstArraySlice = faceIdx; - rtvDesc.Texture2DArray.ArraySize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mRenderTargetFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsvDesc.Texture2DArray.MipSlice = level; - dsvDesc.Texture2DArray.FirstArraySlice = faceIdx; - dsvDesc.Texture2DArray.ArraySize = 1; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else - { - UNREACHABLE(); - } - } - - return mRenderTarget[faceIdx][level]; - } - else - { - return NULL; - } -} - -ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV() -{ - if (!mSRV) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); - srvDesc.TextureCube.MostDetailedMip = 0; - - HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL)); - } - ASSERT(SUCCEEDED(result)); - } - - return mSRV; -} - -void TextureStorage11_Cube::generateMipmap(int face, int level) -{ - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level)); - - generateMipmapLayer(source, dest); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h deleted file mode 100644 index 3c5ded05b8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// 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. -// - -// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived -// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. - -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ - -#include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/TextureStorage.h" - -namespace rx -{ -class RenderTarget; -class RenderTarget11; -class Renderer; -class Renderer11; -class SwapChain11; - -class TextureStorage11 : public TextureStorage -{ - public: - TextureStorage11(Renderer *renderer, UINT bindFlags); - virtual ~TextureStorage11(); - - static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); - - static DWORD GetTextureBindFlags(DXGI_FORMAT d3dfmt, GLenum glusage, bool forceRenderable); - static bool IsTextureFormatRenderable(DXGI_FORMAT format); - - UINT getBindFlags() const; - - virtual ID3D11Texture2D *getBaseTexture() const; - virtual ID3D11ShaderResourceView *getSRV() = 0; - virtual RenderTarget *getRenderTarget() { return getRenderTarget(0); } - virtual RenderTarget *getRenderTarget(int level) { return NULL; } - virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return getRenderTarget(faceTarget, 0); } - virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level) { return NULL; } - - virtual void generateMipmap(int level) {}; - virtual void generateMipmap(int face, int level) {}; - - virtual int getLodOffset() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int levelCount(); - UINT getSubresourceIndex(int level, int faceTarget); - - bool updateSubresourceLevel(ID3D11Texture2D *texture, unsigned int sourceSubresource, int level, - int faceTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - protected: - void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); - - Renderer11 *mRenderer; - int mLodOffset; - unsigned int mMipLevels; - - ID3D11Texture2D *mTexture; - DXGI_FORMAT mTextureFormat; - DXGI_FORMAT mShaderResourceFormat; - DXGI_FORMAT mRenderTargetFormat; - DXGI_FORMAT mDepthStencilFormat; - unsigned int mTextureWidth; - unsigned int mTextureHeight; - - ID3D11ShaderResourceView *mSRV; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11); - - const UINT mBindFlags; -}; - -class TextureStorage11_2D : public TextureStorage11 -{ - public: - TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain); - TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual ~TextureStorage11_2D(); - - static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); - - virtual ID3D11ShaderResourceView *getSRV(); - virtual RenderTarget *getRenderTarget(int level); - - virtual void generateMipmap(int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); - - RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureStorage11_Cube : public TextureStorage11 -{ - public: - TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - virtual ~TextureStorage11_Cube(); - - static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); - - virtual ID3D11ShaderResourceView *getSRV(); - virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level); - - virtual void generateMipmap(int face, int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); - - RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp deleted file mode 100644 index 6f9b4181f1..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp +++ /dev/null @@ -1,440 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 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. -// - -// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. - -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/BufferStorage.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/Context.h" - -namespace rx -{ - -VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) -{ - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; -} - -VertexBuffer11::~VertexBuffer11() -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } -} - -bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } - - updateSerial(); - - if (size > 0) - { - ID3D11Device* dxDevice = mRenderer->getDevice(); - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = size; - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return false; - } - } - - mBufferSize = size; - mDynamicUsage = dynamicUsage; - return true; -} - -VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); - return static_cast<VertexBuffer11*>(vetexBuffer); -} - -bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, - GLsizei instances, unsigned int offset) -{ - if (mBuffer) - { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - - int inputStride = attrib.stride(); - const VertexConverter &converter = getVertexConversion(attrib); - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - char* output = reinterpret_cast<char*>(mappedResource.pData) + offset; - - const char *input = NULL; - if (buffer) - { - BufferStorage *storage = buffer->getStorage(); - input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset); - } - else - { - input = static_cast<const char*>(attrib.mPointer); - } - - if (instances == 0 || attrib.mDivisor == 0) - { - input += inputStride * start; - } - - converter.conversionFunc(input, inputStride, count, output); - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset) -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - char* bufferData = static_cast<char*>(mappedResource.pData); - memcpy(bufferData + offset, data, size); - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances, unsigned int *outSpaceRequired) const -{ - unsigned int elementSize = getVertexConversion(attrib).outputElementSize; - - unsigned int elementCount = 0; - if (instances == 0 || attrib.mDivisor == 0) - { - elementCount = count; - } - else - { - if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1)) - { - // Round up - elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; - } - else - { - elementCount = instances / attrib.mDivisor; - } - } - - if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return true; - } - else - { - return false; - } -} - -bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const -{ - return !getVertexConversion(attrib).identity; -} - -unsigned int VertexBuffer11::getBufferSize() const -{ - return mBufferSize; -} - -bool VertexBuffer11::setBufferSize(unsigned int size) -{ - if (size > mBufferSize) - { - return initialize(size, mDynamicUsage); - } - else - { - return true; - } -} - -bool VertexBuffer11::discard() -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const -{ - return getVertexConversion(attrib).outputElementSize; -} - -DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const -{ - return getVertexConversion(attrib).dxgiFormat; -} - -ID3D11Buffer *VertexBuffer11::getBuffer() const -{ - return mBuffer; -} - -template <typename T, unsigned int componentCount, bool widen, bool normalized> -static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output) -{ - unsigned int attribSize = sizeof(T) * componentCount; - - if (attribSize == stride && !widen) - { - memcpy(output, input, count * attribSize); - } - else - { - unsigned int outputStride = widen ? 4 : componentCount; - T defaultVal = normalized ? std::numeric_limits<T>::max() : T(1); - - for (unsigned int i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + i * stride); - T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride; - - for (unsigned int j = 0; j < componentCount; j++) - { - offsetOutput[j] = offsetInput[j]; - } - - if (widen) - { - offsetOutput[3] = defaultVal; - } - } - } -} - -template <unsigned int componentCount> -static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output) -{ - static const float divisor = 1.0f / (1 << 16); - - for (unsigned int i = 0; i < count; i++) - { - const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(reinterpret_cast<const char*>(input) + stride * i); - float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount; - - for (unsigned int j = 0; j < componentCount; j++) - { - offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor; - } - } -} - -template <typename T, unsigned int componentCount, bool normalized> -static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output) -{ - typedef std::numeric_limits<T> NL; - - for (unsigned int i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + stride * i); - float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount; - - for (unsigned int j = 0; j < componentCount; j++) - { - if (normalized) - { - if (NL::is_signed) - { - const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1); - offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor; - } - else - { - offsetOutput[j] = static_cast<float>(offsetInput[j]) / NL::max(); - } - } - else - { - offsetOutput[j] = static_cast<float>(offsetInput[j]); - } - } - } -} - -const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = -{ - { // GL_BYTE - { // unnormalized - { ©ToFloatVertexData<GLbyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData<GLbyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData<GLbyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData<GLbyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData<GLbyte, 1, false, true>, true, DXGI_FORMAT_R8_SNORM, 1 }, - { ©VertexData<GLbyte, 2, false, true>, true, DXGI_FORMAT_R8G8_SNORM, 2 }, - { ©VertexData<GLbyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, - { ©VertexData<GLbyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, - }, - }, - { // GL_UNSIGNED_BYTE - { // unnormalized - { ©ToFloatVertexData<GLubyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData<GLubyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData<GLubyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData<GLubyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData<GLubyte, 1, false, true>, true, DXGI_FORMAT_R8_UNORM, 1 }, - { ©VertexData<GLubyte, 2, false, true>, true, DXGI_FORMAT_R8G8_UNORM, 2 }, - { ©VertexData<GLubyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, - { ©VertexData<GLubyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, - }, - }, - { // GL_SHORT - { // unnormalized - { ©ToFloatVertexData<GLshort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData<GLshort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData<GLshort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData<GLshort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData<GLshort, 1, false, true>, true, DXGI_FORMAT_R16_SNORM, 2 }, - { ©VertexData<GLshort, 2, false, true>, true, DXGI_FORMAT_R16G16_SNORM, 4 }, - { ©VertexData<GLshort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, - { ©VertexData<GLshort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, - }, - }, - { // GL_UNSIGNED_SHORT - { // unnormalized - { ©ToFloatVertexData<GLushort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData<GLushort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData<GLushort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData<GLushort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData<GLushort, 1, false, true>, true, DXGI_FORMAT_R16_UNORM, 2 }, - { ©VertexData<GLushort, 2, false, true>, true, DXGI_FORMAT_R16G16_UNORM, 4 }, - { ©VertexData<GLushort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, - { ©VertexData<GLushort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, - }, - }, - { // GL_FIXED - { // unnormalized - { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - }, - { // GL_FLOAT - { // unnormalized - { ©VertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©VertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©VertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©VertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©VertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©VertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©VertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - }, -}; - -const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute) -{ - unsigned int typeIndex = 0; - switch (attribute.mType) - { - case GL_BYTE: typeIndex = 0; break; - case GL_UNSIGNED_BYTE: typeIndex = 1; break; - case GL_SHORT: typeIndex = 2; break; - case GL_UNSIGNED_SHORT: typeIndex = 3; break; - case GL_FIXED: typeIndex = 4; break; - case GL_FLOAT: typeIndex = 5; break; - default: UNREACHABLE(); break; - } - - return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1]; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp deleted file mode 100644 index 34b8259a80..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp +++ /dev/null @@ -1,688 +0,0 @@ -#include "precompiled.h" -// -// 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. -// - -// renderer11_utils.cpp: Conversion functions and other utility routines -// specific to the D3D11 renderer. - -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" - -#include "common/debug.h" - -namespace gl_d3d11 -{ - -D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) -{ - D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; - - switch (glBlend) - { - case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break; - case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break; - case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break; - case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; - default: UNREACHABLE(); - } - - return d3dBlend; -} - -D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) -{ - D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; - - switch (glBlendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break; - default: UNREACHABLE(); - } - - return d3dBlendOp; -} - -UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) -{ - UINT8 mask = 0; - if (red) - { - mask |= D3D11_COLOR_WRITE_ENABLE_RED; - } - if (green) - { - mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; - } - if (blue) - { - mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; - } - if (alpha) - { - mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; - } - return mask; -} - -D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) -{ - D3D11_CULL_MODE cull = D3D11_CULL_NONE; - - if (cullEnabled) - { - switch (cullMode) - { - case GL_FRONT: cull = D3D11_CULL_FRONT; break; - case GL_BACK: cull = D3D11_CULL_BACK; break; - case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break; - default: UNREACHABLE(); - } - } - else - { - cull = D3D11_CULL_NONE; - } - - return cull; -} - -D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) -{ - D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; - switch (comparison) - { - case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break; - case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break; - case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break; - case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break; - case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break; - case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break; - case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break; - case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break; - default: UNREACHABLE(); - } - - return d3dComp; -} - -D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) -{ - return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; -} - -UINT8 ConvertStencilMask(GLuint stencilmask) -{ - return static_cast<UINT8>(stencilmask); -} - -D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) -{ - D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; - - switch (stencilOp) - { - case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break; - case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break; - case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break; - default: UNREACHABLE(); - } - - return d3dStencilOp; -} - -D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) -{ - if (maxAnisotropy > 1.0f) - { - return D3D11_ENCODE_ANISOTROPIC_FILTER(false); - } - else - { - D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; - D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; - switch (minFilter) - { - case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break; - case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break; - default: UNREACHABLE(); - } - - D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; - switch (magFilter) - { - case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break; - default: UNREACHABLE(); - } - - return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, false); - } -} - -D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) -{ - switch (wrap) - { - case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP; - case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP; - case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR; - default: UNREACHABLE(); - } - - return D3D11_TEXTURE_ADDRESS_WRAP; -} - -FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset) -{ - return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : -FLT_MAX; -} - -FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset) -{ - return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : FLT_MAX; -} - -} - -namespace d3d11_gl -{ - -GLenum ConvertBackBufferFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES; - case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -GLenum ConvertDepthStencilFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_UNKNOWN: return GL_NONE; - case DXGI_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(); - } - - return GL_DEPTH24_STENCIL8_OES; -} - -GLenum ConvertRenderbufferFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_B8G8R8A8_UNORM: - return GL_BGRA8_EXT; - case DXGI_FORMAT_R8G8B8A8_UNORM: - return GL_RGBA8_OES; - case DXGI_FORMAT_D16_UNORM: - return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: - return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -GLenum ConvertTextureInternalFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - return GL_RGBA8_OES; - case DXGI_FORMAT_A8_UNORM: - return GL_ALPHA8_EXT; - case DXGI_FORMAT_BC1_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - case DXGI_FORMAT_BC2_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - case DXGI_FORMAT_BC3_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - case DXGI_FORMAT_R32G32B32A32_FLOAT: - return GL_RGBA32F_EXT; - case DXGI_FORMAT_R32G32B32_FLOAT: - return GL_RGB32F_EXT; - case DXGI_FORMAT_R16G16B16A16_FLOAT: - return GL_RGBA16F_EXT; - case DXGI_FORMAT_B8G8R8A8_UNORM: - return GL_BGRA8_EXT; - case DXGI_FORMAT_R8_UNORM: - return GL_R8_EXT; - case DXGI_FORMAT_R8G8_UNORM: - return GL_RG8_EXT; - case DXGI_FORMAT_R16_FLOAT: - return GL_R16F_EXT; - case DXGI_FORMAT_R16G16_FLOAT: - return GL_RG16F_EXT; - case DXGI_FORMAT_D16_UNORM: - return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: - return GL_DEPTH24_STENCIL8_OES; - case DXGI_FORMAT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -} - -namespace gl_d3d11 -{ - -DXGI_FORMAT ConvertRenderbufferFormat(GLenum format) -{ - switch (format) - { - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8_OES: - case GL_RGB565: - case GL_RGB8_OES: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case GL_BGRA8_EXT: - return DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_DEPTH_COMPONENT16: - return DXGI_FORMAT_D16_UNORM; - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: - return DXGI_FORMAT_D24_UNORM_S8_UINT; - default: - UNREACHABLE(); - } - - return DXGI_FORMAT_R8G8B8A8_UNORM; -} - -DXGI_FORMAT ConvertTextureFormat(GLenum internalformat, D3D_FEATURE_LEVEL featureLevel) -{ - switch (internalformat) - { - case GL_RGB565: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB8_OES: - case GL_RGBA8_OES: - case GL_LUMINANCE8_EXT: - case GL_LUMINANCE8_ALPHA8_EXT: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case GL_ALPHA8_EXT: - return featureLevel >= D3D_FEATURE_LEVEL_10_0 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return DXGI_FORMAT_BC1_UNORM; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - return DXGI_FORMAT_BC2_UNORM; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return DXGI_FORMAT_BC3_UNORM; - case GL_RGBA32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - case GL_RGB32F_EXT: - case GL_LUMINANCE32F_EXT: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - case GL_RGBA16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - case GL_RGB16F_EXT: - case GL_LUMINANCE16F_EXT: - return DXGI_FORMAT_R16G16B16A16_FLOAT; - case GL_BGRA8_EXT: - return DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_R8_EXT: - return DXGI_FORMAT_R8_UNORM; - case GL_RG8_EXT: - return DXGI_FORMAT_R8G8_UNORM; - case GL_R16F_EXT: - return DXGI_FORMAT_R16_FLOAT; - case GL_RG16F_EXT: - return DXGI_FORMAT_R16G16_FLOAT; - case GL_DEPTH_COMPONENT16: - return DXGI_FORMAT_D16_UNORM; - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - return DXGI_FORMAT_D24_UNORM_S8_UINT; - case GL_NONE: - return DXGI_FORMAT_UNKNOWN; - default: - UNREACHABLE(); - } - - return DXGI_FORMAT_R8G8B8A8_UNORM; -} - -} - -namespace d3d11 -{ - -void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) -{ - vertex->x = x; - vertex->y = y; - vertex->u = u; - vertex->v = v; -} - -void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, - const gl::Color &color) -{ - vertex->x = x; - vertex->y = y; - vertex->z = z; - vertex->r = color.red; - vertex->g = color.green; - vertex->b = color.blue; - vertex->a = color.alpha; -} - -size_t ComputePixelSizeBits(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R1_UNORM: - return 1; - - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_R8_SINT: - case DXGI_FORMAT_R8_SNORM: - case DXGI_FORMAT_R8_TYPELESS: - case DXGI_FORMAT_R8_UINT: - case DXGI_FORMAT_R8_UNORM: - return 8; - - case DXGI_FORMAT_B5G5R5A1_UNORM: - case DXGI_FORMAT_B5G6R5_UNORM: - case DXGI_FORMAT_D16_UNORM: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_R16_SINT: - case DXGI_FORMAT_R16_SNORM: - case DXGI_FORMAT_R16_TYPELESS: - case DXGI_FORMAT_R16_UINT: - case DXGI_FORMAT_R16_UNORM: - case DXGI_FORMAT_R8G8_SINT: - case DXGI_FORMAT_R8G8_SNORM: - case DXGI_FORMAT_R8G8_TYPELESS: - case DXGI_FORMAT_R8G8_UINT: - case DXGI_FORMAT_R8G8_UNORM: - return 16; - - case DXGI_FORMAT_B8G8R8X8_TYPELESS: - case DXGI_FORMAT_B8G8R8X8_UNORM: - case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_G8R8_G8B8_UNORM: - case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: - case DXGI_FORMAT_R10G10B10A2_TYPELESS: - case DXGI_FORMAT_R10G10B10A2_UINT: - case DXGI_FORMAT_R10G10B10A2_UNORM: - case DXGI_FORMAT_R11G11B10_FLOAT: - case DXGI_FORMAT_R16G16_FLOAT: - case DXGI_FORMAT_R16G16_SINT: - case DXGI_FORMAT_R16G16_SNORM: - case DXGI_FORMAT_R16G16_TYPELESS: - case DXGI_FORMAT_R16G16_UINT: - case DXGI_FORMAT_R16G16_UNORM: - case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: - case DXGI_FORMAT_R24G8_TYPELESS: - case DXGI_FORMAT_R32_FLOAT: - case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: - case DXGI_FORMAT_R32_SINT: - case DXGI_FORMAT_R32_TYPELESS: - case DXGI_FORMAT_R32_UINT: - case DXGI_FORMAT_R8G8_B8G8_UNORM: - case DXGI_FORMAT_R8G8B8A8_SINT: - case DXGI_FORMAT_R8G8B8A8_SNORM: - case DXGI_FORMAT_R8G8B8A8_TYPELESS: - case DXGI_FORMAT_R8G8B8A8_UINT: - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - case DXGI_FORMAT_B8G8R8A8_TYPELESS: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: - case DXGI_FORMAT_X24_TYPELESS_G8_UINT: - case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: - return 32; - - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_R16G16B16A16_SINT: - case DXGI_FORMAT_R16G16B16A16_SNORM: - case DXGI_FORMAT_R16G16B16A16_TYPELESS: - case DXGI_FORMAT_R16G16B16A16_UINT: - case DXGI_FORMAT_R16G16B16A16_UNORM: - case DXGI_FORMAT_R32G32_FLOAT: - case DXGI_FORMAT_R32G32_SINT: - case DXGI_FORMAT_R32G32_TYPELESS: - case DXGI_FORMAT_R32G32_UINT: - case DXGI_FORMAT_R32G8X24_TYPELESS: - return 64; - - case DXGI_FORMAT_R32G32B32_FLOAT: - case DXGI_FORMAT_R32G32B32_SINT: - case DXGI_FORMAT_R32G32B32_TYPELESS: - case DXGI_FORMAT_R32G32B32_UINT: - return 96; - - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R32G32B32A32_SINT: - case DXGI_FORMAT_R32G32B32A32_TYPELESS: - case DXGI_FORMAT_R32G32B32A32_UINT: - return 128; - - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - return 4; - - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 8; - - default: - return 0; - } -} - -size_t ComputeBlockSizeBits(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return ComputePixelSizeBits(format) * 16; - default: - UNREACHABLE(); - return 0; - } -} - -bool IsCompressed(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return true; - case DXGI_FORMAT_UNKNOWN: - UNREACHABLE(); - return false; - default: - return false; - } -} - -unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 4; - case DXGI_FORMAT_UNKNOWN: - UNREACHABLE(); - return 1; - default: - return 1; - } -} - -bool IsDepthStencilFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_D16_UNORM: - return true; - default: - return false; - } -} - -DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS; - case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_TYPELESS; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24G8_TYPELESS; - case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_TYPELESS; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } -} - -DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; - case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_UINT; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; - case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_UNORM; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } -} - -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) -{ -#if defined(_DEBUG) - return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); -#else - return S_OK; -#endif -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h deleted file mode 100644 index 70ad4fea2b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// 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. -// - -// renderer11_utils.h: Conversion functions and other utility routines -// specific to the D3D11 renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H -#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H - -#include "libGLESv2/angletypes.h" - -namespace gl_d3d11 -{ - -D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); -D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); -UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); - -D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); - -D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); -D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); -UINT8 ConvertStencilMask(GLuint stencilmask); -D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); - -D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy); -D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); -FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset); -FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset); - -DXGI_FORMAT ConvertRenderbufferFormat(GLenum format); -DXGI_FORMAT ConvertTextureFormat(GLenum format, D3D_FEATURE_LEVEL featureLevel); -} - -namespace d3d11_gl -{ - -GLenum ConvertBackBufferFormat(DXGI_FORMAT format); -GLenum ConvertDepthStencilFormat(DXGI_FORMAT format); -GLenum ConvertRenderbufferFormat(DXGI_FORMAT format); -GLenum ConvertTextureInternalFormat(DXGI_FORMAT format); - -} - -namespace d3d11 -{ - -struct PositionTexCoordVertex -{ - float x, y; - float u, v; -}; -void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); - -struct PositionDepthColorVertex -{ - float x, y, z; - float r, g, b, a; -}; -void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, - const gl::Color &color); - -size_t ComputePixelSizeBits(DXGI_FORMAT format); -size_t ComputeBlockSizeBits(DXGI_FORMAT format); - -bool IsCompressed(DXGI_FORMAT format); -unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format); - -bool IsDepthStencilFormat(DXGI_FORMAT format); -DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format); -DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format); - -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); - -inline bool isDeviceLostError(HRESULT errorCode) -{ - switch (errorCode) - { - case DXGI_ERROR_DEVICE_HUNG: - case DXGI_ERROR_DEVICE_REMOVED: - case DXGI_ERROR_DEVICE_RESET: - case DXGI_ERROR_DRIVER_INTERNAL_ERROR: - case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: - return true; - default: - return false; - } -} - -} - -#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl deleted file mode 100644 index cb132dc99c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl +++ /dev/null @@ -1,42 +0,0 @@ -void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) -{ - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} - -// Assume we are in SM4+, which has 8 color outputs -struct PS_OutputMultiple -{ - float4 color0 : SV_TARGET0; - float4 color1 : SV_TARGET1; - float4 color2 : SV_TARGET2; - float4 color3 : SV_TARGET3; -#ifdef SM4 - float4 color4 : SV_TARGET4; - float4 color5 : SV_TARGET5; - float4 color6 : SV_TARGET6; - float4 color7 : SV_TARGET7; -#endif -}; - -PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) -{ - PS_OutputMultiple outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; -#ifdef SM4 - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; -#endif - return outColor; -} - -float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0 -{ - return inColor; -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl deleted file mode 100644 index 43b7801efc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl +++ /dev/null @@ -1,29 +0,0 @@ -Texture2D Texture : register(t0); -SamplerState Sampler : register(s0); - -void VS_Passthrough( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0, - out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0) -{ - outPosition = float4(inPosition, 0.0f, 1.0f); - outTexCoord = inTexCoord; -} - -float4 PS_PassthroughRGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return Texture.Sample(Sampler, inTexCoord).rgba; -} - -float4 PS_PassthroughRGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(Texture.Sample(Sampler, inTexCoord).rgb, 1.0f); -} - -float4 PS_PassthroughLum(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(Texture.Sample(Sampler, inTexCoord).rrr, 1.0f); -} - -float4 PS_PassthroughLumAlpha(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return Texture.Sample(Sampler, inTexCoord).rrra; -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp deleted file mode 100644 index 9fdc1246f1..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 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. -// - -// BufferStorage9.cpp Defines the BufferStorage9 class. - -#include "libGLESv2/renderer/d3d9/BufferStorage9.h" -#include "common/debug.h" - -namespace rx -{ - -BufferStorage9::BufferStorage9() -{ - mMemory = NULL; - mAllocatedSize = 0; - mSize = 0; -} - -BufferStorage9::~BufferStorage9() -{ - delete[] mMemory; -} - -BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage)); - return static_cast<BufferStorage9*>(bufferStorage); -} - -void *BufferStorage9::getData() -{ - return mMemory; -} - -void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset) -{ - if (!mMemory || offset + size > mAllocatedSize) - { - unsigned int newAllocatedSize = offset + size; - void *newMemory = new char[newAllocatedSize]; - - if (offset > 0 && mMemory && mAllocatedSize > 0) - { - memcpy(newMemory, mMemory, std::min(offset, mAllocatedSize)); - } - - delete[] mMemory; - mMemory = newMemory; - mAllocatedSize = newAllocatedSize; - } - - mSize = std::max(mSize, offset + size); - if (data) - { - memcpy(reinterpret_cast<char*>(mMemory) + offset, data, size); - } -} - -void BufferStorage9::clear() -{ - mSize = 0; -} - -unsigned int BufferStorage9::getSize() const -{ - return mSize; -} - -bool BufferStorage9::supportsDirectBinding() const -{ - return false; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h deleted file mode 100644 index 3e803969bc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2013 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. -// - -// BufferStorage9.h Defines the BufferStorage9 class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ - -class BufferStorage9 : public BufferStorage -{ - public: - BufferStorage9(); - virtual ~BufferStorage9(); - - static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage); - - virtual void *getData(); - virtual void setData(const void* data, unsigned int size, unsigned int offset); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; - - private: - DISALLOW_COPY_AND_ASSIGN(BufferStorage9); - - void *mMemory; - unsigned int mAllocatedSize; - - unsigned int mSize; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp deleted file mode 100644 index 639c37b4e4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 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. -// - -// Fence9.cpp: Defines the rx::Fence9 class. - -#include "libGLESv2/renderer/d3d9/Fence9.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -namespace rx -{ - -Fence9::Fence9(rx::Renderer9 *renderer) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Fence9::~Fence9() -{ - if (mQuery) - { - mRenderer->freeEventQuery(mQuery); - mQuery = NULL; - } -} - -GLboolean Fence9::isFence() -{ - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return mQuery != NULL; -} - -void Fence9::setFence(GLenum condition) -{ - if (!mQuery) - { - mQuery = mRenderer->allocateEventQuery(); - if (!mQuery) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - setCondition(condition); - setStatus(GL_FALSE); -} - -GLboolean Fence9::testFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } - - HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if (d3d9::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - return getStatus(); -} - -void Fence9::finishFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - while (!testFence()) - { - Sleep(0); - } -} - -void Fence9::getFenceiv(GLenum pname, GLint *params) -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV - // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - if (getStatus()) - { - params[0] = GL_TRUE; - return; - } - - HRESULT result = mQuery->GetData(NULL, 0, 0); - - if (d3d9::isDeviceLostError(result)) - { - params[0] = GL_TRUE; - mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - params[0] = getStatus(); - - break; - } - case GL_FENCE_CONDITION_NV: - params[0] = getCondition(); - break; - default: - return gl::error(GL_INVALID_ENUM); - break; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp deleted file mode 100644 index 090431db99..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "precompiled.h" -// -// 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. -// - -// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 -// pointers retained by renderbuffers. - -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) -{ - mRenderer = Renderer9::makeRenderer9(renderer); - mRenderTarget = surface; - - if (mRenderTarget) - { - D3DSURFACE_DESC description; - mRenderTarget->GetDesc(&description); - - mWidth = description.Width; - mHeight = description.Height; - - mInternalFormat = d3d9_gl::GetEquivalentFormat(description.Format); - mActualFormat = d3d9_gl::GetEquivalentFormat(description.Format); - mSamples = d3d9_gl::GetSamplesFromMultisampleType(description.MultiSampleType); - } -} - -RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples) -{ - mRenderer = Renderer9::makeRenderer9(renderer); - mRenderTarget = NULL; - - D3DFORMAT requestedFormat = gl_d3d9::ConvertRenderbufferFormat(format); - int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); - - if (supportedSamples == -1) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } - - HRESULT result = D3DERR_INVALIDCALL; - - if (width > 0 && height > 0) - { - if (requestedFormat == D3DFMT_D24S8) - { - result = mRenderer->getDevice()->CreateDepthStencilSurface(width, height, requestedFormat, - gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), - 0, FALSE, &mRenderTarget, NULL); - } - else - { - result = mRenderer->getDevice()->CreateRenderTarget(width, height, requestedFormat, - gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), - 0, FALSE, &mRenderTarget, NULL); - } - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } - - ASSERT(SUCCEEDED(result)); - } - - mWidth = width; - mHeight = height; - mInternalFormat = format; - mSamples = supportedSamples; - mActualFormat = d3d9_gl::GetEquivalentFormat(requestedFormat); -} - -RenderTarget9::~RenderTarget9() -{ - if (mRenderTarget) - { - mRenderTarget->Release(); - } -} - -RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); - return static_cast<rx::RenderTarget9*>(target); -} - -IDirect3DSurface9 *RenderTarget9::getSurface() -{ - // Caller is responsible for releasing the returned surface reference. - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -}
\ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp deleted file mode 100644 index 57f5bcd256..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp +++ /dev/null @@ -1,530 +0,0 @@ -#include "precompiled.h" -// -// 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. -// - -// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. - -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d9/vertexconversion.h" -#include "libGLESv2/renderer/BufferStorage.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -#include "libGLESv2/Buffer.h" - -namespace rx -{ - -bool VertexBuffer9::mTranslationsInitialized = false; -VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - -VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) -{ - mVertexBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; - - if (!mTranslationsInitialized) - { - initializeTranslations(renderer->getCapsDeclTypes()); - mTranslationsInitialized = true; - } -} - -VertexBuffer9::~VertexBuffer9() -{ - if (mVertexBuffer) - { - mVertexBuffer->Release(); - mVertexBuffer = NULL; - } -} - -bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) -{ - if (mVertexBuffer) - { - mVertexBuffer->Release(); - mVertexBuffer = NULL; - } - - updateSerial(); - - if (size > 0) - { - DWORD flags = D3DUSAGE_WRITEONLY; - if (dynamicUsage) - { - flags |= D3DUSAGE_DYNAMIC; - } - - HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", size); - return false; - } - } - - mBufferSize = size; - mDynamicUsage = dynamicUsage; - return true; -} - -VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); - return static_cast<VertexBuffer9*>(vertexBuffer); -} - -bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, - GLsizei instances, unsigned int offset) -{ - if (mVertexBuffer) - { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - - int inputStride = attrib.stride(); - int elementSize = attrib.typeSize(); - const FormatConverter &converter = formatConverter(attrib); - - DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - - unsigned int mapSize; - if (!spaceRequired(attrib, count, instances, &mapSize)) - { - return false; - } - - HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return false; - } - - const char *input = NULL; - if (buffer) - { - BufferStorage *storage = buffer->getStorage(); - input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset); - } - else - { - input = static_cast<const char*>(attrib.mPointer); - } - - if (instances == 0 || attrib.mDivisor == 0) - { - input += inputStride * start; - } - - if (converter.identity && inputStride == elementSize) - { - memcpy(mapPtr, input, count * inputStride); - } - else - { - converter.convertArray(input, inputStride, count, mapPtr); - } - - mVertexBuffer->Unlock(); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset) -{ - if (mVertexBuffer) - { - DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return false; - } - - memcpy(mapPtr, data, size); - - mVertexBuffer->Unlock(); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const -{ - return spaceRequired(attrib, count, instances, outSpaceRequired); -} - -bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const -{ - return !formatConverter(attrib).identity; -} - -unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const -{ - unsigned int spaceRequired; - return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0; -} - -D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const -{ - return formatConverter(attrib).d3dDeclType; -} - -unsigned int VertexBuffer9::getBufferSize() const -{ - return mBufferSize; -} - -bool VertexBuffer9::setBufferSize(unsigned int size) -{ - if (size > mBufferSize) - { - return initialize(size, mDynamicUsage); - } - else - { - return true; - } -} - -bool VertexBuffer9::discard() -{ - if (mVertexBuffer) - { - void *dummy; - HRESULT result; - - result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - ERR("Discard lock failed with error 0x%08x", result); - return false; - } - - result = mVertexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Discard unlock failed with error 0x%08x", result); - return false; - } - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const -{ - return mVertexBuffer; -} - -// 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> : NoWiden<size> { }; -template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { }; -template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { }; -template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { }; -template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { }; -template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : 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 : 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> : Normalize<typename GLToCType<fromType>::type> { }; - -// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. -template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { }; -template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 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> : NormalizedDefaultValues<T> { }; -template <class T> struct DefaultVertexValuesStage2<T, false> : 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> : 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 - : 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 }; -}; - -// Initialize 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 VertexBuffer9::TranslationDescription VertexBuffer9::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 VertexBuffer9::initializeTranslations(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) - { - mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; - } - else - { - mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; - } - } - } - } -} - -unsigned int VertexBuffer9::typeIndex(GLenum type) -{ - 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; - } -} - -const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute) -{ - return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; -} - -bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) -{ - unsigned int elementSize = formatConverter(attrib).outputElementSize; - - if (attrib.mArrayEnabled) - { - unsigned int elementCount = 0; - if (instances == 0 || attrib.mDivisor == 0) - { - elementCount = count; - } - else - { - if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1)) - { - // Round up - elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; - } - else - { - elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor; - } - } - - if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return true; - } - else - { - return false; - } - } - else - { - const unsigned int elementSize = 4; - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * 4; - } - return true; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h deleted file mode 100644 index 2f88117bda..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h +++ /dev/null @@ -1,91 +0,0 @@ -// -// 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. -// - -// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ - -#include "libGLESv2/renderer/VertexBuffer.h" - -namespace rx -{ -class Renderer9; - -class VertexBuffer9 : public VertexBuffer -{ - public: - explicit VertexBuffer9(rx::Renderer9 *const renderer); - virtual ~VertexBuffer9(); - - virtual bool initialize(unsigned int size, bool dynamicUsage); - - static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); - - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int offset); - virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); - - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; - - virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; - - unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; - D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const; - - virtual unsigned int getBufferSize() const; - virtual bool setBufferSize(unsigned int size); - virtual bool discard(); - - IDirect3DVertexBuffer9 *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); - - rx::Renderer9 *const mRenderer; - - IDirect3DVertexBuffer9 *mVertexBuffer; - unsigned int mBufferSize; - bool mDynamicUsage; - - // Attribute format conversion - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - 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; - }; - - static bool mTranslationsInitialized; - static void initializeTranslations(DWORD declTypes); - - // [GL types as enumerated by typeIndex()][normalized][size - 1] - static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - - struct TranslationDescription - { - DWORD capsFlag; - FormatConverter preferredConversion; - FormatConverter fallbackConversion; - }; - - // This table is used to generate mFormatConverters. - // [GL types as enumerated by typeIndex()][normalized][size - 1] - static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - - static unsigned int typeIndex(GLenum type); - static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); - - static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired); -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp deleted file mode 100644 index b7f2ffb1d9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp +++ /dev/null @@ -1,500 +0,0 @@ -#include "precompiled.h" -// -// 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. -// - -// renderer9_utils.cpp: Conversion functions and other utility routines -// specific to the D3D9 renderer. - -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/Context.h" - -#include "common/debug.h" - -namespace gl_d3d9 -{ - -D3DCMPFUNC ConvertComparison(GLenum comparison) -{ - D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; - switch (comparison) - { - case GL_NEVER: d3dComp = D3DCMP_NEVER; break; - case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; - case GL_LESS: d3dComp = D3DCMP_LESS; break; - case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; - case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; - case GL_GREATER: d3dComp = D3DCMP_GREATER; break; - case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; - case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; - default: UNREACHABLE(); - } - - return d3dComp; -} - -D3DCOLOR ConvertColor(gl::Color color) -{ - return D3DCOLOR_RGBA(gl::unorm<8>(color.red), - gl::unorm<8>(color.green), - gl::unorm<8>(color.blue), - gl::unorm<8>(color.alpha)); -} - -D3DBLEND ConvertBlendFunc(GLenum blend) -{ - D3DBLEND d3dBlend = D3DBLEND_ZERO; - - switch (blend) - { - case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; - case GL_ONE: d3dBlend = D3DBLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; - case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; - case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; - default: UNREACHABLE(); - } - - return d3dBlend; -} - -D3DBLENDOP ConvertBlendOp(GLenum blendOp) -{ - D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; - - switch (blendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; - default: UNREACHABLE(); - } - - return d3dBlendOp; -} - -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) -{ - D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; - - switch (stencilOp) - { - case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; - case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; - case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; - default: UNREACHABLE(); - } - - return d3dStencilOp; -} - -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) -{ - D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; - - switch (wrap) - { - case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; - case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; - case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; - default: UNREACHABLE(); - } - - return d3dWrap; -} - -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) -{ - D3DCULL cull = D3DCULL_CCW; - switch (cullFace) - { - case GL_FRONT: - cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); - break; - case GL_BACK: - cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); - break; - case GL_FRONT_AND_BACK: - cull = D3DCULL_NONE; // culling will be handled during draw - break; - default: UNREACHABLE(); - } - - return cull; -} - -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) -{ - D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; - - 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_POSITIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - face = D3DCUBEMAP_FACE_NEGATIVE_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) | - (green ? D3DCOLORWRITEENABLE_GREEN : 0) | - (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | - (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); -} - -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) -{ - if (maxAnisotropy > 1.0f) - { - return D3DTEXF_ANISOTROPIC; - } - - D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; - switch (magFilter) - { - case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; - case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; - default: UNREACHABLE(); - } - - return d3dMagFilter; -} - -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) -{ - switch (minFilter) - { - case GL_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_NEAREST_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_LINEAR_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_NEAREST_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - default: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - UNREACHABLE(); - } - - if (maxAnisotropy > 1.0f) - { - *d3dMinFilter = D3DTEXF_ANISOTROPIC; - } -} - -D3DFORMAT ConvertRenderbufferFormat(GLenum format) -{ - switch (format) - { - case GL_NONE: return D3DFMT_NULL; - 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 d3d9_gl -{ - -unsigned int GetStencilSize(D3DFORMAT stencilFormat) -{ - if (stencilFormat == D3DFMT_INTZ) - { - return 8; - } - switch(stencilFormat) - { - case D3DFMT_D24FS8: - case D3DFMT_D24S8: - return 8; - case D3DFMT_D24X4S4: - return 4; - case D3DFMT_D15S1: - return 1; - case D3DFMT_D16_LOCKABLE: - case D3DFMT_D32: - case D3DFMT_D24X8: - 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: - return 0; - } -} - -unsigned int GetAlphaSize(D3DFORMAT colorFormat) -{ - switch (colorFormat) - { - case D3DFMT_A16B16G16R16F: - return 16; - case D3DFMT_A32B32G32R32F: - return 32; - case D3DFMT_A2R10G10B10: - return 2; - case D3DFMT_A8R8G8B8: - return 8; - case D3DFMT_A1R5G5B5: - return 1; - case D3DFMT_X8R8G8B8: - case D3DFMT_R5G6B5: - return 0; - default: - return 0; - } -} - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) -{ - if (type == D3DMULTISAMPLE_NONMASKABLE) - return 0; - else - return type; -} - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) -{ - switch (d3dformat) - { - case D3DFMT_L8: - return (format == GL_LUMINANCE); - case D3DFMT_A8L8: - return (format == GL_LUMINANCE_ALPHA); - case D3DFMT_DXT1: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT); - case D3DFMT_DXT3: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - case D3DFMT_DXT5: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - case D3DFMT_A8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return (format == GL_RGBA || format == GL_BGRA_EXT); - case D3DFMT_X8R8G8B8: - return (format == GL_RGB); - default: - if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format)) - return true; - return false; - } -} - -GLenum ConvertBackBufferFormat(D3DFORMAT format) -{ - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - default: - UNREACHABLE(); - } - - return GL_RGBA4; -} - -GLenum ConvertDepthStencilFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return GL_DEPTH24_STENCIL8_OES; - } - switch (format) - { - case D3DFMT_D16: - case D3DFMT_D24X8: - return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_DEPTH24_STENCIL8_OES; -} - -GLenum ConvertRenderTargetFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return GL_DEPTH24_STENCIL8_OES; - } - - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - case D3DFMT_D16: - case D3DFMT_D24X8: - return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_RGBA4; -} - -GLenum GetEquivalentFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - return GL_DEPTH24_STENCIL8_OES; - if (format == D3DFMT_NULL) - return GL_NONE; - - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - case D3DFMT_D16: return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: return GL_NONE; - case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT; - case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT; - case D3DFMT_L8: return GL_LUMINANCE8_EXT; - case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT; - default: UNREACHABLE(); - return GL_NONE; - } -} - -} - -namespace d3d9 -{ - -bool IsCompressedFormat(D3DFORMAT surfaceFormat) -{ - switch(surfaceFormat) - { - case D3DFMT_DXT1: - case D3DFMT_DXT2: - case D3DFMT_DXT3: - case D3DFMT_DXT4: - case D3DFMT_DXT5: - return true; - default: - return false; - } -} - -size_t ComputeRowSize(D3DFORMAT format, unsigned int width) -{ - if (format == D3DFMT_INTZ) - { - return 4 * width; - } - switch (format) - { - case D3DFMT_L8: - return 1 * width; - case D3DFMT_A8L8: - return 2 * width; - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - return 4 * width; - case D3DFMT_A16B16G16R16F: - return 8 * width; - case D3DFMT_A32B32G32R32F: - return 16 * width; - case D3DFMT_DXT1: - return 8 * ((width + 3) / 4); - case D3DFMT_DXT3: - case D3DFMT_DXT5: - return 16 * ((width + 3) / 4); - default: - UNREACHABLE(); - return 0; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps deleted file mode 100644 index dcb3bd0e76..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps +++ /dev/null @@ -1,39 +0,0 @@ -// -// 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. -// - -sampler2D tex : s0; - -uniform float4 mode : c0; - -// Passthrough Pixel Shader -// Outputs texture 0 sampled at texcoord 0. -float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR -{ - return tex2D(tex, texcoord.xy); -}; - -// Luminance Conversion Pixel Shader -// Outputs sample(tex0, tc0).rrra. -// For LA output (pass A) set C0.X = 1, C0.Y = 0. -// For L output (A = 1) set C0.X = 0, C0.Y = 1. -float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR -{ - float4 tmp = tex2D(tex, texcoord.xy); - tmp.w = tmp.w * mode.x + mode.y; - return tmp.xxxw; -}; - -// RGB/A Component Mask Pixel Shader -// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1. -// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1. -// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0. -float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR -{ - float4 tmp = tex2D(tex, texcoord.xy); - tmp.xyz = tmp.xyz * mode.x; - tmp.w = tmp.w * mode.z + mode.w; - return tmp; -}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h index 8e1973605b..a57b00d444 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // @@ -10,194 +10,19 @@ #ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_ #define LIBGLESV2_RENDERER_GENERATEMIP_H_ -#include "libGLESv2/mathutil.h" +#include "libGLESv2/renderer/imageformats.h" +#include "libGLESv2/angletypes.h" namespace rx { -struct L8 -{ - unsigned char L; - - static void average(L8 *dst, const L8 *src1, const L8 *src2) - { - dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L); - } -}; - -typedef L8 R8; // R8 type is functionally equivalent for mip purposes -typedef L8 A8; // A8 type is functionally equivalent for mip purposes - -struct A8L8 -{ - unsigned char L; - unsigned char A; - - static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -typedef A8L8 R8G8; // R8G8 type is functionally equivalent for mip purposes - -struct A8R8G8B8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - unsigned char A; - - static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -typedef A8R8G8B8 R8G8B8A8; // R8G8B8A8 type is functionally equivalent for mip purposes - -struct A16B16G16R16F -{ - unsigned short R; - unsigned short G; - unsigned short B; - unsigned short A; - - static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) - { - dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); - dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f); - dst->B = gl::float32ToFloat16((gl::float16ToFloat32(src1->B) + gl::float16ToFloat32(src2->B)) * 0.5f); - dst->A = gl::float32ToFloat16((gl::float16ToFloat32(src1->A) + gl::float16ToFloat32(src2->A)) * 0.5f); - } -}; - -struct R16F -{ - unsigned short R; - - static void average(R16F *dst, const R16F *src1, const R16F *src2) - { - dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); - } -}; - -struct R16G16F -{ - unsigned short R; - unsigned short G; - - static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) - { - dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); - dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f); - } -}; - -struct A32B32G32R32F -{ - float R; - float G; - float B; - float A; - - static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - dst->G = (src1->G + src2->G) * 0.5f; - dst->B = (src1->B + src2->B) * 0.5f; - dst->A = (src1->A + src2->A) * 0.5f; - } -}; - -struct R32F -{ - float R; - - static void average(R32F *dst, const R32F *src1, const R32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - } -}; - -struct R32G32F -{ - float R; - float G; - - static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - dst->G = (src1->G + src2->G) * 0.5f; - } -}; - -struct R32G32B32F -{ - float R; - float G; - float B; - - static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - dst->G = (src1->G + src2->G) * 0.5f; - dst->B = (src1->B + src2->B) * 0.5f; - } -}; template <typename T> -static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight, - const unsigned char *sourceData, int sourcePitch, - unsigned char *destData, int destPitch) -{ - unsigned int mipWidth = std::max(1U, sourceWidth >> 1); - unsigned int mipHeight = std::max(1U, sourceHeight >> 1); - - if (sourceHeight == 1) - { - ASSERT(sourceWidth != 1); - - const T *src = (const T*)sourceData; - T *dst = (T*)destData; - - for (unsigned int x = 0; x < mipWidth; x++) - { - T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]); - } - } - else if (sourceWidth == 1) - { - ASSERT(sourceHeight != 1); +inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); - for (unsigned int y = 0; y < mipHeight; y++) - { - const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); - const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); - T *dst = (T*)(destData + y * destPitch); - - T::average(dst, src0, src1); - } - } - else - { - for (unsigned int y = 0; y < mipHeight; y++) - { - const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); - const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); - T *dst = (T*)(destData + y * destPitch); - - for (unsigned int x = 0; x < mipWidth; x++) - { - T tmp0; - T tmp1; - - T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]); - T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]); - T::average(&dst[x], &tmp0, &tmp1); - } - } - } -} } +#include "generatemip.inl" + #endif // LIBGLESV2_RENDERER_GENERATEMIP_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl new file mode 100644 index 0000000000..6788a42f03 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl @@ -0,0 +1,266 @@ +// +// Copyright (c) 2014 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. +// + +// generatemip.inl: Defines the GenerateMip function, templated on the format +// type of the image for which mip levels are being generated. + +#include "common/mathutil.h" + +namespace rx +{ + +namespace priv +{ + +template <typename T> +static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast<T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); +} + +template <typename T> +static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast<const T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); +} + +template <typename T> +static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth == 1); + + for (size_t y = 0; y < destHeight; y++) + { + const T *src0 = GetPixel<T>(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel<T>(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel<T>(destData, 0, y, 0, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template <typename T> +static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth == 1); + + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel<T>(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel<T>(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel<T>(destData, x, 0, 0, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template <typename T> +static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + const T *src0 = GetPixel<T>(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel<T>(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel<T>(destData, 0, 0, z, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template <typename T> +static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth == 1); + + for (size_t y = 0; y < destHeight; y++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel<T>(destData, x, y, 0, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template <typename T> +static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t y = 0; y < destHeight; y++) + { + const T *src0 = GetPixel<T>(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel<T>(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel<T>(destData, 0, y, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template <typename T> +static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel<T>(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel<T>(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel<T>(destData, x, 0, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template <typename T> +static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t y = 0; y < destHeight; y++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src4 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src5 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src6 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src7 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel<T>(destData, x, y, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(&tmp2, src4, src5); + T::average(&tmp3, src6, src7); + + T::average(&tmp4, &tmp0, &tmp1); + T::average(&tmp5, &tmp2, &tmp3); + + T::average(dst, &tmp4, &tmp5); + } + } + } +} + + +typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); + +template <typename T> +static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth) +{ + uint8_t index = ((sourceWidth > 1) ? 1 : 0) | + ((sourceHeight > 1) ? 2 : 0) | + ((sourceDepth > 1) ? 4 : 0); + + switch (index) + { + case 0: return NULL; + case 1: return GenerateMip_X<T>; // W x 1 x 1 + case 2: return GenerateMip_Y<T>; // 1 x H x 1 + case 3: return GenerateMip_XY<T>; // W x H x 1 + case 4: return GenerateMip_Z<T>; // 1 x 1 x D + case 5: return GenerateMip_XZ<T>; // W x 1 x D + case 6: return GenerateMip_YZ<T>; // 1 x H x D + case 7: return GenerateMip_XYZ<T>; // W x H x D + } + + UNREACHABLE(); + return NULL; +} + +} + +template <typename T> +inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + size_t mipWidth = std::max<size_t>(1, sourceWidth >> 1); + size_t mipHeight = std::max<size_t>(1, sourceHeight >> 1); + size_t mipDepth = std::max<size_t>(1, sourceDepth >> 1); + + priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction<T>(sourceWidth, sourceHeight, sourceDepth); + ASSERT(generationFunction != NULL); + + generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch, + mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h b/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h new file mode 100644 index 0000000000..2140a9ee72 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h @@ -0,0 +1,2029 @@ +// +// Copyright (c) 2013 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. +// + +// imageformats.h: Defines image format types with functions for mip generation +// and copying. + +#ifndef LIBGLESV2_RENDERER_IMAGEFORMATS_H_ +#define LIBGLESV2_RENDERER_IMAGEFORMATS_H_ + +#include "common/mathutil.h" + +namespace rx +{ + +// Several structures share functionality for reading, writing or mipmapping but the layout +// must match the texture format which the structure represents. If collapsing or typedefing +// structs in this header, make sure the functionality and memory layout is exactly the same. + +struct L8 +{ + unsigned char L; + + static void readColor(gl::ColorF *dst, const L8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = 1.0f; + } + + static void writeColor(L8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f); + } + + static void average(L8 *dst, const L8 *src1, const L8 *src2) + { + dst->L = gl::average(src1->L, src2->L); + } +}; + +struct R8 +{ + unsigned char R; + + static void readColor(gl::ColorF *dst, const R8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned char>(src->red); + } + + static void writeColor(R8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned char>(src->red); + } + + static void average(R8 *dst, const R8 *src1, const R8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct A8 +{ + unsigned char A; + + static void readColor(gl::ColorF *dst, const A8 *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(A8 *dst, const gl::ColorF *src) + { + dst->A = gl::floatToNormalized<unsigned char>(src->alpha); + } + + static void average(A8 *dst, const A8 *src1, const A8 *src2) + { + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct L8A8 +{ + unsigned char L; + unsigned char A; + + static void readColor(gl::ColorF *dst, const L8A8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(L8A8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::floatToNormalized<unsigned char>(src->alpha); + } + + static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +struct A8L8 +{ + unsigned char A; + unsigned char L; + + static void readColor(gl::ColorF *dst, const A8L8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(A8L8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::floatToNormalized<unsigned char>(src->alpha); + } + + static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +struct R8G8 +{ + unsigned char R; + unsigned char G; + + static void readColor(gl::ColorF *dst, const R8G8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8G8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8G8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned char>(src->red); + dst->G = gl::floatToNormalized<unsigned char>(src->green); + } + + static void writeColor(R8G8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned char>(src->red); + dst->G = static_cast<unsigned char>(src->green); + } + + static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +struct R8G8B8 +{ + unsigned char R; + unsigned char G; + unsigned char B; + + static void readColor(gl::ColorF *dst, const R8G8B8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8G8B8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->G; + dst->alpha = 1; + } + + static void writeColor(R8G8B8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned char>(src->red); + dst->G = gl::floatToNormalized<unsigned char>(src->green); + dst->B = gl::floatToNormalized<unsigned char>(src->blue); + } + + static void writeColor(R8G8B8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned char>(src->red); + dst->G = static_cast<unsigned char>(src->green); + dst->B = static_cast<unsigned char>(src->blue); + } + + static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct B8G8R8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + + static void readColor(gl::ColorF *dst, const B8G8R8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const B8G8R8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->G; + dst->alpha = 1; + } + + static void writeColor(B8G8R8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned char>(src->red); + dst->G = gl::floatToNormalized<unsigned char>(src->green); + dst->B = gl::floatToNormalized<unsigned char>(src->blue); + } + + static void writeColor(B8G8R8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned char>(src->red); + dst->G = static_cast<unsigned char>(src->green); + dst->B = static_cast<unsigned char>(src->blue); + } + + static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R5G6B5 +{ + unsigned short RGB; + + static void readColor(gl::ColorF *dst, const R5G6B5 *src) + { + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB)); + dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB)); + dst->alpha = 1.0f; + } + + static void writeColor(R5G6B5 *dst, const gl::ColorF *src) + { + dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) | + gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); + } + + static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2) + { + dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB), gl::getShiftedData<5, 11>(src2->RGB))) | + gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB), gl::getShiftedData<6, 5>(src2->RGB))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB), gl::getShiftedData<5, 0>(src2->RGB))); + } +}; + +struct A8R8G8B8 +{ + unsigned char A; + unsigned char R; + unsigned char G; + unsigned char B; + + static void readColor(gl::ColorF *dst, const A8R8G8B8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned char>(src->red); + dst->G = gl::floatToNormalized<unsigned char>(src->green); + dst->B = gl::floatToNormalized<unsigned char>(src->blue); + dst->A = gl::floatToNormalized<unsigned char>(src->alpha); + } + + static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned char>(src->red); + dst->G = static_cast<unsigned char>(src->green); + dst->B = static_cast<unsigned char>(src->blue); + dst->A = static_cast<unsigned char>(src->alpha); + } + + static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +struct R8G8B8A8 +{ + unsigned char R; + unsigned char G; + unsigned char B; + unsigned char A; + + static void readColor(gl::ColorF *dst, const R8G8B8A8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned char>(src->red); + dst->G = gl::floatToNormalized<unsigned char>(src->green); + dst->B = gl::floatToNormalized<unsigned char>(src->blue); + dst->A = gl::floatToNormalized<unsigned char>(src->alpha); + } + + static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned char>(src->red); + dst->G = static_cast<unsigned char>(src->green); + dst->B = static_cast<unsigned char>(src->blue); + dst->A = static_cast<unsigned char>(src->alpha); + } + + static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +struct B8G8R8A8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + unsigned char A; + + static void readColor(gl::ColorF *dst, const B8G8R8A8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned char>(src->red); + dst->G = gl::floatToNormalized<unsigned char>(src->green); + dst->B = gl::floatToNormalized<unsigned char>(src->blue); + dst->A = gl::floatToNormalized<unsigned char>(src->alpha); + } + + static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned char>(src->red); + dst->G = static_cast<unsigned char>(src->green); + dst->B = static_cast<unsigned char>(src->blue); + dst->A = static_cast<unsigned char>(src->alpha); + } + + static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +struct B8G8R8X8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + unsigned char X; + + static void readColor(gl::ColorF *dst, const B8G8R8X8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned char>(src->red); + dst->G = gl::floatToNormalized<unsigned char>(src->green); + dst->B = gl::floatToNormalized<unsigned char>(src->blue); + dst->X = 255; + } + + static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned char>(src->red); + dst->G = static_cast<unsigned char>(src->green); + dst->B = static_cast<unsigned char>(src->blue); + dst->X = 255; + } + + static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + dst->X = 255; + } +}; + +struct B5G5R5A1 +{ + unsigned short BGRA; + + static void readColor(gl::ColorF *dst, const B5G5R5A1 *src) + { + dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->BGRA)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->BGRA)); + dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->BGRA)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGRA)); + } + + static void writeColor(B5G5R5A1 *dst, const gl::ColorF *src) + { + dst->BGRA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | + gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->red)) | + gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); + } + + static void average(B5G5R5A1 *dst, const B5G5R5A1 *src1, const B5G5R5A1 *src2) + { + dst->BGRA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->BGRA), gl::getShiftedData<1, 15>(src2->BGRA))) | + gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->BGRA), gl::getShiftedData<5, 10>(src2->BGRA))) | + gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->BGRA), gl::getShiftedData<5, 5>(src2->BGRA))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGRA), gl::getShiftedData<5, 0>(src2->BGRA))); + } +}; + +struct R5G5B5A1 +{ + unsigned short RGBA; + + static void readColor(gl::ColorF *dst, const R5G5B5A1 *src) + { + dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->RGBA)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->RGBA)); + dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->RGBA)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGBA)); + } + + static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src) + { + dst->RGBA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | + gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->blue)) | + gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->red)); + } + + static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2) + { + dst->RGBA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->RGBA), gl::getShiftedData<1, 15>(src2->RGBA))) | + gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->RGBA), gl::getShiftedData<5, 10>(src2->RGBA))) | + gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->RGBA), gl::getShiftedData<5, 5>(src2->RGBA))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGBA), gl::getShiftedData<5, 0>(src2->RGBA))); + } +}; + +struct R4G4B4A4 +{ + unsigned char R : 4; + unsigned char G : 4; + unsigned char B : 4; + unsigned char A : 4; + + static void readColor(gl::ColorF *dst, const R4G4B4A4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct A4R4G4B4 +{ + unsigned char A : 4; + unsigned char R : 4; + unsigned char G : 4; + unsigned char B : 4; + + static void readColor(gl::ColorF *dst, const A4R4G4B4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct B4G4R4A4 +{ + unsigned char B : 4; + unsigned char G : 4; + unsigned char R : 4; + unsigned char A : 4; + + static void readColor(gl::ColorF *dst, const B4G4R4A4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(B4G4R4A4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(B4G4R4A4 *dst, const B4G4R4A4 *src1, const B4G4R4A4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R16 +{ + unsigned short R; + + static void readColor(gl::ColorF *dst, const R16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned short>(src->red); + } + + static void writeColor(R16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned short>(src->red); + } + + static void average(R16 *dst, const R16 *src1, const R16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R16G16 +{ + unsigned short R; + unsigned short G; + + static void readColor(gl::ColorF *dst, const R16G16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16G16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16G16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned short>(src->red); + dst->G = gl::floatToNormalized<unsigned short>(src->green); + } + + static void writeColor(R16G16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned short>(src->red); + dst->G = static_cast<unsigned short>(src->green); + } + + static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R16G16B16 +{ + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const R16G16B16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16G16B16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R16G16B16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned short>(src->red); + dst->G = gl::floatToNormalized<unsigned short>(src->green); + dst->B = gl::floatToNormalized<unsigned short>(src->blue); + } + + static void writeColor(R16G16B16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned short>(src->red); + dst->G = static_cast<unsigned short>(src->green); + dst->B = static_cast<unsigned short>(src->blue); + } + + static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R16G16B16A16 +{ + unsigned short R; + unsigned short G; + unsigned short B; + unsigned short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned short>(src->red); + dst->G = gl::floatToNormalized<unsigned short>(src->green); + dst->B = gl::floatToNormalized<unsigned short>(src->blue); + dst->A = gl::floatToNormalized<unsigned short>(src->alpha); + } + + static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned short>(src->red); + dst->G = static_cast<unsigned short>(src->green); + dst->B = static_cast<unsigned short>(src->blue); + dst->A = static_cast<unsigned short>(src->alpha); + } + + static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32 +{ + unsigned int R; + + static void readColor(gl::ColorF *dst, const R32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned int>(src->red); + } + + static void writeColor(R32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned int>(src->red); + } + + static void average(R32 *dst, const R32 *src1, const R32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R32G32 +{ + unsigned int R; + unsigned int G; + + static void readColor(gl::ColorF *dst, const R32G32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32G32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32G32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned int>(src->red); + dst->G = gl::floatToNormalized<unsigned int>(src->green); + } + + static void writeColor(R32G32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned int>(src->red); + dst->G = static_cast<unsigned int>(src->green); + } + + static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32 +{ + unsigned int R; + unsigned int G; + unsigned int B; + + static void readColor(gl::ColorF *dst, const R32G32B32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32G32B32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R32G32B32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned int>(src->red); + dst->G = gl::floatToNormalized<unsigned int>(src->green); + dst->B = gl::floatToNormalized<unsigned int>(src->blue); + } + + static void writeColor(R32G32B32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned int>(src->red); + dst->G = static_cast<unsigned int>(src->green); + dst->B = static_cast<unsigned int>(src->blue); + } + + static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R32G32B32A32 +{ + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<unsigned int>(src->red); + dst->G = gl::floatToNormalized<unsigned int>(src->green); + dst->B = gl::floatToNormalized<unsigned int>(src->blue); + dst->A = gl::floatToNormalized<unsigned int>(src->alpha); + } + + static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned int>(src->red); + dst->G = static_cast<unsigned int>(src->green); + dst->B = static_cast<unsigned int>(src->blue); + dst->A = static_cast<unsigned int>(src->alpha); + } + + static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R8S +{ + char R; + + static void readColor(gl::ColorF *dst, const R8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<char>(src->red); + } + + static void writeColor(R8S *dst, const gl::ColorI *src) + { + dst->R = static_cast<char>(src->red); + } + + static void average(R8S *dst, const R8S *src1, const R8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R8G8S +{ + char R; + char G; + + static void readColor(gl::ColorF *dst, const R8G8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8G8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8G8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<char>(src->red); + dst->G = gl::floatToNormalized<char>(src->green); + } + + static void writeColor(R8G8S *dst, const gl::ColorI *src) + { + dst->R = static_cast<char>(src->red); + dst->G = static_cast<char>(src->green); + } + + static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R8G8B8S +{ + char R; + char G; + char B; + + static void readColor(gl::ColorF *dst, const R8G8B8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8G8B8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R8G8B8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<char>(src->red); + dst->G = gl::floatToNormalized<char>(src->green); + dst->B = gl::floatToNormalized<char>(src->blue); + } + + static void writeColor(R8G8B8S *dst, const gl::ColorI *src) + { + dst->R = static_cast<char>(src->red); + dst->G = static_cast<char>(src->green); + dst->B = static_cast<char>(src->blue); + } + + static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R8G8B8A8S +{ + char R; + char G; + char B; + char A; + + static void readColor(gl::ColorF *dst, const R8G8B8A8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R8G8B8A8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<char>(src->red); + dst->G = gl::floatToNormalized<char>(src->green); + dst->B = gl::floatToNormalized<char>(src->blue); + dst->A = gl::floatToNormalized<char>(src->alpha); + } + + static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src) + { + dst->R = static_cast<char>(src->red); + dst->G = static_cast<char>(src->green); + dst->B = static_cast<char>(src->blue); + dst->A = static_cast<char>(src->alpha); + } + + static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R16S +{ + short R; + + static void readColor(gl::ColorF *dst, const R16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<short>(src->red); + } + + static void writeColor(R16S *dst, const gl::ColorI *src) + { + dst->R = static_cast<short>(src->red); + } + + static void average(R16S *dst, const R16S *src1, const R16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R16G16S +{ + short R; + short G; + + static void readColor(gl::ColorF *dst, const R16G16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16G16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16G16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<short>(src->red); + dst->G = gl::floatToNormalized<short>(src->green); + } + + static void writeColor(R16G16S *dst, const gl::ColorI *src) + { + dst->R = static_cast<short>(src->red); + dst->G = static_cast<short>(src->green); + } + + static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R16G16B16S +{ + short R; + short G; + short B; + + static void readColor(gl::ColorF *dst, const R16G16B16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16G16B16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R16G16B16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<short>(src->red); + dst->G = gl::floatToNormalized<short>(src->green); + dst->B = gl::floatToNormalized<short>(src->blue); + } + + static void writeColor(R16G16B16S *dst, const gl::ColorI *src) + { + dst->R = static_cast<short>(src->red); + dst->G = static_cast<short>(src->green); + dst->B = static_cast<short>(src->blue); + } + + static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R16G16B16A16S +{ + short R; + short G; + short B; + short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R16G16B16A16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<short>(src->red); + dst->G = gl::floatToNormalized<short>(src->green); + dst->B = gl::floatToNormalized<short>(src->blue); + dst->A = gl::floatToNormalized<short>(src->alpha); + } + + static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src) + { + dst->R = static_cast<short>(src->red); + dst->G = static_cast<short>(src->green); + dst->B = static_cast<short>(src->blue); + dst->A = static_cast<short>(src->alpha); + } + + static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32S +{ + int R; + + static void readColor(gl::ColorF *dst, const R32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<int>(src->red); + } + + static void writeColor(R32S *dst, const gl::ColorI *src) + { + dst->R = static_cast<int>(src->red); + } + + static void average(R32S *dst, const R32S *src1, const R32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R32G32S +{ + int R; + int G; + + static void readColor(gl::ColorF *dst, const R32G32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32G32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32G32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<int>(src->red); + dst->G = gl::floatToNormalized<int>(src->green); + } + + static void writeColor(R32G32S *dst, const gl::ColorI *src) + { + dst->R = static_cast<int>(src->red); + dst->G = static_cast<int>(src->green); + } + + static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32S +{ + int R; + int G; + int B; + + static void readColor(gl::ColorF *dst, const R32G32B32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32G32B32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R32G32B32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<int>(src->red); + dst->G = gl::floatToNormalized<int>(src->green); + dst->B = gl::floatToNormalized<int>(src->blue); + } + + static void writeColor(R32G32B32S *dst, const gl::ColorI *src) + { + dst->R = static_cast<int>(src->red); + dst->G = static_cast<int>(src->green); + dst->B = static_cast<int>(src->blue); + } + + static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R32G32B32A32S +{ + int R; + int G; + int B; + int A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R32G32B32A32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<int>(src->red); + dst->G = gl::floatToNormalized<int>(src->green); + dst->B = gl::floatToNormalized<int>(src->blue); + dst->A = gl::floatToNormalized<int>(src->alpha); + } + + static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src) + { + dst->R = static_cast<int>(src->red); + dst->G = static_cast<int>(src->green); + dst->B = static_cast<int>(src->blue); + dst->A = static_cast<int>(src->alpha); + } + + static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct A16B16G16R16F +{ + unsigned short A; + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const A16B16G16R16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16G16B16A16F +{ + unsigned short R; + unsigned short G; + unsigned short B; + unsigned short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16F +{ + unsigned short R; + + static void readColor(gl::ColorF *dst, const R16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + } + + static void average(R16F *dst, const R16F *src1, const R16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + } +}; + +struct A16F +{ + unsigned short A; + + static void readColor(gl::ColorF *dst, const A16F *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(A16F *dst, const gl::ColorF *src) + { + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(A16F *dst, const A16F *src1, const A16F *src2) + { + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct L16F +{ + unsigned short L; + + static void readColor(gl::ColorF *dst, const L16F *src) + { + float lum = gl::float16ToFloat32(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = 1.0f; + } + + static void writeColor(L16F *dst, const gl::ColorF *src) + { + dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); + } + + static void average(L16F *dst, const L16F *src1, const L16F *src2) + { + dst->L = gl::averageHalfFloat(src1->L, src2->L); + } +}; + +struct L16A16F +{ + unsigned short L; + unsigned short A; + + static void readColor(gl::ColorF *dst, const L16A16F *src) + { + float lum = gl::float16ToFloat32(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(L16A16F *dst, const gl::ColorF *src) + { + dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2) + { + dst->L = gl::averageHalfFloat(src1->L, src2->L); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16G16F +{ + unsigned short R; + unsigned short G; + + static void readColor(gl::ColorF *dst, const R16G16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R16G16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + } + + static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + } +}; + +struct R16G16B16F +{ + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const R16G16B16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = 1.0f; + } + + static void writeColor(R16G16B16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + } + + static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + } +}; + +struct A32B32G32R32F +{ + float A; + float R; + float G; + float B; + + static void readColor(gl::ColorF *dst, const A32B32G32R32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + dst->A = src->alpha; + } + + static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32G32B32A32F +{ + float R; + float G; + float B; + float A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + dst->A = src->alpha; + } + + static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32F +{ + float R; + + static void readColor(gl::ColorF *dst, const R32F *src) + { + dst->red = src->R; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + } + + static void average(R32F *dst, const R32F *src1, const R32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct A32F +{ + float A; + + static void readColor(gl::ColorF *dst, const A32F *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = src->A; + } + + static void writeColor(A32F *dst, const gl::ColorF *src) + { + dst->A = src->alpha; + } + + static void average(A32F *dst, const A32F *src1, const A32F *src2) + { + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct L32F +{ + float L; + + static void readColor(gl::ColorF *dst, const L32F *src) + { + dst->red = src->L; + dst->green = src->L; + dst->blue = src->L; + dst->alpha = 1.0f; + } + + static void writeColor(L32F *dst, const gl::ColorF *src) + { + dst->L = (src->red + src->green + src->blue) / 3.0f; + } + + static void average(L32F *dst, const L32F *src1, const L32F *src2) + { + dst->L = gl::average(src1->L, src2->L); + } +}; + +struct L32A32F +{ + float L; + float A; + + static void readColor(gl::ColorF *dst, const L32A32F *src) + { + dst->red = src->L; + dst->green = src->L; + dst->blue = src->L; + dst->alpha = src->A; + } + + static void writeColor(L32A32F *dst, const gl::ColorF *src) + { + dst->L = (src->red + src->green + src->blue) / 3.0f; + dst->A = src->alpha; + } + + static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2) + { + dst->L = gl::average(src1->L, src2->L); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32G32F +{ + float R; + float G; + + static void readColor(gl::ColorF *dst, const R32G32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R32G32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + } + + static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32F +{ + float R; + float G; + float B; + + static void readColor(gl::ColorF *dst, const R32G32B32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1.0f; + } + + static void writeColor(R32G32B32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + } + + static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R10G10B10A2 +{ + unsigned int R : 10; + unsigned int G : 10; + unsigned int B : 10; + unsigned int A : 2; + + static void readColor(gl::ColorF *dst, const R10G10B10A2 *src) + { + dst->red = gl::normalizedToFloat<10>(src->R); + dst->green = gl::normalizedToFloat<10>(src->G); + dst->blue = gl::normalizedToFloat<10>(src->B); + dst->alpha = gl::normalizedToFloat< 2>(src->A); + } + + static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<10, unsigned int>(src->red); + dst->G = gl::floatToNormalized<10, unsigned int>(src->green); + dst->B = gl::floatToNormalized<10, unsigned int>(src->blue); + dst->A = gl::floatToNormalized< 2, unsigned int>(src->alpha); + } + + static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src) + { + dst->R = static_cast<unsigned int>(src->red); + dst->G = static_cast<unsigned int>(src->green); + dst->B = static_cast<unsigned int>(src->blue); + dst->A = static_cast<unsigned int>(src->alpha); + } + + static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R9G9B9E5 +{ + unsigned int R : 9; + unsigned int G : 9; + unsigned int B : 9; + unsigned int E : 5; + + static void readColor(gl::ColorF *dst, const R9G9B9E5 *src) + { + gl::convert999E5toRGBFloats(gl::bitCast<unsigned int>(*src), &dst->red, &dst->green, &dst->blue); + dst->alpha = 1.0f; + } + + static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src) + { + *reinterpret_cast<unsigned int*>(dst) = gl::convertRGBFloatsTo999E5(src->red, + src->green, + src->blue); + } + + static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2) + { + float r1, g1, b1; + gl::convert999E5toRGBFloats(*reinterpret_cast<const unsigned int*>(src1), &r1, &g1, &b1); + + float r2, g2, b2; + gl::convert999E5toRGBFloats(*reinterpret_cast<const unsigned int*>(src2), &r2, &g2, &b2); + + *reinterpret_cast<unsigned int*>(dst) = gl::convertRGBFloatsTo999E5(gl::average(r1, r2), + gl::average(g1, g2), + gl::average(b1, b2)); + } +}; + +struct R11G11B10F +{ + unsigned int R : 11; + unsigned int G : 11; + unsigned int B : 10; + + static void readColor(gl::ColorF *dst, const R11G11B10F *src) + { + dst->red = gl::float11ToFloat32(src->R); + dst->green = gl::float11ToFloat32(src->G); + dst->blue = gl::float10ToFloat32(src->B); + dst->alpha = 1.0f; + } + + static void writeColor(R11G11B10F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat11(src->red); + dst->G = gl::float32ToFloat11(src->green); + dst->B = gl::float32ToFloat10(src->blue); + } + + static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2) + { + dst->R = gl::averageFloat11(src1->R, src2->R); + dst->G = gl::averageFloat11(src1->G, src2->G); + dst->B = gl::averageFloat10(src1->B, src2->B); + } +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGEFORMATS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp new file mode 100644 index 0000000000..4a294608ae --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp @@ -0,0 +1,662 @@ +#include "precompiled.h" +// +// Copyright (c) 2013-2014 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. +// + +// loadimage.cpp: Defines image loading functions. + +#include "libGLESv2/renderer/loadimage.h" + +namespace rx +{ + +void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = static_cast<uint32_t>(source[x]) << 24; + } + } + } +} + +void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0.0f; + dest[4 * x + 1] = 0.0f; + dest[4 * x + 2] = 0.0f; + dest[4 * x + 3] = source[x]; + } + } + } +} + +void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } + } +} + +void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 1.0f; + } + } + } +} + +void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = gl::Float16One; + } + } + } +} + +void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2 * x + 0]; + dest[4 * x + 1] = source[2 * x + 0]; + dest[4 * x + 2] = source[2 * x + 0]; + dest[4 * x + 3] = source[2 * x + 1]; + } + } + } +} + +void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2 * x + 0]; + dest[4 * x + 1] = source[2 * x + 0]; + dest[4 * x + 2] = source[2 * x + 0]; + dest[4 * x + 3] = source[2 * x + 1]; + } + } + } +} + +void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2 * x + 0]; + dest[4 * x + 1] = source[2 * x + 0]; + dest[4 * x + 2] = source[2 * x + 0]; + dest[4 * x + 3] = source[2 * x + 1]; + } + } + } +} + +void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 2]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 0]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0x00; + dest[4 * x + 1] = source[x * 2 + 1]; + dest[4 * x + 2] = source[x * 2 + 0]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0x00; + dest[4 * x + 1] = 0x00; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgb = source[x]; + dest[4 * x + 0] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); + dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgb = source[x]; + dest[4 * x + 0] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); + dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } + } +} + +void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); + dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); + dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); + dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + } + } + } +} + +void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); + dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); + dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); + dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + } + } + } +} + +void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t bgra = source[x]; + dest[4 * x + 0] = ((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12); + dest[4 * x + 1] = ((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8); + dest[4 * x + 2] = ((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4); + dest[4 * x + 3] = ((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0); + } + } + } +} + +void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); + dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); + dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + } + } + } +} + +void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); + dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); + dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + } + } + } +} + + +void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t bgra = source[x]; + dest[4 * x + 0] = ((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13); + dest[4 * x + 1] = ((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8); + dest[4 * x + 2] = ((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3); + dest[4 * x + 3] = (bgra & 0x0001) ? 0xFF : 0; + } + } + } +} + +void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t rgba = source[x]; + dest[4 * x + 0] = (rgba & 0x000003FF) >> 2; + dest[4 * x + 1] = (rgba & 0x000FFC00) >> 12; + dest[4 * x + 2] = (rgba & 0x3FF00000) >> 22; + dest[4 * x + 3] = ((rgba & 0xC0000000) >> 30) * 0x55; + } + } + } +} + +void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]), + gl::float16ToFloat32(source[x * 3 + 1]), + gl::float16ToFloat32(source[x * 3 + 2])); + } + } + } +} + +void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1], source[x * 3 + 2]); + } + } + } +} + +void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) | + (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) | + (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22); + } + } + } +} + +void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) | + (gl::float32ToFloat11(source[x * 3 + 1]) << 11) | + (gl::float32ToFloat10(source[x * 3 + 2]) << 22); + } + } + } +} + +void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t d = source[x] >> 8; + uint8_t s = source[x] & 0xFF; + dest[x] = d | (s << 24); + } + } + } +} + +void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]); + dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]); + dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]); + dest[x * 4 + 3] = gl::Float16One; + } + } + } +} + +void LoadR32ToR16(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = source[x] >> 16; + } + } + } +} + +void LoadR32ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x++) + { + dest[x] = source[x] >> 8; + } + } + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h new file mode 100644 index 0000000000..bcdff24a66 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h @@ -0,0 +1,193 @@ +// +// Copyright (c) 2013-2014 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. +// + +// loadimage.h: Defines image loading functions + +#ifndef LIBGLESV2_RENDERER_LOADIMAGE_H_ +#define LIBGLESV2_RENDERER_LOADIMAGE_H_ + +#include "libGLESv2/angletypes.h" + +#include <cstdint> + +namespace rx +{ + +void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template <typename type, size_t componentCount> +inline void LoadToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template <typename type, uint32_t fourthComponentBits> +inline void LoadToNative3To4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template <size_t componentCount> +inline void Load32FTo16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template <size_t blockWidth, size_t blockHeight, size_t blockSize> +inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR32ToR16(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits> +inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR32ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template <typename T> +inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); + +template <typename T> +inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); + +} + +#include "loadimage.inl" + +#endif // LIBGLESV2_RENDERER_LOADIMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl new file mode 100644 index 0000000000..abd0a3673c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl @@ -0,0 +1,156 @@ +// +// Copyright (c) 2014 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. +// + +#include "common/mathutil.h" + +namespace rx +{ + +template <typename T> +inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast<T*>(data + (y * rowPitch) + (z * depthPitch)); +} + +template <typename T> +inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast<const T*>(data + (y * rowPitch) + (z * depthPitch)); +} + +template <typename type, size_t componentCount> +inline void LoadToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t rowSize = width * sizeof(type) * componentCount; + const size_t layerSize = rowSize * height; + const size_t imageSize = layerSize * depth; + + if (layerSize == inputDepthPitch && layerSize == outputDepthPitch) + { + ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch); + memcpy(output, input, imageSize); + } + else if (rowSize == inputRowPitch && rowSize == outputRowPitch) + { + for (size_t z = 0; z < depth; z++) + { + const type *source = OffsetDataPointer<type>(input, 0, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer<type>(output, 0, z, outputRowPitch, outputDepthPitch); + + memcpy(dest, source, layerSize); + } + } + else + { + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const type *source = OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); + memcpy(dest, source, width * sizeof(type) * componentCount); + } + } + } +} + +template <typename type, uint32_t fourthComponentBits> +inline void LoadToNative3To4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const type fourthValue = gl::bitCast<type>(fourthComponentBits); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const type *source = OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x * 4 + 0] = source[x * 3 + 0]; + dest[x * 4 + 1] = source[x * 3 + 1]; + dest[x * 4 + 2] = source[x * 3 + 2]; + dest[x * 4 + 3] = fourthValue; + } + } + } +} + +template <size_t componentCount> +inline void Load32FTo16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t elementWidth = componentCount * width; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < elementWidth; x++) + { + dest[x] = gl::float32ToFloat16(source[x]); + } + } + } +} + +template <size_t blockWidth, size_t blockHeight, size_t blockSize> +inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t columns = (width + (blockWidth - 1)) / blockWidth; + const size_t rows = (height + (blockHeight - 1)) / blockHeight; + + for (size_t z = 0; z < depth; ++z) + { + for (size_t y = 0; y < rows; ++y) + { + const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch); + memcpy(dest, source, columns * blockSize); + } + } +} + +template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits> +inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + type writeValues[4] = + { + gl::bitCast<type>(firstBits), + gl::bitCast<type>(secondBits), + gl::bitCast<type>(thirdBits), + gl::bitCast<type>(fourthBits), + }; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + type *destRow = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + type* destPixel = destRow + x * 4; + + // This could potentially be optimized by generating an entire row of initialization + // data and copying row by row instead of pixel by pixel. + memcpy(destPixel, writeValues, sizeof(type) * 4); + } + } + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp new file mode 100644 index 0000000000..dcf347d421 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp @@ -0,0 +1,113 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2014 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. +// + +// loadimageSSE2.cpp: Defines image loading functions. It's +// in a separated file for GCC, which can enable SSE usage only per-file, +// not for code blocks that use SSE2 explicitly. + +#include "libGLESv2/renderer/loadimage.h" + +#if !defined(__SSE2__) && (defined(_M_X64) || _M_IX86_FP == 2) +#define __SSE2__ +#endif + +namespace rx +{ + +void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ +#ifdef __SSE2__ + __m128i zeroWide = _mm_setzero_si128(); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + + size_t x = 0; + + // Make output writes aligned + for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++) + { + dest[x] = static_cast<uint32_t>(source[x]) << 24; + } + + for (; x + 7 < width; x += 8) + { + __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x])); + // Interleave each byte to 16bit, make the lower byte to zero + sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); + // Interleave each 16bit to 32bit, make the lower 16bit to zero + __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); + __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); + + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); + } + + // Handle the remainder + for (; x < width; x++) + { + dest[x] = static_cast<uint32_t>(source[x]) << 24; + } + } + } +#endif +} + +void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ +#ifdef __SSE2__ + __m128i brMask = _mm_set1_epi32(0x00ff00ff); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch); + + size_t x = 0; + + // Make output writes aligned + for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++) + { + uint32_t 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++) + { + uint32_t rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } + } +#endif +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h index 590b9d48a3..590b9d48a3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h |