Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: gpu/command_buffer/client/gles2_implementation.cc

Issue 116863003: gpu: Reuse transfer buffers more aggresively (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Async upload token part of existing Async command; use separate shared memory to sync async upload … Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 // A class to emulate GLES2 over command buffers. 5 // A class to emulate GLES2 over command buffers.
6 6
7 #include "gpu/command_buffer/client/gles2_implementation.h" 7 #include "gpu/command_buffer/client/gles2_implementation.h"
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <map> 10 #include <map>
11 #include <queue> 11 #include <queue>
12 #include <set> 12 #include <set>
13 #include <limits> 13 #include <limits>
14 #include <stdio.h> 14 #include <stdio.h>
15 #include <string.h> 15 #include <string.h>
16 #include <GLES2/gl2ext.h> 16 #include <GLES2/gl2ext.h>
17 #include <GLES2/gl2extchromium.h> 17 #include <GLES2/gl2extchromium.h>
18 #include "base/bind.h"
18 #include "gpu/command_buffer/client/buffer_tracker.h" 19 #include "gpu/command_buffer/client/buffer_tracker.h"
19 #include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h" 20 #include "gpu/command_buffer/client/gpu_memory_buffer_tracker.h"
20 #include "gpu/command_buffer/client/program_info_manager.h" 21 #include "gpu/command_buffer/client/program_info_manager.h"
21 #include "gpu/command_buffer/client/query_tracker.h" 22 #include "gpu/command_buffer/client/query_tracker.h"
22 #include "gpu/command_buffer/client/transfer_buffer.h" 23 #include "gpu/command_buffer/client/transfer_buffer.h"
23 #include "gpu/command_buffer/client/vertex_array_object_manager.h" 24 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
24 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 25 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
25 #include "gpu/command_buffer/common/gpu_control.h" 26 #include "gpu/command_buffer/common/gpu_control.h"
26 #include "gpu/command_buffer/common/trace_event.h" 27 #include "gpu/command_buffer/common/trace_event.h"
27 #include "ui/gfx/gpu_memory_buffer.h" 28 #include "ui/gfx/gpu_memory_buffer.h"
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 unpack_skip_pixels_(0), 101 unpack_skip_pixels_(0),
101 pack_reverse_row_order_(false), 102 pack_reverse_row_order_(false),
102 active_texture_unit_(0), 103 active_texture_unit_(0),
103 bound_framebuffer_(0), 104 bound_framebuffer_(0),
104 bound_read_framebuffer_(0), 105 bound_read_framebuffer_(0),
105 bound_renderbuffer_(0), 106 bound_renderbuffer_(0),
106 current_program_(0), 107 current_program_(0),
107 bound_array_buffer_id_(0), 108 bound_array_buffer_id_(0),
108 bound_pixel_pack_transfer_buffer_id_(0), 109 bound_pixel_pack_transfer_buffer_id_(0),
109 bound_pixel_unpack_transfer_buffer_id_(0), 110 bound_pixel_unpack_transfer_buffer_id_(0),
111 async_upload_sync_(NULL),
piman 2014/02/07 22:58:20 Also need initializers for async_upload_token_, a
jadahl 2014/02/19 14:06:20 async_upload_token_ is needed indeed, but shm_id a
piman 2014/02/20 01:52:37 Per style guide ( http://google-styleguide.googlec
110 error_bits_(0), 112 error_bits_(0),
111 debug_(false), 113 debug_(false),
112 use_count_(0), 114 use_count_(0),
113 error_message_callback_(NULL), 115 error_message_callback_(NULL),
114 gpu_control_(gpu_control), 116 gpu_control_(gpu_control),
115 surface_visible_(true), 117 surface_visible_(true),
116 free_everything_when_invisible_(free_everything_when_invisible), 118 free_everything_when_invisible_(free_everything_when_invisible),
117 capabilities_(gpu_control->GetCapabilities()), 119 capabilities_(gpu_control->GetCapabilities()),
118 weak_ptr_factory_(this) { 120 weak_ptr_factory_(this) {
119 DCHECK(helper); 121 DCHECK(helper);
(...skipping 27 matching lines...) Expand all
147 if (!transfer_buffer_->Initialize( 149 if (!transfer_buffer_->Initialize(
148 starting_transfer_buffer_size, 150 starting_transfer_buffer_size,
149 kStartingOffset, 151 kStartingOffset,
150 min_transfer_buffer_size, 152 min_transfer_buffer_size,
151 max_transfer_buffer_size, 153 max_transfer_buffer_size,
152 kAlignment, 154 kAlignment,
153 kSizeToFlush)) { 155 kSizeToFlush)) {
154 return false; 156 return false;
155 } 157 }
156 158
157 mapped_memory_.reset(new MappedMemoryManager(helper_, mapped_memory_limit)); 159 mapped_memory_.reset(
160 new MappedMemoryManager(helper_,
161 base::Bind(&GLES2Implementation::PollAsyncUploads,
162 base::Unretained(this),
epennerAtGoogle 2014/02/07 20:43:58 Nit: Maybe overkill in this case, but it never hur
163 false),
164 mapped_memory_limit));
158 165
159 unsigned chunk_size = 2 * 1024 * 1024; 166 unsigned chunk_size = 2 * 1024 * 1024;
160 if (mapped_memory_limit != kNoLimit) { 167 if (mapped_memory_limit != kNoLimit) {
161 // Use smaller chunks if the client is very memory conscientious. 168 // Use smaller chunks if the client is very memory conscientious.
162 chunk_size = std::min(mapped_memory_limit / 4, chunk_size); 169 chunk_size = std::min(mapped_memory_limit / 4, chunk_size);
163 } 170 }
164 mapped_memory_->set_chunk_size_multiple(chunk_size); 171 mapped_memory_->set_chunk_size_multiple(chunk_size);
165 172
166 if (!QueryAndCacheStaticState()) 173 if (!QueryAndCacheStaticState())
167 return false; 174 return false;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 // by the queries. The GPU process when validating that memory is still 277 // by the queries. The GPU process when validating that memory is still
271 // shared will fail and abort (ie, it will stop running). 278 // shared will fail and abort (ie, it will stop running).
272 WaitForCmd(); 279 WaitForCmd();
273 query_tracker_.reset(); 280 query_tracker_.reset();
274 281
275 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 282 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
276 DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]); 283 DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]);
277 #endif 284 #endif
278 buffer_tracker_.reset(); 285 buffer_tracker_.reset();
279 286
287 // Wait for all async uploads to finish so we can free their buffers.
288 PollAsyncUploads(true);
289
290 if (async_upload_sync_) {
291 mapped_memory_->Free(static_cast<void*>(async_upload_sync_));
piman 2014/02/07 22:58:20 nit: static_cast isn't needed.
292 async_upload_sync_ = NULL;
293 }
294
280 // Make sure the commands make it the service. 295 // Make sure the commands make it the service.
281 WaitForCmd(); 296 WaitForCmd();
282 } 297 }
283 298
284 GLES2CmdHelper* GLES2Implementation::helper() const { 299 GLES2CmdHelper* GLES2Implementation::helper() const {
285 return helper_; 300 return helper_;
286 } 301 }
287 302
288 IdHandlerInterface* GLES2Implementation::GetIdHandler(int namespace_id) const { 303 IdHandlerInterface* GLES2Implementation::GetIdHandler(int namespace_id) const {
289 return share_group_->GetIdHandler(namespace_id); 304 return share_group_->GetIdHandler(namespace_id);
(...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 return; 1386 return;
1372 } 1387 }
1373 1388
1374 GLuint buffer_id; 1389 GLuint buffer_id;
1375 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) { 1390 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) {
1376 if (!buffer_id) { 1391 if (!buffer_id) {
1377 return; 1392 return;
1378 } 1393 }
1379 1394
1380 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); 1395 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
1381 if (buffer) { 1396 if (buffer)
1382 // Free buffer memory, pending the passage of a token. 1397 RemoveTransferBuffer(buffer);
1383 buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken());
1384
1385 // Remove old buffer.
1386 buffer_tracker_->RemoveBuffer(buffer_id);
1387 }
1388 1398
1389 // Create new buffer. 1399 // Create new buffer.
1390 buffer = buffer_tracker_->CreateBuffer(buffer_id, size); 1400 buffer = buffer_tracker_->CreateBuffer(buffer_id, size);
1391 DCHECK(buffer); 1401 DCHECK(buffer);
1392 if (buffer->address() && data) 1402 if (buffer->address() && data)
1393 memcpy(buffer->address(), data, size); 1403 memcpy(buffer->address(), data, size);
1394 return; 1404 return;
1395 } 1405 }
1396 1406
1397 if (size == 0) { 1407 if (size == 0) {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { 1515 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
1506 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1516 GPU_CLIENT_SINGLE_THREAD_CHECK();
1507 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData(" 1517 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1508 << GLES2Util::GetStringBufferTarget(target) << ", " 1518 << GLES2Util::GetStringBufferTarget(target) << ", "
1509 << offset << ", " << size << ", " 1519 << offset << ", " << size << ", "
1510 << static_cast<const void*>(data) << ")"); 1520 << static_cast<const void*>(data) << ")");
1511 BufferSubDataHelper(target, offset, size, data); 1521 BufferSubDataHelper(target, offset, size, data);
1512 CheckGLError(); 1522 CheckGLError();
1513 } 1523 }
1514 1524
1525 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer* buffer) {
1526 int32 token = buffer->last_usage_token();
1527 uint32 async_token = buffer->async_token();
1528
1529 base::subtle::MemoryBarrier();
epennerAtGoogle 2014/02/07 20:43:58 See nit on other MemoryBarrier. This one also seem
1530
1531 if (async_token) {
1532 if (HasAsyncUploadTokenPassed(async_token)) {
1533 buffer_tracker_->Free(buffer);
1534 } else {
1535 detached_async_upload_memory_.push_back(
1536 std::make_pair(buffer->address(), async_token));
1537 buffer_tracker_->Unmanage(buffer);
1538 }
1539 } else if (token) {
1540 if (helper_->HasTokenPassed(token))
1541 buffer_tracker_->Free(buffer);
1542 else
1543 buffer_tracker_->FreePendingToken(buffer, token);
1544 } else {
1545 buffer_tracker_->Free(buffer);
1546 }
1547
1548 buffer_tracker_->RemoveBuffer(buffer->id());
1549 }
1550
1515 bool GLES2Implementation::GetBoundPixelTransferBuffer( 1551 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1516 GLenum target, 1552 GLenum target,
1517 const char* function_name, 1553 const char* function_name,
1518 GLuint* buffer_id) { 1554 GLuint* buffer_id) {
1519 *buffer_id = 0; 1555 *buffer_id = 0;
1520 1556
1521 switch (target) { 1557 switch (target) {
1522 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: 1558 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
1523 *buffer_id = bound_pixel_pack_transfer_buffer_id_; 1559 *buffer_id = bound_pixel_pack_transfer_buffer_id_;
1524 break; 1560 break;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1580 // CompressedTexImage2D. 1616 // CompressedTexImage2D.
1581 if (bound_pixel_unpack_transfer_buffer_id_) { 1617 if (bound_pixel_unpack_transfer_buffer_id_) {
1582 GLuint offset = ToGLuint(data); 1618 GLuint offset = ToGLuint(data);
1583 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 1619 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
1584 bound_pixel_unpack_transfer_buffer_id_, 1620 bound_pixel_unpack_transfer_buffer_id_,
1585 "glCompressedTexImage2D", offset, image_size); 1621 "glCompressedTexImage2D", offset, image_size);
1586 if (buffer && buffer->shm_id() != -1) { 1622 if (buffer && buffer->shm_id() != -1) {
1587 helper_->CompressedTexImage2D( 1623 helper_->CompressedTexImage2D(
1588 target, level, internalformat, width, height, border, image_size, 1624 target, level, internalformat, width, height, border, image_size,
1589 buffer->shm_id(), buffer->shm_offset() + offset); 1625 buffer->shm_id(), buffer->shm_offset() + offset);
1590 buffer->set_transfer_ready_token(helper_->InsertToken()); 1626 buffer->set_last_usage_token(helper_->InsertToken());
1591 } 1627 }
1592 return; 1628 return;
1593 } 1629 }
1594 SetBucketContents(kResultBucketId, data, image_size); 1630 SetBucketContents(kResultBucketId, data, image_size);
1595 helper_->CompressedTexImage2DBucket( 1631 helper_->CompressedTexImage2DBucket(
1596 target, level, internalformat, width, height, border, kResultBucketId); 1632 target, level, internalformat, width, height, border, kResultBucketId);
1597 // Free the bucket. This is not required but it does free up the memory. 1633 // Free the bucket. This is not required but it does free up the memory.
1598 // and we don't have to wait for the result so from the client's perspective 1634 // and we don't have to wait for the result so from the client's perspective
1599 // it's cheap. 1635 // it's cheap.
1600 helper_->SetBucketSize(kResultBucketId, 0); 1636 helper_->SetBucketSize(kResultBucketId, 0);
(...skipping 20 matching lines...) Expand all
1621 // CompressedTexSubImage2D. 1657 // CompressedTexSubImage2D.
1622 if (bound_pixel_unpack_transfer_buffer_id_) { 1658 if (bound_pixel_unpack_transfer_buffer_id_) {
1623 GLuint offset = ToGLuint(data); 1659 GLuint offset = ToGLuint(data);
1624 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 1660 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
1625 bound_pixel_unpack_transfer_buffer_id_, 1661 bound_pixel_unpack_transfer_buffer_id_,
1626 "glCompressedTexSubImage2D", offset, image_size); 1662 "glCompressedTexSubImage2D", offset, image_size);
1627 if (buffer && buffer->shm_id() != -1) { 1663 if (buffer && buffer->shm_id() != -1) {
1628 helper_->CompressedTexSubImage2D( 1664 helper_->CompressedTexSubImage2D(
1629 target, level, xoffset, yoffset, width, height, format, image_size, 1665 target, level, xoffset, yoffset, width, height, format, image_size,
1630 buffer->shm_id(), buffer->shm_offset() + offset); 1666 buffer->shm_id(), buffer->shm_offset() + offset);
1631 buffer->set_transfer_ready_token(helper_->InsertToken()); 1667 buffer->set_last_usage_token(helper_->InsertToken());
1632 CheckGLError(); 1668 CheckGLError();
1633 } 1669 }
1634 return; 1670 return;
1635 } 1671 }
1636 SetBucketContents(kResultBucketId, data, image_size); 1672 SetBucketContents(kResultBucketId, data, image_size);
1637 helper_->CompressedTexSubImage2DBucket( 1673 helper_->CompressedTexSubImage2DBucket(
1638 target, level, xoffset, yoffset, width, height, format, kResultBucketId); 1674 target, level, xoffset, yoffset, width, height, format, kResultBucketId);
1639 // Free the bucket. This is not required but it does free up the memory. 1675 // Free the bucket. This is not required but it does free up the memory.
1640 // and we don't have to wait for the result so from the client's perspective 1676 // and we don't have to wait for the result so from the client's perspective
1641 // it's cheap. 1677 // it's cheap.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 // If there's a pixel unpack buffer bound use it when issuing TexImage2D. 1744 // If there's a pixel unpack buffer bound use it when issuing TexImage2D.
1709 if (bound_pixel_unpack_transfer_buffer_id_) { 1745 if (bound_pixel_unpack_transfer_buffer_id_) {
1710 GLuint offset = ToGLuint(pixels); 1746 GLuint offset = ToGLuint(pixels);
1711 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 1747 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
1712 bound_pixel_unpack_transfer_buffer_id_, 1748 bound_pixel_unpack_transfer_buffer_id_,
1713 "glTexImage2D", offset, size); 1749 "glTexImage2D", offset, size);
1714 if (buffer && buffer->shm_id() != -1) { 1750 if (buffer && buffer->shm_id() != -1) {
1715 helper_->TexImage2D( 1751 helper_->TexImage2D(
1716 target, level, internalformat, width, height, border, format, type, 1752 target, level, internalformat, width, height, border, format, type,
1717 buffer->shm_id(), buffer->shm_offset() + offset); 1753 buffer->shm_id(), buffer->shm_offset() + offset);
1718 buffer->set_transfer_ready_token(helper_->InsertToken()); 1754 buffer->set_last_usage_token(helper_->InsertToken());
1719 CheckGLError(); 1755 CheckGLError();
1720 } 1756 }
1721 return; 1757 return;
1722 } 1758 }
1723 1759
1724 // If there's no data just issue TexImage2D 1760 // If there's no data just issue TexImage2D
1725 if (!pixels) { 1761 if (!pixels) {
1726 helper_->TexImage2D( 1762 helper_->TexImage2D(
1727 target, level, internalformat, width, height, border, format, type, 1763 target, level, internalformat, width, height, border, format, type,
1728 0, 0); 1764 0, 0);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1814 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D. 1850 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
1815 if (bound_pixel_unpack_transfer_buffer_id_) { 1851 if (bound_pixel_unpack_transfer_buffer_id_) {
1816 GLuint offset = ToGLuint(pixels); 1852 GLuint offset = ToGLuint(pixels);
1817 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 1853 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
1818 bound_pixel_unpack_transfer_buffer_id_, 1854 bound_pixel_unpack_transfer_buffer_id_,
1819 "glTexSubImage2D", offset, temp_size); 1855 "glTexSubImage2D", offset, temp_size);
1820 if (buffer && buffer->shm_id() != -1) { 1856 if (buffer && buffer->shm_id() != -1) {
1821 helper_->TexSubImage2D( 1857 helper_->TexSubImage2D(
1822 target, level, xoffset, yoffset, width, height, format, type, 1858 target, level, xoffset, yoffset, width, height, format, type,
1823 buffer->shm_id(), buffer->shm_offset() + offset, false); 1859 buffer->shm_id(), buffer->shm_offset() + offset, false);
1824 buffer->set_transfer_ready_token(helper_->InsertToken()); 1860 buffer->set_last_usage_token(helper_->InsertToken());
1825 CheckGLError(); 1861 CheckGLError();
1826 } 1862 }
1827 return; 1863 return;
1828 } 1864 }
1829 1865
1830 // compute the advance bytes per row for the src pixels 1866 // compute the advance bytes per row for the src pixels
1831 uint32 src_padded_row_size; 1867 uint32 src_padded_row_size;
1832 if (unpack_row_length_ > 0) { 1868 if (unpack_row_length_ > 0) {
1833 if (!GLES2Util::ComputeImagePaddedRowSize( 1869 if (!GLES2Util::ComputeImagePaddedRowSize(
1834 unpack_row_length_, format, type, unpack_alignment_, 1870 unpack_row_length_, format, type, unpack_alignment_,
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
2397 } 2433 }
2398 2434
2399 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id 2435 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
2400 // generates a new resource. On newer versions of OpenGL they don't. The code 2436 // generates a new resource. On newer versions of OpenGL they don't. The code
2401 // related to binding below will need to change if we switch to the new OpenGL 2437 // related to binding below will need to change if we switch to the new OpenGL
2402 // model. Specifically it assumes a bind will succeed which is always true in 2438 // model. Specifically it assumes a bind will succeed which is always true in
2403 // the old model but possibly not true in the new model if another context has 2439 // the old model but possibly not true in the new model if another context has
2404 // deleted the resource. 2440 // deleted the resource.
2405 2441
2406 bool GLES2Implementation::BindBufferHelper( 2442 bool GLES2Implementation::BindBufferHelper(
2407 GLenum target, GLuint buffer) { 2443 GLenum target, GLuint buffer_id) {
2408 // TODO(gman): See note #1 above. 2444 // TODO(gman): See note #1 above.
2409 bool changed = false; 2445 bool changed = false;
2410 switch (target) { 2446 switch (target) {
2411 case GL_ARRAY_BUFFER: 2447 case GL_ARRAY_BUFFER:
2412 if (bound_array_buffer_id_ != buffer) { 2448 if (bound_array_buffer_id_ != buffer_id) {
2413 bound_array_buffer_id_ = buffer; 2449 bound_array_buffer_id_ = buffer_id;
2414 changed = true; 2450 changed = true;
2415 } 2451 }
2416 break; 2452 break;
2417 case GL_ELEMENT_ARRAY_BUFFER: 2453 case GL_ELEMENT_ARRAY_BUFFER:
2418 changed = vertex_array_object_manager_->BindElementArray(buffer); 2454 changed = vertex_array_object_manager_->BindElementArray(buffer_id);
2419 break; 2455 break;
2420 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: 2456 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
2421 bound_pixel_pack_transfer_buffer_id_ = buffer; 2457 bound_pixel_pack_transfer_buffer_id_ = buffer_id;
2422 break; 2458 break;
2423 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: 2459 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
2424 bound_pixel_unpack_transfer_buffer_id_ = buffer; 2460 bound_pixel_unpack_transfer_buffer_id_ = buffer_id;
2425 break; 2461 break;
2426 default: 2462 default:
2427 changed = true; 2463 changed = true;
2428 break; 2464 break;
2429 } 2465 }
2430 // TODO(gman): There's a bug here. If the target is invalid the ID will not be 2466 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2431 // used even though it's marked it as used here. 2467 // used even though it's marked it as used here.
2432 GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer); 2468 GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer_id);
2433 return changed; 2469 return changed;
2434 } 2470 }
2435 2471
2436 bool GLES2Implementation::BindFramebufferHelper( 2472 bool GLES2Implementation::BindFramebufferHelper(
2437 GLenum target, GLuint framebuffer) { 2473 GLenum target, GLuint framebuffer) {
2438 // TODO(gman): See note #1 above. 2474 // TODO(gman): See note #1 above.
2439 bool changed = false; 2475 bool changed = false;
2440 switch (target) { 2476 switch (target) {
2441 case GL_FRAMEBUFFER: 2477 case GL_FRAMEBUFFER:
2442 if (bound_framebuffer_ != framebuffer || 2478 if (bound_framebuffer_ != framebuffer ||
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2556 SetGLError( 2592 SetGLError(
2557 GL_INVALID_VALUE, 2593 GL_INVALID_VALUE,
2558 "glDeleteBuffers", "id not created by this context."); 2594 "glDeleteBuffers", "id not created by this context.");
2559 return; 2595 return;
2560 } 2596 }
2561 for (GLsizei ii = 0; ii < n; ++ii) { 2597 for (GLsizei ii = 0; ii < n; ++ii) {
2562 if (buffers[ii] == bound_array_buffer_id_) { 2598 if (buffers[ii] == bound_array_buffer_id_) {
2563 bound_array_buffer_id_ = 0; 2599 bound_array_buffer_id_ = 0;
2564 } 2600 }
2565 vertex_array_object_manager_->UnbindBuffer(buffers[ii]); 2601 vertex_array_object_manager_->UnbindBuffer(buffers[ii]);
2602
2566 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]); 2603 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]);
2567 if (buffer) { 2604 if (buffer)
2568 // Free buffer memory, pending the passage of a token. 2605 RemoveTransferBuffer(buffer);
2569 buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); 2606
2570 // Remove buffer.
2571 buffer_tracker_->RemoveBuffer(buffers[ii]);
2572 }
2573 if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) { 2607 if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) {
2574 bound_pixel_unpack_transfer_buffer_id_ = 0; 2608 bound_pixel_unpack_transfer_buffer_id_ = 0;
2575 } 2609 }
2576 } 2610 }
2577 } 2611 }
2578 2612
2579 void GLES2Implementation::DeleteBuffersStub( 2613 void GLES2Implementation::DeleteBuffersStub(
2580 GLsizei n, const GLuint* buffers) { 2614 GLsizei n, const GLuint* buffers) {
2581 helper_->DeleteBuffersImmediate(n, buffers); 2615 helper_->DeleteBuffersImmediate(n, buffers);
2582 } 2616 }
(...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after
3584 } 3618 }
3585 if (buffer->mapped()) { 3619 if (buffer->mapped()) {
3586 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped"); 3620 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped");
3587 return NULL; 3621 return NULL;
3588 } 3622 }
3589 // Here we wait for previous transfer operations to be finished. 3623 // Here we wait for previous transfer operations to be finished.
3590 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work 3624 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
3591 // with this method of synchronization. Until this is fixed, 3625 // with this method of synchronization. Until this is fixed,
3592 // MapBufferCHROMIUM will not block even if the transfer is not ready 3626 // MapBufferCHROMIUM will not block even if the transfer is not ready
3593 // for these calls. 3627 // for these calls.
3594 if (buffer->transfer_ready_token()) { 3628 if (buffer->last_usage_token()) {
3595 helper_->WaitForToken(buffer->transfer_ready_token()); 3629 helper_->WaitForToken(buffer->last_usage_token());
3596 buffer->set_transfer_ready_token(0); 3630 buffer->set_last_usage_token(0);
3597 } 3631 }
3598 buffer->set_mapped(true); 3632 buffer->set_mapped(true);
3599 3633
3600 GPU_CLIENT_LOG(" returned " << buffer->address()); 3634 GPU_CLIENT_LOG(" returned " << buffer->address());
3601 CheckGLError(); 3635 CheckGLError();
3602 return buffer->address(); 3636 return buffer->address();
3603 } 3637 }
3604 3638
3605 GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) { 3639 GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) {
3606 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3640 GPU_CLIENT_SINGLE_THREAD_CHECK();
(...skipping 13 matching lines...) Expand all
3620 } 3654 }
3621 if (!buffer->mapped()) { 3655 if (!buffer->mapped()) {
3622 SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped"); 3656 SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped");
3623 return false; 3657 return false;
3624 } 3658 }
3625 buffer->set_mapped(false); 3659 buffer->set_mapped(false);
3626 CheckGLError(); 3660 CheckGLError();
3627 return true; 3661 return true;
3628 } 3662 }
3629 3663
3664 bool GLES2Implementation::EnsureAsyncUploadSync() {
3665 if (async_upload_sync_)
3666 return true;
3667
3668 int32 shm_id;
3669 unsigned int shm_offset;
3670 void* mem = mapped_memory_->Alloc(sizeof(AsyncUploadSync),
3671 &shm_id,
3672 &shm_offset);
3673 if (!mem)
3674 return false;
3675
3676 async_upload_sync_shm_id_ = shm_id;
3677 async_upload_sync_shm_offset_ = shm_offset;
3678 async_upload_sync_ = static_cast<AsyncUploadSync*>(mem);
3679 async_upload_sync_->Reset();
3680
3681 return true;
3682 }
3683
3684 uint32 GLES2Implementation::NextAsyncUploadToken() {
3685 async_upload_token_++;
3686 if (async_upload_token_ == 0)
3687 async_upload_token_++;
3688 return async_upload_token_;
3689 }
3690
3691 void GLES2Implementation::PollAsyncUploads(bool wait) {
3692 if (!async_upload_sync_)
3693 return;
3694
3695 do {
3696 base::subtle::MemoryBarrier();
epennerAtGoogle 2014/02/07 20:43:58 It wouldn't hurt to document each of these base::s
piman 2014/02/07 22:58:20 TBH, I'd rather make the access to the AsyncUpload
jadahl 2014/02/08 09:18:25 To be honest, I added the barrier here mostly beca
piman 2014/02/11 00:09:09 Some useful background: http://software.intel.com/
3697 DetachedAsyncUploadMemoryList::iterator it =
3698 detached_async_upload_memory_.begin();
3699 while (it != detached_async_upload_memory_.end()) {
3700 if (HasAsyncUploadTokenPassed(it->second)) {
piman 2014/02/07 22:58:20 Similar to what I mentioned in FencedAllocator, we
3701 mapped_memory_->Free(it->first);
3702 it = detached_async_upload_memory_.erase(it);
3703 } else {
3704 break;
3705 }
3706 }
3707 if (wait)
3708 WaitForCmd();
piman 2014/02/07 22:58:20 We need more than this, otherwise we'll spin loop
3709 } while (!detached_async_upload_memory_.empty() && wait);
3710 }
3711
3630 void GLES2Implementation::AsyncTexImage2DCHROMIUM( 3712 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
3631 GLenum target, GLint level, GLint internalformat, GLsizei width, 3713 GLenum target, GLint level, GLint internalformat, GLsizei width,
3632 GLsizei height, GLint border, GLenum format, GLenum type, 3714 GLsizei height, GLint border, GLenum format, GLenum type,
3633 const void* pixels) { 3715 const void* pixels) {
3634 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3716 GPU_CLIENT_SINGLE_THREAD_CHECK();
3635 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D(" 3717 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
3636 << GLES2Util::GetStringTextureTarget(target) << ", " 3718 << GLES2Util::GetStringTextureTarget(target) << ", "
3637 << level << ", " 3719 << level << ", "
3638 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " 3720 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", "
3639 << width << ", " << height << ", " << border << ", " 3721 << width << ", " << height << ", " << border << ", "
(...skipping 11 matching lines...) Expand all
3651 width, height, format, type, unpack_alignment_, &size, 3733 width, height, format, type, unpack_alignment_, &size,
3652 &unpadded_row_size, &padded_row_size)) { 3734 &unpadded_row_size, &padded_row_size)) {
3653 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large"); 3735 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large");
3654 return; 3736 return;
3655 } 3737 }
3656 3738
3657 // If there's no data/buffer just issue the AsyncTexImage2D 3739 // If there's no data/buffer just issue the AsyncTexImage2D
3658 if (!pixels && !bound_pixel_unpack_transfer_buffer_id_) { 3740 if (!pixels && !bound_pixel_unpack_transfer_buffer_id_) {
3659 helper_->AsyncTexImage2DCHROMIUM( 3741 helper_->AsyncTexImage2DCHROMIUM(
3660 target, level, internalformat, width, height, border, format, type, 3742 target, level, internalformat, width, height, border, format, type,
3661 0, 0); 3743 0, 0, 0, 0, 0);
3662 return; 3744 return;
3663 } 3745 }
3664 3746
3747 if (!EnsureAsyncUploadSync()) {
3748 SetGLError(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory");
3749 return;
3750 }
3751
3665 // Otherwise, async uploads require a transfer buffer to be bound. 3752 // Otherwise, async uploads require a transfer buffer to be bound.
3666 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use 3753 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3667 // the buffer before the transfer is finished. (Currently such 3754 // the buffer before the transfer is finished. (Currently such
3668 // synchronization has to be handled manually.) 3755 // synchronization has to be handled manually.)
3669 GLuint offset = ToGLuint(pixels); 3756 GLuint offset = ToGLuint(pixels);
3670 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 3757 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
3671 bound_pixel_unpack_transfer_buffer_id_, 3758 bound_pixel_unpack_transfer_buffer_id_,
3672 "glAsyncTexImage2DCHROMIUM", offset, size); 3759 "glAsyncTexImage2DCHROMIUM", offset, size);
3673 if (buffer && buffer->shm_id() != -1) { 3760 if (buffer && buffer->shm_id() != -1) {
3761 uint32 async_token = NextAsyncUploadToken();
3762 buffer->set_async_token(async_token);
3674 helper_->AsyncTexImage2DCHROMIUM( 3763 helper_->AsyncTexImage2DCHROMIUM(
3675 target, level, internalformat, width, height, border, format, type, 3764 target, level, internalformat, width, height, border, format, type,
3676 buffer->shm_id(), buffer->shm_offset() + offset); 3765 buffer->shm_id(), buffer->shm_offset() + offset,
3766 async_token,
3767 async_upload_sync_shm_id_, async_upload_sync_shm_offset_);
3677 } 3768 }
3678 } 3769 }
3679 3770
3680 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM( 3771 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
3681 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, 3772 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
3682 GLsizei height, GLenum format, GLenum type, const void* pixels) { 3773 GLsizei height, GLenum format, GLenum type, const void* pixels) {
3683 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3774 GPU_CLIENT_SINGLE_THREAD_CHECK();
3684 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM(" 3775 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
3685 << GLES2Util::GetStringTextureTarget(target) << ", " 3776 << GLES2Util::GetStringTextureTarget(target) << ", "
3686 << level << ", " 3777 << level << ", "
(...skipping 12 matching lines...) Expand all
3699 uint32 unpadded_row_size; 3790 uint32 unpadded_row_size;
3700 uint32 padded_row_size; 3791 uint32 padded_row_size;
3701 if (!GLES2Util::ComputeImageDataSizes( 3792 if (!GLES2Util::ComputeImageDataSizes(
3702 width, height, format, type, unpack_alignment_, &size, 3793 width, height, format, type, unpack_alignment_, &size,
3703 &unpadded_row_size, &padded_row_size)) { 3794 &unpadded_row_size, &padded_row_size)) {
3704 SetGLError( 3795 SetGLError(
3705 GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "size to large"); 3796 GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "size to large");
3706 return; 3797 return;
3707 } 3798 }
3708 3799
3800 if (!EnsureAsyncUploadSync()) {
3801 SetGLError(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory");
3802 return;
3803 }
3804
3709 // Async uploads require a transfer buffer to be bound. 3805 // Async uploads require a transfer buffer to be bound.
3710 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use 3806 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3711 // the buffer before the transfer is finished. (Currently such 3807 // the buffer before the transfer is finished. (Currently such
3712 // synchronization has to be handled manually.) 3808 // synchronization has to be handled manually.)
3713 GLuint offset = ToGLuint(pixels); 3809 GLuint offset = ToGLuint(pixels);
3714 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 3810 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
3715 bound_pixel_unpack_transfer_buffer_id_, 3811 bound_pixel_unpack_transfer_buffer_id_,
3716 "glAsyncTexSubImage2DCHROMIUM", offset, size); 3812 "glAsyncTexSubImage2DCHROMIUM", offset, size);
3717 if (buffer && buffer->shm_id() != -1) { 3813 if (buffer && buffer->shm_id() != -1) {
3814 uint32 async_token = NextAsyncUploadToken();
3815 buffer->set_async_token(async_token);
3718 helper_->AsyncTexSubImage2DCHROMIUM( 3816 helper_->AsyncTexSubImage2DCHROMIUM(
3719 target, level, xoffset, yoffset, width, height, format, type, 3817 target, level, xoffset, yoffset, width, height, format, type,
3720 buffer->shm_id(), buffer->shm_offset() + offset); 3818 buffer->shm_id(), buffer->shm_offset() + offset,
3819 async_token,
3820 async_upload_sync_shm_id_, async_upload_sync_shm_offset_);
3721 } 3821 }
3722 } 3822 }
3723 3823
3724 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) { 3824 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) {
3725 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3825 GPU_CLIENT_SINGLE_THREAD_CHECK();
3726 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM(" 3826 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
3727 << GLES2Util::GetStringTextureTarget(target) << ")"); 3827 << GLES2Util::GetStringTextureTarget(target) << ")");
3728 helper_->WaitAsyncTexImage2DCHROMIUM(target); 3828 helper_->WaitAsyncTexImage2DCHROMIUM(target);
3729 CheckGLError(); 3829 CheckGLError();
3730 } 3830 }
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3897 CheckGLError(); 3997 CheckGLError();
3898 } 3998 }
3899 3999
3900 // Include the auto-generated part of this file. We split this because it means 4000 // Include the auto-generated part of this file. We split this because it means
3901 // we can easily edit the non-auto generated parts right here in this file 4001 // we can easily edit the non-auto generated parts right here in this file
3902 // instead of having to edit some template or the code generator. 4002 // instead of having to edit some template or the code generator.
3903 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" 4003 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
3904 4004
3905 } // namespace gles2 4005 } // namespace gles2
3906 } // namespace gpu 4006 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698