mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1232902. Update ANGLE to chromium/2592
This commit is contained in:
parent
7a214251e9
commit
0c3f12d6f9
@ -222,6 +222,7 @@ config("libANGLE_config") {
|
||||
}
|
||||
defines += [
|
||||
"GL_GLEXT_PROTOTYPES",
|
||||
"EGL_EGLEXT_PROTOTYPES",
|
||||
]
|
||||
|
||||
if (is_win) {
|
||||
|
@ -19,7 +19,7 @@ deps = {
|
||||
"https://android.googlesource.com/platform/external/cherry@af6c09fe05115f0cca61ae23ee871bda27cf1ff5",
|
||||
|
||||
"third_party/deqp/src":
|
||||
"https://android.googlesource.com/platform/external/deqp@92f7752da82925ca5e7288c5b4814efa7a381d89",
|
||||
"https://android.googlesource.com/platform/external/deqp@cc0ded6c77267bbb14d21aac358fc5d9690c07f8",
|
||||
|
||||
"third_party/libpng":
|
||||
"https://android.googlesource.com/platform/external/libpng@094e181e79a3d6c23fd005679025058b7df1ad6c",
|
||||
|
@ -7,6 +7,7 @@ The goal of ANGLE is to allow users of multiple operating systems to seamlessly
|
||||
| OpenGL ES 3.0 | | nearing completion | nearing completion | planned |
|
||||
[Level of OpenGL ES support via backing renderers]
|
||||
|
||||
|
||||
| | Direct3D 9 | Direct3D 11 | Desktop GL |
|
||||
|------------:|:--------------:|:--------------:|:-------------:|
|
||||
| Windows | * | * | * |
|
||||
@ -20,8 +21,11 @@ ANGLE is used as the default WebGL backend for both Google Chrome and Mozilla Fi
|
||||
|
||||
Portions of the ANGLE shader compiler are used as a shader validator and translator by WebGL implementations across multiple platforms. It is used on Mac OS X, Linux, and in mobile variants of the browsers. Having one shader validator helps to ensure that a consistent set of GLSL ES shaders are accepted across browsers and platforms. The shader translator can be used to translate shaders to other shading languages, and to optionally apply shader modifications to work around bugs or quirks in the native graphics drivers. The translator targets Desktop GLSL, Direct3D HLSL, and even ESSL for native GLES2 platforms.
|
||||
|
||||
##Browsing
|
||||
Browse ANGLE's source in the [repository](https://chromium.googlesource.com/angle/angle)
|
||||
|
||||
##Building
|
||||
View the [Dev setup instructions](doc/DevSetup.md).
|
||||
View the [Dev setup instructions](doc/DevSetup.md). For generating a Windows Store version of ANGLE view the [Windows Store instructions](doc/BuildingAngleForWindowsStore.md)
|
||||
|
||||
##Contributing
|
||||
* Join our [Google group](https://groups.google.com/group/angleproject) to keep up to date.
|
||||
@ -33,7 +37,7 @@ View the [Dev setup instructions](doc/DevSetup.md).
|
||||
* [Choose an ANGLE branch](doc/ChoosingANGLEBranch.md) to track in your own project.
|
||||
* File bugs in the [issue tracker](http://code.google.com/p/angleproject/issues/list) (preferably with an isolated test-case).
|
||||
* Read about WebGL on the [Khronos WebGL Wiki](http://khronos.org/webgl/wiki/Main_Page).
|
||||
* Learn about implementation details in the [OpenGL Insights chapter on ANGLE](http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-ANGLE.pdf) and this [ANGLE presentation](https://code.google.com/p/angleproject/downloads/detail?name=ANGLE%20and%20Cross-Platform%20WebGL%20Support.pdf&can=2&q=).
|
||||
* Learn about implementation details in the [OpenGL Insights chapter on ANGLE](http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-ANGLE.pdf) and this [ANGLE presentation](https://drive.google.com/file/d/0Bw29oYeC09QbbHoxNE5EUFh0RGs/view?usp=sharing).
|
||||
* Learn about the past, present, and future of the ANGLE implementation in [this recent presentation](https://docs.google.com/presentation/d/1CucIsdGVDmdTWRUbg68IxLE5jXwCb2y1E9YVhQo0thg/pub?start=false&loop=false).
|
||||
* If you use ANGLE in your own project, we'd love to hear about it!
|
||||
|
||||
|
@ -499,6 +499,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
|
||||
#define EGL_FIXED_SIZE_ANGLE 0x3201
|
||||
#endif /* EGL_ANGLE_window_fixed_size */
|
||||
|
||||
#ifndef EGL_ANGLE_x11_visual
|
||||
#define EGL_ANGLE_x11_visual
|
||||
#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
|
||||
#endif /* EGL_ANGLE_x11_visual */
|
||||
|
||||
#ifndef EGL_ARM_pixmap_multisample_discard
|
||||
#define EGL_ARM_pixmap_multisample_discard 1
|
||||
#define EGL_DISCARD_SAMPLES_ARM 0x3286
|
||||
@ -539,6 +544,16 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a
|
||||
#endif
|
||||
#endif /* EGL_EXT_device_base */
|
||||
|
||||
#ifndef EGL_ANGLE_device_creation
|
||||
#define EGL_ANGLE_device_creation 1
|
||||
typedef EGLDeviceEXT (EGLAPIENTRYP PFNEGLCREATEDEVICEANGLEPROC) (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASEDEVICEANGLEPROC) (EGLDeviceEXT device);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE (EGLDeviceEXT device);
|
||||
#endif
|
||||
#endif /* EGL_ANGLE_device_creation */
|
||||
|
||||
#ifndef EGL_EXT_device_drm
|
||||
#define EGL_EXT_device_drm 1
|
||||
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
|
||||
|
@ -1,3 +1,3 @@
|
||||
#define ANGLE_COMMIT_HASH "316930d51ea9"
|
||||
#define ANGLE_COMMIT_HASH "d00f803db3a2"
|
||||
#define ANGLE_COMMIT_HASH_SIZE 12
|
||||
#define ANGLE_COMMIT_DATE "2015-12-03 16:34:05 -0500"
|
||||
#define ANGLE_COMMIT_DATE "2015-12-15 23:09:49 -0500"
|
||||
|
@ -105,7 +105,7 @@ bool DebugAnnotationsActive();
|
||||
#if !defined(NDEBUG)
|
||||
#define ASSERT(expression) { \
|
||||
if(!(expression)) \
|
||||
ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
|
||||
ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression); \
|
||||
assert(expression); \
|
||||
} ANGLE_EMPTY_STATEMENT
|
||||
#define UNUSED_ASSERTION_VARIABLE(variable)
|
||||
|
@ -15,26 +15,53 @@
|
||||
namespace angle
|
||||
{
|
||||
|
||||
void SplitString(const std::string &input,
|
||||
char delimiter,
|
||||
std::vector<std::string> *tokensOut)
|
||||
{
|
||||
std::istringstream stream(input);
|
||||
std::string token;
|
||||
const char kWhitespaceASCII[] = " \f\n\r\t\v";
|
||||
|
||||
while (std::getline(stream, token, delimiter))
|
||||
std::vector<std::string> SplitString(const std::string &input,
|
||||
const std::string &delimiters,
|
||||
WhitespaceHandling whitespace,
|
||||
SplitResult resultType)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
if (input.empty())
|
||||
{
|
||||
if (!token.empty())
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string::size_type start = 0;
|
||||
while (start != std::string::npos)
|
||||
{
|
||||
auto end = input.find_first_of(delimiters, start);
|
||||
|
||||
std::string piece;
|
||||
if (end == std::string::npos)
|
||||
{
|
||||
tokensOut->push_back(token);
|
||||
piece = input.substr(start);
|
||||
start = std::string::npos;
|
||||
}
|
||||
else
|
||||
{
|
||||
piece = input.substr(start, end - start);
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
if (whitespace == TRIM_WHITESPACE)
|
||||
{
|
||||
piece = TrimString(piece, kWhitespaceASCII);
|
||||
}
|
||||
|
||||
if (resultType == SPLIT_WANT_ALL || !piece.empty())
|
||||
{
|
||||
result.push_back(piece);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SplitStringAlongWhitespace(const std::string &input,
|
||||
std::vector<std::string> *tokensOut)
|
||||
{
|
||||
const char *delimiters = " \f\n\r\t\v";
|
||||
|
||||
std::istringstream stream(input);
|
||||
std::string line;
|
||||
@ -42,7 +69,7 @@ void SplitStringAlongWhitespace(const std::string &input,
|
||||
while (std::getline(stream, line))
|
||||
{
|
||||
size_t prev = 0, pos;
|
||||
while ((pos = line.find_first_of(delimiters, prev)) != std::string::npos)
|
||||
while ((pos = line.find_first_of(kWhitespaceASCII, prev)) != std::string::npos)
|
||||
{
|
||||
if (pos > prev)
|
||||
tokensOut->push_back(line.substr(prev, pos - prev));
|
||||
@ -53,6 +80,23 @@ void SplitStringAlongWhitespace(const std::string &input,
|
||||
}
|
||||
}
|
||||
|
||||
std::string TrimString(const std::string &input, const std::string &trimChars)
|
||||
{
|
||||
auto begin = input.find_first_not_of(trimChars);
|
||||
if (begin == std::string::npos)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string::size_type end = input.find_last_not_of(trimChars);
|
||||
if (end == std::string::npos)
|
||||
{
|
||||
return input.substr(begin);
|
||||
}
|
||||
|
||||
return input.substr(begin, end - begin + 1);
|
||||
}
|
||||
|
||||
bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
|
@ -16,13 +16,30 @@
|
||||
namespace angle
|
||||
{
|
||||
|
||||
void SplitString(const std::string &input,
|
||||
char delimiter,
|
||||
std::vector<std::string> *tokensOut);
|
||||
extern const char kWhitespaceASCII[];
|
||||
|
||||
enum WhitespaceHandling
|
||||
{
|
||||
KEEP_WHITESPACE,
|
||||
TRIM_WHITESPACE,
|
||||
};
|
||||
|
||||
enum SplitResult
|
||||
{
|
||||
SPLIT_WANT_ALL,
|
||||
SPLIT_WANT_NONEMPTY,
|
||||
};
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &input,
|
||||
const std::string &delimiters,
|
||||
WhitespaceHandling whitespace,
|
||||
SplitResult resultType);
|
||||
|
||||
void SplitStringAlongWhitespace(const std::string &input,
|
||||
std::vector<std::string> *tokensOut);
|
||||
|
||||
std::string TrimString(const std::string &input, const std::string &trimChars);
|
||||
|
||||
bool HexStringToUInt(const std::string &input, unsigned int *uintOut);
|
||||
|
||||
bool ReadFileToString(const std::string &path, std::string *stringOut);
|
||||
|
@ -16,34 +16,101 @@ using namespace angle;
|
||||
namespace
|
||||
{
|
||||
|
||||
// Basic functionality tests for SplitString
|
||||
TEST(StringUtilsTest, SplitStringBasic)
|
||||
// Basic SplitString tests
|
||||
TEST(StringUtilsTest, SplitString_Basics)
|
||||
{
|
||||
std::string testString("AxBxCxxxDExxFGHx");
|
||||
std::vector<std::string> tokens;
|
||||
SplitString(testString, 'x', &tokens);
|
||||
std::vector<std::string> r;
|
||||
|
||||
ASSERT_EQ(5u, tokens.size());
|
||||
EXPECT_EQ("A", tokens[0]);
|
||||
EXPECT_EQ("B", tokens[1]);
|
||||
EXPECT_EQ("C", tokens[2]);
|
||||
EXPECT_EQ("DE", tokens[3]);
|
||||
EXPECT_EQ("FGH", tokens[4]);
|
||||
r = SplitString(std::string(), ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
|
||||
EXPECT_TRUE(r.empty());
|
||||
|
||||
// Empty separator list
|
||||
r = SplitString("hello, world", "", KEEP_WHITESPACE, SPLIT_WANT_ALL);
|
||||
ASSERT_EQ(1u, r.size());
|
||||
EXPECT_EQ("hello, world", r[0]);
|
||||
|
||||
// Should split on any of the separators.
|
||||
r = SplitString("::,,;;", ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
|
||||
ASSERT_EQ(7u, r.size());
|
||||
for (auto str : r)
|
||||
ASSERT_TRUE(str.empty());
|
||||
|
||||
r = SplitString("red, green; blue:", ",:;", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
||||
ASSERT_EQ(3u, r.size());
|
||||
EXPECT_EQ("red", r[0]);
|
||||
EXPECT_EQ("green", r[1]);
|
||||
EXPECT_EQ("blue", r[2]);
|
||||
|
||||
// Want to split a string along whitespace sequences.
|
||||
r = SplitString(" red green \tblue\n", " \t\n", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
||||
ASSERT_EQ(3u, r.size());
|
||||
EXPECT_EQ("red", r[0]);
|
||||
EXPECT_EQ("green", r[1]);
|
||||
EXPECT_EQ("blue", r[2]);
|
||||
|
||||
// Weird case of splitting on spaces but not trimming.
|
||||
r = SplitString(" red ", " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
|
||||
ASSERT_EQ(3u, r.size());
|
||||
EXPECT_EQ("", r[0]); // Before the first space.
|
||||
EXPECT_EQ("red", r[1]);
|
||||
EXPECT_EQ("", r[2]); // After the last space.
|
||||
}
|
||||
|
||||
// Basic functionality tests for SplitStringAlongWhitespace
|
||||
TEST(StringUtilsTest, SplitStringAlongWhitespaceBasic)
|
||||
// Check different whitespace and result types for SplitString
|
||||
TEST(StringUtilsTest, SplitString_WhitespaceAndResultType)
|
||||
{
|
||||
std::string testString("A B\nC\r\tDE\v\fFGH \t\r\n");
|
||||
std::vector<std::string> tokens;
|
||||
SplitStringAlongWhitespace(testString, &tokens);
|
||||
std::vector<std::string> r;
|
||||
|
||||
ASSERT_EQ(5u, tokens.size());
|
||||
EXPECT_EQ("A", tokens[0]);
|
||||
EXPECT_EQ("B", tokens[1]);
|
||||
EXPECT_EQ("C", tokens[2]);
|
||||
EXPECT_EQ("DE", tokens[3]);
|
||||
EXPECT_EQ("FGH", tokens[4]);
|
||||
// Empty input handling.
|
||||
r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
|
||||
EXPECT_TRUE(r.empty());
|
||||
r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
||||
EXPECT_TRUE(r.empty());
|
||||
|
||||
// Input string is space and we're trimming.
|
||||
r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
|
||||
ASSERT_EQ(1u, r.size());
|
||||
EXPECT_EQ("", r[0]);
|
||||
r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
||||
EXPECT_TRUE(r.empty());
|
||||
|
||||
// Test all 4 combinations of flags on ", ,".
|
||||
r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
|
||||
ASSERT_EQ(3u, r.size());
|
||||
EXPECT_EQ("", r[0]);
|
||||
EXPECT_EQ(" ", r[1]);
|
||||
EXPECT_EQ("", r[2]);
|
||||
r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
||||
ASSERT_EQ(1u, r.size());
|
||||
ASSERT_EQ(" ", r[0]);
|
||||
r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
|
||||
ASSERT_EQ(3u, r.size());
|
||||
EXPECT_EQ("", r[0]);
|
||||
EXPECT_EQ("", r[1]);
|
||||
EXPECT_EQ("", r[2]);
|
||||
r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
||||
ASSERT_TRUE(r.empty());
|
||||
}
|
||||
|
||||
// Tests for TrimString
|
||||
TEST(StringUtilsTest, TrimString)
|
||||
{
|
||||
// Basic tests
|
||||
EXPECT_EQ("a", TrimString("a", kWhitespaceASCII));
|
||||
EXPECT_EQ("a", TrimString(" a", kWhitespaceASCII));
|
||||
EXPECT_EQ("a", TrimString("a ", kWhitespaceASCII));
|
||||
EXPECT_EQ("a", TrimString(" a ", kWhitespaceASCII));
|
||||
|
||||
// Tests with empty strings
|
||||
EXPECT_EQ("", TrimString("", kWhitespaceASCII));
|
||||
EXPECT_EQ("", TrimString(" \n\r\t", kWhitespaceASCII));
|
||||
EXPECT_EQ(" foo ", TrimString(" foo ", ""));
|
||||
|
||||
// Tests it doesn't removes characters in the middle
|
||||
EXPECT_EQ("foo bar", TrimString(" foo bar ", kWhitespaceASCII));
|
||||
|
||||
// Test with non-whitespace trimChars
|
||||
EXPECT_EQ(" ", TrimString("foo bar", "abcdefghijklmnopqrstuvwxyz"));
|
||||
}
|
||||
|
||||
// Basic functionality tests for HexStringToUInt
|
||||
|
@ -66,13 +66,13 @@ class PullGradient : public TIntermTraverser
|
||||
}
|
||||
}
|
||||
|
||||
bool visitLoop(Visit visit, TIntermLoop *loop)
|
||||
bool visitLoop(Visit visit, TIntermLoop *loop) override
|
||||
{
|
||||
visitControlFlow(visit, loop);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitSelection(Visit visit, TIntermSelection *selection)
|
||||
bool visitSelection(Visit visit, TIntermSelection *selection) override
|
||||
{
|
||||
visitControlFlow(visit, selection);
|
||||
return true;
|
||||
@ -333,7 +333,7 @@ class PushDiscontinuousLoops : public TIntermTraverser
|
||||
ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0));
|
||||
}
|
||||
|
||||
bool visitLoop(Visit visit, TIntermLoop *loop)
|
||||
bool visitLoop(Visit visit, TIntermLoop *loop) override
|
||||
{
|
||||
bool isDiscontinuous = mMetadata->mDiscontinuousLoops.count(loop) > 0;
|
||||
|
||||
|
@ -294,12 +294,14 @@ TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[],
|
||||
// Unroll for-loop markup needs to happen after validateLimitations pass.
|
||||
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
|
||||
{
|
||||
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kIntegerIndex);
|
||||
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kIntegerIndex,
|
||||
shouldRunLoopAndIndexingValidation(compileOptions));
|
||||
root->traverse(&marker);
|
||||
}
|
||||
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX))
|
||||
{
|
||||
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kSamplerArrayIndex);
|
||||
ForLoopUnrollMarker marker(ForLoopUnrollMarker::kSamplerArrayIndex,
|
||||
shouldRunLoopAndIndexingValidation(compileOptions));
|
||||
root->traverse(&marker);
|
||||
if (marker.samplerArrayIndexIsFloatLoopIndex())
|
||||
{
|
||||
@ -423,11 +425,6 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
|
||||
floatingPoint.secondarySize = 1;
|
||||
floatingPoint.array = false;
|
||||
|
||||
TPublicType sampler;
|
||||
sampler.primarySize = 1;
|
||||
sampler.secondarySize = 1;
|
||||
sampler.array = false;
|
||||
|
||||
switch(shaderType)
|
||||
{
|
||||
case GL_FRAGMENT_SHADER:
|
||||
@ -440,14 +437,15 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
|
||||
default:
|
||||
assert(false && "Language not supported");
|
||||
}
|
||||
// We set defaults for all the sampler types, even those that are
|
||||
// Set defaults for sampler types that have default precision, even those that are
|
||||
// only available if an extension exists.
|
||||
for (int samplerType = EbtGuardSamplerBegin + 1;
|
||||
samplerType < EbtGuardSamplerEnd; ++samplerType)
|
||||
{
|
||||
sampler.type = static_cast<TBasicType>(samplerType);
|
||||
symbolTable.setDefaultPrecision(sampler, EbpLow);
|
||||
}
|
||||
// New sampler types in ESSL3 don't have default precision. ESSL1 types do.
|
||||
initSamplerDefaultPrecision(EbtSampler2D);
|
||||
initSamplerDefaultPrecision(EbtSamplerCube);
|
||||
// SamplerExternalOES is specified in the extension to have default precision.
|
||||
initSamplerDefaultPrecision(EbtSamplerExternalOES);
|
||||
// It isn't specified whether Sampler2DRect has default precision.
|
||||
initSamplerDefaultPrecision(EbtSampler2DRect);
|
||||
|
||||
InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
|
||||
|
||||
@ -456,6 +454,17 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
|
||||
return true;
|
||||
}
|
||||
|
||||
void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
|
||||
{
|
||||
ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
|
||||
TPublicType sampler;
|
||||
sampler.primarySize = 1;
|
||||
sampler.secondarySize = 1;
|
||||
sampler.array = false;
|
||||
sampler.type = samplerType;
|
||||
symbolTable.setDefaultPrecision(sampler, EbpLow);
|
||||
}
|
||||
|
||||
void TCompiler::setResourceString()
|
||||
{
|
||||
std::ostringstream strstream;
|
||||
@ -689,7 +698,7 @@ void TCompiler::rewriteCSSShader(TIntermNode* root)
|
||||
|
||||
bool TCompiler::validateLimitations(TIntermNode* root)
|
||||
{
|
||||
ValidateLimitations validate(shaderType, infoSink.info);
|
||||
ValidateLimitations validate(shaderType, &infoSink.info);
|
||||
root->traverse(&validate);
|
||||
return validate.numErrors() == 0;
|
||||
}
|
||||
|
@ -179,6 +179,8 @@ class TCompiler : public TShHandleBase
|
||||
bool tagUsedFunctions();
|
||||
void internalTagUsedFunction(size_t index);
|
||||
|
||||
void initSamplerDefaultPrecision(TBasicType samplerType);
|
||||
|
||||
// Removes unused function declarations and prototypes from the AST
|
||||
class UnusedPredicate;
|
||||
bool pruneUnusedFunctions(TIntermNode *root);
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
#include "compiler/translator/ForLoopUnroll.h"
|
||||
|
||||
#include "compiler/translator/ValidateLimitations.h"
|
||||
#include "angle_gl.h"
|
||||
|
||||
bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node)
|
||||
{
|
||||
if (mUnrollCondition != kSamplerArrayIndex)
|
||||
@ -38,11 +41,16 @@ bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node)
|
||||
|
||||
bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
|
||||
{
|
||||
if (mUnrollCondition == kIntegerIndex)
|
||||
bool canBeUnrolled = mHasRunLoopValidation;
|
||||
if (!mHasRunLoopValidation)
|
||||
{
|
||||
canBeUnrolled = ValidateLimitations::IsLimitedForLoop(node);
|
||||
}
|
||||
if (mUnrollCondition == kIntegerIndex && canBeUnrolled)
|
||||
{
|
||||
// Check if loop index type is integer.
|
||||
// This is called after ValidateLimitations pass, so all the calls
|
||||
// should be valid. See ValidateLimitations::validateForLoopInit().
|
||||
// This is called after ValidateLimitations pass, so the loop has the limited form specified
|
||||
// in ESSL 1.00 appendix A.
|
||||
TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence();
|
||||
TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
|
||||
if (symbol->getBasicType() == EbtInt)
|
||||
@ -50,11 +58,18 @@ bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
|
||||
}
|
||||
|
||||
TIntermNode *body = node->getBody();
|
||||
if (body != NULL)
|
||||
if (body != nullptr)
|
||||
{
|
||||
mLoopStack.push(node);
|
||||
body->traverse(this);
|
||||
mLoopStack.pop();
|
||||
if (canBeUnrolled)
|
||||
{
|
||||
mLoopStack.push(node);
|
||||
body->traverse(this);
|
||||
mLoopStack.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
body->traverse(this);
|
||||
}
|
||||
}
|
||||
// The loop is fully processed - no need to visit children.
|
||||
return false;
|
||||
|
@ -24,11 +24,12 @@ class ForLoopUnrollMarker : public TIntermTraverser
|
||||
kSamplerArrayIndex
|
||||
};
|
||||
|
||||
ForLoopUnrollMarker(UnrollCondition condition)
|
||||
ForLoopUnrollMarker(UnrollCondition condition, bool hasRunLoopValidation)
|
||||
: TIntermTraverser(true, false, false),
|
||||
mUnrollCondition(condition),
|
||||
mSamplerArrayIndexIsFloatLoopIndex(false),
|
||||
mVisitSamplerArrayIndexNodeInsideLoop(false)
|
||||
mVisitSamplerArrayIndexNodeInsideLoop(false),
|
||||
mHasRunLoopValidation(hasRunLoopValidation)
|
||||
{
|
||||
}
|
||||
|
||||
@ -46,6 +47,7 @@ class ForLoopUnrollMarker : public TIntermTraverser
|
||||
TLoopStack mLoopStack;
|
||||
bool mSamplerArrayIndexIsFloatLoopIndex;
|
||||
bool mVisitSamplerArrayIndexNodeInsideLoop;
|
||||
bool mHasRunLoopValidation;
|
||||
};
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,7 @@ class OutputHLSL : public TIntermTraverser
|
||||
static bool canWriteAsHLSLLiteral(TIntermTyped *expression);
|
||||
|
||||
protected:
|
||||
void header(const BuiltInFunctionEmulator *builtInFunctionEmulator);
|
||||
void header(TInfoSinkBase &out, const BuiltInFunctionEmulator *builtInFunctionEmulator);
|
||||
|
||||
// Visit AST nodes and output their code to the body stream
|
||||
void visitSymbol(TIntermSymbol*);
|
||||
@ -66,22 +66,31 @@ class OutputHLSL : public TIntermTraverser
|
||||
bool visitBranch(Visit visit, TIntermBranch*);
|
||||
|
||||
bool isSingleStatement(TIntermNode *node);
|
||||
bool handleExcessiveLoop(TIntermLoop *node);
|
||||
bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node);
|
||||
|
||||
// Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString.
|
||||
void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out);
|
||||
void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString);
|
||||
void outputLineDirective(int line);
|
||||
void outputTriplet(TInfoSinkBase &out,
|
||||
Visit visit,
|
||||
const char *preString,
|
||||
const char *inString,
|
||||
const char *postString);
|
||||
void outputLineDirective(TInfoSinkBase &out, int line);
|
||||
TString argumentString(const TIntermSymbol *symbol);
|
||||
int vectorSize(const TType &type) const;
|
||||
|
||||
// Emit constructor. Called with literal names so using const char* instead of TString.
|
||||
void outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters);
|
||||
const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *constUnion);
|
||||
void outputConstructor(TInfoSinkBase &out,
|
||||
Visit visit,
|
||||
const TType &type,
|
||||
const char *name,
|
||||
const TIntermSequence *parameters);
|
||||
const TConstantUnion *writeConstantUnion(TInfoSinkBase &out,
|
||||
const TType &type,
|
||||
const TConstantUnion *constUnion);
|
||||
|
||||
void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
|
||||
|
||||
void writeEmulatedFunctionTriplet(Visit visit, const char *preStr);
|
||||
void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, const char *preStr);
|
||||
void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
|
||||
|
||||
// Returns true if it found a 'same symbol' initializer (initializer that references the variable it's initting)
|
||||
@ -92,7 +101,7 @@ class OutputHLSL : public TIntermTraverser
|
||||
TIntermTyped *expression);
|
||||
|
||||
void writeDeferredGlobalInitializers(TInfoSinkBase &out);
|
||||
void writeSelection(TIntermSelection *node);
|
||||
void writeSelection(TInfoSinkBase &out, TIntermSelection *node);
|
||||
|
||||
// Returns the function name
|
||||
TString addStructEqualityFunction(const TStructure &structure);
|
||||
|
@ -226,24 +226,25 @@ bool TParseContext::precisionErrorCheck(const TSourceLoc &line,
|
||||
{
|
||||
if (!mChecksPrecisionErrors)
|
||||
return false;
|
||||
switch (type)
|
||||
if (precision == EbpUndefined)
|
||||
{
|
||||
case EbtFloat:
|
||||
if (precision == EbpUndefined)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EbtFloat:
|
||||
error(line, "No precision specified for (float)", "");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EbtInt:
|
||||
if (precision == EbpUndefined)
|
||||
{
|
||||
case EbtInt:
|
||||
case EbtUInt:
|
||||
UNREACHABLE(); // there's always a predeclared qualifier
|
||||
error(line, "No precision specified (int)", "");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
default:
|
||||
if (IsSampler(type))
|
||||
{
|
||||
error(line, "No precision specified (sampler)", "");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
|
||||
|
||||
int level = static_cast<int>(precisionStack.size()) - 1;
|
||||
assert(level >= 0); // Just to be safe. Should not happen.
|
||||
// If we dont find anything we return this. Should we error check this?
|
||||
// If we dont find anything we return this. Some types don't have predefined default precision.
|
||||
TPrecision prec = EbpUndefined;
|
||||
while (level >= 0)
|
||||
{
|
||||
|
@ -435,6 +435,8 @@ class TSymbolTable : angle::NonCopyable
|
||||
{
|
||||
if (!SupportsPrecision(type.type))
|
||||
return false;
|
||||
if (type.type == EbtUInt)
|
||||
return false; // ESSL 3.00.4 section 4.5.4
|
||||
if (type.isAggregate())
|
||||
return false; // Not allowed to set for aggregate types
|
||||
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
|
||||
|
@ -59,6 +59,27 @@ bool TStructure::equals(const TStructure &other) const
|
||||
return (uniqueId() == other.uniqueId());
|
||||
}
|
||||
|
||||
TString TType::getCompleteString() const
|
||||
{
|
||||
TStringStream stream;
|
||||
|
||||
if (invariant)
|
||||
stream << "invariant ";
|
||||
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
|
||||
stream << getQualifierString() << " ";
|
||||
if (precision != EbpUndefined)
|
||||
stream << getPrecisionString() << " ";
|
||||
if (array)
|
||||
stream << "array[" << getArraySize() << "] of ";
|
||||
if (isMatrix())
|
||||
stream << getCols() << "X" << getRows() << " matrix of ";
|
||||
else if (isVector())
|
||||
stream << getNominalSize() << "-component vector of ";
|
||||
|
||||
stream << getBasicString();
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
//
|
||||
// Recursively generate mangled names.
|
||||
//
|
||||
|
@ -53,15 +53,37 @@ class ValidateConstIndexExpr : public TIntermTraverser
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
ValidateLimitations::ValidateLimitations(sh::GLenum shaderType,
|
||||
TInfoSinkBase &sink)
|
||||
ValidateLimitations::ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase *sink)
|
||||
: TIntermTraverser(true, false, false),
|
||||
mShaderType(shaderType),
|
||||
mSink(sink),
|
||||
mNumErrors(0)
|
||||
mNumErrors(0),
|
||||
mValidateIndexing(true),
|
||||
mValidateInnerLoops(true)
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
bool ValidateLimitations::IsLimitedForLoop(TIntermLoop *loop)
|
||||
{
|
||||
// The shader type doesn't matter in this case.
|
||||
ValidateLimitations validate(GL_FRAGMENT_SHADER, nullptr);
|
||||
validate.mValidateIndexing = false;
|
||||
validate.mValidateInnerLoops = false;
|
||||
if (!validate.validateLoopType(loop))
|
||||
return false;
|
||||
if (!validate.validateForLoopHeader(loop))
|
||||
return false;
|
||||
TIntermNode *body = loop->getBody();
|
||||
if (body != nullptr)
|
||||
{
|
||||
validate.mLoopStack.push(loop);
|
||||
body->traverse(&validate);
|
||||
validate.mLoopStack.pop();
|
||||
}
|
||||
return (validate.mNumErrors == 0);
|
||||
}
|
||||
|
||||
bool ValidateLimitations::visitBinary(Visit, TIntermBinary *node)
|
||||
{
|
||||
// Check if loop index is modified in the loop body.
|
||||
@ -72,10 +94,11 @@ bool ValidateLimitations::visitBinary(Visit, TIntermBinary *node)
|
||||
{
|
||||
case EOpIndexDirect:
|
||||
case EOpIndexIndirect:
|
||||
validateIndexing(node);
|
||||
break;
|
||||
if (mValidateIndexing)
|
||||
validateIndexing(node);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -102,6 +125,9 @@ bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate *node)
|
||||
|
||||
bool ValidateLimitations::visitLoop(Visit, TIntermLoop *node)
|
||||
{
|
||||
if (!mValidateInnerLoops)
|
||||
return true;
|
||||
|
||||
if (!validateLoopType(node))
|
||||
return false;
|
||||
|
||||
@ -123,9 +149,12 @@ bool ValidateLimitations::visitLoop(Visit, TIntermLoop *node)
|
||||
void ValidateLimitations::error(TSourceLoc loc,
|
||||
const char *reason, const char *token)
|
||||
{
|
||||
mSink.prefix(EPrefixError);
|
||||
mSink.location(loc);
|
||||
mSink << "'" << token << "' : " << reason << "\n";
|
||||
if (mSink)
|
||||
{
|
||||
mSink->prefix(EPrefixError);
|
||||
mSink->location(loc);
|
||||
(*mSink) << "'" << token << "' : " << reason << "\n";
|
||||
}
|
||||
++mNumErrors;
|
||||
}
|
||||
|
||||
@ -433,8 +462,8 @@ bool ValidateLimitations::validateOperation(TIntermOperator *node,
|
||||
|
||||
bool ValidateLimitations::isConstExpr(TIntermNode *node)
|
||||
{
|
||||
ASSERT(node != NULL);
|
||||
return node->getAsConstantUnion() != NULL;
|
||||
ASSERT(node != nullptr);
|
||||
return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst;
|
||||
}
|
||||
|
||||
bool ValidateLimitations::isConstIndexExpr(TIntermNode *node)
|
||||
@ -453,13 +482,6 @@ bool ValidateLimitations::validateIndexing(TIntermBinary *node)
|
||||
|
||||
bool valid = true;
|
||||
TIntermTyped *index = node->getRight();
|
||||
// The index expression must have integral type.
|
||||
if (!index->isScalarInt()) {
|
||||
error(index->getLine(),
|
||||
"Index expression must have integral type",
|
||||
index->getCompleteString().c_str());
|
||||
valid = false;
|
||||
}
|
||||
// The index expession must be a constant-index-expression unless
|
||||
// the operand is a uniform in a vertex shader.
|
||||
TIntermTyped *operand = node->getLeft();
|
||||
|
@ -17,7 +17,7 @@ class TInfoSinkBase;
|
||||
class ValidateLimitations : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase &sink);
|
||||
ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase *sink);
|
||||
|
||||
int numErrors() const { return mNumErrors; }
|
||||
|
||||
@ -26,6 +26,8 @@ class ValidateLimitations : public TIntermTraverser
|
||||
bool visitAggregate(Visit, TIntermAggregate *) override;
|
||||
bool visitLoop(Visit, TIntermLoop *) override;
|
||||
|
||||
static bool IsLimitedForLoop(TIntermLoop *node);
|
||||
|
||||
private:
|
||||
void error(TSourceLoc loc, const char *reason, const char *token);
|
||||
|
||||
@ -51,9 +53,11 @@ class ValidateLimitations : public TIntermTraverser
|
||||
bool validateIndexing(TIntermBinary *node);
|
||||
|
||||
sh::GLenum mShaderType;
|
||||
TInfoSinkBase &mSink;
|
||||
TInfoSinkBase *mSink;
|
||||
int mNumErrors;
|
||||
TLoopStack mLoopStack;
|
||||
bool mValidateIndexing;
|
||||
bool mValidateInnerLoops;
|
||||
};
|
||||
|
||||
#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
|
||||
|
@ -65,28 +65,6 @@ void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
|
||||
TString TType::getCompleteString() const
|
||||
{
|
||||
TStringStream stream;
|
||||
|
||||
if (invariant)
|
||||
stream << "invariant ";
|
||||
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
|
||||
stream << getQualifierString() << " ";
|
||||
if (precision != EbpUndefined)
|
||||
stream << getPrecisionString() << " ";
|
||||
if (array)
|
||||
stream << "array[" << getArraySize() << "] of ";
|
||||
if (isMatrix())
|
||||
stream << getCols() << "X" << getRows() << " matrix of ";
|
||||
else if (isVector())
|
||||
stream << getNominalSize() << "-component vector of ";
|
||||
|
||||
stream << getBasicString();
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
//
|
||||
// The rest of the file are the traversal functions. The last one
|
||||
// is the one that starts the traversal.
|
||||
|
@ -92,7 +92,7 @@ class BinaryInputStream : angle::NonCopyable
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOffset + length > mLength)
|
||||
if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength)
|
||||
{
|
||||
mError = true;
|
||||
return;
|
||||
@ -104,7 +104,7 @@ class BinaryInputStream : angle::NonCopyable
|
||||
|
||||
void skip(size_t length)
|
||||
{
|
||||
if (mOffset + length > mLength)
|
||||
if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength)
|
||||
{
|
||||
mError = true;
|
||||
return;
|
||||
@ -144,9 +144,15 @@ class BinaryInputStream : angle::NonCopyable
|
||||
{
|
||||
StaticAssertIsFundamental<T>();
|
||||
|
||||
if (!rx::IsUnsignedMultiplicationSafe(num, sizeof(T)))
|
||||
{
|
||||
mError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t length = num * sizeof(T);
|
||||
|
||||
if (mOffset + length > mLength)
|
||||
if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength)
|
||||
{
|
||||
mError = true;
|
||||
return;
|
||||
|
71
gfx/angle/src/libANGLE/BinaryStream_unittest.cpp
Normal file
71
gfx/angle/src/libANGLE/BinaryStream_unittest.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
//
|
||||
// Copyright (c) 2015 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.
|
||||
//
|
||||
|
||||
// BinaryStream_unittest.cpp: Unit tests of the binary stream classes.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "libANGLE/BinaryStream.h"
|
||||
|
||||
namespace angle
|
||||
{
|
||||
|
||||
// Test that errors are properly generated for overflows.
|
||||
TEST(BinaryInputStream, Overflow)
|
||||
{
|
||||
const uint8_t goodValue = 2;
|
||||
const uint8_t badValue = 255;
|
||||
|
||||
const size_t dataSize = 1024;
|
||||
const size_t slopSize = 1024;
|
||||
|
||||
std::vector<uint8_t> data(dataSize + slopSize);
|
||||
std::fill(data.begin(), data.begin() + dataSize, goodValue);
|
||||
std::fill(data.begin() + dataSize, data.end(), badValue);
|
||||
|
||||
std::vector<uint8_t> outputData(dataSize);
|
||||
|
||||
auto checkDataIsSafe = [=](uint8_t item)
|
||||
{
|
||||
return item == goodValue;
|
||||
};
|
||||
|
||||
{
|
||||
// One large read
|
||||
gl::BinaryInputStream stream(data.data(), dataSize);
|
||||
stream.readBytes(outputData.data(), dataSize);
|
||||
ASSERT_FALSE(stream.error());
|
||||
ASSERT_TRUE(std::all_of(outputData.begin(), outputData.end(), checkDataIsSafe));
|
||||
ASSERT_TRUE(stream.endOfStream());
|
||||
}
|
||||
|
||||
{
|
||||
// Two half-sized reads
|
||||
gl::BinaryInputStream stream(data.data(), dataSize);
|
||||
stream.readBytes(outputData.data(), dataSize / 2);
|
||||
ASSERT_FALSE(stream.error());
|
||||
stream.readBytes(outputData.data() + dataSize / 2, dataSize / 2);
|
||||
ASSERT_FALSE(stream.error());
|
||||
ASSERT_TRUE(std::all_of(outputData.begin(), outputData.end(), checkDataIsSafe));
|
||||
ASSERT_TRUE(stream.endOfStream());
|
||||
}
|
||||
|
||||
{
|
||||
// One large read that is too big
|
||||
gl::BinaryInputStream stream(data.data(), dataSize);
|
||||
stream.readBytes(outputData.data(), dataSize + 1);
|
||||
ASSERT_TRUE(stream.error());
|
||||
}
|
||||
|
||||
{
|
||||
// Two reads, one that overflows the offset
|
||||
gl::BinaryInputStream stream(data.data(), dataSize);
|
||||
stream.readBytes(outputData.data(), dataSize - 1);
|
||||
ASSERT_FALSE(stream.error());
|
||||
stream.readBytes(outputData.data(), std::numeric_limits<size_t>::max() - dataSize - 2);
|
||||
}
|
||||
}
|
||||
}
|
@ -114,6 +114,7 @@ Extensions::Extensions()
|
||||
textureCompressionASTCLDR(false),
|
||||
compressedETC1RGB8Texture(false),
|
||||
depthTextures(false),
|
||||
depth32(false),
|
||||
textureStorage(false),
|
||||
textureNPOT(false),
|
||||
drawBuffers(false),
|
||||
@ -177,6 +178,7 @@ std::vector<std::string> Extensions::getStrings() const
|
||||
InsertExtensionString("GL_OES_compressed_ETC1_RGB8_texture", compressedETC1RGB8Texture, &extensionStrings);
|
||||
InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings);
|
||||
InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings);
|
||||
InsertExtensionString("GL_OES_depth32", depth32, &extensionStrings);
|
||||
InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings);
|
||||
InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings);
|
||||
InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings);
|
||||
@ -435,6 +437,15 @@ static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps)
|
||||
return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
|
||||
}
|
||||
|
||||
// Check for GL_OES_depth32
|
||||
static bool DetermineDepth32Support(const TextureCapsMap &textureCaps)
|
||||
{
|
||||
std::vector<GLenum> requiredFormats;
|
||||
requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES);
|
||||
|
||||
return GetFormatSupport(textureCaps, requiredFormats, false, false, true);
|
||||
}
|
||||
|
||||
// Check for GL_EXT_color_buffer_float
|
||||
static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps)
|
||||
{
|
||||
@ -468,6 +479,7 @@ void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
|
||||
compressedETC1RGB8Texture = DetermineETC1RGB8TextureSupport(textureCaps);
|
||||
sRGB = DetermineSRGBTextureSupport(textureCaps);
|
||||
depthTextures = DetermineDepthTextureSupport(textureCaps);
|
||||
depth32 = DetermineDepth32Support(textureCaps);
|
||||
colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps);
|
||||
}
|
||||
|
||||
@ -636,9 +648,13 @@ std::vector<std::string> DeviceExtensions::getStrings() const
|
||||
ClientExtensions::ClientExtensions()
|
||||
: clientExtensions(false),
|
||||
platformBase(false),
|
||||
platformDevice(false),
|
||||
platformANGLE(false),
|
||||
platformANGLED3D(false),
|
||||
platformANGLEOpenGL(false),
|
||||
deviceCreation(false),
|
||||
deviceCreationD3D11(false),
|
||||
x11Visual(false),
|
||||
clientGetAllProcAddresses(false)
|
||||
{
|
||||
}
|
||||
@ -651,9 +667,13 @@ std::vector<std::string> ClientExtensions::getStrings() const
|
||||
// | Extension name | Supported flag | Output vector |
|
||||
InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings);
|
||||
InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings);
|
||||
InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
|
||||
InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
|
||||
// clang-format on
|
||||
|
||||
|
@ -83,7 +83,7 @@ struct Extensions
|
||||
// GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr
|
||||
// GL_OES_compressed_ETC1_RGB8_texture
|
||||
// GL_EXT_sRGB
|
||||
// GL_ANGLE_depth_texture
|
||||
// GL_ANGLE_depth_texture, GL_OES_depth32
|
||||
// GL_EXT_color_buffer_float
|
||||
void setTextureExtensionSupport(const TextureCapsMap &textureCaps);
|
||||
|
||||
@ -158,6 +158,10 @@ struct Extensions
|
||||
// GL_ANGLE_depth_texture
|
||||
bool depthTextures;
|
||||
|
||||
// GL_OES_depth32
|
||||
// Allows DEPTH_COMPONENT32_OES as a valid Renderbuffer format.
|
||||
bool depth32;
|
||||
|
||||
// GL_EXT_texture_storage
|
||||
bool textureStorage;
|
||||
|
||||
@ -467,6 +471,9 @@ struct ClientExtensions
|
||||
// EGL_EXT_platform_base
|
||||
bool platformBase;
|
||||
|
||||
// EGL_EXT_platform_device
|
||||
bool platformDevice;
|
||||
|
||||
// EGL_ANGLE_platform_angle
|
||||
bool platformANGLE;
|
||||
|
||||
@ -476,6 +483,15 @@ struct ClientExtensions
|
||||
// EGL_ANGLE_platform_angle_opengl
|
||||
bool platformANGLEOpenGL;
|
||||
|
||||
// EGL_ANGLE_device_creation
|
||||
bool deviceCreation;
|
||||
|
||||
// EGL_ANGLE_device_creation_d3d11
|
||||
bool deviceCreationD3D11;
|
||||
|
||||
// EGL_ANGLE_x11_visual
|
||||
bool x11Visual;
|
||||
|
||||
// EGL_KHR_client_get_all_proc_addresses
|
||||
bool clientGetAllProcAddresses;
|
||||
};
|
||||
|
@ -144,8 +144,6 @@ Context::Context(const egl::Config *config,
|
||||
// In the initial state, a default transform feedback object is bound and treated as
|
||||
// a transform feedback object with a name of zero. That object is bound any time
|
||||
// BindTransformFeedback is called with id of zero
|
||||
mTransformFeedbackZero.set(
|
||||
new TransformFeedback(mRenderer->createTransformFeedback(), 0, mCaps));
|
||||
bindTransformFeedback(0);
|
||||
}
|
||||
|
||||
@ -189,10 +187,12 @@ Context::~Context()
|
||||
SafeDelete(vertexArray.second);
|
||||
}
|
||||
|
||||
mTransformFeedbackZero.set(NULL);
|
||||
for (auto transformFeedback : mTransformFeedbackMap)
|
||||
{
|
||||
transformFeedback.second->release();
|
||||
if (transformFeedback.second != nullptr)
|
||||
{
|
||||
transformFeedback.second->release();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &zeroTexture : mZeroTextures)
|
||||
@ -324,14 +324,9 @@ GLsync Context::createFenceSync()
|
||||
|
||||
GLuint Context::createVertexArray()
|
||||
{
|
||||
GLuint handle = mVertexArrayHandleAllocator.allocate();
|
||||
|
||||
// Although the spec states VAO state is not initialized until the object is bound,
|
||||
// we create it immediately. The resulting behaviour is transparent to the application,
|
||||
// since it's not currently possible to access the state until the object is bound.
|
||||
VertexArray *vertexArray = new VertexArray(mRenderer, handle, MAX_VERTEX_ATTRIBS);
|
||||
mVertexArrayMap[handle] = vertexArray;
|
||||
return handle;
|
||||
GLuint vertexArray = mVertexArrayHandleAllocator.allocate();
|
||||
mVertexArrayMap[vertexArray] = nullptr;
|
||||
return vertexArray;
|
||||
}
|
||||
|
||||
GLuint Context::createSampler()
|
||||
@ -341,11 +336,9 @@ GLuint Context::createSampler()
|
||||
|
||||
GLuint Context::createTransformFeedback()
|
||||
{
|
||||
GLuint handle = mTransformFeedbackAllocator.allocate();
|
||||
TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle, mCaps);
|
||||
transformFeedback->addRef();
|
||||
mTransformFeedbackMap[handle] = transformFeedback;
|
||||
return handle;
|
||||
GLuint transformFeedback = mTransformFeedbackAllocator.allocate();
|
||||
mTransformFeedbackMap[transformFeedback] = nullptr;
|
||||
return transformFeedback;
|
||||
}
|
||||
|
||||
// Returns an unused framebuffer name
|
||||
@ -428,15 +421,18 @@ void Context::deleteFenceSync(GLsync fenceSync)
|
||||
|
||||
void Context::deleteVertexArray(GLuint vertexArray)
|
||||
{
|
||||
auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
|
||||
|
||||
if (vertexArrayObject != mVertexArrayMap.end())
|
||||
auto iter = mVertexArrayMap.find(vertexArray);
|
||||
if (iter != mVertexArrayMap.end())
|
||||
{
|
||||
detachVertexArray(vertexArray);
|
||||
VertexArray *vertexArrayObject = iter->second;
|
||||
if (vertexArrayObject != nullptr)
|
||||
{
|
||||
detachVertexArray(vertexArray);
|
||||
delete vertexArrayObject;
|
||||
}
|
||||
|
||||
mVertexArrayHandleAllocator.release(vertexArrayObject->first);
|
||||
delete vertexArrayObject->second;
|
||||
mVertexArrayMap.erase(vertexArrayObject);
|
||||
mVertexArrayMap.erase(iter);
|
||||
mVertexArrayHandleAllocator.release(vertexArray);
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,10 +451,15 @@ void Context::deleteTransformFeedback(GLuint transformFeedback)
|
||||
auto iter = mTransformFeedbackMap.find(transformFeedback);
|
||||
if (iter != mTransformFeedbackMap.end())
|
||||
{
|
||||
detachTransformFeedback(transformFeedback);
|
||||
mTransformFeedbackAllocator.release(transformFeedback);
|
||||
iter->second->release();
|
||||
TransformFeedback *transformFeedbackObject = iter->second;
|
||||
if (transformFeedbackObject != nullptr)
|
||||
{
|
||||
detachTransformFeedback(transformFeedback);
|
||||
transformFeedbackObject->release();
|
||||
}
|
||||
|
||||
mTransformFeedbackMap.erase(iter);
|
||||
mTransformFeedbackAllocator.release(transformFeedback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,15 +536,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const
|
||||
VertexArray *Context::getVertexArray(GLuint handle) const
|
||||
{
|
||||
auto vertexArray = mVertexArrayMap.find(handle);
|
||||
|
||||
if (vertexArray == mVertexArrayMap.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return vertexArray->second;
|
||||
}
|
||||
return (vertexArray != mVertexArrayMap.end()) ? vertexArray->second : nullptr;
|
||||
}
|
||||
|
||||
Sampler *Context::getSampler(GLuint handle) const
|
||||
@ -553,15 +546,8 @@ Sampler *Context::getSampler(GLuint handle) const
|
||||
|
||||
TransformFeedback *Context::getTransformFeedback(GLuint handle) const
|
||||
{
|
||||
if (handle == 0)
|
||||
{
|
||||
return mTransformFeedbackZero.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(handle);
|
||||
return (iter != mTransformFeedbackMap.end()) ? iter->second : NULL;
|
||||
}
|
||||
auto iter = mTransformFeedbackMap.find(handle);
|
||||
return (iter != mTransformFeedbackMap.end()) ? iter->second : nullptr;
|
||||
}
|
||||
|
||||
bool Context::isSampler(GLuint samplerName) const
|
||||
@ -631,11 +617,7 @@ void Context::bindRenderbuffer(GLuint renderbuffer)
|
||||
|
||||
void Context::bindVertexArray(GLuint vertexArray)
|
||||
{
|
||||
if (!getVertexArray(vertexArray))
|
||||
{
|
||||
VertexArray *vertexArrayObject = new VertexArray(mRenderer, vertexArray, MAX_VERTEX_ATTRIBS);
|
||||
mVertexArrayMap[vertexArray] = vertexArrayObject;
|
||||
}
|
||||
checkVertexArrayAllocation(vertexArray);
|
||||
|
||||
mState.setVertexArrayBinding(getVertexArray(vertexArray));
|
||||
}
|
||||
@ -711,6 +693,8 @@ void Context::useProgram(GLuint program)
|
||||
|
||||
void Context::bindTransformFeedback(GLuint transformFeedback)
|
||||
{
|
||||
checkTransformFeedbackAllocation(transformFeedback);
|
||||
|
||||
mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback));
|
||||
}
|
||||
|
||||
@ -1093,20 +1077,6 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case GL_PIXEL_PACK_BUFFER_BINDING:
|
||||
case GL_PIXEL_UNPACK_BUFFER_BINDING:
|
||||
{
|
||||
if (mExtensions.pixelBufferObject)
|
||||
{
|
||||
*type = GL_INT;
|
||||
*numParams = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case GL_MAX_VIEWPORT_DIMS:
|
||||
{
|
||||
*type = GL_INT;
|
||||
@ -1210,6 +1180,15 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
|
||||
*type = GL_INT;
|
||||
*numParams = 1;
|
||||
return true;
|
||||
case GL_PIXEL_PACK_BUFFER_BINDING:
|
||||
case GL_PIXEL_UNPACK_BUFFER_BINDING:
|
||||
if ((mClientVersion < 3) && !mExtensions.pixelBufferObject)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*type = GL_INT;
|
||||
*numParams = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mClientVersion < 3)
|
||||
@ -1271,6 +1250,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
|
||||
case GL_TRANSFORM_FEEDBACK_ACTIVE:
|
||||
case GL_TRANSFORM_FEEDBACK_PAUSED:
|
||||
case GL_PRIMITIVE_RESTART_FIXED_INDEX:
|
||||
case GL_RASTERIZER_DISCARD:
|
||||
{
|
||||
*type = GL_BOOL;
|
||||
*numParams = 1;
|
||||
@ -1492,6 +1472,37 @@ EGLenum Context::getRenderBuffer() const
|
||||
}
|
||||
}
|
||||
|
||||
void Context::checkVertexArrayAllocation(GLuint vertexArray)
|
||||
{
|
||||
if (!getVertexArray(vertexArray))
|
||||
{
|
||||
VertexArray *vertexArrayObject =
|
||||
new VertexArray(mRenderer, vertexArray, MAX_VERTEX_ATTRIBS);
|
||||
mVertexArrayMap[vertexArray] = vertexArrayObject;
|
||||
}
|
||||
}
|
||||
|
||||
void Context::checkTransformFeedbackAllocation(GLuint transformFeedback)
|
||||
{
|
||||
if (!getTransformFeedback(transformFeedback))
|
||||
{
|
||||
TransformFeedback *transformFeedbackObject =
|
||||
new TransformFeedback(mRenderer->createTransformFeedback(), transformFeedback, mCaps);
|
||||
transformFeedbackObject->addRef();
|
||||
mTransformFeedbackMap[transformFeedback] = transformFeedbackObject;
|
||||
}
|
||||
}
|
||||
|
||||
bool Context::isVertexArrayGenerated(GLuint vertexArray)
|
||||
{
|
||||
return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
|
||||
}
|
||||
|
||||
bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
|
||||
{
|
||||
return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
|
||||
}
|
||||
|
||||
void Context::detachTexture(GLuint texture)
|
||||
{
|
||||
// Simple pass-through to State's detachTexture method, as textures do not require
|
||||
@ -1503,20 +1514,15 @@ void Context::detachTexture(GLuint texture)
|
||||
|
||||
void Context::detachBuffer(GLuint buffer)
|
||||
{
|
||||
// Buffer detachment is handled by Context, because the buffer must also be
|
||||
// attached from any VAOs in existence, and Context holds the VAO map.
|
||||
// Simple pass-through to State's detachBuffer method, since
|
||||
// only buffer attachments to container objects that are bound to the current context
|
||||
// should be detached. And all those are available in State.
|
||||
|
||||
// [OpenGL ES 2.0.24] section 2.9 page 22:
|
||||
// If a buffer object is deleted while it is bound, all bindings to that object in the current context
|
||||
// (i.e. in the thread that called Delete-Buffers) are reset to zero.
|
||||
|
||||
mState.removeArrayBufferBinding(buffer);
|
||||
|
||||
// mark as freed among the vertex array objects
|
||||
for (auto &vaoPair : mVertexArrayMap)
|
||||
{
|
||||
vaoPair.second->detachBuffer(buffer);
|
||||
}
|
||||
// [OpenGL ES 3.2] section 5.1.2 page 45:
|
||||
// Attachments to unbound container objects, such as
|
||||
// deletion of a buffer attached to a vertex array object which is not bound to the context,
|
||||
// are not affected and continue to act as references on the deleted object
|
||||
mState.detachBuffer(buffer);
|
||||
}
|
||||
|
||||
void Context::detachFramebuffer(GLuint framebuffer)
|
||||
|
@ -153,6 +153,9 @@ class Context final : public ValidationContext
|
||||
|
||||
bool isSampler(GLuint samplerName) const;
|
||||
|
||||
bool isVertexArrayGenerated(GLuint vertexArray);
|
||||
bool isTransformFeedbackGenerated(GLuint vertexArray);
|
||||
|
||||
void getBooleanv(GLenum pname, GLboolean *params);
|
||||
void getFloatv(GLenum pname, GLfloat *params);
|
||||
void getIntegerv(GLenum pname, GLint *params);
|
||||
@ -217,6 +220,9 @@ class Context final : public ValidationContext
|
||||
void syncRendererState(const State::DirtyBits &bitMask);
|
||||
|
||||
private:
|
||||
void checkVertexArrayAllocation(GLuint vertexArray);
|
||||
void checkTransformFeedbackAllocation(GLuint transformFeedback);
|
||||
|
||||
void detachBuffer(GLuint buffer);
|
||||
void detachTexture(GLuint texture);
|
||||
void detachFramebuffer(GLuint framebuffer);
|
||||
@ -265,7 +271,6 @@ class Context final : public ValidationContext
|
||||
VertexArrayMap mVertexArrayMap;
|
||||
HandleAllocator mVertexArrayHandleAllocator;
|
||||
|
||||
BindingPointer<TransformFeedback> mTransformFeedbackZero;
|
||||
typedef std::map<GLuint, TransformFeedback*> TransformFeedbackMap;
|
||||
TransformFeedbackMap mTransformFeedbackMap;
|
||||
HandleAllocator mTransformFeedbackAllocator;
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include "common/platform.h"
|
||||
#include "libANGLE/renderer/DeviceImpl.h"
|
||||
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
#include "libANGLE/renderer/d3d/DeviceD3D.h"
|
||||
#endif
|
||||
|
||||
namespace egl
|
||||
{
|
||||
|
||||
@ -31,16 +35,67 @@ static std::string GenerateExtensionsString(const T &extensions)
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
Device::Device(Display *display, rx::DeviceImpl *impl)
|
||||
: mDisplay(display),
|
||||
mImplementation(impl)
|
||||
typedef std::set<egl::Device *> DeviceSet;
|
||||
static DeviceSet *GetDeviceSet()
|
||||
{
|
||||
static DeviceSet devices;
|
||||
return &devices;
|
||||
}
|
||||
|
||||
// Static factory methods
|
||||
egl::Error Device::CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice)
|
||||
{
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
if (deviceType == EGL_D3D11_DEVICE_ANGLE)
|
||||
{
|
||||
rx::DeviceD3D *deviceD3D = new rx::DeviceD3D();
|
||||
egl::Error error = deviceD3D->initialize(devicePointer, deviceType, EGL_TRUE);
|
||||
if (error.isError())
|
||||
{
|
||||
*outDevice = nullptr;
|
||||
return error;
|
||||
}
|
||||
|
||||
*outDevice = new Device(nullptr, deviceD3D);
|
||||
GetDeviceSet()->insert(*outDevice);
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Note that creating an EGL device from inputted D3D9 parameters isn't currently supported
|
||||
*outDevice = nullptr;
|
||||
return egl::Error(EGL_BAD_ATTRIBUTE);
|
||||
}
|
||||
|
||||
egl::Error Device::CreateDevice(Display *owningDisplay, rx::DeviceImpl *impl, Device **outDevice)
|
||||
{
|
||||
*outDevice = new Device(owningDisplay, impl);
|
||||
GetDeviceSet()->insert(*outDevice);
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
bool Device::IsValidDevice(Device *device)
|
||||
{
|
||||
const DeviceSet *deviceSet = GetDeviceSet();
|
||||
return deviceSet->find(device) != deviceSet->end();
|
||||
}
|
||||
|
||||
Device::Device(Display *owningDisplay, rx::DeviceImpl *impl)
|
||||
: mOwningDisplay(owningDisplay), mImplementation(impl)
|
||||
{
|
||||
initDeviceExtensions();
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
ASSERT(GetDeviceSet()->find(this) != GetDeviceSet()->end());
|
||||
GetDeviceSet()->erase(this);
|
||||
|
||||
if (mImplementation->deviceExternallySourced())
|
||||
{
|
||||
// If the device isn't externally sourced then it is up to the renderer to delete the impl
|
||||
SafeDelete(mImplementation);
|
||||
}
|
||||
}
|
||||
|
||||
Error Device::getDevice(EGLAttrib *value)
|
||||
|
@ -24,11 +24,10 @@ namespace egl
|
||||
class Device final : angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
Device(Display *display, rx::DeviceImpl *impl);
|
||||
virtual ~Device();
|
||||
|
||||
Error getDevice(EGLAttrib *value);
|
||||
Display *getDisplay() { return mDisplay; };
|
||||
Display *getOwningDisplay() { return mOwningDisplay; };
|
||||
EGLint getType();
|
||||
|
||||
const DeviceExtensions &getExtensions() const;
|
||||
@ -36,10 +35,18 @@ class Device final : angle::NonCopyable
|
||||
|
||||
rx::DeviceImpl *getImplementation() { return mImplementation; }
|
||||
|
||||
static egl::Error CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice);
|
||||
static egl::Error CreateDevice(Display *owningDisplay,
|
||||
rx::DeviceImpl *impl,
|
||||
Device **outDevice);
|
||||
|
||||
static bool IsValidDevice(Device *device);
|
||||
|
||||
private:
|
||||
Device(Display *owningDisplay, rx::DeviceImpl *impl);
|
||||
void initDeviceExtensions();
|
||||
|
||||
Display *mDisplay;
|
||||
Display *mOwningDisplay;
|
||||
rx::DeviceImpl *mImplementation;
|
||||
|
||||
DeviceExtensions mDeviceExtensions;
|
||||
|
@ -85,14 +85,52 @@ static WindowSurfaceMap *GetWindowSurfaces()
|
||||
return &windowSurfaces;
|
||||
}
|
||||
|
||||
typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
|
||||
static DisplayMap *GetDisplayMap()
|
||||
typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap;
|
||||
static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
|
||||
{
|
||||
static DisplayMap displays;
|
||||
static ANGLEPlatformDisplayMap displays;
|
||||
return &displays;
|
||||
}
|
||||
|
||||
rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap)
|
||||
typedef std::map<Device *, Display *> DevicePlatformDisplayMap;
|
||||
static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
|
||||
{
|
||||
static DevicePlatformDisplayMap displays;
|
||||
return &displays;
|
||||
}
|
||||
|
||||
rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice)
|
||||
{
|
||||
rx::DisplayImpl *impl = nullptr;
|
||||
|
||||
switch (eglDevice->getType())
|
||||
{
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
case EGL_D3D11_DEVICE_ANGLE:
|
||||
impl = new rx::DisplayD3D();
|
||||
break;
|
||||
#endif
|
||||
#if defined(ANGLE_ENABLE_D3D9)
|
||||
case EGL_D3D9_DEVICE_ANGLE:
|
||||
// Currently the only way to get EGLDeviceEXT representing a D3D9 device
|
||||
// is to retrieve one from an already-existing EGLDisplay.
|
||||
// When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT,
|
||||
// the already-existing display should be returned.
|
||||
// Therefore this codepath to create a new display from the device
|
||||
// should never be hit.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(impl != nullptr);
|
||||
return impl;
|
||||
}
|
||||
|
||||
rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap)
|
||||
{
|
||||
rx::DisplayImpl *impl = nullptr;
|
||||
EGLint displayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
|
||||
@ -149,15 +187,17 @@ rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap)
|
||||
|
||||
}
|
||||
|
||||
Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap)
|
||||
Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap)
|
||||
{
|
||||
// Initialize the global platform if not already
|
||||
InitDefaultPlatformImpl();
|
||||
|
||||
Display *display = NULL;
|
||||
Display *display = nullptr;
|
||||
|
||||
DisplayMap *displays = GetDisplayMap();
|
||||
DisplayMap::const_iterator iter = displays->find(displayId);
|
||||
EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
|
||||
|
||||
ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
|
||||
ANGLEPlatformDisplayMap::const_iterator iter = displays->find(displayId);
|
||||
if (iter != displays->end())
|
||||
{
|
||||
display = iter->second;
|
||||
@ -171,21 +211,71 @@ Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display = new Display(displayId);
|
||||
display = new Display(EGL_PLATFORM_ANGLE_ANGLE, displayId, nullptr);
|
||||
displays->insert(std::make_pair(displayId, display));
|
||||
}
|
||||
|
||||
// Apply new attributes if the display is not initialized yet.
|
||||
if (!display->isInitialized())
|
||||
{
|
||||
rx::DisplayImpl* impl = CreateDisplayImpl(attribMap);
|
||||
rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap);
|
||||
display->setAttributes(impl, attribMap);
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
Display::Display(EGLNativeDisplayType displayId)
|
||||
Display *Display::GetDisplayFromDevice(void *native_display)
|
||||
{
|
||||
// Initialize the global platform if not already
|
||||
InitDefaultPlatformImpl();
|
||||
|
||||
Display *display = nullptr;
|
||||
|
||||
Device *eglDevice = reinterpret_cast<Device *>(native_display);
|
||||
ASSERT(Device::IsValidDevice(eglDevice));
|
||||
|
||||
ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap();
|
||||
DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
|
||||
|
||||
// First see if this eglDevice is in use by a Display created using ANGLE platform
|
||||
for (auto &displayMapEntry : *anglePlatformDisplays)
|
||||
{
|
||||
egl::Display *iterDisplay = displayMapEntry.second;
|
||||
if (iterDisplay->getDevice() == eglDevice)
|
||||
{
|
||||
display = iterDisplay;
|
||||
}
|
||||
}
|
||||
|
||||
if (display == nullptr)
|
||||
{
|
||||
// See if the eglDevice is in use by a Display created using the DEVICE platform
|
||||
DevicePlatformDisplayMap::const_iterator iter = devicePlatformDisplays->find(eglDevice);
|
||||
if (iter != devicePlatformDisplays->end())
|
||||
{
|
||||
display = iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (display == nullptr)
|
||||
{
|
||||
// Otherwise create a new Display
|
||||
display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, eglDevice);
|
||||
devicePlatformDisplays->insert(std::make_pair(eglDevice, display));
|
||||
}
|
||||
|
||||
// Apply new attributes if the display is not initialized yet.
|
||||
if (!display->isInitialized())
|
||||
{
|
||||
rx::DisplayImpl *impl = CreateDisplayFromDevice(eglDevice);
|
||||
display->setAttributes(impl, egl::AttributeMap());
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
|
||||
: mImplementation(nullptr),
|
||||
mDisplayId(displayId),
|
||||
mAttributeMap(),
|
||||
@ -196,7 +286,8 @@ Display::Display(EGLNativeDisplayType displayId)
|
||||
mDisplayExtensions(),
|
||||
mDisplayExtensionString(),
|
||||
mVendorString(),
|
||||
mDevice(nullptr)
|
||||
mDevice(eglDevice),
|
||||
mPlatform(platform)
|
||||
{
|
||||
}
|
||||
|
||||
@ -204,11 +295,27 @@ Display::~Display()
|
||||
{
|
||||
terminate();
|
||||
|
||||
DisplayMap *displays = GetDisplayMap();
|
||||
DisplayMap::iterator iter = displays->find(mDisplayId);
|
||||
if (iter != displays->end())
|
||||
if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
|
||||
{
|
||||
displays->erase(iter);
|
||||
ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
|
||||
ANGLEPlatformDisplayMap::iterator iter = displays->find(mDisplayId);
|
||||
if (iter != displays->end())
|
||||
{
|
||||
displays->erase(iter);
|
||||
}
|
||||
}
|
||||
else if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
|
||||
{
|
||||
DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
|
||||
DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
|
||||
if (iter != displays->end())
|
||||
{
|
||||
displays->erase(iter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
SafeDelete(mDevice);
|
||||
@ -264,19 +371,34 @@ Error Display::initialize()
|
||||
initDisplayExtensions();
|
||||
initVendorString();
|
||||
|
||||
if (mDisplayExtensions.deviceQuery)
|
||||
// Populate the Display's EGLDeviceEXT if the Display wasn't created using one
|
||||
if (mPlatform != EGL_PLATFORM_DEVICE_EXT)
|
||||
{
|
||||
rx::DeviceImpl *impl = nullptr;
|
||||
error = mImplementation->getDevice(&impl);
|
||||
if (error.isError())
|
||||
if (mDisplayExtensions.deviceQuery)
|
||||
{
|
||||
return error;
|
||||
rx::DeviceImpl *impl = nullptr;
|
||||
error = mImplementation->getDevice(&impl);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
error = Device::CreateDevice(this, impl, &mDevice);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mDevice = nullptr;
|
||||
}
|
||||
mDevice = new Device(this, impl);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDevice = nullptr;
|
||||
// For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
|
||||
// an external device
|
||||
ASSERT(mDevice != nullptr);
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
@ -298,8 +420,20 @@ void Display::terminate()
|
||||
destroyImage(*mImageSet.begin());
|
||||
}
|
||||
|
||||
while (!mImplementation->getSurfaceSet().empty())
|
||||
{
|
||||
destroySurface(*mImplementation->getSurfaceSet().begin());
|
||||
}
|
||||
|
||||
mConfigSet.clear();
|
||||
|
||||
if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
|
||||
{
|
||||
// Don't delete the device if it was created externally using eglCreateDeviceANGLE
|
||||
// We also shouldn't set it to null in case eglInitialize() is called again later
|
||||
SafeDelete(mDevice);
|
||||
}
|
||||
|
||||
mImplementation->terminate();
|
||||
|
||||
mInitialized = false;
|
||||
@ -705,12 +839,22 @@ static ClientExtensions GenerateClientExtensions()
|
||||
|
||||
#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
|
||||
extensions.platformANGLED3D = true;
|
||||
extensions.platformDevice = true;
|
||||
#endif
|
||||
|
||||
#if defined(ANGLE_ENABLE_OPENGL)
|
||||
extensions.platformANGLEOpenGL = true;
|
||||
#endif
|
||||
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
extensions.deviceCreation = true;
|
||||
extensions.deviceCreationD3D11 = true;
|
||||
#endif
|
||||
|
||||
#if defined(ANGLE_USE_X11)
|
||||
extensions.x11Visual = true;
|
||||
#endif
|
||||
|
||||
extensions.clientGetAllProcAddresses = true;
|
||||
|
||||
return extensions;
|
||||
@ -755,8 +899,17 @@ bool Display::isValidNativeWindow(EGLNativeWindowType window) const
|
||||
|
||||
bool Display::isValidDisplay(const egl::Display *display)
|
||||
{
|
||||
const DisplayMap *displayMap = GetDisplayMap();
|
||||
for (const auto &displayPair : *displayMap)
|
||||
const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
|
||||
for (const auto &displayPair : *anglePlatformDisplayMap)
|
||||
{
|
||||
if (displayPair.second == display)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
|
||||
for (const auto &displayPair : *devicePlatformDisplayMap)
|
||||
{
|
||||
if (displayPair.second == display)
|
||||
{
|
||||
|
@ -44,7 +44,8 @@ class Display final : angle::NonCopyable
|
||||
Error initialize();
|
||||
void terminate();
|
||||
|
||||
static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap);
|
||||
static egl::Display *GetDisplayFromDevice(void *native_display);
|
||||
static egl::Display *GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap);
|
||||
|
||||
static const ClientExtensions &getClientExtensions();
|
||||
static const std::string &getClientExtensionString();
|
||||
@ -101,9 +102,10 @@ class Display final : angle::NonCopyable
|
||||
|
||||
rx::DisplayImpl *getImplementation() { return mImplementation; }
|
||||
Device *getDevice() const;
|
||||
EGLenum getPlatform() const { return mPlatform; }
|
||||
|
||||
private:
|
||||
Display(EGLNativeDisplayType displayId);
|
||||
Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice);
|
||||
|
||||
void setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap);
|
||||
|
||||
@ -135,6 +137,7 @@ class Display final : angle::NonCopyable
|
||||
std::string mVendorString;
|
||||
|
||||
Device *mDevice;
|
||||
EGLenum mPlatform;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "libANGLE/Framebuffer.h"
|
||||
|
||||
#include "common/Optional.h"
|
||||
#include "common/utilities.h"
|
||||
#include "libANGLE/Config.h"
|
||||
#include "libANGLE/Context.h"
|
||||
@ -124,6 +125,42 @@ const FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment() cons
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Framebuffer::Data::attachmentsHaveSameDimensions() const
|
||||
{
|
||||
Optional<Extents> attachmentSize;
|
||||
|
||||
auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
|
||||
{
|
||||
if (!attachment.isAttached())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!attachmentSize.valid())
|
||||
{
|
||||
attachmentSize = attachment.getSize();
|
||||
return false;
|
||||
}
|
||||
|
||||
return (attachment.getSize() != attachmentSize.value());
|
||||
};
|
||||
|
||||
for (const auto &attachment : mColorAttachments)
|
||||
{
|
||||
if (hasMismatchedSize(attachment))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasMismatchedSize(mDepthAttachment))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !hasMismatchedSize(mStencilAttachment);
|
||||
}
|
||||
|
||||
Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id)
|
||||
: mData(caps), mImpl(factory->createFramebuffer(mData)), mId(id)
|
||||
{
|
||||
@ -288,6 +325,11 @@ size_t Framebuffer::getNumColorBuffers() const
|
||||
return mData.mColorAttachments.size();
|
||||
}
|
||||
|
||||
bool Framebuffer::hasDepth() const
|
||||
{
|
||||
return (mData.mDepthAttachment.isAttached() && mData.mDepthAttachment.getDepthSize() > 0);
|
||||
}
|
||||
|
||||
bool Framebuffer::hasStencil() const
|
||||
{
|
||||
return (mData.mStencilAttachment.isAttached() && mData.mStencilAttachment.getStencilSize() > 0);
|
||||
@ -315,8 +357,6 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
return GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
unsigned int colorbufferSize = 0;
|
||||
int samples = -1;
|
||||
bool missingAttachment = true;
|
||||
@ -325,7 +365,8 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
{
|
||||
if (colorAttachment.isAttached())
|
||||
{
|
||||
if (colorAttachment.getWidth() == 0 || colorAttachment.getHeight() == 0)
|
||||
const Extents &size = colorAttachment.getSize();
|
||||
if (size.width == 0 || size.height == 0)
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
}
|
||||
@ -337,13 +378,18 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
{
|
||||
if (!formatCaps.renderable)
|
||||
{
|
||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
}
|
||||
|
||||
if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
}
|
||||
|
||||
if (colorAttachment.layer() >= size.depth)
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
}
|
||||
}
|
||||
else if (colorAttachment.type() == GL_RENDERBUFFER)
|
||||
{
|
||||
@ -355,12 +401,6 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
|
||||
if (!missingAttachment)
|
||||
{
|
||||
// all color attachments must have the same width and height
|
||||
if (colorAttachment.getWidth() != width || colorAttachment.getHeight() != height)
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
|
||||
}
|
||||
|
||||
// APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
|
||||
// all color attachments have the same number of samples for the FBO to be complete.
|
||||
if (colorAttachment.getSamples() != samples)
|
||||
@ -380,8 +420,6 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
}
|
||||
else
|
||||
{
|
||||
width = colorAttachment.getWidth();
|
||||
height = colorAttachment.getHeight();
|
||||
samples = colorAttachment.getSamples();
|
||||
colorbufferSize = formatInfo.pixelBytes;
|
||||
missingAttachment = false;
|
||||
@ -392,7 +430,8 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
const FramebufferAttachment &depthAttachment = mData.mDepthAttachment;
|
||||
if (depthAttachment.isAttached())
|
||||
{
|
||||
if (depthAttachment.getWidth() == 0 || depthAttachment.getHeight() == 0)
|
||||
const Extents &size = depthAttachment.getSize();
|
||||
if (size.width == 0 || size.height == 0)
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
}
|
||||
@ -410,7 +449,7 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
|
||||
if (!formatCaps.renderable)
|
||||
{
|
||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
}
|
||||
|
||||
if (formatInfo.depthBits == 0)
|
||||
@ -428,15 +467,9 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
|
||||
if (missingAttachment)
|
||||
{
|
||||
width = depthAttachment.getWidth();
|
||||
height = depthAttachment.getHeight();
|
||||
samples = depthAttachment.getSamples();
|
||||
missingAttachment = false;
|
||||
}
|
||||
else if (width != depthAttachment.getWidth() || height != depthAttachment.getHeight())
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
|
||||
}
|
||||
else if (samples != depthAttachment.getSamples())
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
|
||||
@ -446,7 +479,8 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
const FramebufferAttachment &stencilAttachment = mData.mStencilAttachment;
|
||||
if (stencilAttachment.isAttached())
|
||||
{
|
||||
if (stencilAttachment.getWidth() == 0 || stencilAttachment.getHeight() == 0)
|
||||
const Extents &size = stencilAttachment.getSize();
|
||||
if (size.width == 0 || size.height == 0)
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
}
|
||||
@ -465,7 +499,7 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
|
||||
if (!formatCaps.renderable)
|
||||
{
|
||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
}
|
||||
|
||||
if (formatInfo.stencilBits == 0)
|
||||
@ -483,15 +517,9 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
|
||||
if (missingAttachment)
|
||||
{
|
||||
width = stencilAttachment.getWidth();
|
||||
height = stencilAttachment.getHeight();
|
||||
samples = stencilAttachment.getSamples();
|
||||
missingAttachment = false;
|
||||
}
|
||||
else if (width != stencilAttachment.getWidth() || height != stencilAttachment.getHeight())
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
|
||||
}
|
||||
else if (samples != stencilAttachment.getSamples())
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
|
||||
@ -504,7 +532,19 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
|
||||
}
|
||||
|
||||
return mImpl->checkStatus();
|
||||
// In ES 2.0, all color attachments must have the same width and height.
|
||||
// In ES 3.0, there is no such restriction.
|
||||
if (data.clientVersion < 3 && !mData.attachmentsHaveSameDimensions())
|
||||
{
|
||||
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
|
||||
}
|
||||
|
||||
if (!mImpl->checkStatus())
|
||||
{
|
||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
Error Framebuffer::discard(size_t count, const GLenum *attachments)
|
||||
@ -524,6 +564,11 @@ Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const
|
||||
|
||||
Error Framebuffer::clear(Context *context, GLbitfield mask)
|
||||
{
|
||||
if (context->getState().isRasterizerDiscardEnabled())
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// Sync the clear state
|
||||
context->syncRendererState(context->getState().clearStateBitMask());
|
||||
|
||||
@ -535,10 +580,14 @@ Error Framebuffer::clearBufferfv(Context *context,
|
||||
GLint drawbuffer,
|
||||
const GLfloat *values)
|
||||
{
|
||||
if (context->getState().isRasterizerDiscardEnabled())
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// Sync the clear state
|
||||
context->syncRendererState(context->getState().clearStateBitMask());
|
||||
|
||||
return mImpl->clearBufferfv(context->getState(), buffer, drawbuffer, values);
|
||||
return mImpl->clearBufferfv(context->getData(), buffer, drawbuffer, values);
|
||||
}
|
||||
|
||||
Error Framebuffer::clearBufferuiv(Context *context,
|
||||
@ -546,10 +595,15 @@ Error Framebuffer::clearBufferuiv(Context *context,
|
||||
GLint drawbuffer,
|
||||
const GLuint *values)
|
||||
{
|
||||
if (context->getState().isRasterizerDiscardEnabled())
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// Sync the clear state
|
||||
context->syncRendererState(context->getState().clearStateBitMask());
|
||||
|
||||
return mImpl->clearBufferuiv(context->getState(), buffer, drawbuffer, values);
|
||||
return mImpl->clearBufferuiv(context->getData(), buffer, drawbuffer, values);
|
||||
}
|
||||
|
||||
Error Framebuffer::clearBufferiv(Context *context,
|
||||
@ -557,10 +611,15 @@ Error Framebuffer::clearBufferiv(Context *context,
|
||||
GLint drawbuffer,
|
||||
const GLint *values)
|
||||
{
|
||||
if (context->getState().isRasterizerDiscardEnabled())
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// Sync the clear state
|
||||
context->syncRendererState(context->getState().clearStateBitMask());
|
||||
|
||||
return mImpl->clearBufferiv(context->getState(), buffer, drawbuffer, values);
|
||||
return mImpl->clearBufferiv(context->getData(), buffer, drawbuffer, values);
|
||||
}
|
||||
|
||||
Error Framebuffer::clearBufferfi(Context *context,
|
||||
@ -569,10 +628,15 @@ Error Framebuffer::clearBufferfi(Context *context,
|
||||
GLfloat depth,
|
||||
GLint stencil)
|
||||
{
|
||||
if (context->getState().isRasterizerDiscardEnabled())
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// Sync the clear state
|
||||
context->syncRendererState(context->getState().clearStateBitMask());
|
||||
|
||||
return mImpl->clearBufferfi(context->getState(), buffer, drawbuffer, depth, stencil);
|
||||
return mImpl->clearBufferfi(context->getData(), buffer, drawbuffer, depth, stencil);
|
||||
}
|
||||
|
||||
GLenum Framebuffer::getImplementationColorReadFormat() const
|
||||
|
@ -66,6 +66,8 @@ class Framebuffer
|
||||
const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
|
||||
const std::vector<FramebufferAttachment> &getColorAttachments() const { return mColorAttachments; }
|
||||
|
||||
bool attachmentsHaveSameDimensions() const;
|
||||
|
||||
private:
|
||||
friend class Framebuffer;
|
||||
|
||||
@ -115,6 +117,7 @@ class Framebuffer
|
||||
bool isEnabledColorAttachment(size_t colorAttachment) const;
|
||||
bool hasEnabledColorAttachment() const;
|
||||
size_t getNumColorBuffers() const;
|
||||
bool hasDepth() const;
|
||||
bool hasStencil() const;
|
||||
int getSamples(const gl::Data &data) const;
|
||||
bool usingExtendedDrawBuffers() const;
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "angle_gl.h"
|
||||
#include "common/angleutils.h"
|
||||
#include "libANGLE/angletypes.h"
|
||||
#include "libANGLE/Error.h"
|
||||
#include "libANGLE/ImageIndex.h"
|
||||
|
||||
@ -111,8 +112,10 @@ class FramebufferAttachment final
|
||||
GLint mipLevel() const;
|
||||
GLint layer() const;
|
||||
|
||||
GLsizei getWidth() const;
|
||||
GLsizei getHeight() const;
|
||||
// The size of the underlying resource the attachment points to. The 'depth' value will
|
||||
// correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
|
||||
// Renderbuffers, it will always be 1.
|
||||
Extents getSize() const;
|
||||
GLenum getInternalFormat() const;
|
||||
GLsizei getSamples() const;
|
||||
GLenum type() const { return mType; }
|
||||
@ -148,8 +151,7 @@ class FramebufferAttachmentObject
|
||||
FramebufferAttachmentObject() {}
|
||||
virtual ~FramebufferAttachmentObject() {}
|
||||
|
||||
virtual GLsizei getAttachmentWidth(const FramebufferAttachment::Target &target) const = 0;
|
||||
virtual GLsizei getAttachmentHeight(const FramebufferAttachment::Target &target) const = 0;
|
||||
virtual Extents getAttachmentSize(const FramebufferAttachment::Target &target) const = 0;
|
||||
virtual GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &target) const = 0;
|
||||
virtual GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const = 0;
|
||||
|
||||
@ -164,14 +166,9 @@ class FramebufferAttachmentObject
|
||||
virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
|
||||
};
|
||||
|
||||
inline GLsizei FramebufferAttachment::getWidth() const
|
||||
inline Extents FramebufferAttachment::getSize() const
|
||||
{
|
||||
return mResource->getAttachmentWidth(mTarget);
|
||||
}
|
||||
|
||||
inline GLsizei FramebufferAttachment::getHeight() const
|
||||
{
|
||||
return mResource->getAttachmentHeight(mTarget);
|
||||
return mResource->getAttachmentSize(mTarget);
|
||||
}
|
||||
|
||||
inline GLenum FramebufferAttachment::getInternalFormat() const
|
||||
|
@ -225,7 +225,8 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element
|
||||
Program::Data::Data()
|
||||
: mAttachedFragmentShader(nullptr),
|
||||
mAttachedVertexShader(nullptr),
|
||||
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS)
|
||||
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
|
||||
mBinaryRetrieveableHint(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -791,6 +792,18 @@ GLint Program::getBinaryLength() const
|
||||
return length;
|
||||
}
|
||||
|
||||
void Program::setBinaryRetrievableHint(bool retrievable)
|
||||
{
|
||||
// TODO(jmadill) : replace with dirty bits
|
||||
mProgram->setBinaryRetrievableHint(retrievable);
|
||||
mData.mBinaryRetrieveableHint = retrievable;
|
||||
}
|
||||
|
||||
bool Program::getBinaryRetrievableHint() const
|
||||
{
|
||||
return mData.mBinaryRetrieveableHint;
|
||||
}
|
||||
|
||||
void Program::release()
|
||||
{
|
||||
mRefCount--;
|
||||
|
@ -215,6 +215,8 @@ class Program : angle::NonCopyable
|
||||
|
||||
// TODO(jmadill): use unordered/hash map when available
|
||||
std::map<int, VariableLocation> mOutputVariables;
|
||||
|
||||
bool mBinaryRetrieveableHint;
|
||||
};
|
||||
|
||||
Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle);
|
||||
@ -237,6 +239,8 @@ class Program : angle::NonCopyable
|
||||
Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length);
|
||||
Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const;
|
||||
GLint getBinaryLength() const;
|
||||
void setBinaryRetrievableHint(bool retrievable);
|
||||
bool getBinaryRetrievableHint() const;
|
||||
|
||||
int getInfoLogLength() const;
|
||||
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
|
||||
|
@ -165,4 +165,9 @@ GLuint Renderbuffer::getId() const
|
||||
{
|
||||
return id();
|
||||
}
|
||||
|
||||
Extents Renderbuffer::getAttachmentSize(const FramebufferAttachment::Target & /*target*/) const
|
||||
{
|
||||
return Extents(mWidth, mHeight, 1);
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,7 @@ class Renderbuffer : public egl::ImageSibling, public gl::FramebufferAttachmentO
|
||||
GLuint getStencilSize() const;
|
||||
|
||||
// FramebufferAttachmentObject Impl
|
||||
GLsizei getAttachmentWidth(const FramebufferAttachment::Target &/*target*/) const override { return getWidth(); }
|
||||
GLsizei getAttachmentHeight(const FramebufferAttachment::Target &/*target*/) const override { return getHeight(); }
|
||||
Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override;
|
||||
GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &/*target*/) const override { return getInternalFormat(); }
|
||||
GLsizei getAttachmentSamples(const FramebufferAttachment::Target &/*target*/) const override { return getSamples(); }
|
||||
|
||||
|
@ -999,17 +999,6 @@ GLuint State::getArrayBufferId() const
|
||||
return mArrayBuffer.id();
|
||||
}
|
||||
|
||||
bool State::removeArrayBufferBinding(GLuint buffer)
|
||||
{
|
||||
if (mArrayBuffer.id() == buffer)
|
||||
{
|
||||
mArrayBuffer.set(NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void State::setGenericUniformBufferBinding(Buffer *buffer)
|
||||
{
|
||||
mGenericUniformBuffer.set(buffer);
|
||||
@ -1062,6 +1051,28 @@ Buffer *State::getTargetBuffer(GLenum target) const
|
||||
}
|
||||
}
|
||||
|
||||
void State::detachBuffer(GLuint bufferName)
|
||||
{
|
||||
BindingPointer<Buffer> *buffers[] = {&mArrayBuffer, &mCopyReadBuffer,
|
||||
&mCopyWriteBuffer, &mPack.pixelBuffer,
|
||||
&mUnpack.pixelBuffer, &mGenericUniformBuffer};
|
||||
for (auto buffer : buffers)
|
||||
{
|
||||
if (buffer->id() == bufferName)
|
||||
{
|
||||
buffer->set(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
|
||||
if (curTransformFeedback)
|
||||
{
|
||||
curTransformFeedback->detachBuffer(bufferName);
|
||||
}
|
||||
|
||||
getVertexArray()->detachBuffer(bufferName);
|
||||
}
|
||||
|
||||
void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
|
||||
{
|
||||
getVertexArray()->enableAttribute(attribNum, enabled);
|
||||
@ -1286,6 +1297,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
|
||||
case GL_PRIMITIVE_RESTART_FIXED_INDEX:
|
||||
*params = mPrimitiveRestart;
|
||||
break;
|
||||
case GL_RASTERIZER_DISCARD:
|
||||
*params = isRasterizerDiscardEnabled() ? GL_TRUE : GL_FALSE;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
@ -1526,7 +1540,7 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
|
||||
*params = mGenericUniformBuffer.id();
|
||||
break;
|
||||
case GL_TRANSFORM_FEEDBACK_BINDING:
|
||||
*params = mTransformFeedback->id();
|
||||
*params = mTransformFeedback.id();
|
||||
break;
|
||||
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
|
||||
*params = mTransformFeedback->getGenericBuffer().id();
|
||||
|
@ -198,7 +198,6 @@ class State : angle::NonCopyable
|
||||
// GL_ARRAY_BUFFER
|
||||
void setArrayBufferBinding(Buffer *buffer);
|
||||
GLuint getArrayBufferId() const;
|
||||
bool removeArrayBufferBinding(GLuint buffer);
|
||||
|
||||
// GL_UNIFORM_BUFFER - Both indexed and generic targets
|
||||
void setGenericUniformBufferBinding(Buffer *buffer);
|
||||
@ -215,6 +214,8 @@ class State : angle::NonCopyable
|
||||
|
||||
// Retrieve typed buffer by target (non-indexed)
|
||||
Buffer *getTargetBuffer(GLenum target) const;
|
||||
// Detach a buffer from all bindings
|
||||
void detachBuffer(GLuint bufferName);
|
||||
|
||||
// Vertex attrib manipulation
|
||||
void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
|
||||
|
@ -185,7 +185,7 @@ Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
|
||||
|
||||
texture->bindTexImageFromSurface(this);
|
||||
mTexture.set(texture);
|
||||
return mImplementation->bindTexImage(buffer);
|
||||
return mImplementation->bindTexImage(texture, buffer);
|
||||
}
|
||||
|
||||
Error Surface::releaseTexImage(EGLint buffer)
|
||||
@ -203,6 +203,11 @@ void Surface::releaseTexImageFromTexture()
|
||||
mTexture.set(nullptr);
|
||||
}
|
||||
|
||||
gl::Extents Surface::getAttachmentSize(const gl::FramebufferAttachment::Target & /*target*/) const
|
||||
{
|
||||
return gl::Extents(getWidth(), getHeight(), 1);
|
||||
}
|
||||
|
||||
GLenum Surface::getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const
|
||||
{
|
||||
const egl::Config *config = getConfig();
|
||||
|
@ -70,8 +70,7 @@ class Surface final : public gl::FramebufferAttachmentObject
|
||||
EGLint isFixedSize() const;
|
||||
|
||||
// FramebufferAttachmentObject implementation
|
||||
GLsizei getAttachmentWidth(const gl::FramebufferAttachment::Target &/*target*/) const override { return getWidth(); }
|
||||
GLsizei getAttachmentHeight(const gl::FramebufferAttachment::Target &/*target*/) const override { return getHeight(); }
|
||||
gl::Extents getAttachmentSize(const gl::FramebufferAttachment::Target &target) const override;
|
||||
GLenum getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const override;
|
||||
GLsizei getAttachmentSamples(const gl::FramebufferAttachment::Target &target) const override;
|
||||
|
||||
|
@ -31,7 +31,7 @@ class MockSurfaceImpl : public rx::SurfaceImpl
|
||||
MOCK_METHOD0(swap, egl::Error());
|
||||
MOCK_METHOD4(postSubBuffer, egl::Error(EGLint, EGLint, EGLint, EGLint));
|
||||
MOCK_METHOD2(querySurfacePointerANGLE, egl::Error(EGLint, void**));
|
||||
MOCK_METHOD1(bindTexImage, egl::Error(EGLint));
|
||||
MOCK_METHOD2(bindTexImage, egl::Error(gl::Texture*, EGLint));
|
||||
MOCK_METHOD1(releaseTexImage, egl::Error(EGLint));
|
||||
MOCK_METHOD1(setSwapInterval, void(EGLint));
|
||||
MOCK_CONST_METHOD0(getWidth, EGLint());
|
||||
|
@ -839,16 +839,9 @@ Texture::SamplerCompletenessCache::SamplerCompletenessCache()
|
||||
{
|
||||
}
|
||||
|
||||
GLsizei Texture::getAttachmentWidth(const gl::FramebufferAttachment::Target &target) const
|
||||
Extents Texture::getAttachmentSize(const gl::FramebufferAttachment::Target &target) const
|
||||
{
|
||||
return static_cast<GLsizei>(
|
||||
getWidth(target.textureIndex().type, target.textureIndex().mipIndex));
|
||||
}
|
||||
|
||||
GLsizei Texture::getAttachmentHeight(const gl::FramebufferAttachment::Target &target) const
|
||||
{
|
||||
return static_cast<GLsizei>(
|
||||
getHeight(target.textureIndex().type, target.textureIndex().mipIndex));
|
||||
return getImageDesc(target.textureIndex().type, target.textureIndex().mipIndex).size;
|
||||
}
|
||||
|
||||
GLenum Texture::getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const
|
||||
|
@ -166,8 +166,7 @@ class Texture final : public egl::ImageSibling, public gl::FramebufferAttachment
|
||||
const rx::TextureImpl *getImplementation() const { return mTexture; }
|
||||
|
||||
// FramebufferAttachmentObject implementation
|
||||
GLsizei getAttachmentWidth(const FramebufferAttachment::Target &target) const override;
|
||||
GLsizei getAttachmentHeight(const FramebufferAttachment::Target &target) const override;
|
||||
Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override;
|
||||
GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &target) const override;
|
||||
GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const override;
|
||||
|
||||
|
@ -85,6 +85,24 @@ void TransformFeedback::bindGenericBuffer(Buffer *buffer)
|
||||
mImplementation->bindGenericBuffer(mGenericBuffer);
|
||||
}
|
||||
|
||||
void TransformFeedback::detachBuffer(GLuint bufferName)
|
||||
{
|
||||
for (size_t index = 0; index < mIndexedBuffers.size(); index++)
|
||||
{
|
||||
if (mIndexedBuffers[index].id() == bufferName)
|
||||
{
|
||||
mIndexedBuffers[index].set(nullptr);
|
||||
mImplementation->bindIndexedBuffer(index, mIndexedBuffers[index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (mGenericBuffer.id() == bufferName)
|
||||
{
|
||||
mGenericBuffer.set(nullptr);
|
||||
mImplementation->bindGenericBuffer(mGenericBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
const BindingPointer<Buffer> &TransformFeedback::getGenericBuffer() const
|
||||
{
|
||||
return mGenericBuffer;
|
||||
|
@ -45,6 +45,8 @@ class TransformFeedback : public RefCountObject
|
||||
const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const;
|
||||
size_t getIndexedBufferCount() const;
|
||||
|
||||
void detachBuffer(GLuint bufferName);
|
||||
|
||||
rx::TransformFeedbackImpl *getImplementation();
|
||||
const rx::TransformFeedbackImpl *getImplementation() const;
|
||||
|
||||
|
@ -133,4 +133,13 @@ bool Box::operator!=(const Box &other) const
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool operator==(const Extents &lhs, const Extents &rhs)
|
||||
{
|
||||
return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth;
|
||||
}
|
||||
|
||||
bool operator!=(const Extents &lhs, const Extents &rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
}
|
||||
|
@ -68,13 +68,21 @@ typedef Color<unsigned int> ColorUI;
|
||||
|
||||
struct Rectangle
|
||||
{
|
||||
Rectangle() : x(0), y(0), width(0), height(0) {}
|
||||
Rectangle(int x_in, int y_in, int width_in, int height_in)
|
||||
: x(x_in), y(y_in), width(width_in), height(height_in)
|
||||
{
|
||||
}
|
||||
|
||||
int x0() const { return x; }
|
||||
int y0() const { return y; }
|
||||
int x1() const { return x + width; }
|
||||
int y1() const { return y + height; }
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
Rectangle() : x(0), y(0), width(0), height(0) { }
|
||||
Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { }
|
||||
};
|
||||
|
||||
bool operator==(const Rectangle &a, const Rectangle &b);
|
||||
@ -104,6 +112,9 @@ struct Extents
|
||||
bool empty() const { return (width * height * depth) == 0; }
|
||||
};
|
||||
|
||||
bool operator==(const Extents &lhs, const Extents &rhs);
|
||||
bool operator!=(const Extents &lhs, const Extents &rhs);
|
||||
|
||||
struct Box
|
||||
{
|
||||
int x;
|
||||
|
@ -416,7 +416,7 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
|
||||
map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, RequireESOrExt<3, &Extensions::depthTextures>)));
|
||||
map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>)));
|
||||
map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>)));
|
||||
map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::depthTextures>, RequireExt<&Extensions::depthTextures>, AlwaysSupported )));
|
||||
map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, AlwaysSupported )));
|
||||
map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported )));
|
||||
map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3>, RequireES<3>, AlwaysSupported )));
|
||||
// STENCIL_INDEX8 is special-cased, see around the bottom of the list.
|
||||
|
@ -29,6 +29,7 @@ class DeviceImpl : angle::NonCopyable
|
||||
virtual egl::Error getDevice(void **outValue) = 0;
|
||||
virtual EGLint getType() = 0;
|
||||
virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0;
|
||||
virtual bool deviceExternallySourced() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,10 +21,7 @@ DisplayImpl::DisplayImpl()
|
||||
|
||||
DisplayImpl::~DisplayImpl()
|
||||
{
|
||||
while (!mSurfaceSet.empty())
|
||||
{
|
||||
destroySurface(*mSurfaceSet.begin());
|
||||
}
|
||||
ASSERT(mSurfaceSet.empty());
|
||||
}
|
||||
|
||||
void DisplayImpl::destroySurface(egl::Surface *surface)
|
||||
|
@ -44,10 +44,23 @@ class FramebufferImpl : angle::NonCopyable
|
||||
virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0;
|
||||
|
||||
virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0;
|
||||
virtual gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0;
|
||||
virtual gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0;
|
||||
virtual gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) = 0;
|
||||
virtual gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0;
|
||||
virtual gl::Error clearBufferfv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLfloat *values) = 0;
|
||||
virtual gl::Error clearBufferuiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLuint *values) = 0;
|
||||
virtual gl::Error clearBufferiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLint *values) = 0;
|
||||
virtual gl::Error clearBufferfi(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
GLfloat depth,
|
||||
GLint stencil) = 0;
|
||||
|
||||
virtual GLenum getImplementationColorReadFormat() const = 0;
|
||||
virtual GLenum getImplementationColorReadType() const = 0;
|
||||
@ -56,7 +69,7 @@ class FramebufferImpl : angle::NonCopyable
|
||||
virtual gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
|
||||
GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0;
|
||||
|
||||
virtual GLenum checkStatus() const = 0;
|
||||
virtual bool checkStatus() const = 0;
|
||||
|
||||
const gl::Framebuffer::Data &getData() const { return mData; }
|
||||
|
||||
|
@ -36,10 +36,10 @@ class MockFramebufferImpl : public rx::FramebufferImpl
|
||||
MOCK_METHOD3(invalidateSub, gl::Error(size_t, const GLenum *, const gl::Rectangle &));
|
||||
|
||||
MOCK_METHOD2(clear, gl::Error(const gl::Data &, GLbitfield));
|
||||
MOCK_METHOD4(clearBufferfv, gl::Error(const gl::State &, GLenum, GLint, const GLfloat *));
|
||||
MOCK_METHOD4(clearBufferuiv, gl::Error(const gl::State &, GLenum, GLint, const GLuint *));
|
||||
MOCK_METHOD4(clearBufferiv, gl::Error(const gl::State &, GLenum, GLint, const GLint *));
|
||||
MOCK_METHOD5(clearBufferfi, gl::Error(const gl::State &, GLenum, GLint, GLfloat, GLint));
|
||||
MOCK_METHOD4(clearBufferfv, gl::Error(const gl::Data &, GLenum, GLint, const GLfloat *));
|
||||
MOCK_METHOD4(clearBufferuiv, gl::Error(const gl::Data &, GLenum, GLint, const GLuint *));
|
||||
MOCK_METHOD4(clearBufferiv, gl::Error(const gl::Data &, GLenum, GLint, const GLint *));
|
||||
MOCK_METHOD5(clearBufferfi, gl::Error(const gl::Data &, GLenum, GLint, GLfloat, GLint));
|
||||
|
||||
MOCK_CONST_METHOD0(getImplementationColorReadFormat, GLenum());
|
||||
MOCK_CONST_METHOD0(getImplementationColorReadType, GLenum());
|
||||
@ -55,7 +55,7 @@ class MockFramebufferImpl : public rx::FramebufferImpl
|
||||
GLenum,
|
||||
const gl::Framebuffer *));
|
||||
|
||||
MOCK_CONST_METHOD0(checkStatus, GLenum());
|
||||
MOCK_CONST_METHOD0(checkStatus, bool());
|
||||
|
||||
MOCK_METHOD0(destroy, void());
|
||||
};
|
||||
|
@ -37,6 +37,7 @@ class ProgramImpl : angle::NonCopyable
|
||||
|
||||
virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
|
||||
virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
|
||||
virtual void setBinaryRetrievableHint(bool retrievable) = 0;
|
||||
|
||||
virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) = 0;
|
||||
virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
|
||||
|
@ -25,6 +25,7 @@ class MockProgramImpl : public rx::ProgramImpl
|
||||
|
||||
MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *));
|
||||
MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
|
||||
MOCK_METHOD1(setBinaryRetrievableHint, void(bool));
|
||||
|
||||
MOCK_METHOD2(link, LinkResult(const gl::Data &, gl::InfoLog &));
|
||||
MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *));
|
||||
|
@ -36,7 +36,7 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
|
||||
virtual egl::Error swap() = 0;
|
||||
virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
|
||||
virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0;
|
||||
virtual egl::Error bindTexImage(EGLint buffer) = 0;
|
||||
virtual egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) = 0;
|
||||
virtual egl::Error releaseTexImage(EGLint buffer) = 0;
|
||||
virtual void setSwapInterval(EGLint interval) = 0;
|
||||
|
||||
|
@ -37,10 +37,15 @@ BufferD3D::~BufferD3D()
|
||||
SafeDelete(mStaticVertexBuffer);
|
||||
SafeDelete(mStaticIndexBuffer);
|
||||
|
||||
// Empty the cache of static vertex buffers too
|
||||
emptyStaticBufferCache();
|
||||
}
|
||||
|
||||
void BufferD3D::emptyStaticBufferCache()
|
||||
{
|
||||
if (mStaticBufferCache != nullptr)
|
||||
{
|
||||
SafeDeleteContainer(*mStaticBufferCache);
|
||||
SafeDelete(mStaticBufferCache);
|
||||
}
|
||||
|
||||
mStaticBufferCacheTotalSize = 0;
|
||||
@ -202,13 +207,7 @@ void BufferD3D::invalidateStaticData(D3DBufferInvalidationType invalidationType)
|
||||
{
|
||||
if (invalidationType == D3D_BUFFER_INVALIDATE_WHOLE_CACHE && mStaticBufferCache != nullptr)
|
||||
{
|
||||
// Empty the cache of static vertex buffers too
|
||||
for (StaticVertexBufferInterface *staticBuffer : *mStaticBufferCache)
|
||||
{
|
||||
SafeDelete(staticBuffer);
|
||||
}
|
||||
mStaticBufferCache->clear();
|
||||
mStaticBufferCacheTotalSize = 0;
|
||||
emptyStaticBufferCache();
|
||||
}
|
||||
|
||||
if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
|
||||
|
@ -71,6 +71,7 @@ class BufferD3D : public BufferImpl
|
||||
protected:
|
||||
void updateSerial();
|
||||
void updateD3DBufferUsage(GLenum usage);
|
||||
void emptyStaticBufferCache();
|
||||
|
||||
BufferFactoryD3D *mFactory;
|
||||
unsigned int mSerial;
|
||||
|
@ -17,16 +17,78 @@
|
||||
namespace rx
|
||||
{
|
||||
|
||||
DeviceD3D::DeviceD3D(void *device, EGLint deviceType) : mDevice(device), mDeviceType(deviceType)
|
||||
DeviceD3D::DeviceD3D()
|
||||
: mDevice(0), mDeviceType(0), mDeviceExternallySourced(false), mIsInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
DeviceD3D::~DeviceD3D()
|
||||
{
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
|
||||
{
|
||||
// DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it.
|
||||
ID3D11Device *device = reinterpret_cast<ID3D11Device *>(mDevice);
|
||||
device->Release();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
egl::Error DeviceD3D::getDevice(void **outValue)
|
||||
{
|
||||
if (!mIsInitialized)
|
||||
{
|
||||
*outValue = nullptr;
|
||||
return egl::Error(EGL_BAD_DEVICE_EXT);
|
||||
}
|
||||
|
||||
*outValue = mDevice;
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error DeviceD3D::initialize(void *device,
|
||||
EGLint deviceType,
|
||||
EGLBoolean deviceExternallySourced)
|
||||
{
|
||||
ASSERT(!mIsInitialized);
|
||||
if (mIsInitialized)
|
||||
{
|
||||
return egl::Error(EGL_BAD_DEVICE_EXT);
|
||||
}
|
||||
|
||||
mDevice = device;
|
||||
mDeviceType = deviceType;
|
||||
mDeviceExternallySourced = !!deviceExternallySourced;
|
||||
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
|
||||
{
|
||||
// Validate the device
|
||||
IUnknown *iunknown = reinterpret_cast<IUnknown *>(device);
|
||||
|
||||
ID3D11Device *d3dDevice = nullptr;
|
||||
HRESULT hr =
|
||||
iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT");
|
||||
}
|
||||
|
||||
// The QI to ID3D11Device adds a ref to the D3D11 device.
|
||||
// Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the
|
||||
// D3D11 device.
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ASSERT(!mDeviceExternallySourced);
|
||||
}
|
||||
|
||||
mIsInitialized = true;
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
EGLint DeviceD3D::getType()
|
||||
{
|
||||
return mDeviceType;
|
||||
|
@ -18,15 +18,20 @@ namespace rx
|
||||
class DeviceD3D : public DeviceImpl
|
||||
{
|
||||
public:
|
||||
DeviceD3D(void *device, EGLint deviceType);
|
||||
DeviceD3D();
|
||||
~DeviceD3D() override;
|
||||
|
||||
egl::Error initialize(void *device, EGLint deviceType, EGLBoolean external);
|
||||
egl::Error getDevice(void **outValue) override;
|
||||
EGLint getType() override;
|
||||
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
|
||||
bool deviceExternallySourced() override { return mDeviceExternallySourced; }
|
||||
|
||||
private:
|
||||
void *mDevice;
|
||||
EGLint mDeviceType;
|
||||
bool mDeviceExternallySourced;
|
||||
bool mIsInitialized;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -55,10 +55,13 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
|
||||
|
||||
std::vector<CreateRendererD3DFunction> rendererCreationFunctions;
|
||||
|
||||
const auto &attribMap = display->getAttributeMap();
|
||||
EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
|
||||
if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
|
||||
{
|
||||
const auto &attribMap = display->getAttributeMap();
|
||||
EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
|
||||
|
||||
EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
|
||||
EGLint requestedDisplayType =
|
||||
attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
|
||||
|
||||
# if defined(ANGLE_ENABLE_D3D11)
|
||||
if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
|
||||
@ -77,27 +80,41 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
|
||||
}
|
||||
# endif
|
||||
|
||||
if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
|
||||
nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
|
||||
requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
|
||||
{
|
||||
if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
|
||||
nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
|
||||
requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
|
||||
{
|
||||
// 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(CreateTypedRendererD3D<Renderer11>);
|
||||
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
|
||||
# endif
|
||||
# if defined(ANGLE_ENABLE_D3D9)
|
||||
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
|
||||
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
|
||||
# endif
|
||||
# else
|
||||
# if defined(ANGLE_ENABLE_D3D9)
|
||||
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
|
||||
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
|
||||
# endif
|
||||
# if defined(ANGLE_ENABLE_D3D11)
|
||||
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
|
||||
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
|
||||
{
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE)
|
||||
{
|
||||
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
egl::Error result(EGL_NOT_INITIALIZED, "No available renderers.");
|
||||
|
@ -125,13 +125,16 @@ gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask)
|
||||
{
|
||||
const gl::State &state = *data.state;
|
||||
ClearParameters clearParams = GetClearParameters(state, mask);
|
||||
return clear(state, clearParams);
|
||||
return clear(data, clearParams);
|
||||
}
|
||||
|
||||
gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
|
||||
gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLfloat *values)
|
||||
{
|
||||
// glClearBufferfv can be called to clear the color buffer or depth buffer
|
||||
ClearParameters clearParams = GetClearParameters(state, 0);
|
||||
ClearParameters clearParams = GetClearParameters(*data.state, 0);
|
||||
|
||||
if (buffer == GL_COLOR)
|
||||
{
|
||||
@ -149,13 +152,16 @@ gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, G
|
||||
clearParams.depthClearValue = values[0];
|
||||
}
|
||||
|
||||
return clear(state, clearParams);
|
||||
return clear(data, clearParams);
|
||||
}
|
||||
|
||||
gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
|
||||
gl::Error FramebufferD3D::clearBufferuiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLuint *values)
|
||||
{
|
||||
// glClearBufferuiv can only be called to clear a color buffer
|
||||
ClearParameters clearParams = GetClearParameters(state, 0);
|
||||
ClearParameters clearParams = GetClearParameters(*data.state, 0);
|
||||
for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
|
||||
{
|
||||
clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
|
||||
@ -163,13 +169,16 @@ gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer,
|
||||
clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
|
||||
clearParams.colorClearType = GL_UNSIGNED_INT;
|
||||
|
||||
return clear(state, clearParams);
|
||||
return clear(data, clearParams);
|
||||
}
|
||||
|
||||
gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
|
||||
gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLint *values)
|
||||
{
|
||||
// glClearBufferiv can be called to clear the color buffer or stencil buffer
|
||||
ClearParameters clearParams = GetClearParameters(state, 0);
|
||||
ClearParameters clearParams = GetClearParameters(*data.state, 0);
|
||||
|
||||
if (buffer == GL_COLOR)
|
||||
{
|
||||
@ -187,19 +196,23 @@ gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, G
|
||||
clearParams.stencilClearValue = values[1];
|
||||
}
|
||||
|
||||
return clear(state, clearParams);
|
||||
return clear(data, clearParams);
|
||||
}
|
||||
|
||||
gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
|
||||
gl::Error FramebufferD3D::clearBufferfi(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
GLfloat depth,
|
||||
GLint stencil)
|
||||
{
|
||||
// glClearBufferfi can only be called to clear a depth stencil buffer
|
||||
ClearParameters clearParams = GetClearParameters(state, 0);
|
||||
ClearParameters clearParams = GetClearParameters(*data.state, 0);
|
||||
clearParams.clearDepth = true;
|
||||
clearParams.depthClearValue = depth;
|
||||
clearParams.clearStencil = true;
|
||||
clearParams.stencilClearValue = stencil;
|
||||
|
||||
return clear(state, clearParams);
|
||||
return clear(data, clearParams);
|
||||
}
|
||||
|
||||
GLenum FramebufferD3D::getImplementationColorReadFormat() const
|
||||
@ -302,14 +315,14 @@ gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sour
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
GLenum FramebufferD3D::checkStatus() const
|
||||
bool FramebufferD3D::checkStatus() const
|
||||
{
|
||||
// if we have both a depth and stencil buffer, they must refer to the same object
|
||||
// since we only support packed_depth_stencil and not separate depth and stencil
|
||||
if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr &&
|
||||
mData.getDepthStencilAttachment() == nullptr)
|
||||
{
|
||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
return false;
|
||||
}
|
||||
|
||||
// D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
|
||||
@ -326,13 +339,19 @@ GLenum FramebufferD3D::checkStatus() const
|
||||
(attachment.id() == prevAttachment.id() &&
|
||||
attachment.type() == prevAttachment.type()))
|
||||
{
|
||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GL_FRAMEBUFFER_COMPLETE;
|
||||
// D3D requires all render targets to have the same dimensions.
|
||||
if (!mData.attachmentsHaveSameDimensions())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(
|
||||
|
@ -67,10 +67,23 @@ class FramebufferD3D : public FramebufferImpl
|
||||
void setReadBuffer(GLenum buffer) override;
|
||||
|
||||
gl::Error clear(const gl::Data &data, GLbitfield mask) override;
|
||||
gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override;
|
||||
gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override;
|
||||
gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override;
|
||||
gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override;
|
||||
gl::Error clearBufferfv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLfloat *values) override;
|
||||
gl::Error clearBufferuiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLuint *values) override;
|
||||
gl::Error clearBufferiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLint *values) override;
|
||||
gl::Error clearBufferfi(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
GLfloat depth,
|
||||
GLint stencil) override;
|
||||
|
||||
GLenum getImplementationColorReadFormat() const override;
|
||||
GLenum getImplementationColorReadType() const override;
|
||||
@ -79,7 +92,7 @@ class FramebufferD3D : public FramebufferImpl
|
||||
gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
|
||||
GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
|
||||
|
||||
GLenum checkStatus() const override;
|
||||
bool checkStatus() const override;
|
||||
|
||||
const gl::AttachmentList &getColorAttachmentsForRender(const WorkaroundsD3D &workarounds) const;
|
||||
|
||||
@ -89,7 +102,7 @@ class FramebufferD3D : public FramebufferImpl
|
||||
mutable bool mInvalidateColorAttachmentCache;
|
||||
|
||||
private:
|
||||
virtual gl::Error clear(const gl::State &state, const ClearParameters &clearParams) = 0;
|
||||
virtual gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) = 0;
|
||||
|
||||
virtual gl::Error readPixelsImpl(const gl::Rectangle &area,
|
||||
GLenum format,
|
||||
|
@ -423,8 +423,7 @@ bool ProgramD3DMetadata::usesBroadcast(const gl::Data &data) const
|
||||
|
||||
bool ProgramD3DMetadata::usesFragDepth(const gl::Program::Data &programData) const
|
||||
{
|
||||
// TODO(jmadill): Rename this or check if we need it for version 300
|
||||
return (getMajorShaderVersion() < 300 && mFragmentShader->usesFragDepth());
|
||||
return mFragmentShader->usesFragDepth();
|
||||
}
|
||||
|
||||
bool ProgramD3DMetadata::usesPointCoord() const
|
||||
@ -1105,6 +1104,10 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
|
||||
{
|
||||
}
|
||||
|
||||
gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
|
||||
ShaderExecutableD3D **outExecutable)
|
||||
{
|
||||
|
@ -150,8 +150,9 @@ class ProgramD3D : public ProgramImpl
|
||||
bool usesGeometryShader(GLenum drawMode) const;
|
||||
bool usesInstancedPointSpriteEmulation() const;
|
||||
|
||||
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
|
||||
gl::Error save(gl::BinaryOutputStream *stream);
|
||||
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
|
||||
gl::Error save(gl::BinaryOutputStream *stream) override;
|
||||
void setBinaryRetrievableHint(bool retrievable) override;
|
||||
|
||||
gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
|
||||
ShaderExecutableD3D **outExectuable);
|
||||
|
@ -45,8 +45,7 @@ RendererD3D::RendererD3D(egl::Display *display)
|
||||
mDeviceLost(false),
|
||||
mAnnotator(nullptr),
|
||||
mScratchMemoryBufferResetCounter(0),
|
||||
mWorkaroundsInitialized(false),
|
||||
mEGLDevice(nullptr)
|
||||
mWorkaroundsInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,8 +56,6 @@ RendererD3D::~RendererD3D()
|
||||
|
||||
void RendererD3D::cleanup()
|
||||
{
|
||||
SafeDelete(mEGLDevice);
|
||||
|
||||
mScratchMemoryBuffer.resize(0);
|
||||
for (auto &incompleteTexture : mIncompleteTextures)
|
||||
{
|
||||
@ -156,13 +153,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
error = applyRenderTarget(data, mode, false);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
error = applyState(data, mode);
|
||||
error = updateState(data, mode);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
@ -246,13 +237,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data,
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
error = applyRenderTarget(data, mode, false);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
error = applyState(data, mode);
|
||||
error = updateState(data, mode);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
@ -346,45 +331,8 @@ gl::Error RendererD3D::generateSwizzles(const gl::Data &data)
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// Applies the render target surface, depth stencil surface, viewport rectangle and
|
||||
// scissor rectangle to the renderer
|
||||
gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport)
|
||||
unsigned int RendererD3D::GetBlendSampleMask(const gl::Data &data, int samples)
|
||||
{
|
||||
const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
|
||||
ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
gl::Error error = applyRenderTarget(framebufferObject);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
float nearZ = data.state->getNearPlane();
|
||||
float farZ = data.state->getFarPlane();
|
||||
setViewport(data.state->getViewport(), nearZ, farZ, drawMode,
|
||||
data.state->getRasterizerState().frontFace, ignoreViewport);
|
||||
|
||||
setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
|
||||
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device
|
||||
gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
|
||||
{
|
||||
const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
|
||||
int samples = framebufferObject->getSamples(data);
|
||||
|
||||
gl::RasterizerState rasterizer = data.state->getRasterizerState();
|
||||
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
|
||||
rasterizer.multiSample = (samples != 0);
|
||||
|
||||
gl::Error error = setRasterizerState(rasterizer);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
unsigned int mask = 0;
|
||||
if (data.state->isSampleCoverageEnabled())
|
||||
{
|
||||
@ -415,21 +363,8 @@ gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
|
||||
{
|
||||
mask = 0xFFFFFFFF;
|
||||
}
|
||||
error = setBlendState(framebufferObject, data.state->getBlendState(),
|
||||
data.state->getBlendColor(), mask);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(),
|
||||
data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
return mask;
|
||||
}
|
||||
|
||||
// Applies the shaders and shader constants to the Direct3D device
|
||||
@ -737,17 +672,4 @@ gl::DebugAnnotator *RendererD3D::getAnnotator()
|
||||
ASSERT(mAnnotator);
|
||||
return mAnnotator;
|
||||
}
|
||||
|
||||
egl::Error RendererD3D::getEGLDevice(DeviceImpl **device)
|
||||
{
|
||||
egl::Error error = initializeEGLDevice(&mEGLDevice);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
*device = static_cast<DeviceImpl *>(mEGLDevice);
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
@ -153,18 +153,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
|
||||
const std::vector<GLint> &vertexUniformBuffers,
|
||||
const std::vector<GLint> &fragmentUniformBuffers) = 0;
|
||||
|
||||
virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0;
|
||||
virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer,
|
||||
const gl::BlendState &blendState,
|
||||
const gl::ColorF &blendColor,
|
||||
unsigned int sampleMask) = 0;
|
||||
|
||||
virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
|
||||
int stencilBackRef, bool frontFaceCCW) = 0;
|
||||
|
||||
virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0;
|
||||
virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
|
||||
bool ignoreViewport) = 0;
|
||||
virtual gl::Error updateState(const gl::Data &data, GLenum drawMode) = 0;
|
||||
|
||||
virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0;
|
||||
virtual gl::Error applyUniforms(const ProgramD3D &programD3D,
|
||||
@ -255,7 +244,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
|
||||
// In D3D11, faster than calling setTexture a jillion times
|
||||
virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0;
|
||||
|
||||
egl::Error getEGLDevice(DeviceImpl **device);
|
||||
virtual egl::Error getEGLDevice(DeviceImpl **device) = 0;
|
||||
|
||||
protected:
|
||||
virtual bool getLUID(LUID *adapterLuid) const = 0;
|
||||
@ -265,8 +254,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
|
||||
|
||||
virtual void createAnnotator() = 0;
|
||||
|
||||
virtual egl::Error initializeEGLDevice(DeviceD3D **outDevice) = 0;
|
||||
|
||||
static unsigned int GetBlendSampleMask(const gl::Data &data, int samples);
|
||||
// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
|
||||
static const uintptr_t DirtyPointer;
|
||||
|
||||
@ -311,7 +299,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
|
||||
gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type);
|
||||
gl::Error generateSwizzles(const gl::Data &data);
|
||||
|
||||
gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport);
|
||||
gl::Error applyState(const gl::Data &data, GLenum drawMode);
|
||||
gl::Error applyShaders(const gl::Data &data, GLenum drawMode);
|
||||
gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType,
|
||||
@ -334,8 +321,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
|
||||
|
||||
mutable bool mWorkaroundsInitialized;
|
||||
mutable WorkaroundsD3D mWorkarounds;
|
||||
|
||||
DeviceD3D *mEGLDevice;
|
||||
};
|
||||
|
||||
struct dx_VertexConstants
|
||||
|
@ -91,7 +91,7 @@ FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::Framebuffer::Dat
|
||||
return mRenderer->createFramebuffer(data);
|
||||
}
|
||||
|
||||
egl::Error SurfaceD3D::bindTexImage(EGLint)
|
||||
egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint)
|
||||
{
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class SurfaceD3D : public SurfaceImpl
|
||||
egl::Error swap() override;
|
||||
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
|
||||
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
|
||||
egl::Error bindTexImage(EGLint buffer) override;
|
||||
egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
|
||||
egl::Error releaseTexImage(EGLint buffer) override;
|
||||
void setSwapInterval(EGLint interval) override;
|
||||
|
||||
|
@ -196,6 +196,23 @@ inline unsigned int GetSwizzleIndex(GLenum swizzle)
|
||||
return colorIndex;
|
||||
}
|
||||
|
||||
D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc()
|
||||
{
|
||||
D3D11_BLEND_DESC desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.RenderTarget[0].BlendEnable = TRUE;
|
||||
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
|
||||
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED |
|
||||
D3D11_COLOR_WRITE_ENABLE_GREEN |
|
||||
D3D11_COLOR_WRITE_ENABLE_BLUE;
|
||||
return desc;
|
||||
}
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC quad2DLayout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
@ -236,6 +253,7 @@ Blit11::Blit11(Renderer11 *renderer)
|
||||
"Blit11 3D input layout"),
|
||||
mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"),
|
||||
mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"),
|
||||
mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"),
|
||||
mSwizzleCB(nullptr)
|
||||
{
|
||||
}
|
||||
@ -729,9 +747,16 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error 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)
|
||||
gl::Error 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,
|
||||
bool maskOffAlpha)
|
||||
{
|
||||
gl::Error error = initResources();
|
||||
if (error.isError())
|
||||
@ -784,7 +809,16 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s
|
||||
deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
|
||||
|
||||
// Apply state
|
||||
deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
|
||||
if (maskOffAlpha)
|
||||
{
|
||||
ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice());
|
||||
ASSERT(blendState);
|
||||
deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
|
||||
}
|
||||
deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
|
||||
|
||||
if (scissor)
|
||||
|
@ -29,9 +29,16 @@ class Blit11 : angle::NonCopyable
|
||||
gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
|
||||
GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
|
||||
|
||||
gl::Error 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);
|
||||
gl::Error 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 maskOffAlpha);
|
||||
|
||||
gl::Error 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,
|
||||
@ -167,6 +174,8 @@ class Blit11 : angle::NonCopyable
|
||||
d3d11::LazyShader<ID3D11VertexShader> mQuad3DVS;
|
||||
d3d11::LazyShader<ID3D11GeometryShader> mQuad3DGS;
|
||||
|
||||
d3d11::LazyBlendState mAlphaMaskBlendState;
|
||||
|
||||
ID3D11Buffer *mSwizzleCB;
|
||||
};
|
||||
|
||||
|
@ -229,21 +229,15 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl
|
||||
const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment();
|
||||
if (colorAttachment != nullptr)
|
||||
{
|
||||
framebufferSize.width = colorAttachment->getWidth();
|
||||
framebufferSize.height = colorAttachment->getHeight();
|
||||
framebufferSize.depth = 1;
|
||||
framebufferSize = colorAttachment->getSize();
|
||||
}
|
||||
else if (depthAttachment != nullptr)
|
||||
{
|
||||
framebufferSize.width = depthAttachment->getWidth();
|
||||
framebufferSize.height = depthAttachment->getHeight();
|
||||
framebufferSize.depth = 1;
|
||||
framebufferSize = depthAttachment->getSize();
|
||||
}
|
||||
else if (stencilAttachment != nullptr)
|
||||
{
|
||||
framebufferSize.width = stencilAttachment->getWidth();
|
||||
framebufferSize.height = stencilAttachment->getHeight();
|
||||
framebufferSize.depth = 1;
|
||||
framebufferSize = stencilAttachment->getSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ gl::Error Framebuffer11::invalidateSwizzles() const
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error Framebuffer11::clear(const gl::State &state, const ClearParameters &clearParams)
|
||||
gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clearParams)
|
||||
{
|
||||
Clear11 *clearer = mRenderer->getClearer();
|
||||
gl::Error error = clearer->clearFramebuffer(clearParams, mData);
|
||||
|
@ -29,7 +29,7 @@ class Framebuffer11 : public FramebufferD3D
|
||||
gl::Error invalidateSwizzles() const;
|
||||
|
||||
private:
|
||||
gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
|
||||
gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override;
|
||||
|
||||
gl::Error readPixelsImpl(const gl::Rectangle &area,
|
||||
GLenum format,
|
||||
|
@ -317,58 +317,11 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
|
||||
}
|
||||
|
||||
ID3D11InputLayout *inputLayout = nullptr;
|
||||
|
||||
auto layoutMapIt = mLayoutMap.find(layout);
|
||||
if (layoutMapIt != mLayoutMap.end())
|
||||
gl::Error error = findInputLayout(layout, inputElementCount, inputElements, programD3D,
|
||||
sortedAttributes, unsortedAttributes.size(), &inputLayout);
|
||||
if (error.isError())
|
||||
{
|
||||
inputLayout = layoutMapIt->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
const gl::InputLayout &shaderInputLayout =
|
||||
GetInputLayout(sortedAttributes, unsortedAttributes.size());
|
||||
|
||||
ShaderExecutableD3D *shader = nullptr;
|
||||
gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
|
||||
for (unsigned int j = 0; j < inputElementCount; ++j)
|
||||
{
|
||||
descs[j] = inputElements[j];
|
||||
}
|
||||
|
||||
HRESULT result = mDevice->CreateInputLayout(descs, inputElementCount, shader11->getFunction(), shader11->getLength(), &inputLayout);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result);
|
||||
}
|
||||
|
||||
if (mLayoutMap.size() >= mCacheSize)
|
||||
{
|
||||
TRACE("Overflowed the limit of %u input layouts, purging half the cache.", mCacheSize);
|
||||
|
||||
// Randomly release every second element
|
||||
auto it = mLayoutMap.begin();
|
||||
while (it != mLayoutMap.end())
|
||||
{
|
||||
it++;
|
||||
if (it != mLayoutMap.end())
|
||||
{
|
||||
// Calling std::map::erase invalidates the current iterator, so make a copy.
|
||||
auto eraseIt = it++;
|
||||
SafeRelease(eraseIt->second);
|
||||
mLayoutMap.erase(eraseIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mLayoutMap[layout] = inputLayout;
|
||||
return error;
|
||||
}
|
||||
|
||||
if (inputLayout != mCurrentIL)
|
||||
@ -406,7 +359,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
|
||||
if (sourceInfo->srcBuffer != nullptr)
|
||||
{
|
||||
const uint8_t *bufferData = nullptr;
|
||||
gl::Error error = sourceInfo->srcBuffer->getData(&bufferData);
|
||||
error = sourceInfo->srcBuffer->getData(&bufferData);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
@ -561,4 +514,70 @@ gl::Error InputLayoutCache::applyVertexBuffers(const std::vector<TranslatedAttri
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error InputLayoutCache::findInputLayout(
|
||||
const PackedAttributeLayout &layout,
|
||||
unsigned int inputElementCount,
|
||||
const D3D11_INPUT_ELEMENT_DESC inputElements[gl::MAX_VERTEX_ATTRIBS],
|
||||
ProgramD3D *programD3D,
|
||||
const TranslatedAttribute *sortedAttributes[gl::MAX_VERTEX_ATTRIBS],
|
||||
size_t attributeCount,
|
||||
ID3D11InputLayout **inputLayout)
|
||||
{
|
||||
if (inputElementCount == 0)
|
||||
{
|
||||
*inputLayout = nullptr;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
auto layoutMapIt = mLayoutMap.find(layout);
|
||||
if (layoutMapIt != mLayoutMap.end())
|
||||
{
|
||||
*inputLayout = layoutMapIt->second;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
const gl::InputLayout &shaderInputLayout = GetInputLayout(sortedAttributes, attributeCount);
|
||||
|
||||
ShaderExecutableD3D *shader = nullptr;
|
||||
gl::Error error =
|
||||
programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
|
||||
|
||||
HRESULT result =
|
||||
mDevice->CreateInputLayout(inputElements, inputElementCount, shader11->getFunction(),
|
||||
shader11->getLength(), inputLayout);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return gl::Error(GL_OUT_OF_MEMORY,
|
||||
"Failed to create internal input layout, HRESULT: 0x%08x", result);
|
||||
}
|
||||
|
||||
if (mLayoutMap.size() >= mCacheSize)
|
||||
{
|
||||
TRACE("Overflowed the limit of %u input layouts, purging half the cache.", mCacheSize);
|
||||
|
||||
// Randomly release every second element
|
||||
auto it = mLayoutMap.begin();
|
||||
while (it != mLayoutMap.end())
|
||||
{
|
||||
it++;
|
||||
if (it != mLayoutMap.end())
|
||||
{
|
||||
// Calling std::map::erase invalidates the current iterator, so make a copy.
|
||||
auto eraseIt = it++;
|
||||
SafeRelease(eraseIt->second);
|
||||
mLayoutMap.erase(eraseIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mLayoutMap[layout] = *inputLayout;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
@ -31,6 +31,7 @@ namespace rx
|
||||
struct TranslatedAttribute;
|
||||
struct TranslatedIndexData;
|
||||
struct SourceIndexData;
|
||||
class ProgramD3D;
|
||||
|
||||
class InputLayoutCache : angle::NonCopyable
|
||||
{
|
||||
@ -76,6 +77,14 @@ class InputLayoutCache : angle::NonCopyable
|
||||
uint32_t attributeData[gl::MAX_VERTEX_ATTRIBS];
|
||||
};
|
||||
|
||||
gl::Error findInputLayout(const PackedAttributeLayout &layout,
|
||||
unsigned int inputElementCount,
|
||||
const D3D11_INPUT_ELEMENT_DESC inputElements[gl::MAX_VERTEX_ATTRIBS],
|
||||
ProgramD3D *programD3D,
|
||||
const TranslatedAttribute *sortedAttributes[gl::MAX_VERTEX_ATTRIBS],
|
||||
size_t attributeCount,
|
||||
ID3D11InputLayout **inputLayout);
|
||||
|
||||
std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap;
|
||||
|
||||
ID3D11InputLayout *mCurrentIL;
|
||||
@ -94,6 +103,6 @@ class InputLayoutCache : angle::NonCopyable
|
||||
D3D_FEATURE_LEVEL mFeatureLevel;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace rx
|
||||
|
||||
#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
namespace rx
|
||||
{
|
||||
using namespace gl_d3d11;
|
||||
|
||||
template <typename mapType>
|
||||
static void ClearStateMap(mapType &map)
|
||||
@ -297,14 +298,31 @@ bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a,
|
||||
return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
|
||||
}
|
||||
|
||||
gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState)
|
||||
gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState,
|
||||
bool disableDepth,
|
||||
bool disableStencil,
|
||||
ID3D11DepthStencilState **outDSState)
|
||||
{
|
||||
if (!mDevice)
|
||||
{
|
||||
return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
|
||||
}
|
||||
|
||||
DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState);
|
||||
gl::DepthStencilState glState = originalState;
|
||||
if (disableDepth)
|
||||
{
|
||||
glState.depthTest = false;
|
||||
glState.depthMask = false;
|
||||
}
|
||||
|
||||
if (disableStencil)
|
||||
{
|
||||
glState.stencilWritemask = 0;
|
||||
glState.stencilBackWritemask = 0;
|
||||
glState.stencilTest = false;
|
||||
}
|
||||
|
||||
auto keyIter = mDepthStencilStateCache.find(glState);
|
||||
if (keyIter != mDepthStencilStateCache.end())
|
||||
{
|
||||
DepthStencilStateCounterPair &state = keyIter->second;
|
||||
@ -312,53 +330,55 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &ds
|
||||
*outDSState = state.first;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
else
|
||||
|
||||
if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
|
||||
{
|
||||
if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
|
||||
{
|
||||
TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used "
|
||||
"to make room.", kMaxDepthStencilStates);
|
||||
TRACE(
|
||||
"Overflowed the limit of %u depth stencil states, removing the least recently used "
|
||||
"to make room.",
|
||||
kMaxDepthStencilStates);
|
||||
|
||||
DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin();
|
||||
for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
|
||||
auto leastRecentlyUsed = mDepthStencilStateCache.begin();
|
||||
for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
|
||||
{
|
||||
if (i->second.second < leastRecentlyUsed->second.second)
|
||||
{
|
||||
if (i->second.second < leastRecentlyUsed->second.second)
|
||||
{
|
||||
leastRecentlyUsed = i;
|
||||
}
|
||||
leastRecentlyUsed = i;
|
||||
}
|
||||
SafeRelease(leastRecentlyUsed->second.first);
|
||||
mDepthStencilStateCache.erase(leastRecentlyUsed);
|
||||
}
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 };
|
||||
dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE;
|
||||
dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask);
|
||||
dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc);
|
||||
dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE;
|
||||
dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask);
|
||||
dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask);
|
||||
dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail);
|
||||
dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail);
|
||||
dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass);
|
||||
dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc);
|
||||
dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail);
|
||||
dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail);
|
||||
dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass);
|
||||
dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc);
|
||||
|
||||
ID3D11DepthStencilState *dx11DepthStencilState = NULL;
|
||||
HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
|
||||
if (FAILED(result) || !dx11DepthStencilState)
|
||||
{
|
||||
return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
|
||||
}
|
||||
|
||||
mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++)));
|
||||
|
||||
*outDSState = dx11DepthStencilState;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
SafeRelease(leastRecentlyUsed->second.first);
|
||||
mDepthStencilStateCache.erase(leastRecentlyUsed);
|
||||
}
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC dsDesc = {0};
|
||||
dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE;
|
||||
dsDesc.DepthWriteMask = ConvertDepthMask(glState.depthMask);
|
||||
dsDesc.DepthFunc = ConvertComparison(glState.depthFunc);
|
||||
dsDesc.StencilEnable = glState.stencilTest ? TRUE : FALSE;
|
||||
dsDesc.StencilReadMask = ConvertStencilMask(glState.stencilMask);
|
||||
dsDesc.StencilWriteMask = ConvertStencilMask(glState.stencilWritemask);
|
||||
dsDesc.FrontFace.StencilFailOp = ConvertStencilOp(glState.stencilFail);
|
||||
dsDesc.FrontFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilPassDepthFail);
|
||||
dsDesc.FrontFace.StencilPassOp = ConvertStencilOp(glState.stencilPassDepthPass);
|
||||
dsDesc.FrontFace.StencilFunc = ConvertComparison(glState.stencilFunc);
|
||||
dsDesc.BackFace.StencilFailOp = ConvertStencilOp(glState.stencilBackFail);
|
||||
dsDesc.BackFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilBackPassDepthFail);
|
||||
dsDesc.BackFace.StencilPassOp = ConvertStencilOp(glState.stencilBackPassDepthPass);
|
||||
dsDesc.BackFace.StencilFunc = ConvertComparison(glState.stencilBackFunc);
|
||||
|
||||
ID3D11DepthStencilState *dx11DepthStencilState = NULL;
|
||||
HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
|
||||
if (FAILED(result) || !dx11DepthStencilState)
|
||||
{
|
||||
return gl::Error(GL_OUT_OF_MEMORY,
|
||||
"Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
|
||||
}
|
||||
|
||||
mDepthStencilStateCache.insert(
|
||||
std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++)));
|
||||
|
||||
*outDSState = dx11DepthStencilState;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState)
|
||||
|
@ -36,7 +36,10 @@ class RenderStateCache : angle::NonCopyable
|
||||
|
||||
gl::Error getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, ID3D11BlendState **outBlendState);
|
||||
gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState);
|
||||
gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState);
|
||||
gl::Error getDepthStencilState(const gl::DepthStencilState &dsState,
|
||||
bool disableDepth,
|
||||
bool disableStencil,
|
||||
ID3D11DepthStencilState **outDSState);
|
||||
gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
|
||||
|
||||
private:
|
||||
|
@ -470,8 +470,7 @@ void Renderer11::SRVCache::clear()
|
||||
Renderer11::Renderer11(egl::Display *display)
|
||||
: RendererD3D(display),
|
||||
mStateCache(this),
|
||||
mCurStencilSize(0),
|
||||
mStateManager(this),
|
||||
mStateManager(),
|
||||
mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()),
|
||||
mDebug(nullptr)
|
||||
{
|
||||
@ -500,6 +499,8 @@ Renderer11::Renderer11(egl::Display *display)
|
||||
|
||||
mD3d11Module = NULL;
|
||||
mDxgiModule = NULL;
|
||||
mCreatedWithDeviceEXT = false;
|
||||
mEGLDevice = nullptr;
|
||||
|
||||
mDevice = NULL;
|
||||
mDeviceContext = NULL;
|
||||
@ -518,58 +519,69 @@ Renderer11::Renderer11(egl::Display *display)
|
||||
|
||||
ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
|
||||
|
||||
const auto &attributes = mDisplay->getAttributeMap();
|
||||
|
||||
EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
|
||||
EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
|
||||
|
||||
if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
|
||||
if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
|
||||
{
|
||||
if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
|
||||
const auto &attributes = mDisplay->getAttributeMap();
|
||||
|
||||
EGLint requestedMajorVersion =
|
||||
attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
|
||||
EGLint requestedMinorVersion =
|
||||
attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
|
||||
|
||||
if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
|
||||
{
|
||||
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
|
||||
if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
|
||||
{
|
||||
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
|
||||
{
|
||||
if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
|
||||
{
|
||||
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
|
||||
}
|
||||
if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
|
||||
{
|
||||
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
|
||||
{
|
||||
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
|
||||
}
|
||||
|
||||
EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
|
||||
switch (requestedDeviceType)
|
||||
{
|
||||
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
|
||||
mDriverType = D3D_DRIVER_TYPE_HARDWARE;
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
|
||||
mDriverType = D3D_DRIVER_TYPE_WARP;
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
|
||||
mDriverType = D3D_DRIVER_TYPE_REFERENCE;
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
|
||||
mDriverType = D3D_DRIVER_TYPE_NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
|
||||
else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
|
||||
{
|
||||
if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
|
||||
{
|
||||
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
|
||||
}
|
||||
if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
|
||||
{
|
||||
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
|
||||
{
|
||||
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
|
||||
}
|
||||
|
||||
EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
|
||||
switch (requestedDeviceType)
|
||||
{
|
||||
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
|
||||
mDriverType = D3D_DRIVER_TYPE_HARDWARE;
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
|
||||
mDriverType = D3D_DRIVER_TYPE_WARP;
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
|
||||
mDriverType = D3D_DRIVER_TYPE_REFERENCE;
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
|
||||
mDriverType = D3D_DRIVER_TYPE_NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
mEGLDevice = GetImplAs<DeviceD3D>(display->getDevice());
|
||||
ASSERT(mEGLDevice != nullptr);
|
||||
mCreatedWithDeviceEXT = true;
|
||||
}
|
||||
|
||||
initializeDebugAnnotator();
|
||||
@ -586,68 +598,12 @@ Renderer11::~Renderer11()
|
||||
|
||||
egl::Error Renderer11::initialize()
|
||||
{
|
||||
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
|
||||
PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
|
||||
{
|
||||
SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
|
||||
TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
|
||||
mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
|
||||
mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
|
||||
|
||||
if (mD3d11Module == nullptr || mDxgiModule == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_NOT_INITIALIZED,
|
||||
D3D11_INIT_MISSING_DEP,
|
||||
"Could not load D3D11 or DXGI library.");
|
||||
}
|
||||
|
||||
// create the D3D11 device
|
||||
ASSERT(mDevice == nullptr);
|
||||
D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
|
||||
|
||||
if (D3D11CreateDevice == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_NOT_INITIALIZED,
|
||||
D3D11_INIT_MISSING_DEP,
|
||||
"Could not retrieve D3D11CreateDevice address.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT result = S_OK;
|
||||
#ifdef _DEBUG
|
||||
|
||||
egl::Error error = initializeD3DDevice();
|
||||
if (error.isError())
|
||||
{
|
||||
TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
|
||||
result = D3D11CreateDevice(
|
||||
NULL, mDriverType, NULL, D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(),
|
||||
static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice,
|
||||
&(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
|
||||
}
|
||||
|
||||
if (!mDevice || FAILED(result))
|
||||
{
|
||||
ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
|
||||
}
|
||||
|
||||
if (!mDevice || FAILED(result))
|
||||
#endif
|
||||
{
|
||||
SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
|
||||
TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
|
||||
|
||||
result = D3D11CreateDevice(NULL, mDriverType, NULL, 0, mAvailableFeatureLevels.data(),
|
||||
static_cast<unsigned int>(mAvailableFeatureLevels.size()),
|
||||
D3D11_SDK_VERSION, &mDevice,
|
||||
&(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
|
||||
|
||||
// Cleanup done by destructor
|
||||
if (!mDevice || FAILED(result))
|
||||
{
|
||||
ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError", static_cast<int>(result));
|
||||
return egl::Error(EGL_NOT_INITIALIZED,
|
||||
D3D11_INIT_CREATEDEVICE_ERROR,
|
||||
"Could not create D3D11 device.");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
|
||||
@ -796,6 +752,106 @@ egl::Error Renderer11::initialize()
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error Renderer11::initializeD3DDevice()
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
|
||||
if (!mCreatedWithDeviceEXT)
|
||||
{
|
||||
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
|
||||
PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
|
||||
{
|
||||
SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS");
|
||||
TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
|
||||
mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
|
||||
mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
|
||||
|
||||
if (mD3d11Module == nullptr || mDxgiModule == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
|
||||
"Could not load D3D11 or DXGI library.");
|
||||
}
|
||||
|
||||
// create the D3D11 device
|
||||
ASSERT(mDevice == nullptr);
|
||||
D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
|
||||
GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
|
||||
|
||||
if (D3D11CreateDevice == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
|
||||
"Could not retrieve D3D11CreateDevice address.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
|
||||
result = D3D11CreateDevice(
|
||||
NULL, mDriverType, NULL, D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(),
|
||||
static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION,
|
||||
&mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
|
||||
}
|
||||
|
||||
if (!mDevice || FAILED(result))
|
||||
{
|
||||
ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
|
||||
}
|
||||
|
||||
if (!mDevice || FAILED(result))
|
||||
#endif
|
||||
{
|
||||
SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
|
||||
TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
|
||||
|
||||
result = D3D11CreateDevice(NULL, mDriverType, NULL, 0, mAvailableFeatureLevels.data(),
|
||||
static_cast<unsigned int>(mAvailableFeatureLevels.size()),
|
||||
D3D11_SDK_VERSION, &mDevice,
|
||||
&(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
|
||||
|
||||
// Cleanup done by destructor
|
||||
if (!mDevice || FAILED(result))
|
||||
{
|
||||
ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
|
||||
static_cast<int>(result));
|
||||
return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR,
|
||||
"Could not create D3D11 device.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should use the inputted D3D11 device instead
|
||||
void *device = nullptr;
|
||||
egl::Error error = mEGLDevice->getDevice(&device);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device);
|
||||
if (FAILED(d3dDevice->GetDeviceRemovedReason()))
|
||||
{
|
||||
return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost.");
|
||||
}
|
||||
|
||||
if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
|
||||
{
|
||||
return egl::Error(EGL_NOT_INITIALIZED,
|
||||
"Inputted D3D11 device must be Feature Level 9_3 or greater.");
|
||||
}
|
||||
|
||||
// The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
|
||||
mDevice = d3dDevice;
|
||||
mDevice->AddRef();
|
||||
mDevice->GetImmediateContext(&mDeviceContext);
|
||||
mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -834,6 +890,8 @@ void Renderer11::initializeDevice()
|
||||
ASSERT(!mPixelTransfer);
|
||||
mPixelTransfer = new PixelTransfer11(this);
|
||||
|
||||
mStateManager.initialize(mDeviceContext, &mStateCache, &mRenderer11DeviceCaps);
|
||||
|
||||
const gl::Caps &rendererCaps = getRendererCaps();
|
||||
|
||||
mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
|
||||
@ -1358,25 +1416,49 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
|
||||
gl::Error Renderer11::updateState(const gl::Data &data, GLenum drawMode)
|
||||
{
|
||||
if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
|
||||
// Applies the render target surface, depth stencil surface, viewport rectangle and
|
||||
// scissor rectangle to the renderer
|
||||
const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
|
||||
ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
|
||||
gl::Error error = applyRenderTarget(framebufferObject);
|
||||
if (error.isError())
|
||||
{
|
||||
ID3D11RasterizerState *dxRasterState = NULL;
|
||||
gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
mDeviceContext->RSSetState(dxRasterState);
|
||||
|
||||
mCurRasterState = rasterState;
|
||||
return error;
|
||||
}
|
||||
|
||||
mForceSetRasterState = false;
|
||||
// Setting viewport state
|
||||
mStateManager.setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(),
|
||||
data.state->getFarPlane());
|
||||
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
// Setting scissor state
|
||||
mStateManager.setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
|
||||
|
||||
// Applying rasterizer state to D3D11 device
|
||||
int samples = framebufferObject->getSamples(data);
|
||||
gl::RasterizerState rasterizer = data.state->getRasterizerState();
|
||||
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
|
||||
rasterizer.multiSample = (samples != 0);
|
||||
|
||||
error = mStateManager.setRasterizerState(rasterizer);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
// Setting blend state
|
||||
unsigned int mask = GetBlendSampleMask(data, samples);
|
||||
error = mStateManager.setBlendState(framebufferObject, data.state->getBlendState(),
|
||||
data.state->getBlendColor(), mask);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
// Setting depth stencil state
|
||||
error = mStateManager.setDepthStencilState(*data.state);
|
||||
return error;
|
||||
}
|
||||
|
||||
void Renderer11::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask)
|
||||
@ -1384,180 +1466,6 @@ void Renderer11::syncState(const gl::State &state, const gl::State::DirtyBits &b
|
||||
mStateManager.syncState(state, bitmask);
|
||||
}
|
||||
|
||||
gl::Error Renderer11::setBlendState(const gl::Framebuffer *framebuffer,
|
||||
const gl::BlendState &blendState,
|
||||
const gl::ColorF &blendColor,
|
||||
unsigned int sampleMask)
|
||||
{
|
||||
return mStateManager.setBlendState(framebuffer, blendState, blendColor, sampleMask);
|
||||
}
|
||||
|
||||
gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
|
||||
int stencilBackRef, bool frontFaceCCW)
|
||||
{
|
||||
if (mForceSetDepthStencilState ||
|
||||
memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
|
||||
stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
|
||||
{
|
||||
// get the maximum size of the stencil ref
|
||||
unsigned int maxStencil = 0;
|
||||
if (depthStencilState.stencilTest && mCurStencilSize > 0)
|
||||
{
|
||||
maxStencil = (1 << mCurStencilSize) - 1;
|
||||
}
|
||||
ASSERT((depthStencilState.stencilWritemask & maxStencil) ==
|
||||
(depthStencilState.stencilBackWritemask & maxStencil));
|
||||
ASSERT(stencilRef == stencilBackRef);
|
||||
ASSERT((depthStencilState.stencilMask & maxStencil) ==
|
||||
(depthStencilState.stencilBackMask & maxStencil));
|
||||
|
||||
ID3D11DepthStencilState *dxDepthStencilState = NULL;
|
||||
gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
ASSERT(dxDepthStencilState);
|
||||
|
||||
// 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
|
||||
static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
|
||||
static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
|
||||
UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
|
||||
|
||||
mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
|
||||
|
||||
mCurDepthStencilState = depthStencilState;
|
||||
mCurStencilRef = stencilRef;
|
||||
mCurStencilBackRef = stencilBackRef;
|
||||
}
|
||||
|
||||
mForceSetDepthStencilState = false;
|
||||
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
|
||||
{
|
||||
if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
|
||||
enabled != mScissorEnabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
D3D11_RECT rect;
|
||||
rect.left = std::max(0, scissor.x);
|
||||
rect.top = std::max(0, scissor.y);
|
||||
rect.right = scissor.x + std::max(0, scissor.width);
|
||||
rect.bottom = scissor.y + std::max(0, scissor.height);
|
||||
|
||||
mDeviceContext->RSSetScissorRects(1, &rect);
|
||||
}
|
||||
|
||||
if (enabled != mScissorEnabled)
|
||||
{
|
||||
mForceSetRasterState = true;
|
||||
}
|
||||
|
||||
mCurScissor = scissor;
|
||||
mScissorEnabled = enabled;
|
||||
}
|
||||
|
||||
mForceSetScissor = false;
|
||||
}
|
||||
|
||||
void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
|
||||
bool ignoreViewport)
|
||||
{
|
||||
gl::Rectangle actualViewport = viewport;
|
||||
float actualZNear = gl::clamp01(zNear);
|
||||
float actualZFar = gl::clamp01(zFar);
|
||||
if (ignoreViewport)
|
||||
{
|
||||
actualViewport.x = 0;
|
||||
actualViewport.y = 0;
|
||||
actualViewport.width = static_cast<int>(mRenderTargetDesc.width);
|
||||
actualViewport.height = static_cast<int>(mRenderTargetDesc.height);
|
||||
actualZNear = 0.0f;
|
||||
actualZFar = 1.0f;
|
||||
}
|
||||
|
||||
bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
|
||||
actualZNear != mCurNear || actualZFar != mCurFar;
|
||||
|
||||
if (viewportChanged)
|
||||
{
|
||||
const gl::Caps& caps = getRendererCaps();
|
||||
|
||||
int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth);
|
||||
int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight);
|
||||
int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
|
||||
int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
|
||||
|
||||
if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
|
||||
{
|
||||
// Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
|
||||
dxMaxViewportBoundsX = static_cast<int>(mRenderTargetDesc.width);
|
||||
dxMaxViewportBoundsY = static_cast<int>(mRenderTargetDesc.height);
|
||||
dxMinViewportBoundsX = 0;
|
||||
dxMinViewportBoundsY = 0;
|
||||
}
|
||||
|
||||
int dxViewportTopLeftX = gl::clamp(actualViewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
|
||||
int dxViewportTopLeftY = gl::clamp(actualViewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
|
||||
int dxViewportWidth = gl::clamp(actualViewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
|
||||
int dxViewportHeight = gl::clamp(actualViewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
|
||||
|
||||
D3D11_VIEWPORT dxViewport;
|
||||
dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
|
||||
dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
|
||||
dxViewport.Width = static_cast<float>(dxViewportWidth);
|
||||
dxViewport.Height = static_cast<float>(dxViewportHeight);
|
||||
dxViewport.MinDepth = actualZNear;
|
||||
dxViewport.MaxDepth = actualZFar;
|
||||
|
||||
mDeviceContext->RSSetViewports(1, &dxViewport);
|
||||
|
||||
mCurViewport = actualViewport;
|
||||
mCurNear = actualZNear;
|
||||
mCurFar = actualZFar;
|
||||
|
||||
// On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders using viewAdjust (like the D3D9 renderer).
|
||||
if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
|
||||
{
|
||||
mVertexConstants.viewAdjust[0] = static_cast<float>((actualViewport.width - dxViewportWidth) + 2 * (actualViewport.x - dxViewportTopLeftX)) / dxViewport.Width;
|
||||
mVertexConstants.viewAdjust[1] = static_cast<float>((actualViewport.height - dxViewportHeight) + 2 * (actualViewport.y - dxViewportTopLeftY)) / dxViewport.Height;
|
||||
mVertexConstants.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width;
|
||||
mVertexConstants.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height;
|
||||
}
|
||||
|
||||
mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
|
||||
mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
|
||||
mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
|
||||
mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
|
||||
|
||||
// Instanced pointsprite emulation requires ViewCoords to be defined in the
|
||||
// the vertex shader.
|
||||
mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
|
||||
mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
|
||||
mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
|
||||
mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
|
||||
|
||||
mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
|
||||
mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
|
||||
|
||||
mVertexConstants.depthRange[0] = actualZNear;
|
||||
mVertexConstants.depthRange[1] = actualZFar;
|
||||
mVertexConstants.depthRange[2] = actualZFar - actualZNear;
|
||||
|
||||
mPixelConstants.depthRange[0] = actualZNear;
|
||||
mPixelConstants.depthRange[1] = actualZFar;
|
||||
mPixelConstants.depthRange[2] = actualZFar - actualZNear;
|
||||
}
|
||||
|
||||
mForceSetViewport = false;
|
||||
}
|
||||
|
||||
bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
|
||||
{
|
||||
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
@ -1635,7 +1543,8 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
|
||||
// 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.
|
||||
if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
|
||||
const gl::Extents &size = colorbuffer->getSize();
|
||||
if (size.width == 0 || size.height == 0)
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
@ -1696,7 +1605,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
|
||||
{
|
||||
renderTargetWidth = depthStencilRenderTarget->getWidth();
|
||||
renderTargetHeight = depthStencilRenderTarget->getHeight();
|
||||
renderTargetFormat = depthStencilRenderTarget->getDXGIFormat();
|
||||
}
|
||||
|
||||
// Unbind render target SRVs from the shader here to prevent D3D11 warnings.
|
||||
@ -1711,30 +1619,21 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
|
||||
}
|
||||
|
||||
unsigned int stencilSize = depthStencil->getStencilSize();
|
||||
if (!mDepthStencilInitialized || stencilSize != mCurStencilSize)
|
||||
{
|
||||
mCurStencilSize = stencilSize;
|
||||
mForceSetDepthStencilState = true;
|
||||
}
|
||||
mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
|
||||
}
|
||||
|
||||
// Apply the render target and depth stencil
|
||||
if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
|
||||
if (!mDepthStencilInitialized ||
|
||||
memcmp(framebufferRTVs, mAppliedRTVs, sizeof(framebufferRTVs)) != 0 ||
|
||||
reinterpret_cast<uintptr_t>(framebufferDSV) != mAppliedDSV)
|
||||
{
|
||||
mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
|
||||
|
||||
mRenderTargetDesc.width = renderTargetWidth;
|
||||
mRenderTargetDesc.height = renderTargetHeight;
|
||||
mRenderTargetDesc.format = renderTargetFormat;
|
||||
mForceSetViewport = true;
|
||||
mForceSetScissor = true;
|
||||
mStateManager.setViewportBounds(renderTargetWidth, renderTargetHeight);
|
||||
mStateManager.forceSetBlendState();
|
||||
|
||||
if (!mDepthStencilInitialized)
|
||||
{
|
||||
mForceSetRasterState = true;
|
||||
mStateManager.forceSetRasterState();
|
||||
}
|
||||
|
||||
for (size_t rtIndex = 0; rtIndex < ArraySize(framebufferRTVs); rtIndex++)
|
||||
@ -1742,7 +1641,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
|
||||
mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(framebufferRTVs[rtIndex]);
|
||||
}
|
||||
mAppliedDSV = reinterpret_cast<uintptr_t>(framebufferDSV);
|
||||
mRenderTargetDescInitialized = true;
|
||||
mDepthStencilInitialized = true;
|
||||
}
|
||||
|
||||
@ -2455,23 +2353,27 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
|
||||
mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
|
||||
}
|
||||
|
||||
if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
|
||||
const dx_VertexConstants &vertexConstants = mStateManager.getVertexConstants();
|
||||
if (memcmp(&vertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
|
||||
{
|
||||
ASSERT(mDriverConstantBufferVS != nullptr);
|
||||
if (mDriverConstantBufferVS)
|
||||
{
|
||||
mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
|
||||
memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
|
||||
mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &vertexConstants,
|
||||
16, 0);
|
||||
memcpy(&mAppliedVertexConstants, &vertexConstants, sizeof(dx_VertexConstants));
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
|
||||
const dx_PixelConstants &pixelConstants = mStateManager.getPixelConstants();
|
||||
if (memcmp(&pixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
|
||||
{
|
||||
ASSERT(mDriverConstantBufferPS != nullptr);
|
||||
if (mDriverConstantBufferPS)
|
||||
{
|
||||
mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
|
||||
memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
|
||||
mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &pixelConstants, 16,
|
||||
0);
|
||||
memcpy(&mAppliedPixelConstants, &pixelConstants, sizeof(dx_PixelConstants));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2503,7 +2405,6 @@ void Renderer11::markAllStateDirty()
|
||||
}
|
||||
mAppliedDSV = DirtyPointer;
|
||||
mDepthStencilInitialized = false;
|
||||
mRenderTargetDescInitialized = false;
|
||||
|
||||
// We reset the current SRV data because it might not be in sync with D3D's state
|
||||
// anymore. For example when a currently used SRV is used as an RTV, D3D silently
|
||||
@ -2524,10 +2425,10 @@ void Renderer11::markAllStateDirty()
|
||||
}
|
||||
|
||||
mStateManager.forceSetBlendState();
|
||||
mForceSetRasterState = true;
|
||||
mForceSetDepthStencilState = true;
|
||||
mForceSetScissor = true;
|
||||
mForceSetViewport = true;
|
||||
mStateManager.forceSetDepthStencilState();
|
||||
mStateManager.forceSetRasterState();
|
||||
mStateManager.forceSetScissorState();
|
||||
mStateManager.forceSetViewportState();
|
||||
|
||||
mAppliedIB = NULL;
|
||||
mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
|
||||
@ -2655,6 +2556,13 @@ void Renderer11::release()
|
||||
|
||||
releaseDeviceResources();
|
||||
|
||||
if (!mCreatedWithDeviceEXT)
|
||||
{
|
||||
// Only delete the device if the Renderer11 owns it
|
||||
// Otherwise we should keep it around in case we try to reinitialize the renderer later
|
||||
SafeDelete(mEGLDevice);
|
||||
}
|
||||
|
||||
SafeRelease(mDxgiFactory);
|
||||
SafeRelease(mDxgiAdapter);
|
||||
|
||||
@ -2880,7 +2788,8 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::
|
||||
|
||||
// Use nearest filtering because source and destination are the same size for the direct
|
||||
// copy
|
||||
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
|
||||
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
|
||||
destFormat, GL_NEAREST, false);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
@ -2931,7 +2840,8 @@ gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl
|
||||
|
||||
// Use nearest filtering because source and destination are the same size for the direct
|
||||
// copy
|
||||
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
|
||||
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
|
||||
destFormat, GL_NEAREST, false);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
@ -2982,7 +2892,8 @@ gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::
|
||||
|
||||
// Use nearest filtering because source and destination are the same size for the direct
|
||||
// copy
|
||||
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
|
||||
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
|
||||
destFormat, GL_NEAREST, false);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
@ -3033,7 +2944,8 @@ gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const
|
||||
|
||||
// Use nearest filtering because source and destination are the same size for the direct
|
||||
// copy
|
||||
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
|
||||
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
|
||||
destFormat, GL_NEAREST, false);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
@ -3802,9 +3714,15 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget,
|
||||
RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
|
||||
bool colorBlit, bool depthBlit, bool stencilBlit)
|
||||
gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
|
||||
const gl::Rectangle &drawRectIn,
|
||||
RenderTargetD3D *readRenderTarget,
|
||||
RenderTargetD3D *drawRenderTarget,
|
||||
GLenum filter,
|
||||
const gl::Rectangle *scissor,
|
||||
bool colorBlit,
|
||||
bool depthBlit,
|
||||
bool stencilBlit)
|
||||
{
|
||||
// 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
|
||||
@ -3870,13 +3788,94 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const
|
||||
gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
|
||||
gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
|
||||
|
||||
// From the spec:
|
||||
// "The actual region taken from the read framebuffer is limited to the intersection of the
|
||||
// source buffers being transferred, which may include the color buffer selected by the read
|
||||
// buffer, the depth buffer, and / or the stencil buffer depending on mask."
|
||||
// This means negative x and y are out of bounds, and not to be read from. We handle this here
|
||||
// by internally scaling the read and draw rectangles.
|
||||
gl::Rectangle readRect = readRectIn;
|
||||
gl::Rectangle drawRect = drawRectIn;
|
||||
auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset)
|
||||
{
|
||||
double readToDrawScale =
|
||||
static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
|
||||
return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
|
||||
};
|
||||
if (readRect.x < 0)
|
||||
{
|
||||
int readOffset = -readRect.x;
|
||||
readRect.x += readOffset;
|
||||
readRect.width -= readOffset;
|
||||
|
||||
int drawOffset = readToDrawX(readOffset);
|
||||
drawRect.x += drawOffset;
|
||||
drawRect.width -= drawOffset;
|
||||
}
|
||||
|
||||
auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset)
|
||||
{
|
||||
double readToDrawScale =
|
||||
static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
|
||||
return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
|
||||
};
|
||||
if (readRect.y < 0)
|
||||
{
|
||||
int readOffset = -readRect.y;
|
||||
readRect.y += readOffset;
|
||||
readRect.height -= readOffset;
|
||||
|
||||
int drawOffset = readToDrawY(readOffset);
|
||||
drawRect.y += drawOffset;
|
||||
drawRect.height -= drawOffset;
|
||||
}
|
||||
|
||||
if (readRect.x1() < 0)
|
||||
{
|
||||
int readOffset = -readRect.x1();
|
||||
readRect.width += readOffset;
|
||||
|
||||
int drawOffset = readToDrawX(readOffset);
|
||||
drawRect.width += drawOffset;
|
||||
}
|
||||
|
||||
if (readRect.y1() < 0)
|
||||
{
|
||||
int readOffset = -readRect.y1();
|
||||
readRect.height += readOffset;
|
||||
|
||||
int drawOffset = readToDrawY(readOffset);
|
||||
drawRect.height += drawOffset;
|
||||
}
|
||||
|
||||
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;
|
||||
const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat());
|
||||
const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat());
|
||||
const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat());
|
||||
|
||||
// Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
|
||||
// emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
|
||||
|
||||
gl::Color<bool> colorMask;
|
||||
colorMask.red = (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) &&
|
||||
(dxgiFormatInfo.redBits > 0);
|
||||
colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
|
||||
(dxgiFormatInfo.greenBits > 0);
|
||||
colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
|
||||
(dxgiFormatInfo.blueBits > 0);
|
||||
colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
|
||||
(dxgiFormatInfo.alphaBits > 0);
|
||||
|
||||
// We only currently support masking off the alpha channel.
|
||||
bool colorMaskingNeeded = colorMask.alpha;
|
||||
ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);
|
||||
|
||||
bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && 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;
|
||||
|
||||
@ -3887,14 +3886,13 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const
|
||||
drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
|
||||
drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
|
||||
|
||||
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat());
|
||||
bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit);
|
||||
|
||||
gl::Error result(GL_NO_ERROR);
|
||||
|
||||
if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() &&
|
||||
!stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
|
||||
(!(depthBlit || stencilBlit) || wholeBufferCopy))
|
||||
!colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
|
||||
{
|
||||
UINT dstX = drawRect.x;
|
||||
UINT dstY = drawRect.y;
|
||||
@ -3964,9 +3962,10 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const
|
||||
}
|
||||
else
|
||||
{
|
||||
GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format;
|
||||
// We don't currently support masking off any other channel than alpha
|
||||
bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
|
||||
result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
|
||||
scissor, format, filter);
|
||||
scissor, destFormatInfo.format, filter, maskOffAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4170,14 +4169,23 @@ gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeSta
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
egl::Error Renderer11::initializeEGLDevice(DeviceD3D **outDevice)
|
||||
egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
|
||||
{
|
||||
if (*outDevice == nullptr)
|
||||
if (mEGLDevice == nullptr)
|
||||
{
|
||||
ASSERT(mDevice != nullptr);
|
||||
*outDevice = new DeviceD3D(reinterpret_cast<void *>(mDevice), EGL_D3D11_DEVICE_ANGLE);
|
||||
mEGLDevice = new DeviceD3D();
|
||||
egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
|
||||
EGL_D3D11_DEVICE_ANGLE, EGL_FALSE);
|
||||
|
||||
if (error.isError())
|
||||
{
|
||||
SafeDelete(mEGLDevice);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
*device = static_cast<DeviceImpl *>(mEGLDevice);
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
@ -121,18 +121,7 @@ class Renderer11 : public RendererD3D
|
||||
const std::vector<GLint> &vertexUniformBuffers,
|
||||
const std::vector<GLint> &fragmentUniformBuffers) override;
|
||||
|
||||
virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
|
||||
gl::Error setBlendState(const gl::Framebuffer *framebuffer,
|
||||
const gl::BlendState &blendState,
|
||||
const gl::ColorF &blendColor,
|
||||
unsigned int sampleMask) override;
|
||||
|
||||
virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
|
||||
int stencilBackRef, bool frontFaceCCW);
|
||||
|
||||
virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
|
||||
virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
|
||||
bool ignoreViewport);
|
||||
gl::Error updateState(const gl::Data &data, GLenum drawMode) override;
|
||||
|
||||
virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
|
||||
gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
|
||||
@ -285,13 +274,13 @@ class Renderer11 : public RendererD3D
|
||||
void onSwap();
|
||||
void onBufferDelete(const Buffer11 *deleted);
|
||||
|
||||
egl::Error getEGLDevice(DeviceImpl **device) override;
|
||||
|
||||
protected:
|
||||
void createAnnotator() override;
|
||||
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
|
||||
gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
|
||||
|
||||
egl::Error initializeEGLDevice(DeviceD3D **outDevice) override;
|
||||
|
||||
void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override;
|
||||
|
||||
private:
|
||||
@ -337,9 +326,12 @@ class Renderer11 : public RendererD3D
|
||||
HMODULE mDxgiModule;
|
||||
std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
|
||||
D3D_DRIVER_TYPE mDriverType;
|
||||
bool mCreatedWithDeviceEXT;
|
||||
DeviceD3D *mEGLDevice;
|
||||
|
||||
HLSLCompiler mCompiler;
|
||||
|
||||
egl::Error initializeD3DDevice();
|
||||
void initializeDevice();
|
||||
void releaseDeviceResources();
|
||||
void release();
|
||||
@ -350,16 +342,6 @@ class Renderer11 : public RendererD3D
|
||||
uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
|
||||
uintptr_t mAppliedDSV;
|
||||
bool mDepthStencilInitialized;
|
||||
bool mRenderTargetDescInitialized;
|
||||
unsigned int mCurStencilSize;
|
||||
|
||||
struct RenderTargetDesc
|
||||
{
|
||||
size_t width;
|
||||
size_t height;
|
||||
DXGI_FORMAT format;
|
||||
};
|
||||
RenderTargetDesc mRenderTargetDesc;
|
||||
|
||||
// Currently applied sampler states
|
||||
std::vector<bool> mForceSetVertexSamplerStates;
|
||||
@ -413,27 +395,6 @@ class Renderer11 : public RendererD3D
|
||||
|
||||
StateManager11 mStateManager;
|
||||
|
||||
// Currently applied rasterizer state
|
||||
bool mForceSetRasterState;
|
||||
gl::RasterizerState mCurRasterState;
|
||||
|
||||
// Currently applied depth stencil state
|
||||
bool mForceSetDepthStencilState;
|
||||
gl::DepthStencilState mCurDepthStencilState;
|
||||
int mCurStencilRef;
|
||||
int mCurStencilBackRef;
|
||||
|
||||
// Currently applied scissor rectangle
|
||||
bool mForceSetScissor;
|
||||
bool mScissorEnabled;
|
||||
gl::Rectangle mCurScissor;
|
||||
|
||||
// Currently applied viewport
|
||||
bool mForceSetViewport;
|
||||
gl::Rectangle mCurViewport;
|
||||
float mCurNear;
|
||||
float mCurFar;
|
||||
|
||||
// Currently applied primitive topology
|
||||
D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
|
||||
|
||||
@ -459,7 +420,6 @@ class Renderer11 : public RendererD3D
|
||||
uintptr_t mAppliedGeometryShader;
|
||||
uintptr_t mAppliedPixelShader;
|
||||
|
||||
dx_VertexConstants mVertexConstants;
|
||||
dx_VertexConstants mAppliedVertexConstants;
|
||||
ID3D11Buffer *mDriverConstantBufferVS;
|
||||
ID3D11Buffer *mCurrentVertexConstantBuffer;
|
||||
@ -467,7 +427,6 @@ class Renderer11 : public RendererD3D
|
||||
GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
|
||||
GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
|
||||
|
||||
dx_PixelConstants mPixelConstants;
|
||||
dx_PixelConstants mAppliedPixelConstants;
|
||||
ID3D11Buffer *mDriverConstantBufferPS;
|
||||
ID3D11Buffer *mCurrentPixelConstantBuffer;
|
||||
|
@ -14,11 +14,26 @@
|
||||
namespace rx
|
||||
{
|
||||
|
||||
StateManager11::StateManager11(Renderer11 *renderer11)
|
||||
StateManager11::StateManager11()
|
||||
: mBlendStateIsDirty(false),
|
||||
mCurBlendColor(0, 0, 0, 0),
|
||||
mCurSampleMask(0),
|
||||
mRenderer11(renderer11)
|
||||
mDepthStencilStateIsDirty(false),
|
||||
mCurStencilRef(0),
|
||||
mCurStencilBackRef(0),
|
||||
mCurStencilSize(0),
|
||||
mRasterizerStateIsDirty(false),
|
||||
mScissorStateIsDirty(false),
|
||||
mCurScissorEnabled(false),
|
||||
mCurScissorRect(),
|
||||
mViewportStateIsDirty(false),
|
||||
mCurViewport(),
|
||||
mCurNear(0.0f),
|
||||
mCurFar(0.0f),
|
||||
mViewportBounds(),
|
||||
mRenderer11DeviceCaps(nullptr),
|
||||
mDeviceContext(nullptr),
|
||||
mStateCache(nullptr)
|
||||
{
|
||||
mCurBlendState.blend = false;
|
||||
mCurBlendState.sourceBlendRGB = GL_ONE;
|
||||
@ -33,12 +48,67 @@ StateManager11::StateManager11(Renderer11 *renderer11)
|
||||
mCurBlendState.colorMaskAlpha = true;
|
||||
mCurBlendState.sampleAlphaToCoverage = false;
|
||||
mCurBlendState.dither = false;
|
||||
|
||||
mCurDepthStencilState.depthTest = false;
|
||||
mCurDepthStencilState.depthFunc = GL_LESS;
|
||||
mCurDepthStencilState.depthMask = true;
|
||||
mCurDepthStencilState.stencilTest = false;
|
||||
mCurDepthStencilState.stencilMask = true;
|
||||
mCurDepthStencilState.stencilFail = GL_KEEP;
|
||||
mCurDepthStencilState.stencilPassDepthFail = GL_KEEP;
|
||||
mCurDepthStencilState.stencilPassDepthPass = GL_KEEP;
|
||||
mCurDepthStencilState.stencilWritemask = static_cast<GLuint>(-1);
|
||||
mCurDepthStencilState.stencilBackFunc = GL_ALWAYS;
|
||||
mCurDepthStencilState.stencilBackMask = static_cast<GLuint>(-1);
|
||||
mCurDepthStencilState.stencilBackFail = GL_KEEP;
|
||||
mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP;
|
||||
mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP;
|
||||
mCurDepthStencilState.stencilBackWritemask = static_cast<GLuint>(-1);
|
||||
|
||||
mCurRasterState.rasterizerDiscard = false;
|
||||
mCurRasterState.cullFace = false;
|
||||
mCurRasterState.cullMode = GL_BACK;
|
||||
mCurRasterState.frontFace = GL_CCW;
|
||||
mCurRasterState.polygonOffsetFill = false;
|
||||
mCurRasterState.polygonOffsetFactor = 0.0f;
|
||||
mCurRasterState.polygonOffsetUnits = 0.0f;
|
||||
mCurRasterState.pointDrawMode = false;
|
||||
mCurRasterState.multiSample = false;
|
||||
}
|
||||
|
||||
StateManager11::~StateManager11()
|
||||
{
|
||||
}
|
||||
|
||||
void StateManager11::initialize(ID3D11DeviceContext *deviceContext,
|
||||
RenderStateCache *stateCache,
|
||||
Renderer11DeviceCaps *renderer11DeviceCaps)
|
||||
{
|
||||
mDeviceContext = deviceContext;
|
||||
mStateCache = stateCache;
|
||||
mRenderer11DeviceCaps = renderer11DeviceCaps;
|
||||
}
|
||||
|
||||
void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
|
||||
unsigned int stencilSize)
|
||||
{
|
||||
if (!depthStencilInitialized || stencilSize != mCurStencilSize)
|
||||
{
|
||||
mCurStencilSize = stencilSize;
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void StateManager11::setViewportBounds(const int width, const int height)
|
||||
{
|
||||
if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3 &&
|
||||
(mViewportBounds.width != width || mViewportBounds.height != height))
|
||||
{
|
||||
mViewportBounds = gl::Extents(width, height, 1);
|
||||
mViewportStateIsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
|
||||
{
|
||||
for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits))
|
||||
@ -104,6 +174,159 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
|
||||
mBlendStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_DEPTH_MASK:
|
||||
if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
|
||||
if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_DEPTH_FUNC:
|
||||
if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
|
||||
if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
|
||||
{
|
||||
const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
|
||||
if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc ||
|
||||
depthStencil.stencilMask != mCurDepthStencilState.stencilMask ||
|
||||
state.getStencilRef() != mCurStencilRef)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
|
||||
{
|
||||
const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
|
||||
if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc ||
|
||||
depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
|
||||
state.getStencilBackRef() != mCurStencilBackRef)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
|
||||
if (state.getDepthStencilState().stencilWritemask !=
|
||||
mCurDepthStencilState.stencilWritemask)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
|
||||
if (state.getDepthStencilState().stencilBackWritemask !=
|
||||
mCurDepthStencilState.stencilBackWritemask)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
|
||||
{
|
||||
const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
|
||||
if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail ||
|
||||
depthStencil.stencilPassDepthFail !=
|
||||
mCurDepthStencilState.stencilPassDepthFail ||
|
||||
depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
|
||||
{
|
||||
const gl::DepthStencilState &depthStencil = state.getDepthStencilState();
|
||||
if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail ||
|
||||
depthStencil.stencilBackPassDepthFail !=
|
||||
mCurDepthStencilState.stencilBackPassDepthFail ||
|
||||
depthStencil.stencilBackPassDepthPass !=
|
||||
mCurDepthStencilState.stencilBackPassDepthPass)
|
||||
{
|
||||
mDepthStencilStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
|
||||
if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
|
||||
{
|
||||
mRasterizerStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_CULL_FACE:
|
||||
if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
|
||||
{
|
||||
mRasterizerStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_FRONT_FACE:
|
||||
if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
|
||||
{
|
||||
mRasterizerStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
|
||||
if (state.getRasterizerState().polygonOffsetFill !=
|
||||
mCurRasterState.polygonOffsetFill)
|
||||
{
|
||||
mRasterizerStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_POLYGON_OFFSET:
|
||||
{
|
||||
const gl::RasterizerState &rasterState = state.getRasterizerState();
|
||||
if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
|
||||
rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
|
||||
{
|
||||
mRasterizerStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
|
||||
if (state.getRasterizerState().rasterizerDiscard !=
|
||||
mCurRasterState.rasterizerDiscard)
|
||||
{
|
||||
mRasterizerStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_SCISSOR:
|
||||
if (state.getScissor() != mCurScissorRect)
|
||||
{
|
||||
mScissorStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
|
||||
if (state.isScissorTestEnabled() != mCurScissorEnabled)
|
||||
{
|
||||
mScissorStateIsDirty = true;
|
||||
// Rasterizer state update needs mCurScissorsEnabled and updates when it changes
|
||||
mRasterizerStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_DEPTH_RANGE:
|
||||
if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
|
||||
{
|
||||
mViewportStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
case gl::State::DIRTY_BIT_VIEWPORT:
|
||||
if (state.getViewport() != mCurViewport)
|
||||
{
|
||||
mViewportStateIsDirty = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -115,47 +338,245 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
|
||||
const gl::ColorF &blendColor,
|
||||
unsigned int sampleMask)
|
||||
{
|
||||
if (mBlendStateIsDirty || sampleMask != mCurSampleMask)
|
||||
if (!mBlendStateIsDirty && sampleMask == mCurSampleMask)
|
||||
{
|
||||
ID3D11BlendState *dxBlendState = nullptr;
|
||||
gl::Error error =
|
||||
mRenderer11->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
ASSERT(dxBlendState != nullptr);
|
||||
|
||||
float blendColors[4] = {0.0f};
|
||||
if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
|
||||
blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
|
||||
blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
|
||||
blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
|
||||
{
|
||||
blendColors[0] = blendColor.red;
|
||||
blendColors[1] = blendColor.green;
|
||||
blendColors[2] = blendColor.blue;
|
||||
blendColors[3] = blendColor.alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
blendColors[0] = blendColor.alpha;
|
||||
blendColors[1] = blendColor.alpha;
|
||||
blendColors[2] = blendColor.alpha;
|
||||
blendColors[3] = blendColor.alpha;
|
||||
}
|
||||
|
||||
mRenderer11->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask);
|
||||
|
||||
mCurBlendState = blendState;
|
||||
mCurBlendColor = blendColor;
|
||||
mCurSampleMask = sampleMask;
|
||||
|
||||
mBlendStateIsDirty = false;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
ID3D11BlendState *dxBlendState = nullptr;
|
||||
gl::Error error = mStateCache->getBlendState(framebuffer, blendState, &dxBlendState);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
ASSERT(dxBlendState != nullptr);
|
||||
|
||||
float blendColors[4] = {0.0f};
|
||||
if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
|
||||
blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
|
||||
blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
|
||||
blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
|
||||
{
|
||||
blendColors[0] = blendColor.red;
|
||||
blendColors[1] = blendColor.green;
|
||||
blendColors[2] = blendColor.blue;
|
||||
blendColors[3] = blendColor.alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
blendColors[0] = blendColor.alpha;
|
||||
blendColors[1] = blendColor.alpha;
|
||||
blendColors[2] = blendColor.alpha;
|
||||
blendColors[3] = blendColor.alpha;
|
||||
}
|
||||
|
||||
mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
|
||||
|
||||
mCurBlendState = blendState;
|
||||
mCurBlendColor = blendColor;
|
||||
mCurSampleMask = sampleMask;
|
||||
|
||||
mBlendStateIsDirty = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
|
||||
{
|
||||
const auto &fbo = *glState.getDrawFramebuffer();
|
||||
|
||||
// Disable the depth test/depth write if we are using a stencil-only attachment.
|
||||
// This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
|
||||
// nor write to the unused depth part of this emulated texture.
|
||||
bool disableDepth = (!fbo.hasDepth() && fbo.hasStencil());
|
||||
|
||||
// Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
|
||||
bool disableStencil = (fbo.hasDepth() && !fbo.hasStencil());
|
||||
|
||||
// CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState.
|
||||
if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() &&
|
||||
disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() &&
|
||||
disableStencil == mCurDisableStencil.value())
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
const auto &depthStencilState = glState.getDepthStencilState();
|
||||
int stencilRef = glState.getStencilRef();
|
||||
int stencilBackRef = glState.getStencilBackRef();
|
||||
|
||||
// get the maximum size of the stencil ref
|
||||
unsigned int maxStencil = 0;
|
||||
if (depthStencilState.stencilTest && mCurStencilSize > 0)
|
||||
{
|
||||
maxStencil = (1 << mCurStencilSize) - 1;
|
||||
}
|
||||
ASSERT((depthStencilState.stencilWritemask & maxStencil) ==
|
||||
(depthStencilState.stencilBackWritemask & maxStencil));
|
||||
ASSERT(stencilRef == stencilBackRef);
|
||||
ASSERT((depthStencilState.stencilMask & maxStencil) ==
|
||||
(depthStencilState.stencilBackMask & maxStencil));
|
||||
|
||||
ID3D11DepthStencilState *dxDepthStencilState = NULL;
|
||||
gl::Error error = mStateCache->getDepthStencilState(depthStencilState, disableDepth,
|
||||
disableStencil, &dxDepthStencilState);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
ASSERT(dxDepthStencilState);
|
||||
|
||||
// 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
|
||||
static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF,
|
||||
"Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
|
||||
static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
|
||||
"Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
|
||||
UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
|
||||
|
||||
mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
|
||||
|
||||
mCurDepthStencilState = depthStencilState;
|
||||
mCurStencilRef = stencilRef;
|
||||
mCurStencilBackRef = stencilBackRef;
|
||||
mCurDisableDepth = disableDepth;
|
||||
mCurDisableStencil = disableStencil;
|
||||
|
||||
mDepthStencilStateIsDirty = false;
|
||||
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState)
|
||||
{
|
||||
if (!mRasterizerStateIsDirty)
|
||||
{
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
ID3D11RasterizerState *dxRasterState = nullptr;
|
||||
gl::Error error =
|
||||
mStateCache->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
mDeviceContext->RSSetState(dxRasterState);
|
||||
|
||||
mCurRasterState = rasterState;
|
||||
mRasterizerStateIsDirty = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
|
||||
{
|
||||
if (!mScissorStateIsDirty)
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
D3D11_RECT rect;
|
||||
rect.left = std::max(0, scissor.x);
|
||||
rect.top = std::max(0, scissor.y);
|
||||
rect.right = scissor.x + std::max(0, scissor.width);
|
||||
rect.bottom = scissor.y + std::max(0, scissor.height);
|
||||
|
||||
mDeviceContext->RSSetScissorRects(1, &rect);
|
||||
}
|
||||
|
||||
mCurScissorRect = scissor;
|
||||
mCurScissorEnabled = enabled;
|
||||
mScissorStateIsDirty = false;
|
||||
}
|
||||
|
||||
void StateManager11::setViewport(const gl::Caps *caps,
|
||||
const gl::Rectangle &viewport,
|
||||
float zNear,
|
||||
float zFar)
|
||||
{
|
||||
if (!mViewportStateIsDirty)
|
||||
return;
|
||||
|
||||
float actualZNear = gl::clamp01(zNear);
|
||||
float actualZFar = gl::clamp01(zFar);
|
||||
|
||||
int dxMaxViewportBoundsX = static_cast<int>(caps->maxViewportWidth);
|
||||
int dxMaxViewportBoundsY = static_cast<int>(caps->maxViewportHeight);
|
||||
int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
|
||||
int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
|
||||
|
||||
if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3)
|
||||
{
|
||||
// Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
|
||||
dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
|
||||
dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height);
|
||||
dxMinViewportBoundsX = 0;
|
||||
dxMinViewportBoundsY = 0;
|
||||
}
|
||||
|
||||
int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
|
||||
int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
|
||||
int dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
|
||||
int dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
|
||||
|
||||
D3D11_VIEWPORT dxViewport;
|
||||
dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
|
||||
dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
|
||||
dxViewport.Width = static_cast<float>(dxViewportWidth);
|
||||
dxViewport.Height = static_cast<float>(dxViewportHeight);
|
||||
dxViewport.MinDepth = actualZNear;
|
||||
dxViewport.MaxDepth = actualZFar;
|
||||
|
||||
mDeviceContext->RSSetViewports(1, &dxViewport);
|
||||
|
||||
mCurViewport = viewport;
|
||||
mCurNear = actualZNear;
|
||||
mCurFar = actualZFar;
|
||||
|
||||
// On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
|
||||
// using viewAdjust (like the D3D9 renderer).
|
||||
if (mRenderer11DeviceCaps->featureLevel <= D3D_FEATURE_LEVEL_9_3)
|
||||
{
|
||||
mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) +
|
||||
2 * (viewport.x - dxViewportTopLeftX)) /
|
||||
dxViewport.Width;
|
||||
mVertexConstants.viewAdjust[1] = static_cast<float>((viewport.height - dxViewportHeight) +
|
||||
2 * (viewport.y - dxViewportTopLeftY)) /
|
||||
dxViewport.Height;
|
||||
mVertexConstants.viewAdjust[2] = static_cast<float>(viewport.width) / dxViewport.Width;
|
||||
mVertexConstants.viewAdjust[3] = static_cast<float>(viewport.height) / dxViewport.Height;
|
||||
}
|
||||
|
||||
mPixelConstants.viewCoords[0] = viewport.width * 0.5f;
|
||||
mPixelConstants.viewCoords[1] = viewport.height * 0.5f;
|
||||
mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f);
|
||||
mPixelConstants.viewCoords[3] = viewport.y + (viewport.height * 0.5f);
|
||||
|
||||
// Instanced pointsprite emulation requires ViewCoords to be defined in the
|
||||
// the vertex shader.
|
||||
mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
|
||||
mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
|
||||
mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
|
||||
mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
|
||||
|
||||
mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
|
||||
mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
|
||||
|
||||
mVertexConstants.depthRange[0] = actualZNear;
|
||||
mVertexConstants.depthRange[1] = actualZFar;
|
||||
mVertexConstants.depthRange[2] = actualZFar - actualZNear;
|
||||
|
||||
mPixelConstants.depthRange[0] = actualZNear;
|
||||
mPixelConstants.depthRange[1] = actualZFar;
|
||||
mPixelConstants.depthRange[2] = actualZFar - actualZNear;
|
||||
|
||||
mViewportStateIsDirty = false;
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
@ -13,19 +13,24 @@
|
||||
#include "libANGLE/Data.h"
|
||||
#include "libANGLE/State.h"
|
||||
#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
|
||||
#include "libANGLE/renderer/d3d/RendererD3D.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class Renderer11;
|
||||
struct RenderTargetDesc;
|
||||
struct Renderer11DeviceCaps;
|
||||
|
||||
class StateManager11 final : angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
StateManager11(Renderer11 *renderer11);
|
||||
|
||||
StateManager11();
|
||||
~StateManager11();
|
||||
|
||||
void initialize(ID3D11DeviceContext *deviceContext,
|
||||
RenderStateCache *stateCache,
|
||||
Renderer11DeviceCaps *renderer11DeviceCaps);
|
||||
|
||||
void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
|
||||
|
||||
gl::Error setBlendState(const gl::Framebuffer *framebuffer,
|
||||
@ -33,7 +38,25 @@ class StateManager11 final : angle::NonCopyable
|
||||
const gl::ColorF &blendColor,
|
||||
unsigned int sampleMask);
|
||||
|
||||
gl::Error setDepthStencilState(const gl::State &glState);
|
||||
|
||||
gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
|
||||
|
||||
void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
|
||||
|
||||
void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar);
|
||||
|
||||
void forceSetBlendState() { mBlendStateIsDirty = true; }
|
||||
void forceSetDepthStencilState() { mDepthStencilStateIsDirty = true; }
|
||||
void forceSetRasterState() { mRasterizerStateIsDirty = true; }
|
||||
void forceSetScissorState() { mScissorStateIsDirty = true; }
|
||||
void forceSetViewportState() { mViewportStateIsDirty = true; }
|
||||
void setViewportBounds(const int width, const int height);
|
||||
|
||||
const dx_VertexConstants &getVertexConstants() const { return mVertexConstants; }
|
||||
const dx_PixelConstants &getPixelConstants() const { return mPixelConstants; }
|
||||
|
||||
void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
|
||||
|
||||
private:
|
||||
// Blend State
|
||||
@ -44,7 +67,40 @@ class StateManager11 final : angle::NonCopyable
|
||||
gl::ColorF mCurBlendColor;
|
||||
unsigned int mCurSampleMask;
|
||||
|
||||
Renderer11 *mRenderer11;
|
||||
// Currently applied depth stencil state
|
||||
bool mDepthStencilStateIsDirty;
|
||||
gl::DepthStencilState mCurDepthStencilState;
|
||||
int mCurStencilRef;
|
||||
int mCurStencilBackRef;
|
||||
unsigned int mCurStencilSize;
|
||||
Optional<bool> mCurDisableDepth;
|
||||
Optional<bool> mCurDisableStencil;
|
||||
|
||||
// Currenly applied rasterizer state
|
||||
bool mRasterizerStateIsDirty;
|
||||
gl::RasterizerState mCurRasterState;
|
||||
|
||||
// Currently applied scissor rectangle state
|
||||
bool mScissorStateIsDirty;
|
||||
bool mCurScissorEnabled;
|
||||
gl::Rectangle mCurScissorRect;
|
||||
|
||||
// Currently applied viewport state
|
||||
bool mViewportStateIsDirty;
|
||||
gl::Rectangle mCurViewport;
|
||||
float mCurNear;
|
||||
float mCurFar;
|
||||
|
||||
// Things needed in viewport state
|
||||
dx_VertexConstants mVertexConstants;
|
||||
dx_PixelConstants mPixelConstants;
|
||||
|
||||
// Render target variables
|
||||
gl::Extents mViewportBounds;
|
||||
|
||||
Renderer11DeviceCaps *mRenderer11DeviceCaps;
|
||||
ID3D11DeviceContext *mDeviceContext;
|
||||
RenderStateCache *mStateCache;
|
||||
};
|
||||
|
||||
} // namespace rx
|
||||
|
@ -554,8 +554,9 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co
|
||||
gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
|
||||
|
||||
Blit11 *blitter = mRenderer->getBlitter();
|
||||
return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
|
||||
gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
|
||||
return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
|
||||
NULL, gl::GetInternalFormatInfo(source->getInternalFormat()).format,
|
||||
GL_LINEAR, false);
|
||||
}
|
||||
|
||||
void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
|
||||
@ -2225,7 +2226,7 @@ gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FO
|
||||
{
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
|
||||
srvDesc.Texture2DArray.MipLevels = 1;
|
||||
srvDesc.Texture2DArray.MipLevels = mipLevels;
|
||||
srvDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT;
|
||||
}
|
||||
|
@ -1334,6 +1334,56 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
|
||||
#endif
|
||||
}
|
||||
|
||||
LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
|
||||
size_t inputDescLen,
|
||||
const BYTE *byteCode,
|
||||
size_t byteCodeLen,
|
||||
const char *debugName)
|
||||
: mInputDesc(inputDescLen),
|
||||
mByteCodeLen(byteCodeLen),
|
||||
mByteCode(byteCode),
|
||||
mDebugName(debugName)
|
||||
{
|
||||
memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
|
||||
}
|
||||
|
||||
ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
|
||||
{
|
||||
checkAssociatedDevice(device);
|
||||
|
||||
if (mResource == nullptr)
|
||||
{
|
||||
HRESULT result =
|
||||
device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()),
|
||||
mByteCode, mByteCodeLen, &mResource);
|
||||
ASSERT(SUCCEEDED(result));
|
||||
UNUSED_ASSERTION_VARIABLE(result);
|
||||
d3d11::SetDebugName(mResource, mDebugName);
|
||||
}
|
||||
|
||||
return mResource;
|
||||
}
|
||||
|
||||
LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
|
||||
: mDesc(desc), mDebugName(debugName)
|
||||
{
|
||||
}
|
||||
|
||||
ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device)
|
||||
{
|
||||
checkAssociatedDevice(device);
|
||||
|
||||
if (mResource == nullptr)
|
||||
{
|
||||
HRESULT result = device->CreateBlendState(&mDesc, &mResource);
|
||||
ASSERT(SUCCEEDED(result));
|
||||
UNUSED_ASSERTION_VARIABLE(result);
|
||||
d3d11::SetDebugName(mResource, mDebugName);
|
||||
}
|
||||
|
||||
return mResource;
|
||||
}
|
||||
|
||||
WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel)
|
||||
{
|
||||
WorkaroundsD3D workarounds;
|
||||
|
@ -296,35 +296,17 @@ class LazyInputLayout final : public LazyResource<ID3D11InputLayout>
|
||||
const char *mDebugName;
|
||||
};
|
||||
|
||||
inline LazyInputLayout::LazyInputLayout(
|
||||
const D3D11_INPUT_ELEMENT_DESC *inputDesc,
|
||||
size_t inputDescLen,
|
||||
const BYTE *byteCode,
|
||||
size_t byteCodeLen,
|
||||
const char *debugName)
|
||||
: mInputDesc(inputDescLen),
|
||||
mByteCodeLen(byteCodeLen),
|
||||
mByteCode(byteCode),
|
||||
mDebugName(debugName)
|
||||
class LazyBlendState final : public LazyResource<ID3D11BlendState>
|
||||
{
|
||||
memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
|
||||
}
|
||||
public:
|
||||
LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
|
||||
|
||||
inline ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
|
||||
{
|
||||
checkAssociatedDevice(device);
|
||||
ID3D11BlendState *resolve(ID3D11Device *device) override;
|
||||
|
||||
if (mResource == nullptr)
|
||||
{
|
||||
HRESULT result = device->CreateInputLayout(
|
||||
&mInputDesc[0], static_cast<UINT>(mInputDesc.size()), mByteCode, mByteCodeLen, &mResource);
|
||||
ASSERT(SUCCEEDED(result));
|
||||
UNUSED_ASSERTION_VARIABLE(result);
|
||||
d3d11::SetDebugName(mResource, mDebugName);
|
||||
}
|
||||
|
||||
return mResource;
|
||||
}
|
||||
private:
|
||||
D3D11_BLEND_DESC mDesc;
|
||||
const char *mDebugName;
|
||||
};
|
||||
|
||||
// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
|
||||
// represent an entire buffer.
|
||||
|
@ -53,7 +53,7 @@ gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangl
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams)
|
||||
gl::Error Framebuffer9::clear(const gl::Data &data, const ClearParameters &clearParams)
|
||||
{
|
||||
const gl::FramebufferAttachment *colorAttachment = mData.getColorAttachment(0);
|
||||
const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment();
|
||||
@ -64,11 +64,12 @@ gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &cle
|
||||
return error;
|
||||
}
|
||||
|
||||
float nearZ = state.getNearPlane();
|
||||
float farZ = state.getFarPlane();
|
||||
mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true);
|
||||
float nearZ = data.state->getNearPlane();
|
||||
float farZ = data.state->getFarPlane();
|
||||
mRenderer->setViewport(data.caps, data.state->getViewport(), nearZ, farZ, GL_TRIANGLES,
|
||||
data.state->getRasterizerState().frontFace, true);
|
||||
|
||||
mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled());
|
||||
mRenderer->setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
|
||||
|
||||
return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class Framebuffer9 : public FramebufferD3D
|
||||
gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
|
||||
|
||||
private:
|
||||
gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
|
||||
gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override;
|
||||
|
||||
gl::Error readPixelsImpl(const gl::Rectangle &area,
|
||||
GLenum format,
|
||||
|
@ -132,6 +132,8 @@ Renderer9::Renderer9(egl::Display *display)
|
||||
mAppliedProgramSerial = 0;
|
||||
|
||||
initializeDebugAnnotator();
|
||||
|
||||
mEGLDevice = nullptr;
|
||||
}
|
||||
|
||||
Renderer9::~Renderer9()
|
||||
@ -154,6 +156,7 @@ void Renderer9::release()
|
||||
|
||||
releaseDeviceResources();
|
||||
|
||||
SafeDelete(mEGLDevice);
|
||||
SafeRelease(mDevice);
|
||||
SafeRelease(mDeviceEx);
|
||||
SafeRelease(mD3d9);
|
||||
@ -883,6 +886,53 @@ gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/,
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error Renderer9::updateState(const gl::Data &data, GLenum drawMode)
|
||||
{
|
||||
// Applies the render target surface, depth stencil surface, viewport rectangle and
|
||||
// scissor rectangle to the renderer
|
||||
const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
|
||||
ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
gl::Error error = applyRenderTarget(framebufferObject);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
// Setting viewport state
|
||||
setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(),
|
||||
data.state->getFarPlane(), drawMode, data.state->getRasterizerState().frontFace,
|
||||
false);
|
||||
|
||||
// Setting scissors state
|
||||
setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
|
||||
|
||||
// Setting rasterizer state
|
||||
int samples = framebufferObject->getSamples(data);
|
||||
gl::RasterizerState rasterizer = data.state->getRasterizerState();
|
||||
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
|
||||
rasterizer.multiSample = (samples != 0);
|
||||
|
||||
error = setRasterizerState(rasterizer);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
// Setting blend state
|
||||
unsigned int mask = GetBlendSampleMask(data, samples);
|
||||
error = setBlendState(framebufferObject, data.state->getBlendState(),
|
||||
data.state->getBlendColor(), mask);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
// Setting depth stencil state
|
||||
error = setDepthStencilState(*data.state);
|
||||
return error;
|
||||
}
|
||||
|
||||
gl::Error Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
|
||||
{
|
||||
bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0;
|
||||
@ -1031,9 +1081,13 @@ gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer,
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
|
||||
int stencilBackRef, bool frontFaceCCW)
|
||||
gl::Error Renderer9::setDepthStencilState(const gl::State &glState)
|
||||
{
|
||||
const auto &depthStencilState = glState.getDepthStencilState();
|
||||
int stencilRef = glState.getStencilRef();
|
||||
int stencilBackRef = glState.getStencilBackRef();
|
||||
bool frontFaceCCW = (glState.getRasterizerState().frontFace == GL_CCW);
|
||||
|
||||
bool depthStencilStateChanged = mForceSetDepthStencilState ||
|
||||
memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0;
|
||||
bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef ||
|
||||
@ -1154,7 +1208,12 @@ void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
|
||||
mForceSetScissor = false;
|
||||
}
|
||||
|
||||
void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
|
||||
void Renderer9::setViewport(const gl::Caps *caps,
|
||||
const gl::Rectangle &viewport,
|
||||
float zNear,
|
||||
float zFar,
|
||||
GLenum drawMode,
|
||||
GLenum frontFace,
|
||||
bool ignoreViewport)
|
||||
{
|
||||
gl::Rectangle actualViewport = viewport;
|
||||
@ -1277,15 +1336,14 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu
|
||||
{
|
||||
ASSERT(depthbuffer);
|
||||
|
||||
GLsizei width = depthbuffer->getWidth();
|
||||
GLsizei height = depthbuffer->getHeight();
|
||||
const gl::Extents &size = depthbuffer->getSize();
|
||||
|
||||
// search cached nullcolorbuffers
|
||||
for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
|
||||
{
|
||||
if (mNullColorbufferCache[i].buffer != NULL &&
|
||||
mNullColorbufferCache[i].width == width &&
|
||||
mNullColorbufferCache[i].height == height)
|
||||
mNullColorbufferCache[i].width == size.width &&
|
||||
mNullColorbufferCache[i].height == size.height)
|
||||
{
|
||||
mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
|
||||
*outColorBuffer = mNullColorbufferCache[i].buffer;
|
||||
@ -1294,7 +1352,7 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu
|
||||
}
|
||||
|
||||
gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0);
|
||||
gl::Error error = nullRenderbuffer->setStorage(GL_NONE, width, height);
|
||||
gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height);
|
||||
if (error.isError())
|
||||
{
|
||||
SafeDelete(nullRenderbuffer);
|
||||
@ -1316,8 +1374,8 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu
|
||||
delete oldest->buffer;
|
||||
oldest->buffer = nullbuffer;
|
||||
oldest->lruCount = ++mMaxNullColorbufferLRU;
|
||||
oldest->width = width;
|
||||
oldest->height = height;
|
||||
oldest->width = size.width;
|
||||
oldest->height = size.height;
|
||||
|
||||
*outColorBuffer = nullbuffer;
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
@ -3052,14 +3110,23 @@ gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStar
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
egl::Error Renderer9::initializeEGLDevice(DeviceD3D **outDevice)
|
||||
egl::Error Renderer9::getEGLDevice(DeviceImpl **device)
|
||||
{
|
||||
if (*outDevice == nullptr)
|
||||
if (mEGLDevice == nullptr)
|
||||
{
|
||||
ASSERT(mDevice != nullptr);
|
||||
*outDevice = new DeviceD3D(reinterpret_cast<void *>(mDevice), EGL_D3D9_DEVICE_ANGLE);
|
||||
mEGLDevice = new DeviceD3D();
|
||||
egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
|
||||
EGL_D3D9_DEVICE_ANGLE, EGL_FALSE);
|
||||
|
||||
if (error.isError())
|
||||
{
|
||||
SafeDelete(mEGLDevice);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
*device = static_cast<DeviceImpl *>(mEGLDevice);
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -96,17 +96,16 @@ class Renderer9 : public RendererD3D
|
||||
const std::vector<GLint> &vertexUniformBuffers,
|
||||
const std::vector<GLint> &fragmentUniformBuffers) override;
|
||||
|
||||
virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
|
||||
gl::Error setBlendState(const gl::Framebuffer *framebuffer,
|
||||
const gl::BlendState &blendState,
|
||||
const gl::ColorF &blendColor,
|
||||
unsigned int sampleMask) override;
|
||||
virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
|
||||
int stencilBackRef, bool frontFaceCCW);
|
||||
gl::Error updateState(const gl::Data &data, GLenum drawMode) override;
|
||||
|
||||
virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
|
||||
virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
|
||||
bool ignoreViewport);
|
||||
void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
|
||||
void setViewport(const gl::Caps *caps,
|
||||
const gl::Rectangle &viewport,
|
||||
float zNear,
|
||||
float zFar,
|
||||
GLenum drawMode,
|
||||
GLenum frontFace,
|
||||
bool ignoreViewport);
|
||||
|
||||
gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
|
||||
gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorAttachment,
|
||||
@ -252,13 +251,13 @@ class Renderer9 : public RendererD3D
|
||||
|
||||
D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; }
|
||||
|
||||
egl::Error getEGLDevice(DeviceImpl **device) override;
|
||||
|
||||
protected:
|
||||
void createAnnotator() override;
|
||||
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
|
||||
gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
|
||||
|
||||
egl::Error initializeEGLDevice(DeviceD3D **outDevice) override;
|
||||
|
||||
private:
|
||||
gl::Error drawArraysImpl(const gl::Data &data,
|
||||
GLenum mode,
|
||||
@ -278,6 +277,13 @@ class Renderer9 : public RendererD3D
|
||||
|
||||
WorkaroundsD3D generateWorkarounds() const override;
|
||||
|
||||
gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
|
||||
gl::Error setBlendState(const gl::Framebuffer *framebuffer,
|
||||
const gl::BlendState &blendState,
|
||||
const gl::ColorF &blendColor,
|
||||
unsigned int sampleMask);
|
||||
gl::Error setDepthStencilState(const gl::State &glState);
|
||||
|
||||
void release();
|
||||
|
||||
void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v);
|
||||
@ -416,6 +422,8 @@ class Renderer9 : public RendererD3D
|
||||
gl::FramebufferAttachment *buffer;
|
||||
} mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
|
||||
UINT mMaxNullColorbufferLRU;
|
||||
|
||||
DeviceD3D *mEGLDevice;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "libANGLE/renderer/gl/StateManagerGL.h"
|
||||
#include "libANGLE/renderer/gl/TextureGL.h"
|
||||
#include "libANGLE/renderer/gl/WorkaroundsGL.h"
|
||||
#include "platform/Platform.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
@ -212,7 +213,10 @@ gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
|
||||
gl::Error FramebufferGL::clearBufferfv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLfloat *values)
|
||||
{
|
||||
syncClearBufferState(buffer, drawbuffer);
|
||||
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
|
||||
@ -221,7 +225,10 @@ gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GL
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
|
||||
gl::Error FramebufferGL::clearBufferuiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLuint *values)
|
||||
{
|
||||
syncClearBufferState(buffer, drawbuffer);
|
||||
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
|
||||
@ -230,7 +237,10 @@ gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, G
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
|
||||
gl::Error FramebufferGL::clearBufferiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLint *values)
|
||||
{
|
||||
syncClearBufferState(buffer, drawbuffer);
|
||||
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
|
||||
@ -239,7 +249,11 @@ gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GL
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
|
||||
gl::Error FramebufferGL::clearBufferfi(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
GLfloat depth,
|
||||
GLint stencil)
|
||||
{
|
||||
syncClearBufferState(buffer, drawbuffer);
|
||||
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
|
||||
@ -285,17 +299,21 @@ gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourc
|
||||
mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
|
||||
mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
|
||||
|
||||
mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
|
||||
destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
|
||||
mask, filter);
|
||||
mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
|
||||
destArea.x, destArea.y, destArea.x1(), destArea.y1(), mask, filter);
|
||||
|
||||
return gl::Error(GL_NO_ERROR);
|
||||
}
|
||||
|
||||
GLenum FramebufferGL::checkStatus() const
|
||||
bool FramebufferGL::checkStatus() const
|
||||
{
|
||||
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
|
||||
return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
|
||||
GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete.");
|
||||
}
|
||||
return (status == GL_FRAMEBUFFER_COMPLETE);
|
||||
}
|
||||
|
||||
GLuint FramebufferGL::getFramebufferID() const
|
||||
|
@ -49,10 +49,23 @@ class FramebufferGL : public FramebufferImpl
|
||||
gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
|
||||
|
||||
gl::Error clear(const gl::Data &data, GLbitfield mask) override;
|
||||
gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override;
|
||||
gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override;
|
||||
gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override;
|
||||
gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override;
|
||||
gl::Error clearBufferfv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLfloat *values) override;
|
||||
gl::Error clearBufferuiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLuint *values) override;
|
||||
gl::Error clearBufferiv(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
const GLint *values) override;
|
||||
gl::Error clearBufferfi(const gl::Data &data,
|
||||
GLenum buffer,
|
||||
GLint drawbuffer,
|
||||
GLfloat depth,
|
||||
GLint stencil) override;
|
||||
|
||||
GLenum getImplementationColorReadFormat() const override;
|
||||
GLenum getImplementationColorReadType() const override;
|
||||
@ -61,7 +74,7 @@ class FramebufferGL : public FramebufferImpl
|
||||
gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
|
||||
GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
|
||||
|
||||
GLenum checkStatus() const override;
|
||||
bool checkStatus() const override;
|
||||
|
||||
void syncDrawState() const;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "libANGLE/renderer/gl/FunctionsGL.h"
|
||||
#include "libANGLE/renderer/gl/ShaderGL.h"
|
||||
#include "libANGLE/renderer/gl/StateManagerGL.h"
|
||||
#include "platform/Platform.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
@ -46,6 +47,11 @@ gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
|
||||
return gl::Error(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
void ProgramGL::setBinaryRetrievableHint(bool retrievable)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
|
||||
{
|
||||
// Reset the program state, delete the current program if one exists
|
||||
@ -105,7 +111,6 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
|
||||
// Verify the link
|
||||
GLint linkStatus = GL_FALSE;
|
||||
mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
|
||||
ASSERT(linkStatus == GL_TRUE);
|
||||
if (linkStatus == GL_FALSE)
|
||||
{
|
||||
// Linking failed, put the error into the info log
|
||||
@ -118,8 +123,11 @@ LinkResult ProgramGL::link(const gl::Data &data, gl::InfoLog &infoLog)
|
||||
mFunctions->deleteProgram(mProgramID);
|
||||
mProgramID = 0;
|
||||
|
||||
infoLog << &buf[0];
|
||||
TRACE("\n%s", &buf[0]);
|
||||
infoLog << buf.data();
|
||||
|
||||
std::string warning = FormatString("Program link failed unexpectedly: %s", buf.data());
|
||||
ANGLEPlatformCurrent()->logWarning(warning.c_str());
|
||||
TRACE("\n%s", warning.c_str());
|
||||
|
||||
// TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
|
||||
return LinkResult(false, gl::Error(GL_NO_ERROR));
|
||||
|
@ -33,6 +33,7 @@ class ProgramGL : public ProgramImpl
|
||||
|
||||
LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
|
||||
gl::Error save(gl::BinaryOutputStream *stream) override;
|
||||
void setBinaryRetrievableHint(bool retrievable) override;
|
||||
|
||||
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
|
||||
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
|
||||
|
@ -113,7 +113,7 @@ SurfaceImpl *DisplayCGL::createWindowSurface(const egl::Config *configuration,
|
||||
EGLNativeWindowType window,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
return new WindowSurfaceCGL(this->getRenderer(), window, mFunctions);
|
||||
return new WindowSurfaceCGL(this->getRenderer(), window, mFunctions, mContext);
|
||||
}
|
||||
|
||||
SurfaceImpl *DisplayCGL::createPbufferSurface(const egl::Config *configuration,
|
||||
|
@ -34,7 +34,7 @@ class PbufferSurfaceCGL : public SurfaceGL
|
||||
egl::Error swap() override;
|
||||
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
|
||||
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
|
||||
egl::Error bindTexImage(EGLint buffer) override;
|
||||
egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
|
||||
egl::Error releaseTexImage(EGLint buffer) override;
|
||||
void setSwapInterval(EGLint interval) override;
|
||||
|
||||
|
@ -95,7 +95,7 @@ egl::Error PbufferSurfaceCGL::querySurfacePointerANGLE(EGLint attribute, void **
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error PbufferSurfaceCGL::bindTexImage(EGLint buffer)
|
||||
egl::Error PbufferSurfaceCGL::bindTexImage(gl::Texture *texture, EGLint buffer)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
|
@ -11,10 +11,14 @@
|
||||
|
||||
#include "libANGLE/renderer/gl/SurfaceGL.h"
|
||||
|
||||
struct _CGLContextObject;
|
||||
typedef _CGLContextObject *CGLContextObj;
|
||||
@class CALayer;
|
||||
struct __IOSurface;
|
||||
typedef __IOSurface *IOSurfaceRef;
|
||||
|
||||
@class SwapLayer;
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
@ -24,12 +28,36 @@ class FunctionsGL;
|
||||
class StateManagerGL;
|
||||
struct WorkaroundsGL;
|
||||
|
||||
class DisplayLink;
|
||||
struct SharedSwapState
|
||||
{
|
||||
struct SwapTexture
|
||||
{
|
||||
GLuint texture;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
uint64_t swapId;
|
||||
};
|
||||
|
||||
SwapTexture textures[3];
|
||||
|
||||
// This code path is not going to be used by Chrome so we take the liberty
|
||||
// to use pthreads directly instead of using mutexes and condition variables
|
||||
// via the Platform API.
|
||||
pthread_mutex_t mutex;
|
||||
// The following members should be accessed only when holding the mutex
|
||||
// (or doing construction / destruction)
|
||||
SwapTexture *beingRendered;
|
||||
SwapTexture *lastRendered;
|
||||
SwapTexture *beingPresented;
|
||||
};
|
||||
|
||||
class WindowSurfaceCGL : public SurfaceGL
|
||||
{
|
||||
public:
|
||||
WindowSurfaceCGL(RendererGL *renderer, CALayer *layer, const FunctionsGL *functions);
|
||||
WindowSurfaceCGL(RendererGL *renderer,
|
||||
CALayer *layer,
|
||||
const FunctionsGL *functions,
|
||||
CGLContextObj context);
|
||||
~WindowSurfaceCGL() override;
|
||||
|
||||
egl::Error initialize() override;
|
||||
@ -38,7 +66,7 @@ class WindowSurfaceCGL : public SurfaceGL
|
||||
egl::Error swap() override;
|
||||
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
|
||||
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
|
||||
egl::Error bindTexImage(EGLint buffer) override;
|
||||
egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
|
||||
egl::Error releaseTexImage(EGLint buffer) override;
|
||||
void setSwapInterval(EGLint interval) override;
|
||||
|
||||
@ -51,27 +79,16 @@ class WindowSurfaceCGL : public SurfaceGL
|
||||
FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override;
|
||||
|
||||
private:
|
||||
struct Surface
|
||||
{
|
||||
IOSurfaceRef ioSurface;
|
||||
GLuint texture;
|
||||
uint64_t lastPresentNanos;
|
||||
};
|
||||
|
||||
void freeSurfaceData(Surface *surface);
|
||||
egl::Error initializeSurfaceData(Surface *surface, int width, int height);
|
||||
SwapLayer *mSwapLayer;
|
||||
SharedSwapState mSwapState;
|
||||
uint64_t mCurrentSwapId;
|
||||
|
||||
CALayer *mLayer;
|
||||
CGLContextObj mContext;
|
||||
const FunctionsGL *mFunctions;
|
||||
StateManagerGL *mStateManager;
|
||||
const WorkaroundsGL &mWorkarounds;
|
||||
DisplayLink *mDisplayLink;
|
||||
|
||||
// CGL doesn't have a default framebuffer, we instead render to an IOSurface
|
||||
// that will be set as the content of the CALayer which is our native window.
|
||||
// We use two IOSurfaces to do double buffering.
|
||||
Surface mSurfaces[2];
|
||||
int mCurrentSurface;
|
||||
GLuint mFramebuffer;
|
||||
GLuint mDSRenderbuffer;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user