blob: 568ecd96c6b6c49ec23cc370aa471ef902e43f51 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
namespace gpu {
namespace gles2 {
TEST_F(GLES3DecoderPassthroughTest, BindBufferBaseValidArgs) {
cmds::BindBufferBase bind_cmd;
bind_cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kClientBufferId);
EXPECT_EQ(error::kNoError, ExecuteCmd(bind_cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, BindBufferBaseValidArgsNewId) {
constexpr GLuint kNewClientId = 502;
cmds::BindBufferBase cmd;
cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
EXPECT_TRUE(IsObjectHelper<cmds::IsBuffer>(kNewClientId));
}
TEST_F(GLES3DecoderPassthroughTest, BindBufferRangeValidArgs) {
const GLenum kTarget = GL_TRANSFORM_FEEDBACK_BUFFER;
const GLintptr kRangeOffset = 4;
const GLsizeiptr kRangeSize = 8;
const GLsizeiptr kBufferSize = kRangeOffset + kRangeSize;
cmds::BindBuffer bind_cmd;
bind_cmd.Init(kTarget, kClientBufferId);
EXPECT_EQ(error::kNoError, ExecuteCmd(bind_cmd));
cmds::BufferData buffer_data_cmd;
buffer_data_cmd.Init(kTarget, kBufferSize, 0, 0, GL_STREAM_DRAW);
EXPECT_EQ(error::kNoError, ExecuteCmd(buffer_data_cmd));
cmds::BindBufferRange bind_buffer_range_cmd;
bind_buffer_range_cmd.Init(kTarget, 2, kClientBufferId, kRangeOffset,
kRangeSize);
EXPECT_EQ(error::kNoError, ExecuteCmd(bind_buffer_range_cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, BindBufferRangeValidArgsWithNoData) {
const GLenum kTarget = GL_TRANSFORM_FEEDBACK_BUFFER;
const GLintptr kRangeOffset = 4;
const GLsizeiptr kRangeSize = 8;
DoBindBuffer(kTarget, kClientBufferId);
cmds::BindBufferRange cmd;
cmd.Init(kTarget, 2, kClientBufferId, kRangeOffset, kRangeSize);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, BindBufferRangeValidArgsWithLessData) {
const GLenum kTarget = GL_TRANSFORM_FEEDBACK_BUFFER;
const GLintptr kRangeOffset = 4;
const GLsizeiptr kRangeSize = 8;
const GLsizeiptr kBufferSize = kRangeOffset + kRangeSize - 4;
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kBufferSize, nullptr, GL_STREAM_DRAW);
cmds::BindBufferRange cmd;
cmd.Init(kTarget, 2, kClientBufferId, kRangeOffset, kRangeSize);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, BindBufferRangeValidArgsNewId) {
cmds::BindBufferRange cmd;
cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId, 4, 4);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
EXPECT_TRUE(IsObjectHelper<cmds::IsBuffer>(kNewClientId));
}
TEST_F(GLES3DecoderPassthroughTest, MapBufferRangeUnmapBufferReadSucceeds) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_READ_BIT;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
// uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kSize + kOffset, nullptr, GL_STREAM_DRAW);
std::vector<int8_t> data(kSize);
for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
data[ii] = static_cast<int8_t>(ii % 255);
}
DoBufferSubData(kTarget, kOffset, kSize, data.data());
{ // MapBufferRange
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
*result = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
EXPECT_EQ(1u, *result);
}
{ // UnmapBuffer
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, MapBufferRangeUnmapBufferWriteSucceeds) {
const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLsizeiptr kTotalSize = kOffset + kSize;
const GLbitfield kAccess = GL_MAP_WRITE_BIT;
const GLbitfield kMappedAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
// uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
int8_t* client_data = GetSharedMemoryAs<int8_t*>() + sizeof(uint32_t);
DoBindBuffer(kTarget, kClientBufferId);
std::vector<int8_t> gpu_data(kTotalSize);
for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
gpu_data[ii] = static_cast<int8_t>(ii % 128);
}
DoBufferData(kTarget, kTotalSize, gpu_data.data(), GL_STREAM_DRAW);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
{ // MapBufferRange succeeds
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
*result = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(1u, *result);
PassthroughResources* passthrough_resources = GetPassthroughResources();
auto mapped_buffer_info_iter =
passthrough_resources->mapped_buffer_map.find(kClientBufferId);
EXPECT_NE(mapped_buffer_info_iter,
passthrough_resources->mapped_buffer_map.end());
const MappedBuffer& mapped_buffer_info = mapped_buffer_info_iter->second;
EXPECT_EQ(mapped_buffer_info.original_access, kAccess);
EXPECT_EQ(mapped_buffer_info.filtered_access, kMappedAccess);
// Verify the buffer range from GPU is copied to client mem.
EXPECT_EQ(0, memcmp(&gpu_data[kOffset], client_data, kSize));
}
// Update the client mem.
const int8_t kValue0 = 21;
memset(client_data, kValue0, kSize);
{ // UnmapBuffer succeeds
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
// Reset the client data before mapping again
const int8_t kValue1 = 0;
memset(client_data, kValue1, kSize);
{ // Re-map the buffer to verify the data
const GLbitfield kReadAccess = GL_MAP_READ_BIT;
cmds::MapBufferRange cmd;
cmd.Init(kTarget, 0, kTotalSize, kReadAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
*result = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(1u, *result);
// Verify the GPU mem is updated
for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
if (ii < kOffset) {
EXPECT_EQ(static_cast<int8_t>(ii % 128), client_data[ii]);
} else {
EXPECT_EQ(kValue0, client_data[ii]);
}
}
}
{ // UnmapBuffer succeeds
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, FlushMappedBufferRangeSucceeds) {
const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
const GLintptr kMappedOffset = 10;
const GLsizeiptr kMappedSize = 64;
const GLintptr kFlushRangeOffset = 5;
const GLsizeiptr kFlushRangeSize = 32;
const GLsizeiptr kTotalSize = kMappedOffset + kMappedSize;
const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
const GLbitfield kMappedAccess = kAccess | GL_MAP_READ_BIT;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
// uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
int8_t* client_data = GetSharedMemoryAs<int8_t*>() + sizeof(uint32_t);
DoBindBuffer(kTarget, kClientBufferId);
std::vector<int8_t> gpu_data(kTotalSize);
for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
gpu_data[ii] = static_cast<int8_t>(ii % 128);
}
DoBufferData(kTarget, kTotalSize, gpu_data.data(), GL_STREAM_DRAW);
{ // MapBufferRange succeeds
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kMappedOffset, kMappedSize, kAccess, data_shm_id,
data_shm_offset, result_shm_id, result_shm_offset);
*result = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(1u, *result);
// Verify the buffer range from GPU is copied to client mem.
EXPECT_EQ(0, memcmp(&gpu_data[kMappedOffset], client_data, kMappedSize));
PassthroughResources* passthrough_resources = GetPassthroughResources();
auto mapped_buffer_info_iter =
passthrough_resources->mapped_buffer_map.find(kClientBufferId);
EXPECT_NE(mapped_buffer_info_iter,
passthrough_resources->mapped_buffer_map.end());
const MappedBuffer& mapped_buffer_info = mapped_buffer_info_iter->second;
EXPECT_EQ(mapped_buffer_info.original_access, kAccess);
EXPECT_EQ(mapped_buffer_info.filtered_access, kMappedAccess);
}
// Update the client mem, including data within and outside the flush range.
const int8_t kValue0 = 21;
memset(client_data, kValue0, kTotalSize);
{ // FlushMappedBufferRange succeeds
cmds::FlushMappedBufferRange cmd;
cmd.Init(kTarget, kFlushRangeOffset, kFlushRangeSize);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
{ // UnmapBuffer succeeds
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
// Reset the client data before mapping again
const int8_t kValue1 = 0;
memset(client_data, kValue1, kTotalSize);
{ // Re-map the buffer to verify the data
const GLbitfield kReadAccess = GL_MAP_READ_BIT;
cmds::MapBufferRange cmd;
cmd.Init(kTarget, 0, kTotalSize, kReadAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
*result = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(1u, *result);
// Verify the GPU memory is updated is but only within the flushed range.
for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
if (ii >= kMappedOffset + kFlushRangeOffset &&
ii < kMappedOffset + kFlushRangeOffset + kFlushRangeSize) {
EXPECT_EQ(kValue0, client_data[ii]);
} else {
EXPECT_EQ(static_cast<int8_t>(ii % 128), client_data[ii]);
}
}
}
{ // UnmapBuffer succeeds
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, MapBufferRangeNotInitFails) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_READ_BIT;
std::vector<int8_t> data(kSize);
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
*result = 1; // Any value other than 0.
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest,
MapBufferRangeWriteInvalidateRangeSucceeds) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
// With MAP_INVALIDATE_RANGE_BIT, no need to append MAP_READ_BIT.
const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kSize + kOffset, nullptr, GL_STREAM_DRAW);
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
*result = 0;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
memset(mem, 72, kSize); // Init to a random value other than 0.
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest,
MapBufferRangeWriteInvalidateBufferSucceeds) {
// Test INVALIDATE_BUFFER_BIT is mapped to INVALIDATE_RANGE_BIT.
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
const GLbitfield kFilteredAccess =
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kSize + kOffset, nullptr, GL_STREAM_DRAW);
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
*result = 0;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
memset(mem, 72, kSize); // Init to a random value other than 0.
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
PassthroughResources* passthrough_resources = GetPassthroughResources();
auto mapped_buffer_info_iter =
passthrough_resources->mapped_buffer_map.find(kClientBufferId);
EXPECT_NE(mapped_buffer_info_iter,
passthrough_resources->mapped_buffer_map.end());
EXPECT_EQ(mapped_buffer_info_iter->second.original_access, kAccess);
EXPECT_EQ(mapped_buffer_info_iter->second.filtered_access, kFilteredAccess);
}
TEST_F(GLES3DecoderPassthroughTest, MapBufferRangeWriteUnsynchronizedBit) {
// Test UNSYNCHRONIZED_BIT is filtered out.
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kSize + kOffset, nullptr, GL_STREAM_DRAW);
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
*result = 0;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
memset(mem, 72, kSize); // Init to a random value other than 0.
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
PassthroughResources* passthrough_resources = GetPassthroughResources();
auto mapped_buffer_info_iter =
passthrough_resources->mapped_buffer_map.find(kClientBufferId);
EXPECT_NE(mapped_buffer_info_iter,
passthrough_resources->mapped_buffer_map.end());
EXPECT_EQ(mapped_buffer_info_iter->second.original_access, kAccess);
EXPECT_EQ(mapped_buffer_info_iter->second.filtered_access, kFilteredAccess);
}
TEST_F(GLES3DecoderPassthroughTest, MapBufferRangeWithError) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_READ_BIT;
std::vector<int8_t> data(kSize);
for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
data[ii] = static_cast<int8_t>(ii % 255);
}
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
*result = 0;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
memset(mem, 72, kSize); // Init to a random value other than 0.
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
memset(&data[0], 72, kSize);
// Mem is untouched.
EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
EXPECT_EQ(0u, *result);
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
PassthroughResources* passthrough_resources = GetPassthroughResources();
auto mapped_buffer_info_iter =
passthrough_resources->mapped_buffer_map.find(kClientBufferId);
EXPECT_EQ(mapped_buffer_info_iter,
passthrough_resources->mapped_buffer_map.end());
}
TEST_F(GLES3DecoderPassthroughTest, MapBufferRangeBadSharedMemoryFails) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_READ_BIT;
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kOffset + kSize, nullptr, GL_STREAM_DRAW);
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
*result = 0;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, kInvalidSharedMemoryId,
data_shm_offset, result_shm_id, result_shm_offset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
kInvalidSharedMemoryId, result_shm_offset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id,
kInvalidSharedMemoryOffset, result_shm_id, result_shm_offset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, kInvalidSharedMemoryOffset);
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
TEST_F(GLES3DecoderPassthroughTest, UnmapBufferWriteNotMappedFails) {
const GLenum kTarget = GL_ARRAY_BUFFER;
DoBindBuffer(kTarget, kClientBufferId);
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, UnmapBufferWriteNoBoundBufferFails) {
const GLenum kTarget = GL_ARRAY_BUFFER;
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
TEST_F(GLES3DecoderPassthroughTest, BufferDataDestroysDataStore) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_WRITE_BIT;
const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
// uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kSize + kOffset, nullptr, GL_STREAM_DRAW);
{ // MapBufferRange succeeds
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
*result = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(1u, *result);
}
{ // Buffer is tracked as mapped
PassthroughResources* passthrough_resources = GetPassthroughResources();
auto mapped_buffer_info_iter =
passthrough_resources->mapped_buffer_map.find(kClientBufferId);
EXPECT_NE(mapped_buffer_info_iter,
passthrough_resources->mapped_buffer_map.end());
EXPECT_EQ(mapped_buffer_info_iter->second.original_access, kAccess);
EXPECT_EQ(mapped_buffer_info_iter->second.filtered_access, kFilteredAccess);
}
{ // BufferData unmaps the data store.
DoBufferData(kTarget, kSize * 2, nullptr, GL_STREAM_DRAW);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
{ // Buffer is no longer tracked as mapped
PassthroughResources* passthrough_resources = GetPassthroughResources();
EXPECT_EQ(passthrough_resources->mapped_buffer_map.find(kClientBufferId),
passthrough_resources->mapped_buffer_map.end());
}
{ // UnmapBuffer fails.
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
}
TEST_F(GLES3DecoderPassthroughTest, DeleteBuffersDestroysDataStore) {
const GLenum kTarget = GL_ARRAY_BUFFER;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_WRITE_BIT;
const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
// uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kSize + kOffset, nullptr, GL_STREAM_DRAW);
{ // MapBufferRange succeeds
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
*result = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(1u, *result);
}
{ // Buffer is tracked as mapped
PassthroughResources* passthrough_resources = GetPassthroughResources();
auto mapped_buffer_info_iter =
passthrough_resources->mapped_buffer_map.find(kClientBufferId);
EXPECT_NE(mapped_buffer_info_iter,
passthrough_resources->mapped_buffer_map.end());
EXPECT_EQ(mapped_buffer_info_iter->second.original_access, kAccess);
EXPECT_EQ(mapped_buffer_info_iter->second.filtered_access, kFilteredAccess);
}
{ // DeleteBuffers unmaps the data store.
DoDeleteBuffer(kClientBufferId);
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
{ // Buffer is no longer tracked as mapped
PassthroughResources* passthrough_resources = GetPassthroughResources();
EXPECT_EQ(passthrough_resources->mapped_buffer_map.find(kClientBufferId),
passthrough_resources->mapped_buffer_map.end());
}
{ // UnmapBuffer fails.
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
}
}
TEST_F(GLES3DecoderPassthroughTest, MapUnmapBufferInvalidTarget) {
const GLenum kTarget = GL_TEXTURE_2D;
const GLintptr kOffset = 10;
const GLsizeiptr kSize = 64;
const GLbitfield kAccess = GL_MAP_WRITE_BIT;
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t data_shm_id = shared_memory_id_;
// uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
{
cmds::MapBufferRange cmd;
cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
result_shm_id, result_shm_offset);
*result = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(0u, *result);
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
}
{
cmds::UnmapBuffer cmd;
cmd.Init(kTarget);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
}
}
TEST_F(GLES3DecoderPassthroughTest, CopyBufferSubDataValidArgs) {
const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
const GLsizeiptr kSize = 64;
const GLsizeiptr kHalfSize = kSize / 2;
const GLintptr kReadOffset = 0;
const GLintptr kWriteOffset = kHalfSize;
const GLsizeiptr kCopySize = 5;
const char kValue0 = 3;
const char kValue1 = 21;
// Set up the buffer so first half is kValue0 and second half is kValue1.
DoBindBuffer(kTarget, kClientBufferId);
DoBufferData(kTarget, kSize, nullptr, GL_STREAM_DRAW);
std::unique_ptr<char[]> data(new char[kHalfSize]);
memset(data.get(), kValue0, kHalfSize);
DoBufferSubData(kTarget, 0, kHalfSize, data.get());
memset(data.get(), kValue1, kHalfSize);
DoBufferSubData(kTarget, kHalfSize, kHalfSize, data.get());
EXPECT_EQ(GL_NO_ERROR, GetGLError());
cmds::CopyBufferSubData cmd;
cmd.Init(kTarget, kTarget, kReadOffset, kWriteOffset, kCopySize);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
} // namespace gles2
} // namespace gpu