| 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 <GLES2/gl2ext.h> | 9 #include <GLES2/gl2ext.h> |
| 10 #include <GLES2/gl2extchromium.h> | 10 #include <GLES2/gl2extchromium.h> |
| (...skipping 1305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 GLuint buffer_id; | 1316 GLuint buffer_id; |
| 1317 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) { | 1317 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) { |
| 1318 if (!buffer_id) { | 1318 if (!buffer_id) { |
| 1319 return; | 1319 return; |
| 1320 } | 1320 } |
| 1321 | 1321 |
| 1322 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); | 1322 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); |
| 1323 if (buffer) | 1323 if (buffer) |
| 1324 RemoveTransferBuffer(buffer); | 1324 RemoveTransferBuffer(buffer); |
| 1325 | 1325 |
| 1326 // Create new buffer. | 1326 // Create new buffer. For the async readback use case, allocate a few |
| 1327 buffer = buffer_tracker_->CreateBuffer(buffer_id, size); | 1327 // extra bytes to contain any service-side glMapBuffer errors. |
| 1328 const GLsizeiptr metadata_size = |
| 1329 target == GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM ? |
| 1330 sizeof(cmds::ReadPixels::Result) : 0; |
| 1331 buffer = buffer_tracker_->CreateBuffer(buffer_id, size, metadata_size); |
| 1328 DCHECK(buffer); | 1332 DCHECK(buffer); |
| 1329 if (buffer->address() && data) | 1333 if (buffer->address() && data) |
| 1330 memcpy(buffer->address(), data, size); | 1334 memcpy(buffer->address(), data, size); |
| 1331 return; | 1335 return; |
| 1332 } | 1336 } |
| 1333 | 1337 |
| 1334 if (size == 0) { | 1338 if (size == 0) { |
| 1335 return; | 1339 return; |
| 1336 } | 1340 } |
| 1337 | 1341 |
| (...skipping 904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2242 uint32 temp_size; | 2246 uint32 temp_size; |
| 2243 uint32 unpadded_row_size; | 2247 uint32 unpadded_row_size; |
| 2244 uint32 padded_row_size; | 2248 uint32 padded_row_size; |
| 2245 if (!GLES2Util::ComputeImageDataSizes( | 2249 if (!GLES2Util::ComputeImageDataSizes( |
| 2246 width, 2, format, type, pack_alignment_, &temp_size, &unpadded_row_size, | 2250 width, 2, format, type, pack_alignment_, &temp_size, &unpadded_row_size, |
| 2247 &padded_row_size)) { | 2251 &padded_row_size)) { |
| 2248 SetGLError(GL_INVALID_VALUE, "glReadPixels", "size too large."); | 2252 SetGLError(GL_INVALID_VALUE, "glReadPixels", "size too large."); |
| 2249 return; | 2253 return; |
| 2250 } | 2254 } |
| 2251 | 2255 |
| 2252 if (bound_pixel_pack_transfer_buffer_id_) { | 2256 if (bound_pixel_pack_transfer_buffer_id_) { // Asynchronous readback path. |
| 2253 GLuint offset = ToGLuint(pixels); | 2257 GLuint offset = ToGLuint(pixels); |
| 2254 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( | 2258 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( |
| 2255 bound_pixel_pack_transfer_buffer_id_, | 2259 bound_pixel_pack_transfer_buffer_id_, |
| 2256 "glReadPixels", offset, padded_row_size * height); | 2260 "glReadPixels", offset, padded_row_size * height); |
| 2257 if (buffer && buffer->shm_id() != -1) { | 2261 if (!buffer || buffer->shm_id() == -1) { |
| 2258 helper_->ReadPixels(xoffset, yoffset, width, height, format, type, | 2262 SetGLError(GL_INVALID_OPERATION, "glReadPixels", "invalid buffer."); |
| 2259 buffer->shm_id(), buffer->shm_offset(), | 2263 return; |
| 2260 0, 0, true); | |
| 2261 CheckGLError(); | |
| 2262 } | 2264 } |
| 2265 |
| 2266 DCHECK_EQ(buffer->metadata_size(), sizeof(Result)); |
| 2267 helper_->ReadPixels( |
| 2268 xoffset, yoffset, width, height, format, type, |
| 2269 buffer->shm_id(), buffer->shm_offset(), |
| 2270 buffer->metadata_shm_id(), buffer->metadata_shm_offset(), |
| 2271 true); |
| 2272 CheckGLError(); |
| 2263 return; | 2273 return; |
| 2264 } | 2274 } |
| 2265 | 2275 |
| 2266 if (!pixels) { | 2276 if (!pixels) { |
| 2267 SetGLError(GL_INVALID_OPERATION, "glReadPixels", "pixels = NULL"); | 2277 SetGLError(GL_INVALID_OPERATION, "glReadPixels", "pixels = NULL"); |
| 2268 return; | 2278 return; |
| 2269 } | 2279 } |
| 2270 | 2280 |
| 2271 // Transfer by rows. | 2281 // Transfer by rows. |
| 2272 // The max rows we can transfer. | 2282 // The max rows we can transfer. |
| 2273 while (height) { | 2283 while (height) { |
| 2274 GLsizei desired_size = padded_row_size * height - 1 + unpadded_row_size; | 2284 GLsizei desired_size = padded_row_size * height - 1 + unpadded_row_size; |
| 2275 ScopedTransferBufferPtr buffer(desired_size, helper_, transfer_buffer_); | 2285 ScopedTransferBufferPtr buffer(desired_size, helper_, transfer_buffer_); |
| 2276 if (!buffer.valid()) { | 2286 if (!buffer.valid()) { |
| 2277 return; | 2287 return; |
| 2278 } | 2288 } |
| 2279 GLint num_rows = ComputeNumRowsThatFitInBuffer( | 2289 GLint num_rows = ComputeNumRowsThatFitInBuffer( |
| 2280 padded_row_size, unpadded_row_size, buffer.size()); | 2290 padded_row_size, unpadded_row_size, buffer.size()); |
| 2281 num_rows = std::min(num_rows, height); | 2291 num_rows = std::min(num_rows, height); |
| 2282 // NOTE: We must look up the address of the result area AFTER allocation | 2292 // NOTE: We must look up the address of the result area AFTER allocation |
| 2283 // of the transfer buffer since the transfer buffer may be reallocated. | 2293 // of the transfer buffer since the transfer buffer may be reallocated. |
| 2284 Result* result = GetResultAs<Result*>(); | 2294 Result* result = GetResultAs<Result*>(); |
| 2285 if (!result) { | 2295 if (!result) { |
| 2286 return; | 2296 return; |
| 2287 } | 2297 } |
| 2288 *result = 0; // mark as failed. | |
| 2289 helper_->ReadPixels( | 2298 helper_->ReadPixels( |
| 2290 xoffset, yoffset, width, num_rows, format, type, | 2299 xoffset, yoffset, width, num_rows, format, type, |
| 2291 buffer.shm_id(), buffer.offset(), | 2300 buffer.shm_id(), buffer.offset(), |
| 2292 GetResultShmId(), GetResultShmOffset(), | 2301 GetResultShmId(), GetResultShmOffset(), |
| 2293 false); | 2302 false); |
| 2294 WaitForCmd(); | 2303 WaitForCmd(); |
| 2295 if (*result != 0) { | 2304 if (*result != GL_NO_ERROR) { |
| 2296 // when doing a y-flip we have to iterate through top-to-bottom chunks | 2305 SetGLError(*result, "glReadPixels", "Service-side error."); |
| 2297 // of the dst. The service side handles reversing the rows within a | |
| 2298 // chunk. | |
| 2299 int8* rows_dst; | |
| 2300 if (pack_reverse_row_order_) { | |
| 2301 rows_dst = dest + (height - num_rows) * padded_row_size; | |
| 2302 } else { | |
| 2303 rows_dst = dest; | |
| 2304 } | |
| 2305 // We have to copy 1 row at a time to avoid writing pad bytes. | |
| 2306 const int8* src = static_cast<const int8*>(buffer.address()); | |
| 2307 for (GLint yy = 0; yy < num_rows; ++yy) { | |
| 2308 memcpy(rows_dst, src, unpadded_row_size); | |
| 2309 rows_dst += padded_row_size; | |
| 2310 src += padded_row_size; | |
| 2311 } | |
| 2312 if (!pack_reverse_row_order_) { | |
| 2313 dest = rows_dst; | |
| 2314 } | |
| 2315 } | |
| 2316 // If it was not marked as successful exit. | |
| 2317 if (*result == 0) { | |
| 2318 return; | 2306 return; |
| 2319 } | 2307 } |
| 2308 |
| 2309 // when doing a y-flip we have to iterate through top-to-bottom chunks |
| 2310 // of the dst. The service side handles reversing the rows within a |
| 2311 // chunk. |
| 2312 int8* rows_dst; |
| 2313 if (pack_reverse_row_order_) { |
| 2314 rows_dst = dest + (height - num_rows) * padded_row_size; |
| 2315 } else { |
| 2316 rows_dst = dest; |
| 2317 } |
| 2318 // We have to copy 1 row at a time to avoid writing pad bytes. |
| 2319 const int8* src = static_cast<const int8*>(buffer.address()); |
| 2320 for (GLint yy = 0; yy < num_rows; ++yy) { |
| 2321 memcpy(rows_dst, src, unpadded_row_size); |
| 2322 rows_dst += padded_row_size; |
| 2323 src += padded_row_size; |
| 2324 } |
| 2325 if (!pack_reverse_row_order_) { |
| 2326 dest = rows_dst; |
| 2327 } |
| 2328 |
| 2320 yoffset += num_rows; | 2329 yoffset += num_rows; |
| 2321 height -= num_rows; | 2330 height -= num_rows; |
| 2322 } | 2331 } |
| 2323 CheckGLError(); | 2332 CheckGLError(); |
| 2324 } | 2333 } |
| 2325 | 2334 |
| 2326 void GLES2Implementation::ActiveTexture(GLenum texture) { | 2335 void GLES2Implementation::ActiveTexture(GLenum texture) { |
| 2327 GPU_CLIENT_SINGLE_THREAD_CHECK(); | 2336 GPU_CLIENT_SINGLE_THREAD_CHECK(); |
| 2328 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture(" | 2337 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glActiveTexture(" |
| 2329 << GLES2Util::GetStringEnum(texture) << ")"); | 2338 << GLES2Util::GetStringEnum(texture) << ")"); |
| (...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3669 } | 3678 } |
| 3670 break; | 3679 break; |
| 3671 default: | 3680 default: |
| 3672 SetGLError( | 3681 SetGLError( |
| 3673 GL_INVALID_ENUM, "glMapBufferCHROMIUM", "invalid target"); | 3682 GL_INVALID_ENUM, "glMapBufferCHROMIUM", "invalid target"); |
| 3674 return NULL; | 3683 return NULL; |
| 3675 } | 3684 } |
| 3676 GLuint buffer_id; | 3685 GLuint buffer_id; |
| 3677 GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id); | 3686 GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id); |
| 3678 if (!buffer_id) { | 3687 if (!buffer_id) { |
| 3688 SetGLError(GL_INVALID_VALUE, "glMapBufferCHROMIUM", "invalid buffer"); |
| 3679 return NULL; | 3689 return NULL; |
| 3680 } | 3690 } |
| 3681 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); | 3691 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); |
| 3682 if (!buffer) { | 3692 if (!buffer) { |
| 3683 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer"); | 3693 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer"); |
| 3684 return NULL; | 3694 return NULL; |
| 3685 } | 3695 } |
| 3696 |
| 3697 if (target == GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM) { |
| 3698 DCHECK_EQ(buffer->metadata_size(), sizeof(cmds::ReadPixels::Result)); |
| 3699 const GLenum error = |
| 3700 *(static_cast<cmds::ReadPixels::Result*>(buffer->metadata_address())); |
| 3701 if (error != GL_NO_ERROR) { |
| 3702 SetGLError(error, "glMapBufferCHROMIUM", "service map buffer error"); |
| 3703 return NULL; |
| 3704 } |
| 3705 } |
| 3706 |
| 3686 if (buffer->mapped()) { | 3707 if (buffer->mapped()) { |
| 3687 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped"); | 3708 SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped"); |
| 3688 return NULL; | 3709 return NULL; |
| 3689 } | 3710 } |
| 3690 // Here we wait for previous transfer operations to be finished. | 3711 // Here we wait for previous transfer operations to be finished. |
| 3691 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work | 3712 // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work |
| 3692 // with this method of synchronization. Until this is fixed, | 3713 // with this method of synchronization. Until this is fixed, |
| 3693 // MapBufferCHROMIUM will not block even if the transfer is not ready | 3714 // MapBufferCHROMIUM will not block even if the transfer is not ready |
| 3694 // for these calls. | 3715 // for these calls. |
| 3695 if (buffer->last_usage_token()) { | 3716 if (buffer->last_usage_token()) { |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4117 return true; | 4138 return true; |
| 4118 } | 4139 } |
| 4119 | 4140 |
| 4120 // Include the auto-generated part of this file. We split this because it means | 4141 // Include the auto-generated part of this file. We split this because it means |
| 4121 // we can easily edit the non-auto generated parts right here in this file | 4142 // we can easily edit the non-auto generated parts right here in this file |
| 4122 // instead of having to edit some template or the code generator. | 4143 // instead of having to edit some template or the code generator. |
| 4123 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" | 4144 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" |
| 4124 | 4145 |
| 4125 } // namespace gles2 | 4146 } // namespace gles2 |
| 4126 } // namespace gpu | 4147 } // namespace gpu |
| OLD | NEW |