Bug 1232902. Update ANGLE to chromium/2592

This commit is contained in:
Jeff Muizelaar 2015-12-15 23:15:12 -05:00
parent 4c16c91d3a
commit b60330f131
166 changed files with 5150 additions and 3048 deletions

View File

@ -222,6 +222,7 @@ config("libANGLE_config") {
}
defines += [
"GL_GLEXT_PROTOTYPES",
"EGL_EGLEXT_PROTOTYPES",
]
if (is_win) {

View File

@ -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",

View File

@ -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!

View File

@ -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

View File

@ -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"

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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;

View File

@ -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.
//

View File

@ -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();

View File

@ -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_

View File

@ -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.

View File

@ -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;

View 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);
}
}
}

View File

@ -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

View File

@ -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;
};

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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)
{

View File

@ -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;
};
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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--;

View File

@ -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;

View File

@ -165,4 +165,9 @@ GLuint Renderbuffer::getId() const
{
return id();
}
Extents Renderbuffer::getAttachmentSize(const FramebufferAttachment::Target & /*target*/) const
{
return Extents(mWidth, mHeight, 1);
}
}

View File

@ -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(); }

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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());

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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.

View File

@ -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;
};
}

View File

@ -21,10 +21,7 @@ DisplayImpl::DisplayImpl()
DisplayImpl::~DisplayImpl()
{
while (!mSurfaceSet.empty())
{
destroySurface(*mSurfaceSet.begin());
}
ASSERT(mSurfaceSet.empty());
}
void DisplayImpl::destroySurface(egl::Surface *surface)

View File

@ -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; }

View File

@ -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());
};

View File

@ -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;

View File

@ -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 *));

View File

@ -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;

View File

@ -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))

View File

@ -71,6 +71,7 @@ class BufferD3D : public BufferImpl
protected:
void updateSerial();
void updateD3DBufferUsage(GLenum usage);
void emptyStaticBufferCache();
BufferFactoryD3D *mFactory;
unsigned int mSerial;

View File

@ -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;

View File

@ -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;
};
}

View File

@ -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.");

View File

@ -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(

View File

@ -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,

View File

@ -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)
{

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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)

View File

@ -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;
};

View File

@ -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
{

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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_

View File

@ -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)

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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.

View File

@ -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);
}

View File

@ -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,

View File

@ -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);
}

View File

@ -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;
};
}

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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