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

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

Issue 706173005: Enable asynchronous glReadPixels on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add mechanism to propagate service-side glMapBuffer errors + tests. Created 6 years, 1 month 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 <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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698