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 // 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |