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

Unified Diff: gpu/command_buffer/client/gles2_implementation.cc

Issue 12892005: Implement client side PBOs for glReadPixel (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: make GLHelper constructor explicit Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/client/gles2_implementation.cc
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 958882357c95e3da3a836f52d202451a6aff6137..fda36b594f93a8fe9658ad1b02f48c8f1201527d 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -96,6 +96,7 @@ GLES2Implementation::GLES2Implementation(
bound_renderbuffer_(0),
current_program_(0),
bound_array_buffer_id_(0),
+ bound_pixel_pack_transfer_buffer_id_(0),
bound_pixel_unpack_transfer_buffer_id_(0),
error_bits_(0),
debug_(false),
@@ -589,6 +590,9 @@ bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) {
return true;
}
return false;
+ case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM:
+ *params = bound_pixel_pack_transfer_buffer_id_;
+ return true;
case GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM:
*params = bound_pixel_unpack_transfer_buffer_id_;
return true;
@@ -1248,10 +1252,9 @@ void GLES2Implementation::BufferDataHelper(
return;
}
- if (target == GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM) {
- GLuint buffer_id = bound_pixel_unpack_transfer_buffer_id_;
+ GLuint buffer_id;
+ if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) {
if (!buffer_id) {
- SetGLError(GL_INVALID_VALUE, "glBufferData", "unknown buffer");
return;
}
@@ -1328,9 +1331,12 @@ void GLES2Implementation::BufferSubDataHelper(
return;
}
- if (target == GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM) {
- BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(
- bound_pixel_unpack_transfer_buffer_id_);
+ GLuint buffer_id;
+ if (GetBoundPixelTransferBuffer(target, "glBufferSubData", &buffer_id)) {
+ if (!buffer_id) {
+ return;
+ }
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
if (!buffer) {
SetGLError(GL_INVALID_VALUE, "glBufferSubData", "unknown buffer");
return;
@@ -1387,12 +1393,37 @@ void GLES2Implementation::BufferSubData(
CheckGLError();
}
+bool GLES2Implementation::GetBoundPixelTransferBuffer(
+ GLenum target,
+ const char* function_name,
+ GLuint* buffer_id) {
+ *buffer_id = 0;
+
+ switch (target) {
+ case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
+ *buffer_id = bound_pixel_pack_transfer_buffer_id_;
+ break;
+ case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
+ *buffer_id = bound_pixel_unpack_transfer_buffer_id_;
+ break;
+ default:
+ // Unknown target
+ return false;
+ }
+ if (!*buffer_id) {
+ SetGLError(GL_INVALID_OPERATION, function_name, "no buffer bound");
+ }
+ return true;
+}
+
BufferTracker::Buffer*
GLES2Implementation::GetBoundPixelUnpackTransferBufferIfValid(
- const char* function_name, GLuint offset, GLsizei size)
+ GLuint buffer_id,
+ const char* function_name,
+ GLuint offset, GLsizei size)
{
- BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(
- bound_pixel_unpack_transfer_buffer_id_);
+ DCHECK(buffer_id);
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
if (!buffer) {
SetGLError(GL_INVALID_OPERATION, function_name, "invalid buffer");
return NULL;
@@ -1431,11 +1462,14 @@ void GLES2Implementation::CompressedTexImage2D(
if (bound_pixel_unpack_transfer_buffer_id_) {
GLuint offset = ToGLuint(data);
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_unpack_transfer_buffer_id_,
"glCompressedTexImage2D", offset, image_size);
- if (buffer)
+ if (buffer) {
helper_->CompressedTexImage2D(
target, level, internalformat, width, height, border, image_size,
buffer->shm_id(), buffer->shm_offset() + offset);
+ buffer->set_transfer_ready_token(helper_->InsertToken());
+ }
return;
}
SetBucketContents(kResultBucketId, data, image_size);
@@ -1469,11 +1503,15 @@ void GLES2Implementation::CompressedTexSubImage2D(
if (bound_pixel_unpack_transfer_buffer_id_) {
GLuint offset = ToGLuint(data);
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_unpack_transfer_buffer_id_,
"glCompressedTexSubImage2D", offset, image_size);
- if (buffer)
+ if (buffer) {
helper_->CompressedTexSubImage2D(
target, level, xoffset, yoffset, width, height, format, image_size,
buffer->shm_id(), buffer->shm_offset() + offset);
+ buffer->set_transfer_ready_token(helper_->InsertToken());
+ CheckGLError();
+ }
return;
}
SetBucketContents(kResultBucketId, data, image_size);
@@ -1552,12 +1590,15 @@ void GLES2Implementation::TexImage2D(
if (bound_pixel_unpack_transfer_buffer_id_) {
GLuint offset = ToGLuint(pixels);
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_unpack_transfer_buffer_id_,
"glTexImage2D", offset, size);
- if (buffer)
+ if (buffer) {
helper_->TexImage2D(
target, level, internalformat, width, height, border, format, type,
buffer->shm_id(), buffer->shm_offset() + offset);
- CheckGLError();
+ buffer->set_transfer_ready_token(helper_->InsertToken());
+ CheckGLError();
+ }
return;
}
@@ -1655,12 +1696,15 @@ void GLES2Implementation::TexSubImage2D(
if (bound_pixel_unpack_transfer_buffer_id_) {
GLuint offset = ToGLuint(pixels);
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_unpack_transfer_buffer_id_,
"glTexSubImage2D", offset, temp_size);
- if (buffer)
+ if (buffer) {
helper_->TexSubImage2D(
target, level, xoffset, yoffset, width, height, format, type,
buffer->shm_id(), buffer->shm_offset() + offset, false);
- CheckGLError();
+ buffer->set_transfer_ready_token(helper_->InsertToken());
+ CheckGLError();
+ }
return;
}
@@ -2113,6 +2157,27 @@ void GLES2Implementation::ReadPixels(
SetGLError(GL_INVALID_VALUE, "glReadPixels", "size too large.");
return;
}
+
+ if (bound_pixel_pack_transfer_buffer_id_) {
+ GLuint offset = ToGLuint(pixels);
+ BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_pack_transfer_buffer_id_,
+ "glReadPixels", offset, temp_size);
+ if (buffer) {
+ helper_->ReadPixels(xoffset, yoffset, width, height, format, type,
+ buffer->shm_id(), buffer->shm_offset(),
+ 0, 0);
+ buffer->set_transfer_ready_token(helper_->InsertToken());
+ CheckGLError();
+ }
+ return;
+ }
+
+ if (!pixels) {
+ SetGLError(GL_INVALID_OPERATION, "glReadPixels", "pixels = NULL");
+ return;
+ }
+
// Transfer by rows.
// The max rows we can transfer.
while (height) {
@@ -2230,6 +2295,9 @@ bool GLES2Implementation::BindBufferHelper(
case GL_ELEMENT_ARRAY_BUFFER:
changed = vertex_array_object_manager_->BindElementArray(buffer);
break;
+ case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
+ bound_pixel_pack_transfer_buffer_id_ = buffer;
+ break;
case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
bound_pixel_unpack_transfer_buffer_id_ = buffer;
break;
@@ -3309,17 +3377,30 @@ void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferCHROMIUM("
<< target << ", " << GLES2Util::GetStringEnum(access) << ")");
- if (target != GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM) {
- SetGLError(
- GL_INVALID_ENUM, "glMapBufferCHROMIUM", "invalid target");
- return NULL;
+ switch (target) {
+ case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
+ if (access != GL_READ_ONLY) {
+ SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode");
+ return NULL;
+ }
+ break;
+ case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
+ if (access != GL_WRITE_ONLY) {
+ SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode");
+ return NULL;
+ }
+ break;
+ default:
+ SetGLError(
+ GL_INVALID_ENUM, "glMapBufferCHROMIUM", "invalid target");
+ return NULL;
}
- if (access != GL_WRITE_ONLY) {
- SetGLError(GL_INVALID_ENUM, "glMapBufferCHROMIUM", "bad access mode");
+ GLuint buffer_id;
+ GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id);
+ if (!buffer_id) {
return NULL;
}
- BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(
- bound_pixel_unpack_transfer_buffer_id_);
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
if (!buffer) {
SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer");
return NULL;
@@ -3328,6 +3409,15 @@ void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) {
SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "already mapped");
return NULL;
}
+ // Here we wait for previous transfer operations to be finished.
+ // TODO(hubbe): AsyncTex(Sub)Image2dCHROMIUM does not currently work
+ // with this method of synchronization. Until this is fixed,
+ // MapBufferCHROMIUM will not block even if the transfer is not ready
+ // for these calls.
+ if (buffer->transfer_ready_token()) {
+ helper_->WaitForToken(buffer->transfer_ready_token());
+ buffer->set_transfer_ready_token(0);
+ }
buffer->set_mapped(true);
GPU_DCHECK(buffer->address());
@@ -3340,12 +3430,14 @@ GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG(
"[" << GetLogPrefix() << "] glUnmapBufferCHROMIUM(" << target << ")");
- if (target != GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM) {
+ GLuint buffer_id;
+ if (!GetBoundPixelTransferBuffer(target, "glMapBufferCHROMIUM", &buffer_id)) {
SetGLError(GL_INVALID_ENUM, "glUnmapBufferCHROMIUM", "invalid target");
+ }
+ if (!buffer_id) {
return false;
}
- BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(
- bound_pixel_unpack_transfer_buffer_id_);
+ BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
if (!buffer) {
SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer");
return false;
@@ -3395,8 +3487,12 @@ void GLES2Implementation::AsyncTexImage2DCHROMIUM(
}
// Otherwise, async uploads require a transfer buffer to be bound.
+ // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
+ // the buffer before the transfer is finished. (Currently such
+ // synchronization has to be handled manually.)
GLuint offset = ToGLuint(pixels);
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_unpack_transfer_buffer_id_,
"glAsyncTexImage2DCHROMIUM", offset, size);
if (!buffer)
return;
@@ -3437,8 +3533,12 @@ void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
}
// Async uploads require a transfer buffer to be bound.
+ // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
+ // the buffer before the transfer is finished. (Currently such
+ // synchronization has to be handled manually.)
GLuint offset = ToGLuint(pixels);
BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_unpack_transfer_buffer_id_,
"glAsyncTexSubImage2DCHROMIUM", offset, size);
if (!buffer)
return;
« no previous file with comments | « gpu/command_buffer/client/gles2_implementation.h ('k') | gpu/command_buffer/client/gles2_implementation_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698