зеркало из https://github.com/AvaloniaUI/angle.git
GLES: Expose OES_mapbuffer in GLES2 on GLES3.
This extension is mandatory for EXT_map_buffer_range support. We can emulate it using GLES 3.0 core map functionality. BUG=angleproject:1751 Change-Id: Idba09ce7276603d5556039f4a49aa0b87cae22aa Reviewed-on: https://chromium-review.googlesource.com/431826 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Родитель
d73f852f8d
Коммит
cc6ac25e95
|
@ -115,11 +115,18 @@ gl::Error BufferGL::map(GLenum access, GLvoid **mapPtr)
|
||||||
{
|
{
|
||||||
*mapPtr = mShadowCopy.data();
|
*mapPtr = mShadowCopy.data();
|
||||||
}
|
}
|
||||||
else
|
else if (mFunctions->mapBuffer)
|
||||||
{
|
{
|
||||||
mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
|
mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
|
||||||
*mapPtr = mFunctions->mapBuffer(DestBufferOperationTarget, access);
|
*mapPtr = mFunctions->mapBuffer(DestBufferOperationTarget, access);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(mFunctions->mapBufferRange && access == GL_WRITE_ONLY_OES);
|
||||||
|
mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
|
||||||
|
*mapPtr =
|
||||||
|
mFunctions->mapBufferRange(DestBufferOperationTarget, 0, mBufferSize, GL_MAP_WRITE_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
mIsMapped = true;
|
mIsMapped = true;
|
||||||
mMapOffset = 0;
|
mMapOffset = 0;
|
||||||
|
|
|
@ -788,6 +788,7 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
|
||||||
extensions->readFormatBGRA = functions->isAtLeastGL(gl::Version(1, 2)) || functions->hasGLExtension("GL_EXT_bgra") ||
|
extensions->readFormatBGRA = functions->isAtLeastGL(gl::Version(1, 2)) || functions->hasGLExtension("GL_EXT_bgra") ||
|
||||||
functions->hasGLESExtension("GL_EXT_read_format_bgra");
|
functions->hasGLESExtension("GL_EXT_read_format_bgra");
|
||||||
extensions->mapBuffer = functions->isAtLeastGL(gl::Version(1, 5)) ||
|
extensions->mapBuffer = functions->isAtLeastGL(gl::Version(1, 5)) ||
|
||||||
|
functions->isAtLeastGLES(gl::Version(3, 0)) ||
|
||||||
functions->hasGLESExtension("GL_OES_mapbuffer");
|
functions->hasGLESExtension("GL_OES_mapbuffer");
|
||||||
extensions->mapBufferRange = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_ARB_map_buffer_range") ||
|
extensions->mapBufferRange = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_ARB_map_buffer_range") ||
|
||||||
functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_map_buffer_range");
|
functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_map_buffer_range");
|
||||||
|
|
|
@ -1230,7 +1230,7 @@ bool ValidateGetBufferParameterBase(ValidationContext *context,
|
||||||
if (!extensions.mapBuffer)
|
if (!extensions.mapBuffer)
|
||||||
{
|
{
|
||||||
context->handleError(
|
context->handleError(
|
||||||
Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
|
Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1242,7 +1242,7 @@ bool ValidateGetBufferParameterBase(ValidationContext *context,
|
||||||
{
|
{
|
||||||
context->handleError(Error(
|
context->handleError(Error(
|
||||||
GL_INVALID_ENUM,
|
GL_INVALID_ENUM,
|
||||||
"pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
|
"pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -4366,7 +4366,7 @@ bool ValidateGetBufferPointervBase(Context *context,
|
||||||
{
|
{
|
||||||
context->handleError(
|
context->handleError(
|
||||||
Error(GL_INVALID_OPERATION,
|
Error(GL_INVALID_OPERATION,
|
||||||
"Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
|
"Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "test_utils/ANGLETest.h"
|
#include "test_utils/ANGLETest.h"
|
||||||
#include "test_utils/gl_raii.h"
|
#include "test_utils/gl_raii.h"
|
||||||
|
|
||||||
|
#include "random_utils.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
using namespace angle;
|
using namespace angle;
|
||||||
|
@ -433,6 +435,54 @@ TEST_P(BufferDataTestES3, BufferResizing)
|
||||||
EXPECT_GL_NO_ERROR();
|
EXPECT_GL_NO_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify OES_mapbuffer is present if EXT_map_buffer_range is.
|
||||||
|
TEST_P(BufferDataTest, ExtensionDependency)
|
||||||
|
{
|
||||||
|
if (extensionEnabled("GL_EXT_map_buffer_range"))
|
||||||
|
{
|
||||||
|
ASSERT_TRUE(extensionEnabled("GL_OES_mapbuffer"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test mapping with the OES extension.
|
||||||
|
TEST_P(BufferDataTest, MapBufferOES)
|
||||||
|
{
|
||||||
|
if (!extensionEnabled("GL_EXT_map_buffer_range"))
|
||||||
|
{
|
||||||
|
// Needed for test validation.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> data(1024);
|
||||||
|
FillVectorWithRandomUBytes(&data);
|
||||||
|
|
||||||
|
GLBuffer buffer;
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, data.size(), nullptr, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// Validate that other map flags don't work.
|
||||||
|
void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
|
||||||
|
EXPECT_EQ(nullptr, badMapPtr);
|
||||||
|
EXPECT_GL_ERROR(GL_INVALID_ENUM);
|
||||||
|
|
||||||
|
// Map and write.
|
||||||
|
void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
|
||||||
|
ASSERT_NE(nullptr, mapPtr);
|
||||||
|
ASSERT_GL_NO_ERROR();
|
||||||
|
memcpy(mapPtr, data.data(), data.size());
|
||||||
|
glUnmapBufferOES(GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
// Validate data with EXT_map_buffer_range
|
||||||
|
void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
|
||||||
|
ASSERT_NE(nullptr, readMapPtr);
|
||||||
|
ASSERT_GL_NO_ERROR();
|
||||||
|
std::vector<uint8_t> actualData(data.size());
|
||||||
|
memcpy(actualData.data(), readMapPtr, data.size());
|
||||||
|
glUnmapBufferOES(GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
EXPECT_EQ(data, actualData);
|
||||||
|
}
|
||||||
|
|
||||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
|
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
|
||||||
ANGLE_INSTANTIATE_TEST(BufferDataTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
|
ANGLE_INSTANTIATE_TEST(BufferDataTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
|
||||||
ANGLE_INSTANTIATE_TEST(BufferDataTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
|
ANGLE_INSTANTIATE_TEST(BufferDataTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "random_utils.h"
|
||||||
|
#include "test_utils/gl_raii.h"
|
||||||
|
|
||||||
using namespace angle;
|
using namespace angle;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -27,8 +30,28 @@ class SimpleOperationTest : public ANGLETest
|
||||||
setConfigBlueBits(8);
|
setConfigBlueBits(8);
|
||||||
setConfigAlphaBits(8);
|
setConfigAlphaBits(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void verifyBuffer(const std::vector<uint8_t> &data, GLenum binding);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SimpleOperationTest::verifyBuffer(const std::vector<uint8_t> &data, GLenum binding)
|
||||||
|
{
|
||||||
|
if (!extensionEnabled("GL_EXT_map_buffer_range"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *mapPointer =
|
||||||
|
static_cast<uint8_t *>(glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, 1024, GL_MAP_READ_BIT));
|
||||||
|
ASSERT_GL_NO_ERROR();
|
||||||
|
|
||||||
|
std::vector<uint8_t> readbackData(data.size());
|
||||||
|
memcpy(readbackData.data(), mapPointer, data.size());
|
||||||
|
glUnmapBufferOES(GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
EXPECT_EQ(data, readbackData);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(SimpleOperationTest, CompileVertexShader)
|
TEST_P(SimpleOperationTest, CompileVertexShader)
|
||||||
{
|
{
|
||||||
const std::string source = SHADER_SOURCE
|
const std::string source = SHADER_SOURCE
|
||||||
|
@ -154,46 +177,47 @@ TEST_P(SimpleOperationTest, LinkProgramWithAttributes)
|
||||||
|
|
||||||
TEST_P(SimpleOperationTest, BufferDataWithData)
|
TEST_P(SimpleOperationTest, BufferDataWithData)
|
||||||
{
|
{
|
||||||
GLuint buffer;
|
GLBuffer buffer;
|
||||||
glGenBuffers(1, &buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
|
||||||
|
|
||||||
std::vector<uint8_t> data(1024);
|
std::vector<uint8_t> data(1024);
|
||||||
|
FillVectorWithRandomUBytes(&data);
|
||||||
glBufferData(GL_ARRAY_BUFFER, data.size(), &data[0], GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, data.size(), &data[0], GL_STATIC_DRAW);
|
||||||
|
|
||||||
glDeleteBuffers(1, &buffer);
|
verifyBuffer(data, GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
EXPECT_GL_NO_ERROR();
|
EXPECT_GL_NO_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(SimpleOperationTest, BufferDataWithNoData)
|
TEST_P(SimpleOperationTest, BufferDataWithNoData)
|
||||||
{
|
{
|
||||||
GLuint buffer;
|
GLBuffer buffer;
|
||||||
glGenBuffers(1, &buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
|
||||||
glDeleteBuffers(1, &buffer);
|
|
||||||
|
|
||||||
EXPECT_GL_NO_ERROR();
|
EXPECT_GL_NO_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(SimpleOperationTest, BufferSubData)
|
TEST_P(SimpleOperationTest, BufferSubData)
|
||||||
{
|
{
|
||||||
GLuint buffer;
|
GLBuffer buffer;
|
||||||
glGenBuffers(1, &buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
|
||||||
|
constexpr size_t bufferSize = 1024;
|
||||||
|
std::vector<uint8_t> data(bufferSize);
|
||||||
|
FillVectorWithRandomUBytes(&data);
|
||||||
|
|
||||||
const size_t bufferSize = 1024;
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
|
||||||
|
|
||||||
const size_t subDataCount = 16;
|
constexpr size_t subDataCount = 16;
|
||||||
std::vector<uint8_t> data(bufferSize / subDataCount);
|
constexpr size_t sliceSize = bufferSize / subDataCount;
|
||||||
for (size_t i = 0; i < subDataCount; i++)
|
for (size_t i = 0; i < subDataCount; i++)
|
||||||
{
|
{
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, data.size() * i, data.size(), &data[0]);
|
size_t offset = i * sliceSize;
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, offset, sliceSize, &data[offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteBuffers(1, &buffer);
|
verifyBuffer(data, GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
EXPECT_GL_NO_ERROR();
|
EXPECT_GL_NO_ERROR();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,16 @@ class ANGLE_EXPORT RNG
|
||||||
std::default_random_engine mGenerator;
|
std::default_random_engine mGenerator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Implemented htis way because of cross-module allocation issues.
|
||||||
|
inline void FillVectorWithRandomUBytes(std::vector<uint8_t> *data)
|
||||||
|
{
|
||||||
|
RNG rng;
|
||||||
|
for (size_t i = 0; i < data->size(); ++i)
|
||||||
|
{
|
||||||
|
(*data)[i] = static_cast<uint8_t>(rng.randomIntBetween(0, 255));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace angle
|
} // namespace angle
|
||||||
|
|
||||||
#endif // UTIL_RANDOM_UTILS_H
|
#endif // UTIL_RANDOM_UTILS_H
|
||||||
|
|
Загрузка…
Ссылка в новой задаче