Skip to content

Commit

Permalink
Run relevant framebuffer cmd decoder unittests on passthrough
Browse files Browse the repository at this point in the history
Also make the passthrough command decoder better replicate the behavior
of HandleReadPixels with / without pack buffers.

BUG=602737

Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I165919177ba94d5cb182148c8f8b2e4d36108671
Reviewed-on: https://chromium-review.googlesource.com/644212
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Antoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#505747}
  • Loading branch information
Kangz authored and Commit Bot committed Oct 2, 2017
1 parent 3169549 commit 9527cb2
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 9 deletions.
5 changes: 4 additions & 1 deletion gpu/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,10 @@ test("gpu_unittests") {
# TODO(geofflang): Run passthrough command decoder unittests on more platforms
# once initialization of ANGLE's NULL context is supported
if ((is_win || (is_linux && !use_ozone)) && !is_asan) {
sources += [ "command_buffer/service/gles2_cmd_decoder_passthrough_unittest_buffers.cc" ]
sources += [
"command_buffer/service/gles2_cmd_decoder_passthrough_unittest_buffers.cc",
"command_buffer/service/gles2_cmd_decoder_passthrough_unittest_framebuffers.cc",
]
}

configs += [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -848,16 +848,26 @@ error::Error GLES2DecoderPassthroughImpl::HandleReadPixels(
GLenum type = static_cast<GLenum>(c.type);
uint32_t pixels_shm_id = c.pixels_shm_id;
uint32_t pixels_shm_offset = c.pixels_shm_offset;
uint32_t result_shm_id = c.result_shm_id;
uint32_t result_shm_offset = c.result_shm_offset;

bool packBufferBound = bound_buffers_[GL_PIXEL_PACK_BUFFER] != 0;

uint8_t* pixels = nullptr;
unsigned int buffer_size = 0;
if (c.pixels_shm_id != 0) {
if (pixels_shm_id != 0) {
if (packBufferBound) {
return error::kInvalidArguments;
}
pixels = GetSharedMemoryAndSizeAs<uint8_t*>(
pixels_shm_id, pixels_shm_offset, 0, &buffer_size);
if (!pixels) {
return error::kOutOfBounds;
}
} else {
if (!packBufferBound) {
return error::kInvalidArguments;
}
pixels =
reinterpret_cast<uint8_t*>(static_cast<intptr_t>(pixels_shm_offset));
}
Expand All @@ -876,20 +886,17 @@ error::Error GLES2DecoderPassthroughImpl::HandleReadPixels(
return error::kOutOfBounds;
}

typedef cmds::ReadPixels::Result Result;
Result* result = nullptr;
if (c.result_shm_id != 0) {
result = GetSharedMemoryAs<Result*>(c.result_shm_id, c.result_shm_offset,
sizeof(*result));
if (result_shm_id != 0) {
typedef cmds::ReadPixels::Result Result;
Result* result = GetSharedMemoryAs<Result*>(
result_shm_id, result_shm_offset, sizeof(*result));
if (!result) {
return error::kOutOfBounds;
}
if (result->success != 0) {
return error::kInvalidArguments;
}
}

if (result) {
result->success = success;
result->row_length = static_cast<uint32_t>(columns);
result->num_rows = static_cast<uint32_t>(rows);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright 2017 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 {

using namespace cmds;

TEST_F(GLES3DecoderPassthroughTest, ReadPixelsBufferBound) {
const GLsizei kWidth = 5;
const GLsizei kHeight = 3;
const GLint kBytesPerPixel = 4;
GLint size = kWidth * kHeight * kBytesPerPixel;
typedef ReadPixels::Result Result;
Result* result = GetSharedMemoryAs<Result*>();
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t pixels_shm_id = shared_memory_id_;
uint32_t pixels_shm_offset = kSharedMemoryOffset + sizeof(Result);

DoBindBuffer(GL_PIXEL_PACK_BUFFER, kClientBufferId);
DoBufferData(GL_PIXEL_PACK_BUFFER, size, nullptr, GL_STATIC_DRAW);

ReadPixels cmd;
cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels_shm_id,
pixels_shm_offset, result_shm_id, result_shm_offset, false);
result->success = 0;
EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}

TEST_F(GLES3DecoderPassthroughTest, ReadPixels2PixelPackBufferNoBufferBound) {
const GLsizei kWidth = 5;
const GLsizei kHeight = 3;

ReadPixels cmd;
cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 0, 0, false);
EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}

TEST_F(GLES3DecoderPassthroughTest, ReadPixels2PixelPackBuffer) {
const GLsizei kWidth = 5;
const GLsizei kHeight = 3;
const GLint kBytesPerPixel = 4;
GLint size = kWidth * kHeight * kBytesPerPixel;

DoBindBuffer(GL_PIXEL_PACK_BUFFER, kClientBufferId);
DoBufferData(GL_PIXEL_PACK_BUFFER, size, nullptr, GL_STATIC_DRAW);

ReadPixels cmd;
cmd.Init(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 0, 0, false);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}

TEST_F(GLES2DecoderPassthroughTest, DiscardFramebufferEXTUnsupported) {
const GLenum target = GL_FRAMEBUFFER;
const GLsizei count = 1;
const GLenum attachments[] = {GL_COLOR_EXT};
DiscardFramebufferEXTImmediate& cmd =
*GetImmediateAs<DiscardFramebufferEXTImmediate>();
cmd.Init(target, count, attachments);
EXPECT_EQ(error::kUnknownCommand,
ExecuteImmediateCmd(cmd, sizeof(attachments)));
}

TEST_F(GLES2DecoderPassthroughTest, ReadPixelsOutOfRange) {
const GLint kWidth = 5;
const GLint kHeight = 3;
const GLenum kFormat = GL_RGBA;

// Set up GL objects for the read pixels with a known framebuffer size
DoBindTexture(GL_TEXTURE_2D, kClientTextureId);
DoTexImage2D(GL_TEXTURE_2D, 0, kFormat, kWidth, kHeight, 0, kFormat,
GL_UNSIGNED_BYTE, 0, 0);
DoBindFramebuffer(GL_FRAMEBUFFER, kClientFramebufferId);
DoFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
kClientTextureId, 0);

// Put the resulting pixels and the result in shared memory
typedef ReadPixels::Result Result;
Result* result = GetSharedMemoryAs<Result*>();
uint32_t result_shm_id = shared_memory_id_;
uint32_t result_shm_offset = kSharedMemoryOffset;
uint32_t pixels_shm_id = shared_memory_id_;
uint32_t pixels_shm_offset = kSharedMemoryOffset + sizeof(*result);

uint8_t* dest = reinterpret_cast<uint8_t*>(&result[1]);

// The test cases
static struct {
GLint x, y, w, h;
} tests[] = {
{
-2, -1, 9, 5,
}, // out of range on all sides
{
2, 1, 9, 5,
}, // out of range on right, bottom
{
-7, -4, 9, 5,
}, // out of range on left, top
{
0, -5, 9, 5,
}, // completely off top
{
0, 3, 9, 5,
}, // completely off bottom
{
-9, 0, 9, 5,
}, // completely off left
{
5, 0, 9, 5,
}, // completely off right
};

for (auto test : tests) {
// Clear the readpixels buffer so that we can see which pixels have been
// written
memset(dest, 0, 4 * test.w * test.h);

ReadPixels cmd;
cmd.Init(test.x, test.y, test.w, test.h, kFormat, GL_UNSIGNED_BYTE,
pixels_shm_id, pixels_shm_offset, result_shm_id, result_shm_offset,
false);
result->success = 0;
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));

EXPECT_TRUE(result->success);

// Check the Result has the correct metadata for what was read.
GLint startx = std::max(test.x, 0);
GLint endx = std::min(test.x + test.w, kWidth);
EXPECT_EQ(result->row_length, endx - startx);

GLint starty = std::max(test.y, 0);
GLint endy = std::min(test.y + test.h, kHeight);
EXPECT_EQ(result->num_rows, endy - starty);

// Check each pixel and expect them to be non-zero if they were written. The
// non-zero values are written by ANGLE's NULL backend to simulate the
// memory that would be modified by the call.
for (GLint dx = 0; dx < test.w; ++dx) {
GLint x = test.x + dx;
for (GLint dy = 0; dy < test.h; ++dy) {
GLint y = test.y + dy;

bool expect_written = 0 <= x && x < kWidth && 0 <= y && y < kHeight;
for (GLint component = 0; component < 4; ++component) {
uint8_t value = dest[4 * (dy * test.w + dx) + component];
EXPECT_EQ(expect_written, value != 0)
<< x << " " << y << " " << value;
}
}
}
}
}

} // namespace gles2
} // namespace gpu
44 changes: 44 additions & 0 deletions gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2348,6 +2348,48 @@ void GLES2DecoderPassthroughTestBase::DoBufferSubData(GLenum target,
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}

void GLES2DecoderPassthroughTestBase::DoBindTexture(GLenum target,
GLuint client_id) {
cmds::BindTexture cmd;
cmd.Init(target, client_id);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}

void GLES2DecoderPassthroughTestBase::DoTexImage2D(
GLenum target,
GLint level,
GLenum internal_format,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
uint32_t shared_memory_id,
uint32_t shared_memory_offset) {
cmds::TexImage2D cmd;
cmd.Init(target, level, internal_format, width, height, format, type,
shared_memory_id, shared_memory_offset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}

void GLES2DecoderPassthroughTestBase::DoBindFramebuffer(GLenum target,
GLuint client_id) {
cmds::BindFramebuffer cmd;
cmd.Init(target, client_id);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}

void GLES2DecoderPassthroughTestBase::DoFramebufferTexture2D(
GLenum target,
GLenum attachment,
GLenum textarget,
GLuint texture_client_id,
GLint level) {
cmds::FramebufferTexture2D cmd;
cmd.Init(target, attachment, textarget, texture_client_id, level);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}

// GCC requires these declarations, but MSVC requires they not be present
#ifndef COMPILER_MSVC
const size_t GLES2DecoderPassthroughTestBase::kSharedBufferSize;
Expand All @@ -2357,6 +2399,8 @@ const int32_t GLES2DecoderPassthroughTestBase::kInvalidSharedMemoryId;

const uint32_t GLES2DecoderPassthroughTestBase::kNewClientId;
const GLuint GLES2DecoderPassthroughTestBase::kClientBufferId;
const GLuint GLES2DecoderPassthroughTestBase::kClientTextureId;
const GLuint GLES2DecoderPassthroughTestBase::kClientFramebufferId;
#endif

} // namespace gles2
Expand Down
28 changes: 28 additions & 0 deletions gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,11 @@ class GLES2DecoderPassthroughTestBase : public testing::Test,
return reinterpret_cast<T>(ptr);
}

template <typename T>
T* GetImmediateAs() {
return reinterpret_cast<T*>(immediate_buffer_);
}

PassthroughResources* GetPassthroughResources() const {
return group_->passthrough_resources();
}
Expand All @@ -890,6 +895,25 @@ class GLES2DecoderPassthroughTestBase : public testing::Test,
GLsizeiptr size,
const void* data);

void DoBindTexture(GLenum target, GLuint client_id);
void DoTexImage2D(GLenum target,
GLint level,
GLenum internal_format,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
uint32_t shared_memory_id,
uint32_t shared_memory_offset);

void DoBindFramebuffer(GLenum target, GLuint client_id);
void DoFramebufferTexture2D(GLenum target,
GLenum attachment,
GLenum textarget,
GLuint texture_client_id,
GLint level);

static const size_t kSharedBufferSize = 2048;
static const uint32_t kSharedMemoryOffset = 132;
static const uint32_t kInvalidSharedMemoryOffset = kSharedBufferSize + 1;
Expand All @@ -898,12 +922,16 @@ class GLES2DecoderPassthroughTestBase : public testing::Test,

static const uint32_t kNewClientId = 501;
static const GLuint kClientBufferId = 100;
static const GLuint kClientTextureId = 101;
static const GLuint kClientFramebufferId = 102;

int32_t shared_memory_id_;
uint32_t shared_memory_offset_;
void* shared_memory_address_;
void* shared_memory_base_;

uint32_t immediate_buffer_[64];

private:
ContextCreationAttribHelper context_creation_attribs_;
GpuPreferences gpu_preferences_;
Expand Down

0 comments on commit 9527cb2

Please sign in to comment.