diff options
author | robert.bradford@intel.com <robert.bradford@intel.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-27 11:44:21 +0000 |
---|---|---|
committer | robert.bradford@intel.com <robert.bradford@intel.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-27 11:44:21 +0000 |
commit | c959a09a4049fdc87dfff3017a1c52ac9f1aad50 (patch) | |
tree | 07f6e5f74201e7c302fa15bb456b8dee4ec0d07e /gpu | |
parent | 95052aaa485e20d220db74d88c567268f30a58f1 (diff) | |
download | chromium_src-c959a09a4049fdc87dfff3017a1c52ac9f1aad50.zip chromium_src-c959a09a4049fdc87dfff3017a1c52ac9f1aad50.tar.gz chromium_src-c959a09a4049fdc87dfff3017a1c52ac9f1aad50.tar.bz2 |
GLHelper: Use preferred BGRA read pixels for YUV read back
When copying to the PBO the driver can use a blit if the requested
format matches the underlying format of the data. Mesa on Intel is
storing the data internally as BGRA (byte order).
This change moves the choice of format to the caller of the
ReadbackAsync and ReadbackPlane functions.
We then use GL_BGRA to read in the plane data for the YUV readback
object. However since the format is now swizzled we must swizzle the
pixel data back. This is done using the existing mechanism for swizzling
the result in the scaling shaders.
The activation of the use of GL_BGRA and swizzling is controlled by
querying the GL implementation for it's preferred format and type. In
the GPU code we pass this request onto the underlying GL implementation
if it supports the GL_OES_read_format extension.
As a result of this change glReadPixels can return immediately after
setting up the blit to the PBO and as such the asynchronous glReadPixels
works as expected when reading back YUV data for Tab Casting.
This is a revised version of the patch that correctly handles that the
extension above can trigger an error but that the GLES specification does not
specify than an error can occur.
Original CL: https://codereview.chromium.org/178583008/
TEST=With the change observe that the time spent in the
HandleReadPixels tracepoint is reduced.
BUG=348015
Review URL: https://codereview.chromium.org/208223004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@259832 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 26 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc | 131 |
2 files changed, 157 insertions, 0 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index e6a1270..9ca8213 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -4177,7 +4177,25 @@ bool GLES2DecoderImpl::GetHelper( switch (pname) { case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *num_written = 1; + // Return the GL implementation's preferred format and (see below type) + // if we have the GL extension that exposes this. This allows the GPU + // client to use the implementation's preferred format for glReadPixels + // for optimisation. + // + // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error + // case when requested on integer/floating point buffers but which is + // acceptable on GLES2 and with the GL_OES_read_format extension. + // + // Therefore if an error occurs we swallow the error and use the + // internal implementation. if (params) { + if (context_->HasExtension("GL_OES_read_format")) { + ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper", + GetErrorState()); + glGetIntegerv(pname, params); + if (glGetError() == GL_NO_ERROR) + return true; + } *params = GLES2Util::GetPreferredGLReadPixelsFormat( GetBoundReadFrameBufferInternalFormat()); } @@ -4185,6 +4203,13 @@ bool GLES2DecoderImpl::GetHelper( case GL_IMPLEMENTATION_COLOR_READ_TYPE: *num_written = 1; if (params) { + if (context_->HasExtension("GL_OES_read_format")) { + ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper", + GetErrorState()); + glGetIntegerv(pname, params); + if (glGetError() == GL_NO_ERROR) + return true; + } *params = GLES2Util::GetPreferredGLReadPixelsType( GetBoundReadFrameBufferInternalFormat(), GetBoundReadFrameBufferTextureType()); @@ -7234,6 +7259,7 @@ void GLES2DecoderImpl::FinishReadPixels( error::Error GLES2DecoderImpl::HandleReadPixels( uint32 immediate_data_size, const cmds::ReadPixels& c) { + TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels"); error::Error fbo_error = WillAccessBoundFramebufferForRead(); if (fbo_error != error::kNoError) return fbo_error; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 15fd1d1..d2e6e97 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -9204,6 +9204,137 @@ TEST_F(GLES2DecoderManualInitTest, TexImage2DFloatConvertsFormatDesktop) { GL_LUMINANCE_ALPHA32F_ARB); } +TEST_F(GLES2DecoderManualInitTest, ReadFormatExtension) { + InitDecoder( + "GL_OES_read_format", // extensions + "2.1", // gl version + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .Times(6) + .RetiresOnSaturation(); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + GetIntegerv cmd; + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); + + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)) + .Times(1) + .RetiresOnSaturation(); + cmd.Init( + GL_IMPLEMENTATION_COLOR_READ_FORMAT, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)) + .Times(1) + .RetiresOnSaturation(); + cmd.Init( + GL_IMPLEMENTATION_COLOR_READ_TYPE, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES2DecoderManualInitTest, NoReadFormatExtension) { + InitDecoder( + "", // extensions + "2.1", // gl version + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + GetIntegerv cmd; + const GLuint kFBOClientTextureId = 4100; + const GLuint kFBOServiceTextureId = 4101; + + // Register a texture id. + EXPECT_CALL(*gl_, GenTextures(_, _)) + .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId)) + .RetiresOnSaturation(); + GenHelper<GenTexturesImmediate>(kFBOClientTextureId); + + // Setup "render to" texture. + DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId); + DoTexImage2D( + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); + DoBindFramebuffer( + GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId); + DoFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR); + + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)) + .Times(0) + .RetiresOnSaturation(); + cmd.Init( + GL_IMPLEMENTATION_COLOR_READ_FORMAT, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + result->size = 0; + EXPECT_CALL(*gl_, GetIntegerv(_, _)) + .Times(0) + .RetiresOnSaturation(); + cmd.Init( + GL_IMPLEMENTATION_COLOR_READ_TYPE, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + // TODO(gman): Complete this test. // TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) { // } |