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

Unified Diff: gpu/command_buffer/service/gles2_cmd_decoder.cc

Issue 16831004: Perform glReadPixels with PBOs in the gpu, if PBOs are available. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: revert gl_in_process_context.cc, deal with out-of-order callbacks in gl_helper.cc Created 7 years, 6 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/service/gles2_cmd_decoder.cc
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index ed54bce9588eb0bb5478f36659982813b13f5155..996940eda1ba2c02802b921810ace50f79271f94 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -59,6 +59,7 @@
#include "gpu/command_buffer/service/vertex_array_manager.h"
#include "gpu/command_buffer/service/vertex_attrib_manager.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
@@ -477,6 +478,19 @@ class BackFramebuffer {
DISALLOW_COPY_AND_ASSIGN(BackFramebuffer);
};
+struct FenceCallback {
+ explicit FenceCallback()
+ : fence(gfx::GLFence::Create()) {
+ DCHECK(fence);
+ }
+ void AddCallback(base::Closure cb) {
+ callbacks.push_back(cb);
+ }
+ std::vector<base::Closure> callbacks;
+ scoped_ptr<gfx::GLFence> fence;
+};
+
+
// } // anonymous namespace.
bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
@@ -587,6 +601,8 @@ class GLES2DecoderImpl : public GLES2Decoder {
virtual bool HasMoreIdleWork() OVERRIDE;
virtual void PerformIdleWork() OVERRIDE;
+ virtual void WaitForReadPixels(base::Closure callback) OVERRIDE;
+
virtual void SetResizeCallback(
const base::Callback<void(gfx::Size, float)>& callback) OVERRIDE;
@@ -1557,6 +1573,9 @@ class GLES2DecoderImpl : public GLES2Decoder {
surface_->DeferDraws();
}
+ void ProcessPendingReadPixels();
+ void FinishReadPixels(const cmds::ReadPixels& c, GLuint buffer);
+
void ForceCompileShaderIfPending(Shader* shader);
// Generate a member function prototype for each command in an automated and
@@ -1725,6 +1744,8 @@ class GLES2DecoderImpl : public GLES2Decoder {
scoped_ptr<GPUTracer> gpu_tracer_;
+ std::queue<linked_ptr<FenceCallback> > pending_readpixel_fences_;
+
DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
};
@@ -2499,6 +2520,7 @@ bool GLES2DecoderImpl::Initialize(
AsyncPixelTransferManager::Create(context.get()));
async_pixel_transfer_manager_->Initialize(texture_manager());
+
piman 2013/07/01 22:24:08 nit: extra blank line unnecessary.
hubbe 2013/07/01 22:34:41 Done.
return true;
}
@@ -2808,6 +2830,7 @@ bool GLES2DecoderImpl::MakeCurrent() {
}
void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
+ ProcessPendingReadPixels();
if (engine() && query_manager_.get())
query_manager_->ProcessPendingTransferQueries();
@@ -3540,6 +3563,7 @@ bool GLES2DecoderImpl::CreateShaderHelper(GLenum type, GLuint client_id) {
void GLES2DecoderImpl::DoFinish() {
glFinish();
+ ProcessPendingReadPixels();
ProcessPendingQueries();
}
@@ -6708,6 +6732,96 @@ error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE(
return error::kNoError;
}
+void GLES2DecoderImpl::FinishReadPixels(
+ const cmds::ReadPixels& c,
+ GLuint buffer) {
+ TRACE_EVENT0("gpu", "GLES2DecoderImpl::FinishReadPixels");
+ GLsizei width = c.width;
+ GLsizei height = c.height;
+ GLenum format = c.format;
+ GLenum type = c.type;
+ typedef cmds::ReadPixels::Result Result;
+ uint32 pixels_size;
+ Result* result = NULL;
+ if (c.result_shm_id != 0) {
+ result = GetSharedMemoryAs<Result*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result));
+ if (!result) {
+ if (buffer != 0) {
+ glDeleteBuffersARB(1, &buffer);
+ }
+ return;
+ }
+ }
+ GLES2Util::ComputeImageDataSizes(
+ width, height, format, type, state_.pack_alignment, &pixels_size,
+ NULL, NULL);
+ void* pixels = GetSharedMemoryAs<void*>(
+ c.pixels_shm_id, c.pixels_shm_offset, pixels_size);
+ if (!pixels) {
+ if (buffer != 0) {
+ glDeleteBuffersARB(1, &buffer);
+ }
+ return;
+ }
+
+ if (buffer != 0) {
+ glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
+ void* data = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
+ memcpy(pixels, data, pixels_size);
+ // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't
+ // have to restore the state.
+ glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ glDeleteBuffersARB(1, &buffer);
+ }
+
+ if (result != NULL) {
+ *result = true;
+ }
+
+ GLenum read_format = GetBoundReadFrameBufferInternalFormat();
+ uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
+ if ((channels_exist & 0x0008) == 0 &&
+ workarounds().clear_alpha_in_readpixels) {
+ // Set the alpha to 255 because some drivers are buggy in this regard.
+ uint32 temp_size;
+
+ uint32 unpadded_row_size;
+ uint32 padded_row_size;
+ if (!GLES2Util::ComputeImageDataSizes(
+ width, 2, format, type, state_.pack_alignment, &temp_size,
+ &unpadded_row_size, &padded_row_size)) {
+ return;
+ }
+ // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
+ // of this implementation.
+ if (type != GL_UNSIGNED_BYTE) {
+ return;
+ }
+ switch (format) {
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ case GL_ALPHA: {
+ int offset = (format == GL_ALPHA) ? 0 : 3;
+ int step = (format == GL_ALPHA) ? 1 : 4;
+ uint8* dst = static_cast<uint8*>(pixels) + offset;
+ for (GLint yy = 0; yy < height; ++yy) {
+ uint8* end = dst + unpadded_row_size;
+ for (uint8* d = dst; d < end; d += step) {
+ *d = 255;
+ }
+ dst += padded_row_size;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+
error::Error GLES2DecoderImpl::HandleReadPixels(
uint32 immediate_data_size, const cmds::ReadPixels& c) {
if (ShouldDeferReads())
@@ -6718,6 +6832,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
GLsizei height = c.height;
GLenum format = c.format;
GLenum type = c.type;
+ GLboolean async = c.async;
if (width < 0 || height < 0) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", "dimensions < 0");
return error::kNoError;
@@ -6817,6 +6932,25 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
dst += padded_row_size;
}
} else {
+ if (async && features().use_async_readpixels) {
+ GLuint buffer;
+ glGenBuffersARB(1, &buffer);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer);
+ glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, GL_STREAM_READ);
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
+ glReadPixels(x, y, width, height, format, type, 0);
+ pending_readpixel_fences_.push(linked_ptr<FenceCallback>(
+ new FenceCallback()));
+ WaitForReadPixels(base::Bind(
+ &GLES2DecoderImpl::FinishReadPixels,
+ base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
+ <GLES2DecoderImpl>(this),
+ c, buffer));
+ glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ return error::kNoError;
+ }
+ }
glReadPixels(x, y, width, height, format, type, pixels);
}
GLenum error = LOCAL_PEEK_GL_ERROR("glReadPixels");
@@ -6824,51 +6958,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
if (result != NULL) {
*result = true;
}
-
- GLenum read_format = GetBoundReadFrameBufferInternalFormat();
- uint32 channels_exist = GLES2Util::GetChannelsForFormat(read_format);
- if ((channels_exist & 0x0008) == 0 &&
- workarounds().clear_alpha_in_readpixels) {
- // Set the alpha to 255 because some drivers are buggy in this regard.
- uint32 temp_size;
-
- uint32 unpadded_row_size;
- uint32 padded_row_size;
- if (!GLES2Util::ComputeImageDataSizes(
- width, 2, format, type, state_.pack_alignment, &temp_size,
- &unpadded_row_size, &padded_row_size)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE, "glReadPixels", "dimensions out of range");
- return error::kNoError;
- }
- // NOTE: Assumes the type is GL_UNSIGNED_BYTE which was true at the time
- // of this implementation.
- if (type != GL_UNSIGNED_BYTE) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION, "glReadPixels",
- "unsupported readPixel format");
- return error::kNoError;
- }
- switch (format) {
- case GL_RGBA:
- case GL_BGRA_EXT:
- case GL_ALPHA: {
- int offset = (format == GL_ALPHA) ? 0 : 3;
- int step = (format == GL_ALPHA) ? 1 : 4;
- uint8* dst = static_cast<uint8*>(pixels) + offset;
- for (GLint yy = 0; yy < height; ++yy) {
- uint8* end = dst + unpadded_row_size;
- for (uint8* d = dst; d < end; d += step) {
- *d = 255;
- }
- dst += padded_row_size;
- }
- break;
- }
- default:
- break;
- }
- }
+ FinishReadPixels(c, 0);
}
return error::kNoError;
@@ -9098,11 +9188,35 @@ bool GLES2DecoderImpl::ProcessPendingQueries() {
return query_manager_->HavePendingQueries();
}
+// Note that if there are no pending readpixels right now,
+// this function will call the callback immediately.
+void GLES2DecoderImpl::WaitForReadPixels(base::Closure callback) {
+ if (features().use_async_readpixels && !pending_readpixel_fences_.empty()) {
+ pending_readpixel_fences_.back()->callbacks.push_back(callback);
+ } else {
+ callback.Run();
+ }
+}
+
+void GLES2DecoderImpl::ProcessPendingReadPixels() {
+ while (!pending_readpixel_fences_.empty() &&
+ pending_readpixel_fences_.front()->fence->HasCompleted()) {
+ std::vector<base::Closure> callbacks =
+ pending_readpixel_fences_.front()->callbacks;
+ pending_readpixel_fences_.pop();
+ for (size_t i = 0; i < callbacks.size(); i++) {
+ callbacks[i].Run();
+ }
+ }
+}
+
bool GLES2DecoderImpl::HasMoreIdleWork() {
- return async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
+ return !pending_readpixel_fences_.empty() ||
+ async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers();
}
void GLES2DecoderImpl::PerformIdleWork() {
+ ProcessPendingReadPixels();
if (!async_pixel_transfer_manager_->NeedsProcessMorePendingTransfers())
return;
async_pixel_transfer_manager_->ProcessMorePendingTransfers();
@@ -9120,6 +9234,7 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
case GL_COMMANDS_ISSUED_CHROMIUM:
case GL_LATENCY_QUERY_CHROMIUM:
case GL_ASYNC_PIXEL_TRANSFERS_COMPLETED_CHROMIUM:
+ case GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM:
case GL_GET_ERROR_QUERY_CHROMIUM:
break;
default:
@@ -9132,6 +9247,8 @@ error::Error GLES2DecoderImpl::HandleBeginQueryEXT(
break;
}
+ // TODO(hubbe): Make it possible to have one query per type running at the
+ // same time.
if (state_.current_query.get()) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress");

Powered by Google App Engine
This is Rietveld 408576698