Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gpu/command_buffer/service/query_manager.h" | 5 #include "gpu/command_buffer/service/query_manager.h" |
| 6 #include "base/atomicops.h" | 6 #include "base/atomicops.h" |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/time.h" | 9 #include "base/time.h" |
| 10 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 10 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 , public base::SupportsWeakPtr<AsyncPixelTransfersCompletedQuery> { | 169 , public base::SupportsWeakPtr<AsyncPixelTransfersCompletedQuery> { |
| 170 public: | 170 public: |
| 171 AsyncPixelTransfersCompletedQuery( | 171 AsyncPixelTransfersCompletedQuery( |
| 172 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); | 172 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset); |
| 173 | 173 |
| 174 virtual bool Begin() OVERRIDE; | 174 virtual bool Begin() OVERRIDE; |
| 175 virtual bool End(uint32 submit_count) OVERRIDE; | 175 virtual bool End(uint32 submit_count) OVERRIDE; |
| 176 virtual bool Process() OVERRIDE; | 176 virtual bool Process() OVERRIDE; |
| 177 virtual void Destroy(bool have_context) OVERRIDE; | 177 virtual void Destroy(bool have_context) OVERRIDE; |
| 178 | 178 |
| 179 void MarkAsCompletedCallback() { MarkAsCompleted(1); } | |
| 180 | |
| 181 protected: | 179 protected: |
| 182 virtual ~AsyncPixelTransfersCompletedQuery(); | 180 virtual ~AsyncPixelTransfersCompletedQuery(); |
| 183 }; | 181 }; |
| 184 | 182 |
| 185 AsyncPixelTransfersCompletedQuery::AsyncPixelTransfersCompletedQuery( | 183 AsyncPixelTransfersCompletedQuery::AsyncPixelTransfersCompletedQuery( |
| 186 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset) | 184 QueryManager* manager, GLenum target, int32 shm_id, uint32 shm_offset) |
| 187 : Query(manager, target, shm_id, shm_offset) { | 185 : Query(manager, target, shm_id, shm_offset) { |
| 188 } | 186 } |
| 189 | 187 |
| 190 bool AsyncPixelTransfersCompletedQuery::Begin() { | 188 bool AsyncPixelTransfersCompletedQuery::Begin() { |
| 191 return true; | 189 return true; |
| 192 } | 190 } |
| 193 | 191 |
| 194 bool AsyncPixelTransfersCompletedQuery::End(uint32 submit_count) { | 192 bool AsyncPixelTransfersCompletedQuery::End(uint32 submit_count) { |
| 195 MarkAsPending(submit_count); | 193 gfx::AsyncMemoryParams mem_params; |
| 194 // Get the real shared memory since it might need to be duped to prevent | |
| 195 // use-after-free of the memory. | |
| 196 Buffer buffer = manager()->decoder()->GetSharedMemoryBuffer(shm_id()); | |
| 197 mem_params.shared_memory = buffer.shared_memory; | |
| 198 mem_params.shm_size = buffer.size; | |
| 199 mem_params.shm_data_offset = shm_offset(); | |
| 200 mem_params.shm_data_size = sizeof(QuerySync); | |
|
epenner
2013/02/07 20:22:56
I was in debate of whether we needed to do this in
reveman
2013/02/07 21:30:52
I think the safe way to do this for now is duplica
| |
| 196 | 201 |
| 197 // This will call MarkAsCompleted(1) as a reply to a task on | 202 // This tells AsyncPixelTransferDelegate to mark QuerySync as completed |
| 198 // the async upload thread, such that it occurs after all previous | 203 // after all previous async transfers are done. |
| 199 // async transfers have completed. | |
| 200 manager()->decoder()->GetAsyncPixelTransferDelegate()->AsyncNotifyCompletion( | 204 manager()->decoder()->GetAsyncPixelTransferDelegate()->AsyncNotifyCompletion( |
|
epenner
2013/02/07 20:22:56
I think to avoid the layering violation, we could
reveman
2013/02/07 21:30:52
yea, sounds like that might be a pretty clean solu
| |
| 201 base::Bind( | 205 mem_params, submit_count); |
| 202 &AsyncPixelTransfersCompletedQuery::MarkAsCompletedCallback, | |
| 203 AsWeakPtr())); | |
| 204 | 206 |
| 205 // TODO(epenner): The async task occurs outside the normal | 207 return AddToPendingTransferQueue(submit_count); |
| 206 // flow, via a callback on this thread. Is there anything | 208 } |
| 207 // missing or wrong with that? | |
| 208 | 209 |
| 209 // TODO(epenner): Could we possibly trigger the completion on | 210 bool AsyncPixelTransfersCompletedQuery::Process() { |
| 210 // the upload thread by writing to the query shared memory | 211 QuerySync* sync = manager()->decoder()->GetSharedMemoryAs<QuerySync*>( |
| 211 // directly? | 212 shm_id(), shm_offset(), sizeof(*sync)); |
| 213 if (!sync) | |
| 214 return false; | |
| 215 | |
| 216 // Check if AsyncPixelTransferDelegate has marked QuerySync as completed. | |
| 217 if (sync->process_count != submit_count()) | |
|
epenner
2013/02/07 20:22:56
Is this thread safe? Given it's simplicity maybe i
reveman
2013/02/07 21:30:52
this is consistent with the code in the client sid
| |
| 218 return true; | |
| 219 | |
| 220 UnmarkAsPending(); | |
| 212 return true; | 221 return true; |
| 213 } | 222 } |
| 214 | 223 |
| 215 bool AsyncPixelTransfersCompletedQuery::Process() { | |
| 216 NOTREACHED(); | |
| 217 return true; | |
| 218 } | |
| 219 | |
| 220 void AsyncPixelTransfersCompletedQuery::Destroy(bool /* have_context */) { | 224 void AsyncPixelTransfersCompletedQuery::Destroy(bool /* have_context */) { |
| 221 if (!IsDeleted()) { | 225 if (!IsDeleted()) { |
| 222 MarkAsDeleted(); | 226 MarkAsDeleted(); |
| 223 } | 227 } |
| 224 } | 228 } |
| 225 | 229 |
| 226 AsyncPixelTransfersCompletedQuery::~AsyncPixelTransfersCompletedQuery() { | 230 AsyncPixelTransfersCompletedQuery::~AsyncPixelTransfersCompletedQuery() { |
| 227 } | 231 } |
| 228 | 232 |
| 229 class GetErrorQuery : public QueryManager::Query { | 233 class GetErrorQuery : public QueryManager::Query { |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 428 return true; | 432 return true; |
| 429 } | 433 } |
| 430 | 434 |
| 431 bool QueryManager::ProcessPendingQueries() { | 435 bool QueryManager::ProcessPendingQueries() { |
| 432 while (!pending_queries_.empty()) { | 436 while (!pending_queries_.empty()) { |
| 433 Query* query = pending_queries_.front().get(); | 437 Query* query = pending_queries_.front().get(); |
| 434 if (!query->Process()) { | 438 if (!query->Process()) { |
| 435 return false; | 439 return false; |
| 436 } | 440 } |
| 437 if (query->pending()) { | 441 if (query->pending()) { |
| 438 return true; | 442 break; |
| 439 } | 443 } |
| 440 pending_queries_.pop_front(); | 444 pending_queries_.pop_front(); |
| 441 } | 445 } |
| 446 while (!pending_transfer_queries_.empty()) { | |
| 447 Query* query = pending_transfer_queries_.front().get(); | |
| 448 if (!query->Process()) { | |
| 449 return false; | |
| 450 } | |
| 451 if (query->pending()) { | |
| 452 break; | |
| 453 } | |
| 454 pending_transfer_queries_.pop_front(); | |
| 455 } | |
| 442 | 456 |
| 443 return true; | 457 return true; |
| 444 } | 458 } |
| 445 | 459 |
| 446 bool QueryManager::HavePendingQueries() { | 460 bool QueryManager::HavePendingQueries() { |
| 447 return !pending_queries_.empty(); | 461 return !pending_queries_.empty() || !pending_transfer_queries_.empty(); |
| 448 } | 462 } |
| 449 | 463 |
| 450 bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { | 464 bool QueryManager::AddPendingQuery(Query* query, uint32 submit_count) { |
| 451 DCHECK(query); | 465 DCHECK(query); |
| 452 DCHECK(!query->IsDeleted()); | 466 DCHECK(!query->IsDeleted()); |
| 453 if (!RemovePendingQuery(query)) { | 467 if (!RemovePendingQuery(query)) { |
| 454 return false; | 468 return false; |
| 455 } | 469 } |
| 456 query->MarkAsPending(submit_count); | 470 query->MarkAsPending(submit_count); |
| 457 pending_queries_.push_back(query); | 471 pending_queries_.push_back(query); |
| 458 return true; | 472 return true; |
| 459 } | 473 } |
| 460 | 474 |
| 475 bool QueryManager::AddPendingTransferQuery(Query* query, uint32 submit_count) { | |
| 476 DCHECK(query); | |
| 477 DCHECK(!query->IsDeleted()); | |
| 478 if (!RemovePendingQuery(query)) { | |
| 479 return false; | |
| 480 } | |
| 481 query->MarkAsPending(submit_count); | |
| 482 pending_transfer_queries_.push_back(query); | |
| 483 return true; | |
| 484 } | |
| 485 | |
| 461 bool QueryManager::RemovePendingQuery(Query* query) { | 486 bool QueryManager::RemovePendingQuery(Query* query) { |
| 462 DCHECK(query); | 487 DCHECK(query); |
| 463 if (query->pending()) { | 488 if (query->pending()) { |
| 464 // TODO(gman): Speed this up if this is a common operation. This would only | 489 // TODO(gman): Speed this up if this is a common operation. This would only |
| 465 // happen if you do being/end begin/end on the same query without waiting | 490 // happen if you do being/end begin/end on the same query without waiting |
| 466 // for the first one to finish. | 491 // for the first one to finish. |
| 467 for (QueryQueue::iterator it = pending_queries_.begin(); | 492 for (QueryQueue::iterator it = pending_queries_.begin(); |
| 468 it != pending_queries_.end(); ++it) { | 493 it != pending_queries_.end(); ++it) { |
| 469 if (it->get() == query) { | 494 if (it->get() == query) { |
| 470 pending_queries_.erase(it); | 495 pending_queries_.erase(it); |
| 471 break; | 496 break; |
| 472 } | 497 } |
| 473 } | 498 } |
| 499 for (QueryQueue::iterator it = pending_transfer_queries_.begin(); | |
| 500 it != pending_transfer_queries_.end(); ++it) { | |
| 501 if (it->get() == query) { | |
| 502 pending_transfer_queries_.erase(it); | |
| 503 break; | |
| 504 } | |
| 505 } | |
| 474 if (!query->MarkAsCompleted(0)) { | 506 if (!query->MarkAsCompleted(0)) { |
| 475 return false; | 507 return false; |
| 476 } | 508 } |
| 477 } | 509 } |
| 478 return true; | 510 return true; |
| 479 } | 511 } |
| 480 | 512 |
| 481 bool QueryManager::BeginQuery(Query* query) { | 513 bool QueryManager::BeginQuery(Query* query) { |
| 482 DCHECK(query); | 514 DCHECK(query); |
| 483 if (!RemovePendingQuery(query)) { | 515 if (!RemovePendingQuery(query)) { |
| 484 return false; | 516 return false; |
| 485 } | 517 } |
| 486 return query->Begin(); | 518 return query->Begin(); |
| 487 } | 519 } |
| 488 | 520 |
| 489 bool QueryManager::EndQuery(Query* query, uint32 submit_count) { | 521 bool QueryManager::EndQuery(Query* query, uint32 submit_count) { |
| 490 DCHECK(query); | 522 DCHECK(query); |
| 491 if (!RemovePendingQuery(query)) { | 523 if (!RemovePendingQuery(query)) { |
| 492 return false; | 524 return false; |
| 493 } | 525 } |
| 494 return query->End(submit_count); | 526 return query->End(submit_count); |
| 495 } | 527 } |
| 496 | 528 |
| 497 } // namespace gles2 | 529 } // namespace gles2 |
| 498 } // namespace gpu | 530 } // namespace gpu |
| 499 | 531 |
| 500 | 532 |
| OLD | NEW |