| Index: gpu/command_buffer/client/gles2_implementation.cc
|
| diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
|
| index 241056cefd013454dd6b64f840c6bdcea1eff4a2..9e7ff75559a6493bd18f64aab386a76bba80c9bd 100644
|
| --- a/gpu/command_buffer/client/gles2_implementation.cc
|
| +++ b/gpu/command_buffer/client/gles2_implementation.cc
|
| @@ -1323,8 +1323,12 @@ void GLES2Implementation::BufferDataHelper(
|
| if (buffer)
|
| RemoveTransferBuffer(buffer);
|
|
|
| - // Create new buffer.
|
| - buffer = buffer_tracker_->CreateBuffer(buffer_id, size);
|
| + // Create new buffer. For the async readback use case, allocate a few
|
| + // extra bytes to contain any service-side glMapBuffer errors.
|
| + const GLsizeiptr metadata_size =
|
| + target == GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM ?
|
| + sizeof(cmds::ReadPixels::Result) : 0;
|
| + buffer = buffer_tracker_->CreateBuffer(buffer_id, size, metadata_size);
|
| DCHECK(buffer);
|
| if (buffer->address() && data)
|
| memcpy(buffer->address(), data, size);
|
| @@ -2249,17 +2253,23 @@ void GLES2Implementation::ReadPixels(
|
| return;
|
| }
|
|
|
| - if (bound_pixel_pack_transfer_buffer_id_) {
|
| + if (bound_pixel_pack_transfer_buffer_id_) { // Asynchronous readback path.
|
| GLuint offset = ToGLuint(pixels);
|
| BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
|
| bound_pixel_pack_transfer_buffer_id_,
|
| "glReadPixels", offset, padded_row_size * height);
|
| - if (buffer && buffer->shm_id() != -1) {
|
| - helper_->ReadPixels(xoffset, yoffset, width, height, format, type,
|
| - buffer->shm_id(), buffer->shm_offset(),
|
| - 0, 0, true);
|
| - CheckGLError();
|
| + if (!buffer || buffer->shm_id() == -1) {
|
| + SetGLError(GL_INVALID_OPERATION, "glReadPixels", "invalid buffer.");
|
| + return;
|
| }
|
| +
|
| + DCHECK_EQ(buffer->metadata_size(), sizeof(Result));
|
| + helper_->ReadPixels(
|
| + xoffset, yoffset, width, height, format, type,
|
| + buffer->shm_id(), buffer->shm_offset(),
|
| + buffer->metadata_shm_id(), buffer->metadata_shm_offset(),
|
| + true);
|
| + CheckGLError();
|
| return;
|
| }
|
|
|
| @@ -2285,38 +2295,37 @@ void GLES2Implementation::ReadPixels(
|
| if (!result) {
|
| return;
|
| }
|
| - *result = 0; // mark as failed.
|
| helper_->ReadPixels(
|
| xoffset, yoffset, width, num_rows, format, type,
|
| buffer.shm_id(), buffer.offset(),
|
| GetResultShmId(), GetResultShmOffset(),
|
| false);
|
| WaitForCmd();
|
| - if (*result != 0) {
|
| - // when doing a y-flip we have to iterate through top-to-bottom chunks
|
| - // of the dst. The service side handles reversing the rows within a
|
| - // chunk.
|
| - int8* rows_dst;
|
| - if (pack_reverse_row_order_) {
|
| - rows_dst = dest + (height - num_rows) * padded_row_size;
|
| - } else {
|
| - rows_dst = dest;
|
| - }
|
| - // We have to copy 1 row at a time to avoid writing pad bytes.
|
| - const int8* src = static_cast<const int8*>(buffer.address());
|
| - for (GLint yy = 0; yy < num_rows; ++yy) {
|
| - memcpy(rows_dst, src, unpadded_row_size);
|
| - rows_dst += padded_row_size;
|
| - src += padded_row_size;
|
| - }
|
| - if (!pack_reverse_row_order_) {
|
| - dest = rows_dst;
|
| - }
|
| - }
|
| - // If it was not marked as successful exit.
|
| - if (*result == 0) {
|
| + if (*result != GL_NO_ERROR) {
|
| + SetGLError(*result, "glReadPixels", "Service-side error.");
|
| return;
|
| }
|
| +
|
| + // when doing a y-flip we have to iterate through top-to-bottom chunks
|
| + // of the dst. The service side handles reversing the rows within a
|
| + // chunk.
|
| + int8* rows_dst;
|
| + if (pack_reverse_row_order_) {
|
| + rows_dst = dest + (height - num_rows) * padded_row_size;
|
| + } else {
|
| + rows_dst = dest;
|
| + }
|
| + // We have to copy 1 row at a time to avoid writing pad bytes.
|
| + const int8* src = static_cast<const int8*>(buffer.address());
|
| + for (GLint yy = 0; yy < num_rows; ++yy) {
|
| + memcpy(rows_dst, src, unpadded_row_size);
|
| + rows_dst += padded_row_size;
|
| + src += padded_row_size;
|
| + }
|
| + if (!pack_reverse_row_order_) {
|
| + dest = rows_dst;
|
| + }
|
| +
|
| yoffset += num_rows;
|
| height -= num_rows;
|
| }
|
| @@ -3676,6 +3685,7 @@ void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) {
|
| GLuint buffer_id;
|
| GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id);
|
| if (!buffer_id) {
|
| + SetGLError(GL_INVALID_VALUE, "glMapBufferCHROMIUM", "invalid buffer");
|
| return NULL;
|
| }
|
| BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
|
| @@ -3683,6 +3693,17 @@ void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) {
|
| SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer");
|
| return NULL;
|
| }
|
| +
|
| + if (target == GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM) {
|
| + DCHECK_EQ(buffer->metadata_size(), sizeof(cmds::ReadPixels::Result));
|
| + const GLenum error =
|
| + *(static_cast<cmds::ReadPixels::Result*>(buffer->metadata_address()));
|
| + if (error != GL_NO_ERROR) {
|
| + SetGLError(error, "glMapBufferCHROMIUM", "service map buffer error");
|
| + return NULL;
|
| + }
|
| + }
|
| +
|
| if (buffer->mapped()) {
|
| SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped");
|
| return NULL;
|
|
|