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_token_(0), | |
112 async_upload_sync_(NULL), | |
110 error_bits_(0), | 113 error_bits_(0), |
111 debug_(false), | 114 debug_(false), |
112 use_count_(0), | 115 use_count_(0), |
113 error_message_callback_(NULL), | 116 error_message_callback_(NULL), |
114 gpu_control_(gpu_control), | 117 gpu_control_(gpu_control), |
115 surface_visible_(true), | 118 surface_visible_(true), |
116 free_everything_when_invisible_(free_everything_when_invisible), | 119 free_everything_when_invisible_(free_everything_when_invisible), |
117 capabilities_(gpu_control->GetCapabilities()), | 120 capabilities_(gpu_control->GetCapabilities()), |
118 weak_ptr_factory_(this) { | 121 weak_ptr_factory_(this) { |
119 DCHECK(helper); | 122 DCHECK(helper); |
(...skipping 27 matching lines...) Expand all Loading... | |
147 if (!transfer_buffer_->Initialize( | 150 if (!transfer_buffer_->Initialize( |
148 starting_transfer_buffer_size, | 151 starting_transfer_buffer_size, |
149 kStartingOffset, | 152 kStartingOffset, |
150 min_transfer_buffer_size, | 153 min_transfer_buffer_size, |
151 max_transfer_buffer_size, | 154 max_transfer_buffer_size, |
152 kAlignment, | 155 kAlignment, |
153 kSizeToFlush)) { | 156 kSizeToFlush)) { |
154 return false; | 157 return false; |
155 } | 158 } |
156 | 159 |
157 mapped_memory_.reset(new MappedMemoryManager(helper_, mapped_memory_limit)); | 160 mapped_memory_.reset( |
161 new MappedMemoryManager( | |
162 helper_, | |
163 base::Bind(&GLES2Implementation::PollAsyncUploads, | |
164 // The mapped memory manager is owned by |this| here, and | |
165 // since its destroyed before before we destroy ourselves | |
166 // we don't need extra safety measures for this closure. | |
167 base::Unretained(this)), | |
168 mapped_memory_limit)); | |
158 | 169 |
159 unsigned chunk_size = 2 * 1024 * 1024; | 170 unsigned chunk_size = 2 * 1024 * 1024; |
160 if (mapped_memory_limit != kNoLimit) { | 171 if (mapped_memory_limit != kNoLimit) { |
161 // Use smaller chunks if the client is very memory conscientious. | 172 // Use smaller chunks if the client is very memory conscientious. |
162 chunk_size = std::min(mapped_memory_limit / 4, chunk_size); | 173 chunk_size = std::min(mapped_memory_limit / 4, chunk_size); |
163 } | 174 } |
164 mapped_memory_->set_chunk_size_multiple(chunk_size); | 175 mapped_memory_->set_chunk_size_multiple(chunk_size); |
165 | 176 |
166 if (!QueryAndCacheStaticState()) | 177 if (!QueryAndCacheStaticState()) |
167 return false; | 178 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 | 281 // by the queries. The GPU process when validating that memory is still |
271 // shared will fail and abort (ie, it will stop running). | 282 // shared will fail and abort (ie, it will stop running). |
272 WaitForCmd(); | 283 WaitForCmd(); |
273 query_tracker_.reset(); | 284 query_tracker_.reset(); |
274 | 285 |
275 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) | 286 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) |
276 DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]); | 287 DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]); |
277 #endif | 288 #endif |
278 buffer_tracker_.reset(); | 289 buffer_tracker_.reset(); |
279 | 290 |
291 // Free all completed unmanaged async uploads buffers. | |
292 PollAsyncUploads(); | |
293 | |
294 // Synchronously free rest of the unmanaged async upload buffers. | |
295 if (!detached_async_upload_memory_.empty()) { | |
296 WaitAllAsyncTexImage2DCHROMIUM(); | |
297 WaitForCmd(); | |
298 PollAsyncUploads(); | |
299 } | |
piman
2014/02/20 01:52:37
It would be nice to do this in FreeEverything too.
| |
300 | |
301 if (async_upload_sync_) { | |
302 mapped_memory_->Free(async_upload_sync_); | |
303 async_upload_sync_ = NULL; | |
304 } | |
305 | |
280 // Make sure the commands make it the service. | 306 // Make sure the commands make it the service. |
281 WaitForCmd(); | 307 WaitForCmd(); |
282 } | 308 } |
283 | 309 |
284 GLES2CmdHelper* GLES2Implementation::helper() const { | 310 GLES2CmdHelper* GLES2Implementation::helper() const { |
285 return helper_; | 311 return helper_; |
286 } | 312 } |
287 | 313 |
288 IdHandlerInterface* GLES2Implementation::GetIdHandler(int namespace_id) const { | 314 IdHandlerInterface* GLES2Implementation::GetIdHandler(int namespace_id) const { |
289 return share_group_->GetIdHandler(namespace_id); | 315 return share_group_->GetIdHandler(namespace_id); |
(...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1371 return; | 1397 return; |
1372 } | 1398 } |
1373 | 1399 |
1374 GLuint buffer_id; | 1400 GLuint buffer_id; |
1375 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) { | 1401 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) { |
1376 if (!buffer_id) { | 1402 if (!buffer_id) { |
1377 return; | 1403 return; |
1378 } | 1404 } |
1379 | 1405 |
1380 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); | 1406 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); |
1381 if (buffer) { | 1407 if (buffer) |
1382 // Free buffer memory, pending the passage of a token. | 1408 RemoveTransferBuffer(buffer); |
1383 buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); | |
1384 | |
1385 // Remove old buffer. | |
1386 buffer_tracker_->RemoveBuffer(buffer_id); | |
1387 } | |
1388 | 1409 |
1389 // Create new buffer. | 1410 // Create new buffer. |
1390 buffer = buffer_tracker_->CreateBuffer(buffer_id, size); | 1411 buffer = buffer_tracker_->CreateBuffer(buffer_id, size); |
1391 DCHECK(buffer); | 1412 DCHECK(buffer); |
1392 if (buffer->address() && data) | 1413 if (buffer->address() && data) |
1393 memcpy(buffer->address(), data, size); | 1414 memcpy(buffer->address(), data, size); |
1394 return; | 1415 return; |
1395 } | 1416 } |
1396 | 1417 |
1397 if (size == 0) { | 1418 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) { | 1526 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { |
1506 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 1527 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
1507 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData(" | 1528 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData(" |
1508 << GLES2Util::GetStringBufferTarget(target) << ", " | 1529 << GLES2Util::GetStringBufferTarget(target) << ", " |
1509 << offset << ", " << size << ", " | 1530 << offset << ", " << size << ", " |
1510 << static_cast<const void*>(data) << ")"); | 1531 << static_cast<const void*>(data) << ")"); |
1511 BufferSubDataHelper(target, offset, size, data); | 1532 BufferSubDataHelper(target, offset, size, data); |
1512 CheckGLError(); | 1533 CheckGLError(); |
1513 } | 1534 } |
1514 | 1535 |
1536 void GLES2Implementation::RemoveTransferBuffer(BufferTracker::Buffer* buffer) { | |
1537 int32 token = buffer->last_usage_token(); | |
1538 uint32 async_token = buffer->last_async_upload_token(); | |
1539 | |
1540 base::subtle::MemoryBarrier(); | |
piman
2014/02/20 01:52:37
Because the necessary memory barrier is handled in
| |
1541 | |
1542 if (async_token) { | |
1543 if (HasAsyncUploadTokenPassed(async_token)) { | |
1544 buffer_tracker_->Free(buffer); | |
1545 } else { | |
1546 detached_async_upload_memory_.push_back( | |
1547 std::make_pair(buffer->address(), async_token)); | |
1548 buffer_tracker_->Unmanage(buffer); | |
1549 } | |
1550 } else if (token) { | |
1551 if (helper_->HasTokenPassed(token)) | |
1552 buffer_tracker_->Free(buffer); | |
1553 else | |
1554 buffer_tracker_->FreePendingToken(buffer, token); | |
1555 } else { | |
1556 buffer_tracker_->Free(buffer); | |
1557 } | |
1558 | |
1559 buffer_tracker_->RemoveBuffer(buffer->id()); | |
1560 } | |
1561 | |
1515 bool GLES2Implementation::GetBoundPixelTransferBuffer( | 1562 bool GLES2Implementation::GetBoundPixelTransferBuffer( |
1516 GLenum target, | 1563 GLenum target, |
1517 const char* function_name, | 1564 const char* function_name, |
1518 GLuint* buffer_id) { | 1565 GLuint* buffer_id) { |
1519 *buffer_id = 0; | 1566 *buffer_id = 0; |
1520 | 1567 |
1521 switch (target) { | 1568 switch (target) { |
1522 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: | 1569 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: |
1523 *buffer_id = bound_pixel_pack_transfer_buffer_id_; | 1570 *buffer_id = bound_pixel_pack_transfer_buffer_id_; |
1524 break; | 1571 break; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1580 // CompressedTexImage2D. | 1627 // CompressedTexImage2D. |
1581 if (bound_pixel_unpack_transfer_buffer_id_) { | 1628 if (bound_pixel_unpack_transfer_buffer_id_) { |
1582 GLuint offset = ToGLuint(data); | 1629 GLuint offset = ToGLuint(data); |
1583 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 1630 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
1584 bound_pixel_unpack_transfer_buffer_id_, | 1631 bound_pixel_unpack_transfer_buffer_id_, |
1585 "glCompressedTexImage2D", offset, image_size); | 1632 "glCompressedTexImage2D", offset, image_size); |
1586 if (buffer && buffer->shm_id() != -1) { | 1633 if (buffer && buffer->shm_id() != -1) { |
1587 helper_->CompressedTexImage2D( | 1634 helper_->CompressedTexImage2D( |
1588 target, level, internalformat, width, height, border, image_size, | 1635 target, level, internalformat, width, height, border, image_size, |
1589 buffer->shm_id(), buffer->shm_offset() + offset); | 1636 buffer->shm_id(), buffer->shm_offset() + offset); |
1590 buffer->set_transfer_ready_token(helper_->InsertToken()); | 1637 buffer->set_last_usage_token(helper_->InsertToken()); |
1591 } | 1638 } |
1592 return; | 1639 return; |
1593 } | 1640 } |
1594 SetBucketContents(kResultBucketId, data, image_size); | 1641 SetBucketContents(kResultBucketId, data, image_size); |
1595 helper_->CompressedTexImage2DBucket( | 1642 helper_->CompressedTexImage2DBucket( |
1596 target, level, internalformat, width, height, border, kResultBucketId); | 1643 target, level, internalformat, width, height, border, kResultBucketId); |
1597 // Free the bucket. This is not required but it does free up the memory. | 1644 // 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 | 1645 // and we don't have to wait for the result so from the client's perspective |
1599 // it's cheap. | 1646 // it's cheap. |
1600 helper_->SetBucketSize(kResultBucketId, 0); | 1647 helper_->SetBucketSize(kResultBucketId, 0); |
(...skipping 20 matching lines...) Expand all Loading... | |
1621 // CompressedTexSubImage2D. | 1668 // CompressedTexSubImage2D. |
1622 if (bound_pixel_unpack_transfer_buffer_id_) { | 1669 if (bound_pixel_unpack_transfer_buffer_id_) { |
1623 GLuint offset = ToGLuint(data); | 1670 GLuint offset = ToGLuint(data); |
1624 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 1671 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
1625 bound_pixel_unpack_transfer_buffer_id_, | 1672 bound_pixel_unpack_transfer_buffer_id_, |
1626 "glCompressedTexSubImage2D", offset, image_size); | 1673 "glCompressedTexSubImage2D", offset, image_size); |
1627 if (buffer && buffer->shm_id() != -1) { | 1674 if (buffer && buffer->shm_id() != -1) { |
1628 helper_->CompressedTexSubImage2D( | 1675 helper_->CompressedTexSubImage2D( |
1629 target, level, xoffset, yoffset, width, height, format, image_size, | 1676 target, level, xoffset, yoffset, width, height, format, image_size, |
1630 buffer->shm_id(), buffer->shm_offset() + offset); | 1677 buffer->shm_id(), buffer->shm_offset() + offset); |
1631 buffer->set_transfer_ready_token(helper_->InsertToken()); | 1678 buffer->set_last_usage_token(helper_->InsertToken()); |
1632 CheckGLError(); | 1679 CheckGLError(); |
1633 } | 1680 } |
1634 return; | 1681 return; |
1635 } | 1682 } |
1636 SetBucketContents(kResultBucketId, data, image_size); | 1683 SetBucketContents(kResultBucketId, data, image_size); |
1637 helper_->CompressedTexSubImage2DBucket( | 1684 helper_->CompressedTexSubImage2DBucket( |
1638 target, level, xoffset, yoffset, width, height, format, kResultBucketId); | 1685 target, level, xoffset, yoffset, width, height, format, kResultBucketId); |
1639 // Free the bucket. This is not required but it does free up the memory. | 1686 // 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 | 1687 // and we don't have to wait for the result so from the client's perspective |
1641 // it's cheap. | 1688 // 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. | 1755 // If there's a pixel unpack buffer bound use it when issuing TexImage2D. |
1709 if (bound_pixel_unpack_transfer_buffer_id_) { | 1756 if (bound_pixel_unpack_transfer_buffer_id_) { |
1710 GLuint offset = ToGLuint(pixels); | 1757 GLuint offset = ToGLuint(pixels); |
1711 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 1758 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
1712 bound_pixel_unpack_transfer_buffer_id_, | 1759 bound_pixel_unpack_transfer_buffer_id_, |
1713 "glTexImage2D", offset, size); | 1760 "glTexImage2D", offset, size); |
1714 if (buffer && buffer->shm_id() != -1) { | 1761 if (buffer && buffer->shm_id() != -1) { |
1715 helper_->TexImage2D( | 1762 helper_->TexImage2D( |
1716 target, level, internalformat, width, height, border, format, type, | 1763 target, level, internalformat, width, height, border, format, type, |
1717 buffer->shm_id(), buffer->shm_offset() + offset); | 1764 buffer->shm_id(), buffer->shm_offset() + offset); |
1718 buffer->set_transfer_ready_token(helper_->InsertToken()); | 1765 buffer->set_last_usage_token(helper_->InsertToken()); |
1719 CheckGLError(); | 1766 CheckGLError(); |
1720 } | 1767 } |
1721 return; | 1768 return; |
1722 } | 1769 } |
1723 | 1770 |
1724 // If there's no data just issue TexImage2D | 1771 // If there's no data just issue TexImage2D |
1725 if (!pixels) { | 1772 if (!pixels) { |
1726 helper_->TexImage2D( | 1773 helper_->TexImage2D( |
1727 target, level, internalformat, width, height, border, format, type, | 1774 target, level, internalformat, width, height, border, format, type, |
1728 0, 0); | 1775 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. | 1861 // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D. |
1815 if (bound_pixel_unpack_transfer_buffer_id_) { | 1862 if (bound_pixel_unpack_transfer_buffer_id_) { |
1816 GLuint offset = ToGLuint(pixels); | 1863 GLuint offset = ToGLuint(pixels); |
1817 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 1864 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
1818 bound_pixel_unpack_transfer_buffer_id_, | 1865 bound_pixel_unpack_transfer_buffer_id_, |
1819 "glTexSubImage2D", offset, temp_size); | 1866 "glTexSubImage2D", offset, temp_size); |
1820 if (buffer && buffer->shm_id() != -1) { | 1867 if (buffer && buffer->shm_id() != -1) { |
1821 helper_->TexSubImage2D( | 1868 helper_->TexSubImage2D( |
1822 target, level, xoffset, yoffset, width, height, format, type, | 1869 target, level, xoffset, yoffset, width, height, format, type, |
1823 buffer->shm_id(), buffer->shm_offset() + offset, false); | 1870 buffer->shm_id(), buffer->shm_offset() + offset, false); |
1824 buffer->set_transfer_ready_token(helper_->InsertToken()); | 1871 buffer->set_last_usage_token(helper_->InsertToken()); |
1825 CheckGLError(); | 1872 CheckGLError(); |
1826 } | 1873 } |
1827 return; | 1874 return; |
1828 } | 1875 } |
1829 | 1876 |
1830 // compute the advance bytes per row for the src pixels | 1877 // compute the advance bytes per row for the src pixels |
1831 uint32 src_padded_row_size; | 1878 uint32 src_padded_row_size; |
1832 if (unpack_row_length_ > 0) { | 1879 if (unpack_row_length_ > 0) { |
1833 if (!GLES2Util::ComputeImagePaddedRowSize( | 1880 if (!GLES2Util::ComputeImagePaddedRowSize( |
1834 unpack_row_length_, format, type, unpack_alignment_, | 1881 unpack_row_length_, format, type, unpack_alignment_, |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2397 } | 2444 } |
2398 | 2445 |
2399 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id | 2446 // 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 | 2447 // 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 | 2448 // 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 | 2449 // 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 | 2450 // the old model but possibly not true in the new model if another context has |
2404 // deleted the resource. | 2451 // deleted the resource. |
2405 | 2452 |
2406 bool GLES2Implementation::BindBufferHelper( | 2453 bool GLES2Implementation::BindBufferHelper( |
2407 GLenum target, GLuint buffer) { | 2454 GLenum target, GLuint buffer_id) { |
2408 // TODO(gman): See note #1 above. | 2455 // TODO(gman): See note #1 above. |
2409 bool changed = false; | 2456 bool changed = false; |
2410 switch (target) { | 2457 switch (target) { |
2411 case GL_ARRAY_BUFFER: | 2458 case GL_ARRAY_BUFFER: |
2412 if (bound_array_buffer_id_ != buffer) { | 2459 if (bound_array_buffer_id_ != buffer_id) { |
2413 bound_array_buffer_id_ = buffer; | 2460 bound_array_buffer_id_ = buffer_id; |
2414 changed = true; | 2461 changed = true; |
2415 } | 2462 } |
2416 break; | 2463 break; |
2417 case GL_ELEMENT_ARRAY_BUFFER: | 2464 case GL_ELEMENT_ARRAY_BUFFER: |
2418 changed = vertex_array_object_manager_->BindElementArray(buffer); | 2465 changed = vertex_array_object_manager_->BindElementArray(buffer_id); |
2419 break; | 2466 break; |
2420 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: | 2467 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: |
2421 bound_pixel_pack_transfer_buffer_id_ = buffer; | 2468 bound_pixel_pack_transfer_buffer_id_ = buffer_id; |
2422 break; | 2469 break; |
2423 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: | 2470 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: |
2424 bound_pixel_unpack_transfer_buffer_id_ = buffer; | 2471 bound_pixel_unpack_transfer_buffer_id_ = buffer_id; |
2425 break; | 2472 break; |
2426 default: | 2473 default: |
2427 changed = true; | 2474 changed = true; |
2428 break; | 2475 break; |
2429 } | 2476 } |
2430 // TODO(gman): There's a bug here. If the target is invalid the ID will not be | 2477 // 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. | 2478 // used even though it's marked it as used here. |
2432 GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer); | 2479 GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer_id); |
2433 return changed; | 2480 return changed; |
2434 } | 2481 } |
2435 | 2482 |
2436 bool GLES2Implementation::BindFramebufferHelper( | 2483 bool GLES2Implementation::BindFramebufferHelper( |
2437 GLenum target, GLuint framebuffer) { | 2484 GLenum target, GLuint framebuffer) { |
2438 // TODO(gman): See note #1 above. | 2485 // TODO(gman): See note #1 above. |
2439 bool changed = false; | 2486 bool changed = false; |
2440 switch (target) { | 2487 switch (target) { |
2441 case GL_FRAMEBUFFER: | 2488 case GL_FRAMEBUFFER: |
2442 if (bound_framebuffer_ != framebuffer || | 2489 if (bound_framebuffer_ != framebuffer || |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2556 SetGLError( | 2603 SetGLError( |
2557 GL_INVALID_VALUE, | 2604 GL_INVALID_VALUE, |
2558 "glDeleteBuffers", "id not created by this context."); | 2605 "glDeleteBuffers", "id not created by this context."); |
2559 return; | 2606 return; |
2560 } | 2607 } |
2561 for (GLsizei ii = 0; ii < n; ++ii) { | 2608 for (GLsizei ii = 0; ii < n; ++ii) { |
2562 if (buffers[ii] == bound_array_buffer_id_) { | 2609 if (buffers[ii] == bound_array_buffer_id_) { |
2563 bound_array_buffer_id_ = 0; | 2610 bound_array_buffer_id_ = 0; |
2564 } | 2611 } |
2565 vertex_array_object_manager_->UnbindBuffer(buffers[ii]); | 2612 vertex_array_object_manager_->UnbindBuffer(buffers[ii]); |
2613 | |
2566 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]); | 2614 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]); |
2567 if (buffer) { | 2615 if (buffer) |
2568 // Free buffer memory, pending the passage of a token. | 2616 RemoveTransferBuffer(buffer); |
2569 buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); | 2617 |
2570 // Remove buffer. | |
2571 buffer_tracker_->RemoveBuffer(buffers[ii]); | |
2572 } | |
2573 if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) { | 2618 if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) { |
2574 bound_pixel_unpack_transfer_buffer_id_ = 0; | 2619 bound_pixel_unpack_transfer_buffer_id_ = 0; |
2575 } | 2620 } |
2576 } | 2621 } |
2577 } | 2622 } |
2578 | 2623 |
2579 void GLES2Implementation::DeleteBuffersStub( | 2624 void GLES2Implementation::DeleteBuffersStub( |
2580 GLsizei n, const GLuint* buffers) { | 2625 GLsizei n, const GLuint* buffers) { |
2581 helper_->DeleteBuffersImmediate(n, buffers); | 2626 helper_->DeleteBuffersImmediate(n, buffers); |
2582 } | 2627 } |
(...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3584 } | 3629 } |
3585 if (buffer->mapped()) { | 3630 if (buffer->mapped()) { |
3586 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped"); | 3631 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped"); |
3587 return NULL; | 3632 return NULL; |
3588 } | 3633 } |
3589 // Here we wait for previous transfer operations to be finished. | 3634 // Here we wait for previous transfer operations to be finished. |
3590 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work | 3635 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work |
3591 // with this method of synchronization. Until this is fixed, | 3636 // with this method of synchronization. Until this is fixed, |
3592 // MapBufferCHROMIUM will not block even if the transfer is not ready | 3637 // MapBufferCHROMIUM will not block even if the transfer is not ready |
3593 // for these calls. | 3638 // for these calls. |
3594 if (buffer->transfer_ready_token()) { | 3639 if (buffer->last_usage_token()) { |
3595 helper_->WaitForToken(buffer->transfer_ready_token()); | 3640 helper_->WaitForToken(buffer->last_usage_token()); |
3596 buffer->set_transfer_ready_token(0); | 3641 buffer->set_last_usage_token(0); |
3597 } | 3642 } |
3598 buffer->set_mapped(true); | 3643 buffer->set_mapped(true); |
3599 | 3644 |
3600 GPU_CLIENT_LOG(" returned " << buffer->address()); | 3645 GPU_CLIENT_LOG(" returned " << buffer->address()); |
3601 CheckGLError(); | 3646 CheckGLError(); |
3602 return buffer->address(); | 3647 return buffer->address(); |
3603 } | 3648 } |
3604 | 3649 |
3605 GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) { | 3650 GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) { |
3606 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 3651 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
(...skipping 13 matching lines...) Expand all Loading... | |
3620 } | 3665 } |
3621 if (!buffer->mapped()) { | 3666 if (!buffer->mapped()) { |
3622 SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped"); | 3667 SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped"); |
3623 return false; | 3668 return false; |
3624 } | 3669 } |
3625 buffer->set_mapped(false); | 3670 buffer->set_mapped(false); |
3626 CheckGLError(); | 3671 CheckGLError(); |
3627 return true; | 3672 return true; |
3628 } | 3673 } |
3629 | 3674 |
3675 bool GLES2Implementation::EnsureAsyncUploadSync() { | |
3676 if (async_upload_sync_) | |
3677 return true; | |
3678 | |
3679 int32 shm_id; | |
3680 unsigned int shm_offset; | |
3681 void* mem = mapped_memory_->Alloc(sizeof(AsyncUploadSync), | |
3682 &shm_id, | |
3683 &shm_offset); | |
3684 if (!mem) | |
3685 return false; | |
3686 | |
3687 async_upload_sync_shm_id_ = shm_id; | |
3688 async_upload_sync_shm_offset_ = shm_offset; | |
3689 async_upload_sync_ = static_cast<AsyncUploadSync*>(mem); | |
3690 async_upload_sync_->Reset(); | |
3691 | |
3692 return true; | |
3693 } | |
3694 | |
3695 uint32 GLES2Implementation::NextAsyncUploadToken() { | |
3696 async_upload_token_++; | |
3697 if (async_upload_token_ == 0) | |
3698 async_upload_token_++; | |
3699 return async_upload_token_; | |
3700 } | |
3701 | |
3702 void GLES2Implementation::PollAsyncUploads() { | |
3703 if (!async_upload_sync_) | |
3704 return; | |
3705 | |
3706 if (helper_->IsContextLost()) { | |
3707 DetachedAsyncUploadMemoryList::iterator it = | |
3708 detached_async_upload_memory_.begin(); | |
3709 while (it != detached_async_upload_memory_.end()) { | |
3710 mapped_memory_->Free(it->first); | |
3711 it = detached_async_upload_memory_.erase(it); | |
3712 } | |
3713 return; | |
3714 } | |
3715 | |
3716 DetachedAsyncUploadMemoryList::iterator it = | |
3717 detached_async_upload_memory_.begin(); | |
3718 while (it != detached_async_upload_memory_.end()) { | |
3719 if (HasAsyncUploadTokenPassed(it->second)) { | |
3720 mapped_memory_->Free(it->first); | |
3721 it = detached_async_upload_memory_.erase(it); | |
3722 } else { | |
3723 break; | |
3724 } | |
3725 } | |
3726 } | |
3727 | |
3630 void GLES2Implementation::AsyncTexImage2DCHROMIUM( | 3728 void GLES2Implementation::AsyncTexImage2DCHROMIUM( |
3631 GLenum target, GLint level, GLint internalformat, GLsizei width, | 3729 GLenum target, GLint level, GLint internalformat, GLsizei width, |
3632 GLsizei height, GLint border, GLenum format, GLenum type, | 3730 GLsizei height, GLint border, GLenum format, GLenum type, |
3633 const void* pixels) { | 3731 const void* pixels) { |
3634 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 3732 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
3635 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D(" | 3733 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D(" |
3636 << GLES2Util::GetStringTextureTarget(target) << ", " | 3734 << GLES2Util::GetStringTextureTarget(target) << ", " |
3637 << level << ", " | 3735 << level << ", " |
3638 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " | 3736 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " |
3639 << width << ", " << height << ", " << border << ", " | 3737 << width << ", " << height << ", " << border << ", " |
(...skipping 11 matching lines...) Expand all Loading... | |
3651 width, height, format, type, unpack_alignment_, &size, | 3749 width, height, format, type, unpack_alignment_, &size, |
3652 &unpadded_row_size, &padded_row_size)) { | 3750 &unpadded_row_size, &padded_row_size)) { |
3653 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large"); | 3751 SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large"); |
3654 return; | 3752 return; |
3655 } | 3753 } |
3656 | 3754 |
3657 // If there's no data/buffer just issue the AsyncTexImage2D | 3755 // If there's no data/buffer just issue the AsyncTexImage2D |
3658 if (!pixels && !bound_pixel_unpack_transfer_buffer_id_) { | 3756 if (!pixels && !bound_pixel_unpack_transfer_buffer_id_) { |
3659 helper_->AsyncTexImage2DCHROMIUM( | 3757 helper_->AsyncTexImage2DCHROMIUM( |
3660 target, level, internalformat, width, height, border, format, type, | 3758 target, level, internalformat, width, height, border, format, type, |
3661 0, 0); | 3759 0, 0, 0, 0, 0); |
3662 return; | 3760 return; |
3663 } | 3761 } |
3664 | 3762 |
3763 if (!EnsureAsyncUploadSync()) { | |
3764 SetGLError(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory"); | |
3765 return; | |
3766 } | |
3767 | |
3665 // Otherwise, async uploads require a transfer buffer to be bound. | 3768 // Otherwise, async uploads require a transfer buffer to be bound. |
3666 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use | 3769 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use |
3667 // the buffer before the transfer is finished. (Currently such | 3770 // the buffer before the transfer is finished. (Currently such |
3668 // synchronization has to be handled manually.) | 3771 // synchronization has to be handled manually.) |
3669 GLuint offset = ToGLuint(pixels); | 3772 GLuint offset = ToGLuint(pixels); |
3670 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 3773 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
3671 bound_pixel_unpack_transfer_buffer_id_, | 3774 bound_pixel_unpack_transfer_buffer_id_, |
3672 "glAsyncTexImage2DCHROMIUM", offset, size); | 3775 "glAsyncTexImage2DCHROMIUM", offset, size); |
3673 if (buffer && buffer->shm_id() != -1) { | 3776 if (buffer && buffer->shm_id() != -1) { |
3777 uint32 async_token = NextAsyncUploadToken(); | |
3778 buffer->set_last_async_upload_token(async_token); | |
3674 helper_->AsyncTexImage2DCHROMIUM( | 3779 helper_->AsyncTexImage2DCHROMIUM( |
3675 target, level, internalformat, width, height, border, format, type, | 3780 target, level, internalformat, width, height, border, format, type, |
3676 buffer->shm_id(), buffer->shm_offset() + offset); | 3781 buffer->shm_id(), buffer->shm_offset() + offset, |
3782 async_token, | |
3783 async_upload_sync_shm_id_, async_upload_sync_shm_offset_); | |
3677 } | 3784 } |
3678 } | 3785 } |
3679 | 3786 |
3680 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM( | 3787 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM( |
3681 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, | 3788 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, |
3682 GLsizei height, GLenum format, GLenum type, const void* pixels) { | 3789 GLsizei height, GLenum format, GLenum type, const void* pixels) { |
3683 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 3790 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
3684 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM(" | 3791 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM(" |
3685 << GLES2Util::GetStringTextureTarget(target) << ", " | 3792 << GLES2Util::GetStringTextureTarget(target) << ", " |
3686 << level << ", " | 3793 << level << ", " |
(...skipping 12 matching lines...) Expand all Loading... | |
3699 uint32 unpadded_row_size; | 3806 uint32 unpadded_row_size; |
3700 uint32 padded_row_size; | 3807 uint32 padded_row_size; |
3701 if (!GLES2Util::ComputeImageDataSizes( | 3808 if (!GLES2Util::ComputeImageDataSizes( |
3702 width, height, format, type, unpack_alignment_, &size, | 3809 width, height, format, type, unpack_alignment_, &size, |
3703 &unpadded_row_size, &padded_row_size)) { | 3810 &unpadded_row_size, &padded_row_size)) { |
3704 SetGLError( | 3811 SetGLError( |
3705 GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "size to large"); | 3812 GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "size to large"); |
3706 return; | 3813 return; |
3707 } | 3814 } |
3708 | 3815 |
3816 if (!EnsureAsyncUploadSync()) { | |
3817 SetGLError(GL_OUT_OF_MEMORY, "glTexImage2D", "out of memory"); | |
3818 return; | |
3819 } | |
3820 | |
3709 // Async uploads require a transfer buffer to be bound. | 3821 // Async uploads require a transfer buffer to be bound. |
3710 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use | 3822 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use |
3711 // the buffer before the transfer is finished. (Currently such | 3823 // the buffer before the transfer is finished. (Currently such |
3712 // synchronization has to be handled manually.) | 3824 // synchronization has to be handled manually.) |
3713 GLuint offset = ToGLuint(pixels); | 3825 GLuint offset = ToGLuint(pixels); |
3714 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 3826 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
3715 bound_pixel_unpack_transfer_buffer_id_, | 3827 bound_pixel_unpack_transfer_buffer_id_, |
3716 "glAsyncTexSubImage2DCHROMIUM", offset, size); | 3828 "glAsyncTexSubImage2DCHROMIUM", offset, size); |
3717 if (buffer && buffer->shm_id() != -1) { | 3829 if (buffer && buffer->shm_id() != -1) { |
3830 uint32 async_token = NextAsyncUploadToken(); | |
3831 buffer->set_last_async_upload_token(async_token); | |
3718 helper_->AsyncTexSubImage2DCHROMIUM( | 3832 helper_->AsyncTexSubImage2DCHROMIUM( |
3719 target, level, xoffset, yoffset, width, height, format, type, | 3833 target, level, xoffset, yoffset, width, height, format, type, |
3720 buffer->shm_id(), buffer->shm_offset() + offset); | 3834 buffer->shm_id(), buffer->shm_offset() + offset, |
3835 async_token, | |
3836 async_upload_sync_shm_id_, async_upload_sync_shm_offset_); | |
3721 } | 3837 } |
3722 } | 3838 } |
3723 | 3839 |
3724 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) { | 3840 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) { |
3725 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 3841 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
3726 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM(" | 3842 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM(" |
3727 << GLES2Util::GetStringTextureTarget(target) << ")"); | 3843 << GLES2Util::GetStringTextureTarget(target) << ")"); |
3728 helper_->WaitAsyncTexImage2DCHROMIUM(target); | 3844 helper_->WaitAsyncTexImage2DCHROMIUM(target); |
3729 CheckGLError(); | 3845 CheckGLError(); |
3730 } | 3846 } |
3731 | 3847 |
3848 void GLES2Implementation::WaitAllAsyncTexImage2DCHROMIUM() { | |
3849 GPU_CLIENT_SINGLE_THREAD_CHECK(); | |
3850 GPU_CLIENT_LOG("[" << GetLogPrefix() | |
3851 << "] glWaitAllAsyncTexImage2DCHROMIUM()"); | |
3852 helper_->WaitAllAsyncTexImage2DCHROMIUM(); | |
3853 CheckGLError(); | |
3854 } | |
3855 | |
3732 GLuint GLES2Implementation::InsertSyncPointCHROMIUM() { | 3856 GLuint GLES2Implementation::InsertSyncPointCHROMIUM() { |
3733 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 3857 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
3734 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM"); | 3858 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glInsertSyncPointCHROMIUM"); |
3735 helper_->CommandBufferHelper::Flush(); | 3859 helper_->CommandBufferHelper::Flush(); |
3736 return gpu_control_->InsertSyncPoint(); | 3860 return gpu_control_->InsertSyncPoint(); |
3737 } | 3861 } |
3738 | 3862 |
3739 GLuint GLES2Implementation::CreateImageCHROMIUMHelper( | 3863 GLuint GLES2Implementation::CreateImageCHROMIUMHelper( |
3740 GLsizei width, GLsizei height, GLenum internalformat) { | 3864 GLsizei width, GLsizei height, GLenum internalformat) { |
3741 if (width <= 0) { | 3865 if (width <= 0) { |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3897 CheckGLError(); | 4021 CheckGLError(); |
3898 } | 4022 } |
3899 | 4023 |
3900 // Include the auto-generated part of this file. We split this because it means | 4024 // 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 | 4025 // 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. | 4026 // instead of having to edit some template or the code generator. |
3903 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" | 4027 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" |
3904 | 4028 |
3905 } // namespace gles2 | 4029 } // namespace gles2 |
3906 } // namespace gpu | 4030 } // namespace gpu |
OLD | NEW |