Chromium Code Reviews| 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 b0efc3769da617acfcc5423f07951c6f8d1dc208..d137473f400fbf894962eab93e0bda8933adac94 100644 |
| --- a/gpu/command_buffer/client/gles2_implementation.cc |
| +++ b/gpu/command_buffer/client/gles2_implementation.cc |
| @@ -1379,16 +1379,19 @@ void GLES2Implementation::BufferDataHelper( |
| BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); |
| if (buffer) { |
| - // Free buffer memory, pending the passage of a token. |
| - buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); |
| - |
| - // Remove old buffer. |
| - buffer_tracker_->RemoveBuffer(buffer_id); |
| + if (buffer->used()) { |
| + buffer->set_used(false); |
| + buffer->set_unused_token(helper_->InsertToken()); |
| + } |
| + DisposeTransferBuffer(buffer); |
| } |
| + CheckBuffersPendingAsyncComplete(); |
| + |
| // Create new buffer. |
| buffer = buffer_tracker_->CreateBuffer(buffer_id, size); |
| DCHECK(buffer); |
| + buffer->set_used(true); |
| if (buffer->address() && data) |
| memcpy(buffer->address(), data, size); |
| return; |
| @@ -1512,6 +1515,49 @@ void GLES2Implementation::BufferSubData( |
| CheckGLError(); |
| } |
| +void GLES2Implementation::FreeTransferBuffer(BufferTracker::Buffer *buffer) { |
| + int32 token = buffer->unused_token(); |
| + // FIXME: This kind of checks exist elsewhere; is it correct? |
| + if (token) { |
| + if (helper_->HasTokenPassed(token)) |
|
piman
2014/01/08 05:08:04
Maybe this logic (if the token is passed, free imm
|
| + buffer_tracker_->Free(buffer); |
| + else |
| + buffer_tracker_->FreePendingToken(buffer, token); |
| + } |
| +} |
| + |
| +void GLES2Implementation::DisposeTransferBuffer(BufferTracker::Buffer* buffer) { |
| + if (buffer->async_query_id()) { |
| + QueryTracker::Query* query = |
| + query_tracker_->GetQuery(buffer->async_query_id()); |
| + if (!query->CheckResultsAvailable(helper_)) { |
| + // Async upload not completed, queue release. |
| + released_buffers_pending_async_complete_.push_back(buffer); |
| + buffer_tracker_->UnmanageBuffer(buffer->id()); |
| + return; |
| + } |
| + } |
| + |
| + FreeTransferBuffer(buffer); |
| + buffer_tracker_->RemoveBuffer(buffer->id()); |
| +} |
| + |
| +void GLES2Implementation::CheckBuffersPendingAsyncComplete() { |
|
epennerAtGoogle
2014/01/07 00:47:59
Hmm, it's unfortunate that we have to check all of
reveman
2014/01/07 06:32:06
you could just keep the list sorted based on query
jadahl
2014/01/07 10:52:03
The enumeration will improve this situation indeed
|
| + BufferList::iterator it = released_buffers_pending_async_complete_.begin(); |
| + while (it != released_buffers_pending_async_complete_.end()) { |
| + BufferTracker::Buffer* buffer = *it; |
| + QueryTracker::Query* query = |
| + query_tracker_->GetQuery(buffer->async_query_id()); |
| + if (query->CheckResultsAvailable(helper_)) { |
| + it = released_buffers_pending_async_complete_.erase(it); |
| + FreeTransferBuffer(buffer); |
| + delete buffer; |
| + } else { |
| + ++it; |
| + } |
| + } |
| +} |
| + |
| bool GLES2Implementation::GetBoundPixelTransferBuffer( |
| GLenum target, |
| const char* function_name, |
| @@ -2404,24 +2450,42 @@ void GLES2Implementation::GenQueriesEXTHelper( |
| // deleted the resource. |
| bool GLES2Implementation::BindBufferHelper( |
| - GLenum target, GLuint buffer) { |
| + GLenum target, GLuint buffer_id) { |
| + BufferTracker::Buffer* buffer; |
| + |
| // TODO(gman): See note #1 above. |
| bool changed = false; |
| switch (target) { |
| case GL_ARRAY_BUFFER: |
| - if (bound_array_buffer_id_ != buffer) { |
| - bound_array_buffer_id_ = buffer; |
| + if (bound_array_buffer_id_ != buffer_id) { |
| + bound_array_buffer_id_ = buffer_id; |
| changed = true; |
| } |
| break; |
| case GL_ELEMENT_ARRAY_BUFFER: |
| - changed = vertex_array_object_manager_->BindElementArray(buffer); |
| + changed = vertex_array_object_manager_->BindElementArray(buffer_id); |
| break; |
| case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: |
| - bound_pixel_pack_transfer_buffer_id_ = buffer; |
| + bound_pixel_pack_transfer_buffer_id_ = buffer_id; |
| break; |
| case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: |
| - bound_pixel_unpack_transfer_buffer_id_ = buffer; |
| + // Mark any previously bound buffer as unused. |
| + if (bound_pixel_unpack_transfer_buffer_id_ != buffer_id && |
| + bound_pixel_unpack_transfer_buffer_id_ != 0) { |
| + buffer = |
| + buffer_tracker_->GetBuffer(bound_pixel_unpack_transfer_buffer_id_); |
| + if (buffer) { |
| + buffer->set_unused_token(helper_->InsertToken()); |
| + } |
| + } |
| + |
| + bound_pixel_unpack_transfer_buffer_id_ = buffer_id; |
| + buffer = buffer_tracker_->GetBuffer(buffer_id); |
| + if (buffer) { |
| + buffer->set_used(true); |
| + buffer->set_unused_token(0); |
| + } |
| + |
| break; |
| default: |
| changed = true; |
| @@ -2429,7 +2493,7 @@ bool GLES2Implementation::BindBufferHelper( |
| } |
| // TODO(gman): There's a bug here. If the target is invalid the ID will not be |
| // used even though it's marked it as used here. |
| - GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer); |
| + GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer_id); |
| return changed; |
| } |
| @@ -2563,13 +2627,14 @@ void GLES2Implementation::DeleteBuffersHelper( |
| bound_array_buffer_id_ = 0; |
| } |
| vertex_array_object_manager_->UnbindBuffer(buffers[ii]); |
| + |
| BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]); |
| if (buffer) { |
| - // Free buffer memory, pending the passage of a token. |
| - buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); |
| - // Remove buffer. |
| - buffer_tracker_->RemoveBuffer(buffers[ii]); |
| + buffer->set_used(false); |
| + buffer->set_unused_token(helper_->InsertToken()); |
| + DisposeTransferBuffer(buffer); |
| } |
| + |
| if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) { |
| bound_pixel_unpack_transfer_buffer_id_ = 0; |
| } |
| @@ -3645,6 +3710,35 @@ GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) { |
| return true; |
| } |
| +void GLES2Implementation::BeginQueryAsyncPixelUnpackCompleted( |
| + BufferTracker::Buffer *buffer) { |
| + DCHECK(!current_private_unpack_query_); |
| + |
| + GLuint id; |
| + GetIdHandler(id_namespaces::kQueries)->MakeIds(this, 0, 1, &id); |
| + QueryTracker::Query* query = |
| + query_tracker_->CreateQuery( |
| + id, GL_ASYNC_PIXEL_UNPACK_COMPLETED_PRIVATE_CHROMIUM); |
| + if (!query) { |
| + MustBeContextLost(); |
| + return; |
| + } |
| + |
| + buffer->set_async_query_id(id); |
| + query->Begin(this); |
| + CheckGLError(); |
| + |
| + current_private_unpack_query_ = query; |
| +} |
| + |
| +void GLES2Implementation::EndQueryAsyncPixelUnpackCompleted() { |
| + DCHECK(current_private_unpack_query_); |
| + |
| + current_private_unpack_query_->End(this); |
| + current_private_unpack_query_ = NULL; |
| + CheckGLError(); |
| +} |
| + |
| void GLES2Implementation::AsyncTexImage2DCHROMIUM( |
| GLenum target, GLint level, GLint internalformat, GLsizei width, |
| GLsizei height, GLint border, GLenum format, GLenum type, |
| @@ -3689,9 +3783,11 @@ void GLES2Implementation::AsyncTexImage2DCHROMIUM( |
| bound_pixel_unpack_transfer_buffer_id_, |
| "glAsyncTexImage2DCHROMIUM", offset, size); |
| if (buffer && buffer->shm_id() != -1) { |
| + BeginQueryAsyncPixelUnpackCompleted(buffer); |
| helper_->AsyncTexImage2DCHROMIUM( |
| target, level, internalformat, width, height, border, format, type, |
| buffer->shm_id(), buffer->shm_offset() + offset); |
| + EndQueryAsyncPixelUnpackCompleted(); |
| } |
| } |
| @@ -3733,9 +3829,11 @@ void GLES2Implementation::AsyncTexSubImage2DCHROMIUM( |
| bound_pixel_unpack_transfer_buffer_id_, |
| "glAsyncTexSubImage2DCHROMIUM", offset, size); |
| if (buffer && buffer->shm_id() != -1) { |
| + BeginQueryAsyncPixelUnpackCompleted(buffer); |
| helper_->AsyncTexSubImage2DCHROMIUM( |
| target, level, xoffset, yoffset, width, height, format, type, |
| buffer->shm_id(), buffer->shm_offset() + offset); |
| + EndQueryAsyncPixelUnpackCompleted(); |
| } |
| } |