summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py29
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h6
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc26
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h25
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc14
6 files changed, 86 insertions, 20 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 0b19010..a1010ec 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -820,6 +820,7 @@ _ENUM_LISTS = {
# This table specifies types and other special data for the commands that
# will be generated.
#
+# cmd_comment: A comment added to the cmd format.
# type: defines which handler will be used to generate code.
# DecoderFunc: defines which function to call in the decoder to execute the
# corresponding GL command. If not specified the GL command will
@@ -832,6 +833,8 @@ _ENUM_LISTS = {
# immediate: Whether or not to generate an immediate command for the GL
# function. The default is if there is exactly 1 pointer argument
# in the GL function an immediate command is generated.
+# impl_func: Whether or not to generate the GLES2Implementation part of this
+# command.
# needs_size: If true a data_size field is added to the command.
# data_type: The type of data the command uses. For PUTn or PUT types.
# count: The number of units per element. For PUTn or PUT types.
@@ -872,8 +875,8 @@ _FUNCTION_INFO = {
'cmd_args': 'GLenum mode, GLsizei count, GLenum type, GLuint index_offset',
},
'EnableVertexAttribArray': {'DecoderFunc': 'DoEnableVertexAttribArray'},
- 'Finish': {'ImplFunc': False},
- 'Flush': {'ImplFunc': False},
+ 'Finish': {'impl_func': False},
+ 'Flush': {'impl_func': False},
'FramebufferRenderbuffer': {'DecoderFunc': 'glFramebufferRenderbufferEXT'},
'FramebufferTexture2D': {'DecoderFunc': 'glFramebufferTexture2DEXT'},
'GenerateMipmap': {
@@ -988,7 +991,20 @@ _FUNCTION_INFO = {
'LinkProgram': {'DecoderFunc': 'DoLinkProgram'},
'PixelStorei': {'type': 'Manual'},
'RenderbufferStorage': {'DecoderFunc': 'glRenderbufferStorageEXT'},
- 'ReadPixels': {'type': 'Custom', 'immediate': False},
+ 'ReadPixels': {
+ 'cmd_comment':
+ '// ReadPixels has the result separated from the pixel buffer so that\n'
+ '// it is easier to specify the result going to some specific place\n'
+ '// that exactly fits the rectangle of pixels.\n',
+ 'type': 'Custom',
+ 'immediate': False,
+ 'impl_func': False,
+ 'cmd_args':
+ 'GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, '
+ 'GLenum type, uint32 pixels_shm_id, uint32 pixels_shm_offset, '
+ 'uint32 result_shm_id, uint32 result_shm_offset',
+ 'result': ['uint32'],
+ },
'ReleaseShaderCompiler': {'type': 'Noop'},
'ShaderBinary': {'type': 'Noop'},
'ShaderSource': {
@@ -1024,7 +1040,7 @@ _FUNCTION_INFO = {
'GLsizei stride, GLuint offset',
},
'SwapBuffers': {
- 'ImplFunc': False,
+ 'impl_func': False,
'DecoderFunc': 'DoSwapBuffers',
'unit_test': False,
},
@@ -1149,6 +1165,9 @@ class TypeHandler(object):
def WriteStruct(self, func, file):
"""Writes a structure that matches the arguments to a function."""
+ comment = func.GetInfo('cmd_comment')
+ if not comment == None:
+ file.Write(comment)
file.Write("struct %s {\n" % func.name)
file.Write(" typedef %s ValueType;\n" % func.name)
file.Write(" static const CommandId kCmdId = k%s;\n" % func.name)
@@ -1413,7 +1432,7 @@ TEST_F(GLES2DecoderTest, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
def WriteGLES2ImplementationHeader(self, func, file):
"""Writes the GLES2 Implemention declaration."""
- impl_func = func.GetInfo('ImplFunc')
+ impl_func = func.GetInfo('impl_func')
if func.can_auto_generate and (impl_func == None or impl_func == True):
file.Write("%s %s(%s) {\n" %
(func.return_type, func.original_name,
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index 2b6185a..df3ed0e 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -667,10 +667,12 @@
void ReadPixels(
GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
- GLenum type, uint32 pixels_shm_id, uint32 pixels_shm_offset) {
+ GLenum type, uint32 pixels_shm_id, uint32 pixels_shm_offset,
+ uint32 result_shm_id, uint32 result_shm_offset) {
gles2::ReadPixels& c = GetCmdSpace<gles2::ReadPixels>();
c.Init(
- x, y, width, height, format, type, pixels_shm_id, pixels_shm_offset);
+ x, y, width, height, format, type, pixels_shm_id, pixels_shm_offset,
+ result_shm_id, result_shm_offset);
}
void RenderbufferStorage(
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index cc895fe..450e48d 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -495,6 +495,8 @@ void GLES2Implementation::ReadPixels(
if (width == 0 || height == 0) {
return;
}
+ typedef gles2::ReadPixels::Result Result;
+ Result* result = static_cast<Result*>(result_buffer_);
int8* dest = reinterpret_cast<int8*>(pixels);
GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize();
GLsizeiptr unpadded_row_size = GLES2Util::ComputeImageDataSize(
@@ -508,12 +510,18 @@ void GLES2Implementation::ReadPixels(
GLint num_rows = std::min(height, max_rows);
GLsizeiptr part_size = num_rows * padded_row_size;
void* buffer = transfer_buffer_.Alloc(part_size);
- // TODO(gman): handle errors.
+ *result = 0; // mark as failed.
helper_->ReadPixels(
xoffset, yoffset, width, num_rows, format, type,
- transfer_buffer_id_, transfer_buffer_.GetOffset(buffer));
+ transfer_buffer_id_, transfer_buffer_.GetOffset(buffer),
+ result_shm_id(), result_shm_offset());
+ WaitForCmd();
+ // If it was not marked as successful exit.
+ if (*result == 0) {
+ return;
+ }
memcpy(dest, buffer, part_size);
- transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken());
+ transfer_buffer_.Free(buffer);
yoffset += num_rows;
dest += part_size;
height -= num_rows;
@@ -532,12 +540,18 @@ void GLES2Implementation::ReadPixels(
GLint num_pixels = std::min(width, max_sub_row_pixels);
GLsizeiptr part_size = num_pixels * element_size;
void* buffer = transfer_buffer_.Alloc(part_size);
- // TODO(gman): handle errors.
+ *result = 0; // mark as failed.
helper_->ReadPixels(
temp_xoffset, yoffset, temp_width, 1, format, type,
- transfer_buffer_id_, transfer_buffer_.GetOffset(buffer));
+ transfer_buffer_id_, transfer_buffer_.GetOffset(buffer),
+ result_shm_id(), result_shm_offset());
+ WaitForCmd();
+ // If it was not marked as successful exit.
+ if (*result == 0) {
+ return;
+ }
memcpy(row_dest, buffer, part_size);
- transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken());
+ transfer_buffer_.Free(buffer);
row_dest += part_size;
temp_xoffset += num_pixels;
temp_width -= num_pixels;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 57a8a4e..19824a4 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -4705,11 +4705,16 @@ COMPILE_ASSERT(offsetof(PolygonOffset, factor) == 4,
COMPILE_ASSERT(offsetof(PolygonOffset, units) == 8,
OffsetOf_PolygonOffset_units_not_8);
+// ReadPixels has the result separated from the pixel buffer so that
+// it is easier to specify the result going to some specific place
+// that exactly fits the rectangle of pixels.
struct ReadPixels {
typedef ReadPixels ValueType;
static const CommandId kCmdId = kReadPixels;
static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ typedef uint32 Result;
+
static uint32 ComputeSize() {
return static_cast<uint32>(sizeof(ValueType)); // NOLINT
}
@@ -4720,7 +4725,8 @@ struct ReadPixels {
void Init(
GLint _x, GLint _y, GLsizei _width, GLsizei _height, GLenum _format,
- GLenum _type, uint32 _pixels_shm_id, uint32 _pixels_shm_offset) {
+ GLenum _type, uint32 _pixels_shm_id, uint32 _pixels_shm_offset,
+ uint32 _result_shm_id, uint32 _result_shm_offset) {
SetHeader();
x = _x;
y = _y;
@@ -4730,16 +4736,19 @@ struct ReadPixels {
type = _type;
pixels_shm_id = _pixels_shm_id;
pixels_shm_offset = _pixels_shm_offset;
+ result_shm_id = _result_shm_id;
+ result_shm_offset = _result_shm_offset;
}
void* Set(
void* cmd, GLint _x, GLint _y, GLsizei _width, GLsizei _height,
GLenum _format, GLenum _type, uint32 _pixels_shm_id,
- uint32 _pixels_shm_offset) {
+ uint32 _pixels_shm_offset, uint32 _result_shm_id,
+ uint32 _result_shm_offset) {
static_cast<ValueType*>(
cmd)->Init(
_x, _y, _width, _height, _format, _type, _pixels_shm_id,
- _pixels_shm_offset);
+ _pixels_shm_offset, _result_shm_id, _result_shm_offset);
return NextCmdAddress<ValueType>(cmd);
}
@@ -4752,10 +4761,12 @@ struct ReadPixels {
uint32 type;
uint32 pixels_shm_id;
uint32 pixels_shm_offset;
+ uint32 result_shm_id;
+ uint32 result_shm_offset;
};
-COMPILE_ASSERT(sizeof(ReadPixels) == 36,
- Sizeof_ReadPixels_is_not_36);
+COMPILE_ASSERT(sizeof(ReadPixels) == 44,
+ Sizeof_ReadPixels_is_not_44);
COMPILE_ASSERT(offsetof(ReadPixels, header) == 0,
OffsetOf_ReadPixels_header_not_0);
COMPILE_ASSERT(offsetof(ReadPixels, x) == 4,
@@ -4774,6 +4785,10 @@ COMPILE_ASSERT(offsetof(ReadPixels, pixels_shm_id) == 28,
OffsetOf_ReadPixels_pixels_shm_id_not_28);
COMPILE_ASSERT(offsetof(ReadPixels, pixels_shm_offset) == 32,
OffsetOf_ReadPixels_pixels_shm_offset_not_32);
+COMPILE_ASSERT(offsetof(ReadPixels, result_shm_id) == 36,
+ OffsetOf_ReadPixels_result_shm_id_not_36);
+COMPILE_ASSERT(offsetof(ReadPixels, result_shm_offset) == 40,
+ OffsetOf_ReadPixels_result_shm_offset_not_40);
struct RenderbufferStorage {
typedef RenderbufferStorage ValueType;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 949cb77..381fea1 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -1754,7 +1754,9 @@ TEST(GLES2FormatTest, ReadPixels) {
static_cast<GLenum>(15),
static_cast<GLenum>(16),
static_cast<uint32>(17),
- static_cast<uint32>(18));
+ static_cast<uint32>(18),
+ static_cast<uint32>(19),
+ static_cast<uint32>(20));
EXPECT_EQ(static_cast<uint32>(ReadPixels::kCmdId),
cmd.header.command);
EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
@@ -1768,6 +1770,8 @@ TEST(GLES2FormatTest, ReadPixels) {
EXPECT_EQ(static_cast<GLenum>(16), cmd.type);
EXPECT_EQ(static_cast<uint32>(17), cmd.pixels_shm_id);
EXPECT_EQ(static_cast<uint32>(18), cmd.pixels_shm_offset);
+ EXPECT_EQ(static_cast<uint32>(19), cmd.result_shm_id);
+ EXPECT_EQ(static_cast<uint32>(20), cmd.result_shm_offset);
}
TEST(GLES2FormatTest, RenderbufferStorage) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index df18f39..c018356 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1942,19 +1942,31 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
GLsizei height = c.height;
GLenum format = c.format;
GLenum type = c.type;
+ // TODO(gman): Handle out of range rectangles.
+ typedef gles2::ReadPixels::Result Result;
uint32 pixels_size = GLES2Util::ComputeImageDataSize(
width, height, format, type, pack_alignment_);
void* pixels = GetSharedMemoryAs<void*>(
c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
- if (!pixels) {
+ Result* result = GetSharedMemoryAs<Result*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result));
+ if (!pixels || !result) {
return error::kOutOfBounds;
}
+
if (!ValidateGLenumReadPixelFormat(format) ||
!ValidateGLenumPixelType(type)) {
SetGLError(GL_INVALID_VALUE);
return error::kNoError;
}
+ CopyRealGLErrorsToWrapper();
glReadPixels(x, y, width, height, format, type, pixels);
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
+ *result = true;
+ } else {
+ SetGLError(error);
+ }
return error::kNoError;
}