diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-11-18 16:35:47 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-11-18 15:45:54 +0000 |
commit | 32f5a1c56531e4210bc4cf8d8c7825d66e081888 (patch) | |
tree | eeeec6822f4d738d8454525233fd0e2e3a659e6d /chromium/gpu/command_buffer | |
parent | 99677208ff3b216fdfec551fbe548da5520cd6fb (diff) | |
download | qtwebengine-chromium-32f5a1c56531e4210bc4cf8d8c7825d66e081888.tar.gz |
BASELINE: Update Chromium to 87.0.4280.67
Change-Id: Ib157360be8c2ffb2c73125751a89f60e049c1d54
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/gpu/command_buffer')
62 files changed, 1219 insertions, 539 deletions
diff --git a/chromium/gpu/command_buffer/client/gl_helper_scaling.cc b/chromium/gpu/command_buffer/client/gl_helper_scaling.cc index a6ac94340fc..e35ccfa7947 100644 --- a/chromium/gpu/command_buffer/client/gl_helper_scaling.cc +++ b/chromium/gpu/command_buffer/client/gl_helper_scaling.cc @@ -523,33 +523,44 @@ class ScalerImpl : public GLHelper::ScalerInterface { src_rect.size() == gfx::SizeF(result_size)) ? GL_NEAREST : GL_LINEAR; - // Bind to the source texture and set the filitering and clamp to the edge, - // as required by all shader programs. - ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, src_texture); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // Prepare the shader program for drawing. - ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( - gl_, scaler_helper_->vertex_attributes_buffer_); - shader_program_->UseProgram(src_texture_size, src_rect, result_size, - spec_.scale_x, spec_.flip_output, - color_weights_); - - // Execute the draw. - gl_->Viewport(0, 0, result_size.width(), result_size.height()); - const GLenum buffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1}; - if (dest_texture_1 > 0) { - DCHECK_LE(2, scaler_helper_->helper_->MaxDrawBuffers()); - gl_->DrawBuffersEXT(2, buffers); - } - gl_->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); - if (dest_texture_1 > 0) { - // Set the draw buffers back to not disrupt external operations. - gl_->DrawBuffersEXT(1, buffers); + + // Set the active texture unit to 0 for the ScopedTextureBinder below, then + // restore the original value when done. (crbug.com/1103385) + GLint oldActiveTexture = 0; + gl_->GetIntegerv(GL_ACTIVE_TEXTURE, &oldActiveTexture); + gl_->ActiveTexture(GL_TEXTURE0); + { + // Bind to the source texture and set the filitering and clamp to the + // edge, as required by all shader programs. + ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, src_texture); + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // Prepare the shader program for drawing. + ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( + gl_, scaler_helper_->vertex_attributes_buffer_); + shader_program_->UseProgram(src_texture_size, src_rect, result_size, + spec_.scale_x, spec_.flip_output, + color_weights_); + + // Execute the draw. + gl_->Viewport(0, 0, result_size.width(), result_size.height()); + const GLenum buffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1}; + if (dest_texture_1 > 0) { + DCHECK_LE(2, scaler_helper_->helper_->MaxDrawBuffers()); + gl_->DrawBuffersEXT(2, buffers); + } + gl_->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); + if (dest_texture_1 > 0) { + // Set the draw buffers back to not disrupt external operations. + gl_->DrawBuffersEXT(1, buffers); + } + + // ScopedTextureBinder ends here, before restoring ActiveTexture state. } + gl_->ActiveTexture(oldActiveTexture); } GLES2Interface* gl_; diff --git a/chromium/gpu/command_buffer/client/gles2_implementation.cc b/chromium/gpu/command_buffer/client/gles2_implementation.cc index 49d050e7e0d..e1611b999bb 100644 --- a/chromium/gpu/command_buffer/client/gles2_implementation.cc +++ b/chromium/gpu/command_buffer/client/gles2_implementation.cc @@ -143,6 +143,19 @@ bool IsReadbackUsage(GLenum usage) { usage == GL_STATIC_READ; } +void UpdateProgramInfo(base::span<const uint8_t>& data, + ProgramInfoManager* manager, + ProgramInfoManager::ProgramInfoType type) { + DCHECK(data.size() > sizeof(cmds::GLES2ReturnProgramInfo)); + const cmds::GLES2ReturnProgramInfo* return_program_info = + reinterpret_cast<const cmds::GLES2ReturnProgramInfo*>(data.data()); + uint32_t program = return_program_info->program_client_id; + base::span<const int8_t> info( + reinterpret_cast<const int8_t*>(return_program_info->deserialized_buffer), + data.size() - sizeof(cmds::GLES2ReturnProgramInfo)); + manager->UpdateProgramInfo(program, info, type); +} + } // anonymous namespace GLES2Implementation::GLStaticState::GLStaticState() = default; @@ -448,7 +461,31 @@ void GLES2Implementation::OnSwapBufferPresented( void GLES2Implementation::OnGpuControlReturnData( base::span<const uint8_t> data) { - NOTIMPLEMENTED(); + DCHECK(data.size() > sizeof(cmds::GLES2ReturnDataHeader)); + const cmds::GLES2ReturnDataHeader& gles2ReturnDataHeader = + *reinterpret_cast<const cmds::GLES2ReturnDataHeader*>(data.data()); + + switch (gles2ReturnDataHeader.return_data_type) { + case GLES2ReturnDataType::kES2ProgramInfo: { + UpdateProgramInfo(data, share_group_->program_info_manager(), + ProgramInfoManager::kES2); + } break; + case GLES2ReturnDataType::kES3UniformBlocks: { + UpdateProgramInfo(data, share_group_->program_info_manager(), + ProgramInfoManager::kES3UniformBlocks); + } break; + case GLES2ReturnDataType::kES3TransformFeedbackVaryings: { + UpdateProgramInfo(data, share_group_->program_info_manager(), + ProgramInfoManager::kES3TransformFeedbackVaryings); + } break; + case GLES2ReturnDataType::kES3Uniforms: { + UpdateProgramInfo(data, share_group_->program_info_manager(), + ProgramInfoManager::kES3Uniformsiv); + } break; + + default: + NOTREACHED(); + } } void GLES2Implementation::FreeSharedMemory(void* mem) { @@ -723,11 +760,14 @@ GLboolean GLES2Implementation::IsEnablediOES(GLenum target, GLuint index) { << ")"); bool state = false; typedef cmds::IsEnabled::Result Result; - auto result = GetResultAs<Result>(); - *result = 0; - helper_->IsEnablediOES(target, index, GetResultShmId(), result.offset()); - WaitForCmd(); - state = (*result) != 0; + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + *result = 0; + helper_->IsEnablediOES(target, index, GetResultShmId(), result.offset()); + WaitForCmd(); + state = (*result) != 0; + } GPU_CLIENT_LOG("returned " << state); CheckGLError(); @@ -4383,35 +4423,38 @@ void GLES2Implementation::GetShaderPrecisionFormat(GLenum shadertype, << static_cast<const void*>(precision) << ", "); TRACE_EVENT0("gpu", "GLES2::GetShaderPrecisionFormat"); typedef cmds::GetShaderPrecisionFormat::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - - GLStaticState::ShaderPrecisionKey key(shadertype, precisiontype); - GLStaticState::ShaderPrecisionMap::iterator i = - static_state_.shader_precisions.find(key); - if (i != static_state_.shader_precisions.end()) { - *result = i->second; - } else { - result->success = false; - helper_->GetShaderPrecisionFormat(shadertype, precisiontype, - GetResultShmId(), result.offset()); - WaitForCmd(); - if (result->success) - static_state_.shader_precisions[key] = *result; - } - - if (result->success) { - if (range) { - range[0] = result->min_range; - range[1] = result->max_range; - GPU_CLIENT_LOG(" min_range: " << range[0]); - GPU_CLIENT_LOG(" min_range: " << range[1]); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - if (precision) { - precision[0] = result->precision; - GPU_CLIENT_LOG(" min_range: " << precision[0]); + + GLStaticState::ShaderPrecisionKey key(shadertype, precisiontype); + GLStaticState::ShaderPrecisionMap::iterator i = + static_state_.shader_precisions.find(key); + if (i != static_state_.shader_precisions.end()) { + *result = i->second; + } else { + result->success = false; + helper_->GetShaderPrecisionFormat(shadertype, precisiontype, + GetResultShmId(), result.offset()); + WaitForCmd(); + if (result->success) + static_state_.shader_precisions[key] = *result; + } + + if (result->success) { + if (range) { + range[0] = result->min_range; + range[1] = result->max_range; + GPU_CLIENT_LOG(" min_range: " << range[0]); + GPU_CLIENT_LOG(" min_range: " << range[1]); + } + if (precision) { + precision[0] = result->precision; + GPU_CLIENT_LOG(" min_range: " << precision[0]); + } } } CheckGLError(); @@ -4570,19 +4613,22 @@ void GLES2Implementation::GetUniformfv(GLuint program, << ")"); TRACE_EVENT0("gpu", "GLES2::GetUniformfv"); typedef cmds::GetUniformfv::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetUniformfv(program, location, GetResultShmId(), result.offset()); - WaitForCmd(); - result->CopyResult(params); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - }); + result->SetNumResults(0); + helper_->GetUniformfv(program, location, GetResultShmId(), result.offset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + } CheckGLError(); } @@ -4595,19 +4641,22 @@ void GLES2Implementation::GetUniformiv(GLuint program, << ")"); TRACE_EVENT0("gpu", "GLES2::GetUniformiv"); typedef cmds::GetUniformiv::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetUniformiv(program, location, GetResultShmId(), result.offset()); - WaitForCmd(); - result->CopyResult(params); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - }); + result->SetNumResults(0); + helper_->GetUniformiv(program, location, GetResultShmId(), result.offset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + } CheckGLError(); } @@ -4620,19 +4669,23 @@ void GLES2Implementation::GetUniformuiv(GLuint program, << static_cast<const void*>(params) << ")"); TRACE_EVENT0("gpu", "GLES2::GetUniformuiv"); typedef cmds::GetUniformuiv::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetUniformuiv(program, location, GetResultShmId(), result.offset()); - WaitForCmd(); - result->CopyResult(params); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - }); + result->SetNumResults(0); + helper_->GetUniformuiv(program, location, GetResultShmId(), + result.offset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + } CheckGLError(); } @@ -5473,19 +5526,22 @@ void GLES2Implementation::GetVertexAttribfv(GLuint index, } TRACE_EVENT0("gpu", "GLES2::GetVertexAttribfv"); typedef cmds::GetVertexAttribfv::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetVertexAttribfv(index, pname, GetResultShmId(), result.offset()); - WaitForCmd(); - result->CopyResult(params); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - }); + result->SetNumResults(0); + helper_->GetVertexAttribfv(index, pname, GetResultShmId(), result.offset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + } CheckGLError(); } @@ -5503,19 +5559,22 @@ void GLES2Implementation::GetVertexAttribiv(GLuint index, } TRACE_EVENT0("gpu", "GLES2::GetVertexAttribiv"); typedef cmds::GetVertexAttribiv::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetVertexAttribiv(index, pname, GetResultShmId(), result.offset()); - WaitForCmd(); - result->CopyResult(params); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - }); + result->SetNumResults(0); + helper_->GetVertexAttribiv(index, pname, GetResultShmId(), result.offset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + } CheckGLError(); } @@ -5533,19 +5592,23 @@ void GLES2Implementation::GetVertexAttribIiv(GLuint index, } TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIiv"); typedef cmds::GetVertexAttribiv::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetVertexAttribIiv(index, pname, GetResultShmId(), result.offset()); - WaitForCmd(); - result->CopyResult(params); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - }); + result->SetNumResults(0); + helper_->GetVertexAttribIiv(index, pname, GetResultShmId(), + result.offset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + } CheckGLError(); } @@ -5563,19 +5626,23 @@ void GLES2Implementation::GetVertexAttribIuiv(GLuint index, } TRACE_EVENT0("gpu", "GLES2::GetVertexAttribIuiv"); typedef cmds::GetVertexAttribiv::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetVertexAttribIuiv(index, pname, GetResultShmId(), result.offset()); - WaitForCmd(); - result->CopyResult(params); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - }); + result->SetNumResults(0); + helper_->GetVertexAttribIuiv(index, pname, GetResultShmId(), + result.offset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + } CheckGLError(); } @@ -7331,18 +7398,23 @@ GLenum GLES2Implementation::ClientWaitSync(GLsync sync, GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClientWaitSync(" << sync << ", " << flags << ", " << timeout << ")"); typedef cmds::ClientWaitSync::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - SetGLError(GL_OUT_OF_MEMORY, "ClientWaitSync", ""); - return GL_WAIT_FAILED; + // Limit scope of result to avoid overlap with CheckGLError() + Result localResult; + { + auto result = GetResultAs<Result>(); + if (!result) { + SetGLError(GL_OUT_OF_MEMORY, "ClientWaitSync", ""); + return GL_WAIT_FAILED; + } + *result = GL_WAIT_FAILED; + helper_->ClientWaitSync(ToGLuint(sync), flags, timeout, GetResultShmId(), + result.offset()); + WaitForCmd(); + localResult = *result; + GPU_CLIENT_LOG("returned " << localResult); } - *result = GL_WAIT_FAILED; - helper_->ClientWaitSync(ToGLuint(sync), flags, timeout, GetResultShmId(), - result.offset()); - WaitForCmd(); - GPU_CLIENT_LOG("returned " << *result); CheckGLError(); - return *result; + return localResult; } void GLES2Implementation::CopyBufferSubData(GLenum readtarget, @@ -7406,26 +7478,29 @@ void GLES2Implementation::GetInternalformativ(GLenum target, return; } typedef cmds::GetInternalformativ::Result Result; - auto result = GetResultAs<Result>(); - if (!result) { - return; - } - result->SetNumResults(0); - helper_->GetInternalformativ(target, format, pname, GetResultShmId(), - result.offset()); - WaitForCmd(); - GPU_CLIENT_LOG_CODE_BLOCK({ - for (int32_t i = 0; i < result->GetNumResults(); ++i) { - GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); - } - }); - if (buf_size > 0 && params) { - GLint* data = result->GetData(); - if (buf_size >= result->GetNumResults()) { - buf_size = result->GetNumResults(); + // Limit scope of result to avoid overlap with CheckGLError() + { + auto result = GetResultAs<Result>(); + if (!result) { + return; } - for (GLsizei ii = 0; ii < buf_size; ++ii) { - params[ii] = data[ii]; + result->SetNumResults(0); + helper_->GetInternalformativ(target, format, pname, GetResultShmId(), + result.offset()); + WaitForCmd(); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + if (buf_size > 0 && params) { + GLint* data = result->GetData(); + if (buf_size >= result->GetNumResults()) { + buf_size = result->GetNumResults(); + } + for (GLsizei ii = 0; ii < buf_size; ++ii) { + params[ii] = data[ii]; + } } } CheckGLError(); diff --git a/chromium/gpu/command_buffer/client/program_info_manager.cc b/chromium/gpu/command_buffer/client/program_info_manager.cc index 5e3299ed9d2..a3f5eb65f2e 100644 --- a/chromium/gpu/command_buffer/client/program_info_manager.cc +++ b/chromium/gpu/command_buffer/client/program_info_manager.cc @@ -10,7 +10,7 @@ namespace { template <typename T> -static T LocalGetAs(const std::vector<int8_t>& data, +static T LocalGetAs(base::span<const int8_t> data, uint32_t offset, size_t size) { const int8_t* p = data.data() + offset; @@ -358,7 +358,7 @@ bool ProgramInfoManager::Program::GetUniformsiv( return false; } -void ProgramInfoManager::Program::UpdateES2(const std::vector<int8_t>& result) { +void ProgramInfoManager::Program::UpdateES2(base::span<const int8_t> result) { if (cached_es2_) { return; } @@ -414,7 +414,7 @@ void ProgramInfoManager::Program::UpdateES2(const std::vector<int8_t>& result) { } void ProgramInfoManager::Program::UpdateES3UniformBlocks( - const std::vector<int8_t>& result) { + base::span<const int8_t> result) { if (cached_es3_uniform_blocks_) { return; } @@ -485,7 +485,7 @@ void ProgramInfoManager::Program::UpdateES3UniformBlocks( } void ProgramInfoManager::Program::UpdateES3Uniformsiv( - const std::vector<int8_t>& result) { + base::span<const int8_t> result) { if (cached_es3_uniformsiv_) { return; } @@ -527,7 +527,7 @@ void ProgramInfoManager::Program::UpdateES3Uniformsiv( } void ProgramInfoManager::Program::UpdateES3TransformFeedbackVaryings( - const std::vector<int8_t>& result) { + base::span<const int8_t> result) { if (cached_es3_transform_feedback_varyings_) { return; } @@ -1059,6 +1059,37 @@ GLint ProgramInfoManager::GetProgramResourceLocation( return gl->GetProgramResourceLocationHelper(program, program_interface, name); } +void ProgramInfoManager::UpdateProgramInfo(GLuint program, + base::span<const int8_t> data, + ProgramInfoType type) { + base::AutoLock auto_lock(lock_); + ProgramInfoMap::iterator it = program_infos_.find(program); + // It's possible that the program has been deleted already. Imagine the code + // snippet below: + // ... + // gl.linkProgram(program); + // gl.deleteProgram(program); + // ... + if (it == program_infos_.end()) + return; + Program* info = &it->second; + switch (type) { + case kES2: + info->UpdateES2(data); + break; + case kES3UniformBlocks: + info->UpdateES3UniformBlocks(data); + break; + case kES3TransformFeedbackVaryings: + info->UpdateES3TransformFeedbackVaryings(data); + break; + case kES3Uniformsiv: + info->UpdateES3Uniformsiv(data); + break; + default: + NOTREACHED(); + } +} + } // namespace gles2 } // namespace gpu - diff --git a/chromium/gpu/command_buffer/client/program_info_manager.h b/chromium/gpu/command_buffer/client/program_info_manager.h index ee39eecb8e1..fb45541986d 100644 --- a/chromium/gpu/command_buffer/client/program_info_manager.h +++ b/chromium/gpu/command_buffer/client/program_info_manager.h @@ -104,6 +104,18 @@ class GLES2_IMPL_EXPORT ProgramInfoManager { GLES2Implementation* gl, GLuint program, GLenum program_interface, const char* name); + enum ProgramInfoType { + kES2, + kES3UniformBlocks, + kES3TransformFeedbackVaryings, + kES3Uniformsiv, + kNone, + }; + + void UpdateProgramInfo(GLuint program, + base::span<const int8_t> result, + ProgramInfoType type); + private: friend class ProgramInfoManagerTest; @@ -114,14 +126,6 @@ class GLES2_IMPL_EXPORT ProgramInfoManager { FRIEND_TEST_ALL_PREFIXES(ProgramInfoManagerTest, GetActiveUniformsivCached); - enum ProgramInfoType { - kES2, - kES3UniformBlocks, - kES3TransformFeedbackVaryings, - kES3Uniformsiv, - kNone, - }; - // Need GLES2_IMPL_EXPORT for tests. class GLES2_IMPL_EXPORT Program { public: @@ -213,16 +217,16 @@ class GLES2_IMPL_EXPORT ProgramInfoManager { GLuint index) const; // Updates the ES2 only program info after a successful link. - void UpdateES2(const std::vector<int8_t>& result); + void UpdateES2(base::span<const int8_t> result); // Updates the ES3 UniformBlock info after a successful link. - void UpdateES3UniformBlocks(const std::vector<int8_t>& result); + void UpdateES3UniformBlocks(base::span<const int8_t> result); // Updates the ES3 Uniformsiv info after a successful link. - void UpdateES3Uniformsiv(const std::vector<int8_t>& result); + void UpdateES3Uniformsiv(base::span<const int8_t> result); // Updates the ES3 TransformFeedbackVaryings info after a successful link. - void UpdateES3TransformFeedbackVaryings(const std::vector<int8_t>& result); + void UpdateES3TransformFeedbackVaryings(base::span<const int8_t> result); bool IsCached(ProgramInfoType type) const; diff --git a/chromium/gpu/command_buffer/client/shared_image_interface.h b/chromium/gpu/command_buffer/client/shared_image_interface.h index 8c33e90124c..0f11fbbeeba 100644 --- a/chromium/gpu/command_buffer/client/shared_image_interface.h +++ b/chromium/gpu/command_buffer/client/shared_image_interface.h @@ -169,10 +169,15 @@ class GPU_EXPORT SharedImageInterface { // |buffer_collection_id| and |buffer_index| fields in NativePixmapHandle, // wrapping it in GpuMemoryBufferHandle and then creating GpuMemoryBuffer from // that handle. - virtual void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id, - zx::channel token, - gfx::BufferFormat format, - gfx::BufferUsage usage) = 0; + // If |register_with_image_pipe| field is set, a new ImagePipe is created and + // |token| is duped to collect ImagePipe constraints. SysmemBufferCollection + // is then available for direct presentation. + virtual void RegisterSysmemBufferCollection( + gfx::SysmemBufferCollectionId id, + zx::channel token, + gfx::BufferFormat format, + gfx::BufferUsage usage, + bool register_with_image_pipe) = 0; virtual void ReleaseSysmemBufferCollection( gfx::SysmemBufferCollectionId id) = 0; diff --git a/chromium/gpu/command_buffer/client/transfer_buffer.cc b/chromium/gpu/command_buffer/client/transfer_buffer.cc index e010ddbdeb0..4b55c05872e 100644 --- a/chromium/gpu/command_buffer/client/transfer_buffer.cc +++ b/chromium/gpu/command_buffer/client/transfer_buffer.cc @@ -61,6 +61,11 @@ void TransferBuffer::Free() { TRACE_EVENT0("gpu", "TransferBuffer::Free"); helper_->OrderingBarrier(); helper_->command_buffer()->DestroyTransferBuffer(buffer_id_); + if (!HaveBuffer()) { + // The above may call this function reentrantly. If the buffer was + // already freed, then our work is done. + return; + } buffer_id_ = -1; buffer_ = nullptr; result_buffer_ = nullptr; diff --git a/chromium/gpu/command_buffer/client/webgpu_implementation.cc b/chromium/gpu/command_buffer/client/webgpu_implementation.cc index 8fd0df66783..c558e420ed0 100644 --- a/chromium/gpu/command_buffer/client/webgpu_implementation.cc +++ b/chromium/gpu/command_buffer/client/webgpu_implementation.cc @@ -141,12 +141,20 @@ bool WebGPUCommandSerializer::Flush() { c2s_buffer_.offset(), c2s_put_offset_); c2s_put_offset_ = 0; c2s_buffer_.Release(); + client_awaiting_flush_ = false; } memory_transfer_service_->FreeHandlesPendingToken(helper_->InsertToken()); return true; } +void WebGPUCommandSerializer::SetClientAwaitingFlush(bool awaiting_flush) { + // If awaiting_flush is true, but the c2s_buffer_ is invalid (empty), that + // means the last command right before this caused a flush. Another flush is + // not needed. + client_awaiting_flush_ = awaiting_flush && c2s_buffer_.valid(); +} + void WebGPUCommandSerializer::HandleGpuControlLostContext() { // Immediately forget pending commands. c2s_buffer_.Discard(); @@ -572,6 +580,54 @@ void WebGPUImplementation::FlushCommands() { helper_->Flush(); } +void WebGPUImplementation::FlushCommands(DawnDeviceClientID device_client_id) { +#if BUILDFLAG(USE_DAWN) + WebGPUCommandSerializer* command_serializer = + GetCommandSerializerWithDeviceClientID(device_client_id); + DCHECK(command_serializer); + command_serializer->Flush(); + helper_->Flush(); +#endif +} + +void WebGPUImplementation::EnsureAwaitingFlush( + DawnDeviceClientID device_client_id, + bool* needs_flush) { +#if BUILDFLAG(USE_DAWN) + WebGPUCommandSerializer* command_serializer = + GetCommandSerializerWithDeviceClientID(device_client_id); + DCHECK(command_serializer); + + // If there is already a flush waiting, we don't need to flush. + // We only want to set |needs_flush| on state transition from + // false -> true. + if (command_serializer->ClientAwaitingFlush()) { + *needs_flush = false; + return; + } + + // Set the state to waiting for flush, and then write |needs_flush|. + // Could still be false if there's no data to flush. + command_serializer->SetClientAwaitingFlush(true); + *needs_flush = command_serializer->ClientAwaitingFlush(); +#else + *needs_flush = false; +#endif +} + +void WebGPUImplementation::FlushAwaitingCommands( + DawnDeviceClientID device_client_id) { +#if BUILDFLAG(USE_DAWN) + WebGPUCommandSerializer* command_serializer = + GetCommandSerializerWithDeviceClientID(device_client_id); + DCHECK(command_serializer); + if (command_serializer->ClientAwaitingFlush()) { + command_serializer->Flush(); + helper_->Flush(); + } +#endif +} + WGPUDevice WebGPUImplementation::GetDevice( DawnDeviceClientID device_client_id) { #if BUILDFLAG(USE_DAWN) diff --git a/chromium/gpu/command_buffer/client/webgpu_implementation.h b/chromium/gpu/command_buffer/client/webgpu_implementation.h index f3fec66d06f..c1fc35bd8c8 100644 --- a/chromium/gpu/command_buffer/client/webgpu_implementation.h +++ b/chromium/gpu/command_buffer/client/webgpu_implementation.h @@ -47,6 +47,9 @@ class WebGPUCommandSerializer final : public dawn_wire::CommandSerializer { void* GetCmdSpace(size_t size) final; bool Flush() final; + void SetClientAwaitingFlush(bool awaiting_flush); + bool ClientAwaitingFlush() const { return client_awaiting_flush_; } + // Called upon context lost. void HandleGpuControlLostContext(); @@ -66,6 +69,8 @@ class WebGPUCommandSerializer final : public dawn_wire::CommandSerializer { uint32_t c2s_put_offset_ = 0; std::unique_ptr<TransferBuffer> c2s_transfer_buffer_; ScopedTransferBufferPtr c2s_buffer_; + + bool client_awaiting_flush_ = false; }; #endif @@ -153,6 +158,10 @@ class WEBGPU_EXPORT WebGPUImplementation final : public WebGPUInterface, // WebGPUInterface implementation const DawnProcTable& GetProcs() const override; void FlushCommands() override; + void FlushCommands(DawnDeviceClientID device_client_id) override; + void EnsureAwaitingFlush(DawnDeviceClientID device_client_id, + bool* needs_flush) override; + void FlushAwaitingCommands(DawnDeviceClientID device_client_id) override; WGPUDevice GetDevice(DawnDeviceClientID device_client_id) override; ReservedTexture ReserveTexture(DawnDeviceClientID device_client_id) override; bool RequestAdapterAsync( diff --git a/chromium/gpu/command_buffer/client/webgpu_interface.h b/chromium/gpu/command_buffer/client/webgpu_interface.h index 56138e7db67..e09175e998f 100644 --- a/chromium/gpu/command_buffer/client/webgpu_interface.h +++ b/chromium/gpu/command_buffer/client/webgpu_interface.h @@ -28,7 +28,24 @@ class WebGPUInterface : public InterfaceBase { virtual ~WebGPUInterface() {} virtual const DawnProcTable& GetProcs() const = 0; + + // Flush all commands. virtual void FlushCommands() = 0; + + // Flush all commands on the device client. + virtual void FlushCommands(DawnDeviceClientID device_client_id) = 0; + + // Ensure the awaiting flush flag is set on the device client. Returns false + // if a flush has already been indicated, or a flush is not needed (there may + // be no commands to flush). Returns true if the caller should schedule a + // flush. + virtual void EnsureAwaitingFlush(DawnDeviceClientID device_client_id, + bool* needs_flush) = 0; + + // If the awaiting flush flag is set, flushes commands. Otherwise, does + // nothing. + virtual void FlushAwaitingCommands(DawnDeviceClientID device_client_id) = 0; + virtual WGPUDevice GetDevice(DawnDeviceClientID device_client_id) = 0; virtual ReservedTexture ReserveTexture( DawnDeviceClientID device_client_id) = 0; diff --git a/chromium/gpu/command_buffer/client/webgpu_interface_stub.cc b/chromium/gpu/command_buffer/client/webgpu_interface_stub.cc index c06f7d21c80..1ace9f20064 100644 --- a/chromium/gpu/command_buffer/client/webgpu_interface_stub.cc +++ b/chromium/gpu/command_buffer/client/webgpu_interface_stub.cc @@ -23,6 +23,12 @@ const DawnProcTable& WebGPUInterfaceStub::GetProcs() const { return null_procs_; } void WebGPUInterfaceStub::FlushCommands() {} +void WebGPUInterfaceStub::FlushCommands(DawnDeviceClientID device_client_id) {} +void WebGPUInterfaceStub::EnsureAwaitingFlush( + DawnDeviceClientID device_client_id, + bool* needs_flush) {} +void WebGPUInterfaceStub::FlushAwaitingCommands( + DawnDeviceClientID device_client_id) {} WGPUDevice WebGPUInterfaceStub::GetDevice(DawnDeviceClientID device_client_id) { return nullptr; } diff --git a/chromium/gpu/command_buffer/client/webgpu_interface_stub.h b/chromium/gpu/command_buffer/client/webgpu_interface_stub.h index 1b99eef4cbd..22a9112fe67 100644 --- a/chromium/gpu/command_buffer/client/webgpu_interface_stub.h +++ b/chromium/gpu/command_buffer/client/webgpu_interface_stub.h @@ -25,6 +25,10 @@ class WebGPUInterfaceStub : public WebGPUInterface { // WebGPUInterface implementation const DawnProcTable& GetProcs() const override; void FlushCommands() override; + void FlushCommands(DawnDeviceClientID device_client_id) override; + void EnsureAwaitingFlush(DawnDeviceClientID device_client_id, + bool* needs_flush) override; + void FlushAwaitingCommands(DawnDeviceClientID device_client_id) override; WGPUDevice GetDevice(DawnDeviceClientID device_client_id) override; ReservedTexture ReserveTexture(DawnDeviceClientID device_client_id) override; bool RequestAdapterAsync( diff --git a/chromium/gpu/command_buffer/common/gles2_cmd_format.h b/chromium/gpu/command_buffer/common/gles2_cmd_format.h index ecb2dc4a03d..188a21224ea 100644 --- a/chromium/gpu/command_buffer/common/gles2_cmd_format.h +++ b/chromium/gpu/command_buffer/common/gles2_cmd_format.h @@ -226,10 +226,40 @@ static_assert(sizeof(UniformBlocksHeader) == 4, static_assert(offsetof(UniformBlocksHeader, num_uniform_blocks) == 0, "offset of UniformBlocksHeader.num_uniform_blocks should be 0"); +enum class GLES2ReturnDataType : uint32_t { + kES2ProgramInfo, + kES3UniformBlocks, + kES3TransformFeedbackVaryings, + kES3Uniforms +}; + namespace cmds { #include "gpu/command_buffer/common/gles2_cmd_format_autogen.h" +struct GLES2ReturnDataHeader { + GLES2ReturnDataType return_data_type; +}; +static_assert(sizeof(GLES2ReturnDataHeader) == 4, + "size of GLES2ReturnDataHeader should be 4"); +static_assert(offsetof(GLES2ReturnDataHeader, return_data_type) == 0, + "The offset of return_data_type should be 0"); + +struct GLES2ReturnProgramInfo { + GLES2ReturnDataHeader return_data_header = { + GLES2ReturnDataType::kES2ProgramInfo}; + uint32_t program_client_id = 0; + char deserialized_buffer[]; +}; +static_assert(sizeof(GLES2ReturnProgramInfo) == 8, + "size of GLES2ReturnProgramInfo should be 8"); +static_assert(offsetof(GLES2ReturnProgramInfo, return_data_header) == 0, + "The offset of return_data_header should be 0"); +static_assert(offsetof(GLES2ReturnProgramInfo, program_client_id) == 4, + "The offset of program_client_id should be 4"); +static_assert(offsetof(GLES2ReturnProgramInfo, deserialized_buffer) == 8, + "The offset of deserialized_buffer should be 8"); + #pragma pack(pop) } // namespace cmd diff --git a/chromium/gpu/command_buffer/common/gpu_memory_buffer_support.cc b/chromium/gpu/command_buffer/common/gpu_memory_buffer_support.cc index c268bc166f5..388de9f4003 100644 --- a/chromium/gpu/command_buffer/common/gpu_memory_buffer_support.cc +++ b/chromium/gpu/command_buffer/common/gpu_memory_buffer_support.cc @@ -55,7 +55,7 @@ bool IsImageSizeValidForGpuMemoryBufferFormat(const gfx::Size& size, uint32_t GetPlatformSpecificTextureTarget() { #if defined(OS_MAC) return macos_specific_texture_target; -#elif defined(OS_ANDROID) || defined(OS_LINUX) +#elif defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) return GL_TEXTURE_EXTERNAL_OES; #elif defined(OS_WIN) || defined(OS_FUCHSIA) return GL_TEXTURE_2D; @@ -85,7 +85,7 @@ GPU_EXPORT uint32_t GetBufferTextureTarget(gfx::BufferUsage usage, GPU_EXPORT bool NativeBufferNeedsPlatformSpecificTextureTarget( gfx::BufferFormat format) { -#if defined(USE_OZONE) || defined(OS_LINUX) +#if defined(USE_OZONE) || defined(OS_LINUX) || defined(OS_CHROMEOS) // Always use GL_TEXTURE_2D as the target for RGB textures. // https://crbug.com/916728 if (format == gfx::BufferFormat::R_8 || format == gfx::BufferFormat::RG_88 || diff --git a/chromium/gpu/command_buffer/common/swap_buffers_complete_params.h b/chromium/gpu/command_buffer/common/swap_buffers_complete_params.h index 766c0bcb20b..252891900cf 100644 --- a/chromium/gpu/command_buffer/common/swap_buffers_complete_params.h +++ b/chromium/gpu/command_buffer/common/swap_buffers_complete_params.h @@ -5,7 +5,10 @@ #ifndef GPU_COMMAND_BUFFER_COMMON_SWAP_BUFFERS_COMPLETE_PARAMS_H_ #define GPU_COMMAND_BUFFER_COMMON_SWAP_BUFFERS_COMPLETE_PARAMS_H_ +#include <vector> + #include "base/optional.h" +#include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/texture_in_use_response.h" #include "ui/gfx/ca_layer_params.h" #include "ui/gfx/geometry/rect.h" @@ -31,9 +34,13 @@ struct GPU_EXPORT SwapBuffersCompleteParams { // Used only on macOS, for coordinating IOSurface reuse with the system // WindowServer. gpu::TextureInUseResponses texture_in_use_responses; + // Used only on macOS, to allow the browser hosted NSWindow to display // content populated in the GPU process. gfx::CALayerParams ca_layer_params; + + // Used only on macOS, for released overlays with SkiaRenderer. + std::vector<Mailbox> released_overlays; }; } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/BUILD.gn b/chromium/gpu/command_buffer/service/BUILD.gn index 7bdea113f63..56cb7346a69 100644 --- a/chromium/gpu/command_buffer/service/BUILD.gn +++ b/chromium/gpu/command_buffer/service/BUILD.gn @@ -448,7 +448,7 @@ target(link_target_type, "gles2_sources") { "texture_owner.h", ] - deps += [ "//media/base/android:android" ] + deps += [ "//base" ] # TODO(cblume): http://crbug.com/911313 # Abstract out the platform specific defines. Right now we need the android @@ -515,8 +515,6 @@ if (is_android) { ":gles2", "//base/test:test_support", "//gpu:test_support", - "//media/base:base", - "//media/base/android:android", "//testing/gmock", "//testing/gtest", "//ui/gl", diff --git a/chromium/gpu/command_buffer/service/DEPS b/chromium/gpu/command_buffer/service/DEPS index ced2955f1ab..ff50b4a7bcd 100644 --- a/chromium/gpu/command_buffer/service/DEPS +++ b/chromium/gpu/command_buffer/service/DEPS @@ -10,13 +10,3 @@ include_rules = [ "+components/viz/common/resources/resource_format_utils.h", "+components/viz/common/resources/resource_sizes.h", ] - -specific_include_rules = { - "image_reader_gl_owner_unittest\.cc": [ - "+media/base/media_switches.h", - "+media/base/android/media_codec_util.h", - ], - "image_reader_gl_owner\.cc": [ - "+media/base/android/media_codec_util.h", - ], -} diff --git a/chromium/gpu/command_buffer/service/abstract_texture_impl_shared_context_state.cc b/chromium/gpu/command_buffer/service/abstract_texture_impl_shared_context_state.cc index 803eb3bd0ec..f14ff3adec4 100644 --- a/chromium/gpu/command_buffer/service/abstract_texture_impl_shared_context_state.cc +++ b/chromium/gpu/command_buffer/service/abstract_texture_impl_shared_context_state.cc @@ -58,22 +58,23 @@ AbstractTextureImplOnSharedContext::AbstractTextureImplOnSharedContext( } AbstractTextureImplOnSharedContext::~AbstractTextureImplOnSharedContext() { + bool have_context = true; + base::Optional<ui::ScopedMakeCurrent> scoped_make_current; if (cleanup_cb_) std::move(cleanup_cb_).Run(this); // If the shared context is lost, |shared_context_state_| will be null. if (!shared_context_state_) { - texture_->RemoveLightweightRef(false); + have_context = false; } else { - base::Optional<ui::ScopedMakeCurrent> scoped_make_current; if (!shared_context_state_->IsCurrent(nullptr)) { scoped_make_current.emplace(shared_context_state_->context(), shared_context_state_->surface()); + have_context = scoped_make_current->IsContextCurrent(); } - texture_->RemoveLightweightRef(true); shared_context_state_->RemoveContextLostObserver(this); } - texture_ = nullptr; + texture_->RemoveLightweightRef(have_context); } TextureBase* AbstractTextureImplOnSharedContext::GetTextureBase() const { @@ -154,14 +155,10 @@ AbstractTextureImplOnSharedContextPassthrough:: AbstractTextureImplOnSharedContextPassthrough:: ~AbstractTextureImplOnSharedContextPassthrough() { + base::Optional<ui::ScopedMakeCurrent> scoped_make_current; if (cleanup_cb_) std::move(cleanup_cb_).Run(this); - // Save the current context and make it current again after deleting the - // |texture_|. - scoped_refptr<gl::GLContext> previous_context = gl::GLContext::GetCurrent(); - scoped_refptr<gl::GLSurface> previous_surface = gl::GLSurface::GetCurrent(); - // If the shared context is lost, |shared_context_state_| will be null and the // |texture_| is already marked to have lost its context. if (shared_context_state_) { @@ -170,16 +167,17 @@ AbstractTextureImplOnSharedContextPassthrough:: // destructor is not guaranteed to be called on the context on which the // |texture_| was created. if (!shared_context_state_->IsCurrent(nullptr)) { - shared_context_state_->MakeCurrent(shared_context_state_->surface(), - true /* needs_gl */); + scoped_make_current.emplace(shared_context_state_->context(), + shared_context_state_->surface()); + + // If |shared_context_state_|'s context is not current, then mark context + // lost for the |texture_|. + if (!scoped_make_current->IsContextCurrent()) + texture_->MarkContextLost(); } shared_context_state_->RemoveContextLostObserver(this); } texture_.reset(); - - // Make the previous context current again. - if (!previous_context->IsCurrent(previous_surface.get())) - previous_context->MakeCurrent(previous_surface.get()); } TextureBase* AbstractTextureImplOnSharedContextPassthrough::GetTextureBase() diff --git a/chromium/gpu/command_buffer/service/external_semaphore.cc b/chromium/gpu/command_buffer/service/external_semaphore.cc index 8bfe986f1f8..d51d00bd0d8 100644 --- a/chromium/gpu/command_buffer/service/external_semaphore.cc +++ b/chromium/gpu/command_buffer/service/external_semaphore.cc @@ -39,7 +39,7 @@ GLuint ImportSemaphoreHandleToGLSemaphore(SemaphoreHandle handle) { }, base::Time::Now())); -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) if (handle.vk_handle_type() != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) { DLOG(ERROR) << "Importing semaphore handle of unexpected type:" diff --git a/chromium/gpu/command_buffer/service/external_semaphore_pool.cc b/chromium/gpu/command_buffer/service/external_semaphore_pool.cc index 2d8af08c456..e4a8180ab1e 100644 --- a/chromium/gpu/command_buffer/service/external_semaphore_pool.cc +++ b/chromium/gpu/command_buffer/service/external_semaphore_pool.cc @@ -15,11 +15,14 @@ namespace gpu { namespace { -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_FUCHSIA) // On Android, semaphores are created with handle type // VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT. With this handle type, // the semaphore will not be reset to un-signalled state after waiting, // so semaphores cannot be reused on Android. +// On Fuchsia semaphores are passed to scenic as zx::event. Scenic doesn't reset +// them after waiting, so they would have to be reset explicitly to be reused. +// OTOH new semaphores are cheap, so reuse doesn't provide significant benefits. constexpr size_t kMaxSemaphoresInPool = 0; #else constexpr size_t kMaxSemaphoresInPool = 16; diff --git a/chromium/gpu/command_buffer/service/external_vk_image_backing.cc b/chromium/gpu/command_buffer/service/external_vk_image_backing.cc index 191c0dd104d..263c79e9986 100644 --- a/chromium/gpu/command_buffer/service/external_vk_image_backing.cc +++ b/chromium/gpu/command_buffer/service/external_vk_image_backing.cc @@ -29,7 +29,7 @@ #include "ui/gl/gl_version_info.h" #include "ui/gl/scoped_binders.h" -#if defined(OS_LINUX) && BUILDFLAG(USE_DAWN) +#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && BUILDFLAG(USE_DAWN) #include "gpu/command_buffer/service/external_vk_image_dawn_representation.h" #endif @@ -127,8 +127,9 @@ bool UseSeparateGLTexture(SharedContextState* context_state, if (format != viz::ResourceFormat::BGRA_8888) return false; - const auto* version_info = context_state->real_context()->GetVersionInfo(); - const auto& ext = gl::g_current_gl_driver->ext; + auto* gl_context = context_state->real_context(); + const auto* version_info = gl_context->GetVersionInfo(); + const auto& ext = gl_context->GetCurrentGL()->Driver->ext; if (!ext.b_GL_EXT_texture_format_BGRA8888) return true; @@ -166,7 +167,7 @@ void WaitSemaphoresOnGrContext(GrDirectContext* gr_context, // static std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::Create( - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, VulkanCommandPool* command_pool, const Mailbox& mailbox, viz::ResourceFormat format, @@ -206,7 +207,7 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::Create( // Must request all available image usage flags if aliasing GL texture. This // is a spec requirement per EXT_memory_object. However, if // ANGLE_memory_object_flags is supported, usage flags can be arbitrary. - if (UseMinimalUsageFlags(context_state)) { + if (UseMinimalUsageFlags(context_state.get())) { // The following additional usage flags are provided for ANGLE: // // - TRANSFER_SRC: Used for copies from this image. @@ -247,10 +248,11 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::Create( if (!image) return nullptr; - bool use_separate_gl_texture = UseSeparateGLTexture(context_state, format); + bool use_separate_gl_texture = + UseSeparateGLTexture(context_state.get(), format); auto backing = std::make_unique<ExternalVkImageBacking>( util::PassKey<ExternalVkImageBacking>(), mailbox, format, size, - color_space, surface_origin, alpha_type, usage, context_state, + color_space, surface_origin, alpha_type, usage, std::move(context_state), std::move(image), command_pool, use_separate_gl_texture); if (!pixel_data.empty()) { @@ -263,7 +265,7 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::Create( // static std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::CreateFromGMB( - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, VulkanCommandPool* command_pool, const Mailbox& mailbox, gfx::GpuMemoryBufferHandle handle, @@ -293,11 +295,12 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::CreateFromGMB( } bool use_separate_gl_texture = - UseSeparateGLTexture(context_state, resource_format); + UseSeparateGLTexture(context_state.get(), resource_format); auto backing = std::make_unique<ExternalVkImageBacking>( util::PassKey<ExternalVkImageBacking>(), mailbox, resource_format, size, - color_space, surface_origin, alpha_type, usage, context_state, - std::move(image), command_pool, use_separate_gl_texture); + color_space, surface_origin, alpha_type, usage, + std::move(context_state), std::move(image), command_pool, + use_separate_gl_texture); backing->SetCleared(); return backing; } @@ -313,10 +316,10 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::CreateFromGMB( if (!shared_memory_wrapper.Initialize(handle, size, resource_format)) return nullptr; - auto backing = - Create(context_state, command_pool, mailbox, resource_format, size, - color_space, surface_origin, alpha_type, usage, image_usage_cache, - base::span<const uint8_t>(), true /* using_gmb */); + auto backing = Create(std::move(context_state), command_pool, mailbox, + resource_format, size, color_space, surface_origin, + alpha_type, usage, image_usage_cache, + base::span<const uint8_t>(), true /* using_gmb */); if (!backing) return nullptr; @@ -333,7 +336,7 @@ ExternalVkImageBacking::ExternalVkImageBacking( GrSurfaceOrigin surface_origin, SkAlphaType alpha_type, uint32_t usage, - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, std::unique_ptr<VulkanImage> image, VulkanCommandPool* command_pool, bool use_separate_gl_texture) @@ -346,7 +349,7 @@ ExternalVkImageBacking::ExternalVkImageBacking( usage, image->device_size(), false /* is_thread_safe */), - context_state_(context_state), + context_state_(std::move(context_state)), image_(std::move(image)), backend_texture_(size.width(), size.height(), @@ -554,10 +557,8 @@ void ExternalVkImageBacking::AddSemaphoresToPendingListOrRelease( // signalling but have not been signalled. In that case, we have to release // them via fence helper to make sure all submitted GPU works is finished // before releasing them. - // |context_state_| is out live fence_helper, so it is safe to use - // base::Unretained(context_state_). fence_helper()->EnqueueCleanupTaskForSubmittedWork(base::BindOnce( - [](SharedContextState* shared_context_state, + [](scoped_refptr<SharedContextState> shared_context_state, std::vector<ExternalSemaphore>, VulkanDeviceQueue* device_queue, bool device_lost) { if (!gl::GLContext::GetCurrent()) { @@ -565,7 +566,7 @@ void ExternalVkImageBacking::AddSemaphoresToPendingListOrRelease( /*needs_gl=*/true); } }, - base::Unretained(context_state_), std::move(semaphores))); + context_state_, std::move(semaphores))); } } @@ -582,7 +583,7 @@ std::unique_ptr<SharedImageRepresentationDawn> ExternalVkImageBacking::ProduceDawn(SharedImageManager* manager, MemoryTypeTracker* tracker, WGPUDevice wgpuDevice) { -#if defined(OS_LINUX) && BUILDFLAG(USE_DAWN) +#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && BUILDFLAG(USE_DAWN) auto wgpu_format = viz::ToWGPUFormat(format()); if (wgpu_format == WGPUTextureFormat_Undefined) { @@ -601,7 +602,7 @@ ExternalVkImageBacking::ProduceDawn(SharedImageManager* manager, return std::make_unique<ExternalVkImageDawnRepresentation>( manager, this, tracker, wgpuDevice, wgpu_format, std::move(memory_fd)); -#else // !defined(OS_LINUX) || !BUILDFLAG(USE_DAWN) +#else // (!defined(OS_LINUX) && !defined(OS_CHROMEOS)) || !BUILDFLAG(USE_DAWN) NOTIMPLEMENTED_LOG_ONCE(); return nullptr; #endif @@ -614,7 +615,7 @@ GLuint ExternalVkImageBacking::ProduceGLTextureInternal() { gl::GLApi* api = gl::g_current_gl_context; base::Optional<ScopedDedicatedMemoryObject> memory_object; if (!use_separate_gl_texture()) { -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) auto memory_fd = image_->GetMemoryFd(); if (!memory_fd.is_valid()) return 0; @@ -662,7 +663,7 @@ GLuint ExternalVkImageBacking::ProduceGLTextureInternal() { // If ANGLE_memory_object_flags is supported, use that to communicate the // exact create and usage flags the image was created with. DCHECK(image_->usage() != 0); - if (UseMinimalUsageFlags(context_state_)) { + if (UseMinimalUsageFlags(context_state())) { api->glTexStorageMemFlags2DANGLEFn( GL_TEXTURE_2D, 1, internal_format, size().width(), size().height(), memory_object->id(), 0, image_->flags(), image_->usage()); @@ -749,7 +750,7 @@ ExternalVkImageBacking::ProduceSkia( scoped_refptr<SharedContextState> context_state) { // This backing type is only used when vulkan is enabled, so SkiaRenderer // should also be using Vulkan. - DCHECK_EQ(context_state_, context_state.get()); + DCHECK_EQ(context_state_, context_state); DCHECK(context_state->GrContextIsVulkan()); return std::make_unique<ExternalVkImageSkiaRepresentation>(manager, this, tracker); diff --git a/chromium/gpu/command_buffer/service/external_vk_image_backing.h b/chromium/gpu/command_buffer/service/external_vk_image_backing.h index 4d4523a4bd6..27397700c98 100644 --- a/chromium/gpu/command_buffer/service/external_vk_image_backing.h +++ b/chromium/gpu/command_buffer/service/external_vk_image_backing.h @@ -34,7 +34,7 @@ struct VulkanImageUsageCache { class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking { public: static std::unique_ptr<ExternalVkImageBacking> Create( - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, VulkanCommandPool* command_pool, const Mailbox& mailbox, viz::ResourceFormat format, @@ -48,7 +48,7 @@ class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking { bool using_gmb = false); static std::unique_ptr<ExternalVkImageBacking> CreateFromGMB( - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, VulkanCommandPool* command_pool, const Mailbox& mailbox, gfx::GpuMemoryBufferHandle handle, @@ -68,14 +68,14 @@ class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking { GrSurfaceOrigin surface_origin, SkAlphaType alpha_type, uint32_t usage, - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, std::unique_ptr<VulkanImage> image, VulkanCommandPool* command_pool, bool use_separate_gl_texture); ~ExternalVkImageBacking() override; - SharedContextState* context_state() const { return context_state_; } + SharedContextState* context_state() const { return context_state_.get(); } const GrBackendTexture& backend_texture() const { return backend_texture_; } VulkanImage* image() const { return image_.get(); } const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough() @@ -178,7 +178,7 @@ class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking { void CopyPixelsFromGLTextureToVkImage(); void CopyPixelsFromShmToGLTexture(); - SharedContextState* const context_state_; + scoped_refptr<SharedContextState> context_state_; std::unique_ptr<VulkanImage> image_; GrBackendTexture backend_texture_; VulkanCommandPool* const command_pool_; diff --git a/chromium/gpu/command_buffer/service/external_vk_image_factory.cc b/chromium/gpu/command_buffer/service/external_vk_image_factory.cc index be1f1ad8cb1..1ac61030927 100644 --- a/chromium/gpu/command_buffer/service/external_vk_image_factory.cc +++ b/chromium/gpu/command_buffer/service/external_vk_image_factory.cc @@ -61,8 +61,8 @@ VulkanImageUsageCache CreateImageUsageCache( } // namespace ExternalVkImageFactory::ExternalVkImageFactory( - SharedContextState* context_state) - : context_state_(context_state), + scoped_refptr<SharedContextState> context_state) + : context_state_(std::move(context_state)), command_pool_(context_state_->vk_context_provider() ->GetDeviceQueue() ->CreateCommandPool()), diff --git a/chromium/gpu/command_buffer/service/external_vk_image_factory.h b/chromium/gpu/command_buffer/service/external_vk_image_factory.h index 63d36f2a1ae..f736400c53b 100644 --- a/chromium/gpu/command_buffer/service/external_vk_image_factory.h +++ b/chromium/gpu/command_buffer/service/external_vk_image_factory.h @@ -22,7 +22,8 @@ class VulkanCommandPool; // that allow it to be exported out and shared with GL. class ExternalVkImageFactory : public SharedImageBackingFactory { public: - explicit ExternalVkImageFactory(SharedContextState* context_state); + explicit ExternalVkImageFactory( + scoped_refptr<SharedContextState> context_state); ~ExternalVkImageFactory() override; // SharedImageBackingFactory implementation. @@ -66,7 +67,7 @@ class ExternalVkImageFactory : public SharedImageBackingFactory { void TransitionToColorAttachment(VkImage image); - SharedContextState* const context_state_; + scoped_refptr<SharedContextState> context_state_; std::unique_ptr<VulkanCommandPool> command_pool_; const VulkanImageUsageCache image_usage_cache_; diff --git a/chromium/gpu/command_buffer/service/external_vk_image_skia_representation.cc b/chromium/gpu/command_buffer/service/external_vk_image_skia_representation.cc index 5a88fd66991..380d617ba45 100644 --- a/chromium/gpu/command_buffer/service/external_vk_image_skia_representation.cc +++ b/chromium/gpu/command_buffer/service/external_vk_image_skia_representation.cc @@ -85,7 +85,7 @@ sk_sp<SkSurface> ExternalVkImageSkiaRepresentation::BeginWriteAccess( // VkImage to VK_QUEUE_FAMILY_EXTERNAL before calling EndAccess(). if (backing_impl()->need_synchronization()) { *end_state = std::make_unique<GrBackendSurfaceMutableState>( - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_EXTERNAL); + VK_IMAGE_LAYOUT_UNDEFINED, VK_QUEUE_FAMILY_EXTERNAL); } return surface; @@ -125,7 +125,7 @@ sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginReadAccess( // VK_QUEUE_FAMILY_EXTERNAL before calling EndAccess(). if (!backing_impl()->use_separate_gl_texture()) { *end_state = std::make_unique<GrBackendSurfaceMutableState>( - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_EXTERNAL); + VK_IMAGE_LAYOUT_UNDEFINED, VK_QUEUE_FAMILY_EXTERNAL); } access_mode_ = kRead; diff --git a/chromium/gpu/command_buffer/service/feature_info.cc b/chromium/gpu/command_buffer/service/feature_info.cc index 422e1bd7d63..d51c538b1fa 100644 --- a/chromium/gpu/command_buffer/service/feature_info.cc +++ b/chromium/gpu/command_buffer/service/feature_info.cc @@ -10,6 +10,7 @@ #include <vector> #include "base/command_line.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" @@ -1822,96 +1823,131 @@ void FeatureInfo::InitializeFloatAndHalfFloatFeatures( if (may_enable_chromium_color_buffer_float && !had_native_chromium_color_buffer_float_ext) { - static_assert(GL_RGBA32F_ARB == GL_RGBA32F && - GL_RGBA32F_EXT == GL_RGBA32F && - GL_RGB32F_ARB == GL_RGB32F && GL_RGB32F_EXT == GL_RGB32F, - "sized float internal format variations must match"); - // We don't check extension support beyond ARB_texture_float on desktop GL, - // and format support varies between GL configurations. For example, spec - // prior to OpenGL 3.0 mandates framebuffer support only for one - // implementation-chosen format, and ES3.0 EXT_color_buffer_float does not - // support rendering to RGB32F. Check for framebuffer completeness with - // formats that the extensions expose, and only enable an extension when a - // framebuffer created with its texture format is reported as complete. - GLint fb_binding = 0; - GLint tex_binding = 0; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb_binding); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex_binding); - - GLuint tex_id = 0; - GLuint fb_id = 0; - GLsizei width = 16; - - glGenTextures(1, &tex_id); - glGenFramebuffersEXT(1, &fb_id); - glBindTexture(GL_TEXTURE_2D, tex_id); - // Nearest filter needed for framebuffer completeness on some drivers. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, GL_RGBA, - GL_FLOAT, nullptr); - glBindFramebufferEXT(GL_FRAMEBUFFER, fb_id); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, tex_id, 0); - GLenum status_rgba = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, GL_RGB, GL_FLOAT, - nullptr); - GLenum status_rgb = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); - - // For desktop systems, check to see if we support rendering to the full - // range of formats supported by EXT_color_buffer_float - if (status_rgba == GL_FRAMEBUFFER_COMPLETE && enable_es3) { - bool full_float_support = true; - GLenum internal_formats[] = { - GL_R16F, GL_RG16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_R11F_G11F_B10F, - }; - GLenum formats[] = { - GL_RED, GL_RG, GL_RGBA, GL_RED, GL_RG, GL_RGB, - }; - DCHECK_EQ(base::size(internal_formats), base::size(formats)); - for (size_t i = 0; i < base::size(formats); ++i) { - glTexImage2D(GL_TEXTURE_2D, 0, internal_formats[i], width, width, 0, - formats[i], GL_FLOAT, nullptr); - full_float_support &= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) == - GL_FRAMEBUFFER_COMPLETE; + if (workarounds_.force_enable_color_buffer_float || + workarounds_.force_enable_color_buffer_float_except_rgb32f) { + if (enable_es3) + enable_ext_color_buffer_float = true; + if (IsWebGL1OrES2Context() && !enable_ext_color_buffer_half_float && + gl_version_info_->IsAtLeastGL(3, 0)) { + enable_ext_color_buffer_half_float = true; + } + feature_flags_.chromium_color_buffer_float_rgba = true; + if (!disallowed_features_.chromium_color_buffer_float_rgba) + EnableCHROMIUMColorBufferFloatRGBA(); + if (!workarounds_.force_enable_color_buffer_float_except_rgb32f) { + feature_flags_.chromium_color_buffer_float_rgb = true; + if (!disallowed_features_.chromium_color_buffer_float_rgb) + EnableCHROMIUMColorBufferFloatRGB(); + } + } else { + static_assert( + GL_RGBA32F_ARB == GL_RGBA32F && GL_RGBA32F_EXT == GL_RGBA32F && + GL_RGB32F_ARB == GL_RGB32F && GL_RGB32F_EXT == GL_RGB32F, + "sized float internal format variations must match"); + // We don't check extension support beyond ARB_texture_float on desktop + // GL, and format support varies between GL configurations. For example, + // spec prior to OpenGL 3.0 mandates framebuffer support only for one + // implementation-chosen format, and ES3.0 EXT_color_buffer_float does not + // support rendering to RGB32F. Check for framebuffer completeness with + // formats that the extensions expose, and only enable an extension when a + // framebuffer created with its texture format is reported as complete. + GLint fb_binding = 0; + GLint tex_binding = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fb_binding); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex_binding); + + GLuint tex_id = 0; + GLuint fb_id = 0; + GLsizei width = 16; + + glGenTextures(1, &tex_id); + glGenFramebuffersEXT(1, &fb_id); + glBindTexture(GL_TEXTURE_2D, tex_id); + // Nearest filter needed for framebuffer completeness on some drivers. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, GL_RGBA, + GL_FLOAT, nullptr); + glBindFramebufferEXT(GL_FRAMEBUFFER, fb_id); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, tex_id, 0); + GLenum status_rgba = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, GL_RGB, + GL_FLOAT, nullptr); + GLenum status_rgb = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + base::UmaHistogramBoolean("GPU.RenderableFormat.RGBA32F.FLOAT", + status_rgba == GL_FRAMEBUFFER_COMPLETE); + base::UmaHistogramBoolean("GPU.RenderableFormat.RGB32F.FLOAT", + status_rgb == GL_FRAMEBUFFER_COMPLETE); + + // For desktop systems, check to see if we support rendering to the full + // range of formats supported by EXT_color_buffer_float + if (status_rgba == GL_FRAMEBUFFER_COMPLETE && enable_es3) { + bool full_float_support = true; + const GLenum kInternalFormats[] = { + GL_R16F, GL_RG16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_R11F_G11F_B10F, + }; + const GLenum kFormats[] = { + GL_RED, GL_RG, GL_RGBA, GL_RED, GL_RG, GL_RGB, + }; + const char* kInternalFormatHistogramNames[] = { + "GPU.RenderableFormat.R16F.FLOAT", + "GPU.RenderableFormat.RG16F.FLOAT", + "GPU.RenderableFormat.RGBA16F.FLOAT", + "GPU.RenderableFormat.R32F.FLOAT", + "GPU.RenderableFormat.RG32F.FLOAT", + "GPU.RenderableFormat.R11F_G11F_B10F.FLOAT", + }; + DCHECK_EQ(base::size(kInternalFormats), base::size(kFormats)); + for (size_t i = 0; i < base::size(kFormats); ++i) { + glTexImage2D(GL_TEXTURE_2D, 0, kInternalFormats[i], width, width, 0, + kFormats[i], GL_FLOAT, nullptr); + bool supported = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) == + GL_FRAMEBUFFER_COMPLETE; + base::UmaHistogramBoolean(kInternalFormatHistogramNames[i], + supported); + full_float_support &= supported; + } + enable_ext_color_buffer_float = full_float_support; + } + // Likewise for EXT_color_buffer_half_float on ES2 contexts. On desktop, + // require at least GL 3.0, to ensure that all formats are defined. + if (IsWebGL1OrES2Context() && !enable_ext_color_buffer_half_float && + (gl_version_info_->IsAtLeastGLES(3, 0) || + gl_version_info_->IsAtLeastGL(3, 0))) { + // EXT_color_buffer_half_float requires at least one of the formats is + // supported to be color-renderable. WebGL's extension requires RGBA16F + // to be the supported effective format. Here we only expose the + // extension if RGBA16F is color-renderable. + GLenum internal_format = GL_RGBA16F; + GLenum format = GL_RGBA; + GLenum data_type = GL_HALF_FLOAT; + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, width, 0, format, + data_type, nullptr); + bool supported = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) == + GL_FRAMEBUFFER_COMPLETE; + base::UmaHistogramBoolean("GPU.RenderableFormat.RGBA16F.HALF_FLOAT", + supported); + enable_ext_color_buffer_half_float = supported; } - enable_ext_color_buffer_float = full_float_support; - } - // Likewise for EXT_color_buffer_half_float on ES2 contexts. On desktop, - // require at least GL 3.0, to ensure that all formats are defined. - if (IsWebGL1OrES2Context() && !enable_ext_color_buffer_half_float && - (gl_version_info_->IsAtLeastGLES(3, 0) || - gl_version_info_->IsAtLeastGL(3, 0))) { - // EXT_color_buffer_half_float requires at least one of the formats is - // supported to be color-renderable. WebGL's extension requires RGBA16F - // to be the supported effective format. Here we only expose the extension - // if RGBA16F is color-renderable. - GLenum internal_format = GL_RGBA16F; - GLenum format = GL_RGBA; - GLenum data_type = GL_HALF_FLOAT; - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, width, 0, format, - data_type, nullptr); - enable_ext_color_buffer_half_float = - (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) == - GL_FRAMEBUFFER_COMPLETE); - } - glDeleteFramebuffersEXT(1, &fb_id); - glDeleteTextures(1, &tex_id); + glDeleteFramebuffersEXT(1, &fb_id); + glDeleteTextures(1, &tex_id); - glBindFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLuint>(fb_binding)); - glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(tex_binding)); + glBindFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLuint>(fb_binding)); + glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(tex_binding)); - DCHECK_EQ(glGetError(), static_cast<GLuint>(GL_NO_ERROR)); + DCHECK_EQ(glGetError(), static_cast<GLuint>(GL_NO_ERROR)); - if (status_rgba == GL_FRAMEBUFFER_COMPLETE) { - feature_flags_.chromium_color_buffer_float_rgba = true; - if (!disallowed_features_.chromium_color_buffer_float_rgba) - EnableCHROMIUMColorBufferFloatRGBA(); - } - if (status_rgb == GL_FRAMEBUFFER_COMPLETE) { - feature_flags_.chromium_color_buffer_float_rgb = true; - if (!disallowed_features_.chromium_color_buffer_float_rgb) - EnableCHROMIUMColorBufferFloatRGB(); + if (status_rgba == GL_FRAMEBUFFER_COMPLETE) { + feature_flags_.chromium_color_buffer_float_rgba = true; + if (!disallowed_features_.chromium_color_buffer_float_rgba) + EnableCHROMIUMColorBufferFloatRGBA(); + } + if (status_rgb == GL_FRAMEBUFFER_COMPLETE) { + feature_flags_.chromium_color_buffer_float_rgb = true; + if (!disallowed_features_.chromium_color_buffer_float_rgb) + EnableCHROMIUMColorBufferFloatRGB(); + } } } diff --git a/chromium/gpu/command_buffer/service/gl_utils.cc b/chromium/gpu/command_buffer/service/gl_utils.cc index 0755855b068..6099654615f 100644 --- a/chromium/gpu/command_buffer/service/gl_utils.cc +++ b/chromium/gpu/command_buffer/service/gl_utils.cc @@ -47,11 +47,9 @@ bool IsValidPVRTCSize(GLint level, GLsizei size) { } bool IsValidS3TCSizeForWebGLAndANGLE(GLint level, GLsizei size) { - // WebGL and ANGLE only allow multiple-of-4 sizes, except for levels > 0 where - // it also allows 1 or 2. See WEBGL_compressed_texture_s3tc and - // ANGLE_compressed_texture_dxt* - return (level && size == 1) || (level && size == 2) || - !(size % kS3TCBlockWidth); + // WebGL and ANGLE only allow multiple-of-4 sizes for the base level. See + // WEBGL_compressed_texture_s3tc and ANGLE_compressed_texture_dxt* + return (level > 0) || (size % kS3TCBlockWidth == 0); } const char* GetDebugSourceString(GLenum source) { diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc index 2c87eac1bea..2d5ca431c5c 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -13981,16 +13981,15 @@ void GLES2DecoderImpl::DoScheduleCALayerInUseQueryCHROMIUM( gl::GLImage* image = nullptr; GLuint texture_id = textures[i]; if (texture_id) { + // If a |texture_id| is invalid (due to a client error), report that it + // is not in use. Failing the GL call can result in compositor hangs. + // https://crbug.com/1120795 TextureRef* ref = texture_manager()->GetTexture(texture_id); - if (!ref) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, - "glScheduleCALayerInUseQueryCHROMIUM", - "unknown texture"); - return; + if (ref) { + Texture::ImageState image_state; + image = ref->texture()->GetLevelImage(ref->texture()->target(), 0, + &image_state); } - Texture::ImageState image_state; - image = ref->texture()->GetLevelImage(ref->texture()->target(), 0, - &image_state); } gl::GLSurface::CALayerInUseQuery query; query.image = image; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index 7a44b17b907..045c71984cb 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc @@ -265,6 +265,27 @@ void UpdateBoundTexturePassthroughSize(gl::GLApi* api, texture->SetEstimatedSize(texture_memory_size); } +void ReturnProgramInfoData(DecoderClient* client, + const std::vector<uint8_t>& info, + GLES2ReturnDataType type, + uint32_t program) { + // Limit the data size in order not to block the IO threads too long. + // https://docs.google.com/document/d/1qEfU0lAkeZ8lU06qtxv7ENGxRxExxztXu1LhIDNGqtU/edit?disco=AAAACksORlU + constexpr static size_t kMaxDataSize = 8 * 1024 * 1024; + if (info.size() > kMaxDataSize) + return; + + std::vector<uint8_t> return_data; + return_data.resize(sizeof(cmds::GLES2ReturnProgramInfo) + info.size()); + auto* return_program_info = + reinterpret_cast<cmds::GLES2ReturnProgramInfo*>(return_data.data()); + return_program_info->return_data_header.return_data_type = type; + return_program_info->program_client_id = program; + memcpy(return_program_info->deserialized_buffer, info.data(), info.size()); + client->HandleReturnData( + base::span<uint8_t>(return_data.data(), return_data.size())); +} + } // anonymous namespace GLES2DecoderPassthroughImpl::TexturePendingBinding::TexturePendingBinding( @@ -2469,6 +2490,52 @@ error::Error GLES2DecoderPassthroughImpl::ProcessQueries(bool did_finish) { api()->glGetProgramivFn(query.program_service_id, GL_LINK_STATUS, &link_status); result = link_status; + + // Send back all program information as early as possible to be cached + // at the client side. + GLuint program_client_id = 0u; + GetClientID(&resources_->program_id_map, query.program_service_id, + &program_client_id); + + // TODO(jie.a.chen@intel.com): Merge the all return data into 1 IPC + // message if it becomes a concern. + std::vector<uint8_t> program_info; + error::Error error = + DoGetProgramInfoCHROMIUM(program_client_id, &program_info); + if (error == error::kNoError) { + ReturnProgramInfoData(client(), program_info, + GLES2ReturnDataType::kES2ProgramInfo, + program_client_id); + } + + if (feature_info_->IsWebGL2OrES3OrHigherContext()) { + std::vector<uint8_t> uniform_blocks; + error = + DoGetUniformBlocksCHROMIUM(program_client_id, &uniform_blocks); + if (error == error::kNoError) { + ReturnProgramInfoData(client(), uniform_blocks, + GLES2ReturnDataType::kES3UniformBlocks, + program_client_id); + } + + std::vector<uint8_t> transform_feedback_varyings; + error = DoGetTransformFeedbackVaryingsCHROMIUM( + program_client_id, &transform_feedback_varyings); + if (error == error::kNoError) { + ReturnProgramInfoData( + client(), transform_feedback_varyings, + GLES2ReturnDataType::kES3TransformFeedbackVaryings, + program_client_id); + } + + std::vector<uint8_t> uniforms; + error = DoGetUniformsES3CHROMIUM(program_client_id, &uniforms); + if (error == error::kNoError) { + ReturnProgramInfoData(client(), uniforms, + GLES2ReturnDataType::kES3Uniforms, + program_client_id); + } + } } break; diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index 6c9948d52a4..f6edc0fbce7 100644 --- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc @@ -1289,8 +1289,14 @@ error::Error GLES2DecoderPassthroughImpl::DoFenceSync(GLenum condition, } error::Error GLES2DecoderPassthroughImpl::DoFinish() { + // Finish can take a long time, make sure the watchdog gives it the most + // amount of time to complete. + group_->ReportProgress(); + api()->glFinishFn(); + group_->ReportProgress(); + error::Error error = ProcessReadPixels(true); if (error != error::kNoError) { return error; @@ -1518,9 +1524,11 @@ error::Error GLES2DecoderPassthroughImpl::DoGetActiveAttrib(GLuint program, } std::vector<char> name_buffer(active_attribute_max_length, 0); - api()->glGetActiveAttribFn(service_id, index, name_buffer.size(), nullptr, + GLsizei length = 0; + api()->glGetActiveAttribFn(service_id, index, name_buffer.size(), &length, size, type, name_buffer.data()); - *name = std::string(name_buffer.data()); + DCHECK(length <= active_attribute_max_length); + *name = length > 0 ? std::string(name_buffer.data(), length) : std::string(); *success = CheckErrorCallbackState() ? 0 : 1; return error::kNoError; } @@ -1543,9 +1551,11 @@ error::Error GLES2DecoderPassthroughImpl::DoGetActiveUniform(GLuint program, } std::vector<char> name_buffer(active_uniform_max_length, 0); - api()->glGetActiveUniformFn(service_id, index, name_buffer.size(), nullptr, + GLsizei length = 0; + api()->glGetActiveUniformFn(service_id, index, name_buffer.size(), &length, size, type, name_buffer.data()); - *name = std::string(name_buffer.data()); + DCHECK(length <= active_uniform_max_length); + *name = length > 0 ? std::string(name_buffer.data(), length) : std::string(); *success = CheckErrorCallbackState() ? 0 : 1; return error::kNoError; } @@ -2080,10 +2090,12 @@ error::Error GLES2DecoderPassthroughImpl::DoGetTransformFeedbackVarying( } std::vector<char> name_buffer(transform_feedback_varying_max_length, 0); + GLsizei length = 0; api()->glGetTransformFeedbackVaryingFn(service_id, index, name_buffer.size(), - nullptr, size, type, + &length, size, type, name_buffer.data()); - *name = std::string(name_buffer.data()); + DCHECK(length <= transform_feedback_varying_max_length); + *name = length > 0 ? std::string(name_buffer.data(), length) : std::string(); *success = CheckErrorCallbackState() ? 0 : 1; return error::kNoError; } @@ -4388,9 +4400,13 @@ error::Error GLES2DecoderPassthroughImpl::DoGetTranslatedShaderSourceANGLE( if (translated_source_length > 0) { std::vector<char> buffer(translated_source_length, 0); + GLsizei length = 0; api()->glGetTranslatedShaderSourceANGLEFn( - service_id, translated_source_length, nullptr, buffer.data()); - *source = std::string(buffer.data()); + service_id, translated_source_length, &length, buffer.data()); + DCHECK(length <= translated_source_length); + *source = length > 0 ? std::string(buffer.data(), length) : std::string(); + } else { + *source = std::string(); } return error::kNoError; } @@ -4909,15 +4925,17 @@ error::Error GLES2DecoderPassthroughImpl::DoScheduleCALayerInUseQueryCHROMIUM( gl::GLImage* image = nullptr; GLuint texture_id = textures[i]; if (texture_id) { + // If a |texture_id| is invalid (due to a client error), report that it + // is not in use. Failing the GL call can result in compositor hangs. + // https://crbug.com/1120795 scoped_refptr<TexturePassthrough> passthrough_texture; - if (!resources_->texture_object_map.GetServiceID(texture_id, - &passthrough_texture) || - passthrough_texture == nullptr) { - InsertError(GL_INVALID_VALUE, "unknown texture"); - return error::kNoError; + if (resources_->texture_object_map.GetServiceID(texture_id, + &passthrough_texture)) { + if (passthrough_texture) { + image = passthrough_texture->GetLevelImage( + passthrough_texture->target(), 0); + } } - image = - passthrough_texture->GetLevelImage(passthrough_texture->target(), 0); } gl::GLSurface::CALayerInUseQuery query; query.image = image; diff --git a/chromium/gpu/command_buffer/service/gpu_fence_manager.cc b/chromium/gpu/command_buffer/service/gpu_fence_manager.cc index c7e11638b0c..b70675a1c6a 100644 --- a/chromium/gpu/command_buffer/service/gpu_fence_manager.cc +++ b/chromium/gpu/command_buffer/service/gpu_fence_manager.cc @@ -40,9 +40,8 @@ bool GpuFenceManager::CreateGpuFence(uint32_t client_id) { return true; } -bool GpuFenceManager::CreateGpuFenceFromHandle( - uint32_t client_id, - const gfx::GpuFenceHandle& handle) { +bool GpuFenceManager::CreateGpuFenceFromHandle(uint32_t client_id, + gfx::GpuFenceHandle handle) { // The handle must be valid. The fallback kEmpty type cannot be duplicated. if (handle.is_null()) return false; @@ -52,7 +51,7 @@ bool GpuFenceManager::CreateGpuFenceFromHandle( if (it != gpu_fence_entries_.end()) return false; - gfx::GpuFence gpu_fence(handle); + gfx::GpuFence gpu_fence(std::move(handle)); auto entry = std::make_unique<GpuFenceEntry>(); entry->gl_fence_ = gl::GLFence::CreateFromGpuFence(gpu_fence); if (!entry->gl_fence_) diff --git a/chromium/gpu/command_buffer/service/gpu_fence_manager.h b/chromium/gpu/command_buffer/service/gpu_fence_manager.h index c6e03a800eb..ee50d6fddd1 100644 --- a/chromium/gpu/command_buffer/service/gpu_fence_manager.h +++ b/chromium/gpu/command_buffer/service/gpu_fence_manager.h @@ -48,8 +48,7 @@ class GPU_GLES2_EXPORT GpuFenceManager { bool CreateGpuFence(uint32_t client_id); - bool CreateGpuFenceFromHandle(uint32_t client_id, - const gfx::GpuFenceHandle& handle); + bool CreateGpuFenceFromHandle(uint32_t client_id, gfx::GpuFenceHandle handle); bool IsValidGpuFence(uint32_t client_id); diff --git a/chromium/gpu/command_buffer/service/gpu_fence_manager_unittest.cc b/chromium/gpu/command_buffer/service/gpu_fence_manager_unittest.cc index cc96195a153..20e5dee63c8 100644 --- a/chromium/gpu/command_buffer/service/gpu_fence_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/gpu_fence_manager_unittest.cc @@ -172,10 +172,9 @@ TEST_F(GpuFenceManagerTest, GetGpuFence) { .RetiresOnSaturation(); std::unique_ptr<gfx::GpuFence> gpu_fence = manager_->GetGpuFence(kClient1Id); EXPECT_TRUE(gpu_fence); - gfx::GpuFenceHandle handle = gpu_fence->GetGpuFenceHandle(); + const gfx::GpuFenceHandle& handle = gpu_fence->GetGpuFenceHandle(); - EXPECT_EQ(handle.type, gfx::GpuFenceHandleType::kAndroidNativeFenceSync); - EXPECT_EQ(handle.native_fd.fd, kFenceFD); + EXPECT_EQ(handle.owned_fd.get(), kFenceFD); // Removing the fence marks it invalid. EXPECT_CALL(*egl_, DestroySyncKHR(_, kDummySync)) @@ -194,8 +193,7 @@ TEST_F(GpuFenceManagerTest, Duplication) { // Create a handle. gfx::GpuFenceHandle handle; - handle.type = gfx::GpuFenceHandleType::kAndroidNativeFenceSync; - handle.native_fd = base::FileDescriptor(kFenceFD, true); + handle.owned_fd = base::ScopedFD(kFenceFD); // Create a duplicate fence object from it. EXPECT_CALL(*egl_, CreateSyncKHR(_, EGL_SYNC_NATIVE_FENCE_ANDROID, _)) @@ -203,7 +201,8 @@ TEST_F(GpuFenceManagerTest, Duplication) { .WillOnce(Return(kDummySync)) .RetiresOnSaturation(); EXPECT_CALL(*gl_, Flush()).Times(1).RetiresOnSaturation(); - EXPECT_TRUE(manager_->CreateGpuFenceFromHandle(kClient1Id, handle)); + EXPECT_TRUE( + manager_->CreateGpuFenceFromHandle(kClient1Id, std::move(handle))); EXPECT_TRUE(manager_->IsValidGpuFence(kClient1Id)); // Try a server wait on it. diff --git a/chromium/gpu/command_buffer/service/image_reader_gl_owner.cc b/chromium/gpu/command_buffer/service/image_reader_gl_owner.cc index bfc7f47b66a..837750ffa17 100644 --- a/chromium/gpu/command_buffer/service/image_reader_gl_owner.cc +++ b/chromium/gpu/command_buffer/service/image_reader_gl_owner.cc @@ -9,6 +9,7 @@ #include <stdint.h> #include "base/android/android_hardware_buffer_compat.h" +#include "base/android/android_image_reader_compat.h" #include "base/android/jni_android.h" #include "base/android/scoped_hardware_buffer_fence_sync.h" #include "base/logging.h" @@ -20,7 +21,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "gpu/command_buffer/service/abstract_texture.h" #include "gpu/ipc/common/android/android_image_reader_utils.h" -#include "media/base/android/media_codec_util.h" #include "ui/gl/android/android_surface_control_compat.h" #include "ui/gl/gl_fence_android_native_fence_sync.h" #include "ui/gl/gl_utils.h" @@ -62,10 +62,11 @@ bool IsSurfaceControl(TextureOwner::Mode mode) { uint32_t NumRequiredMaxImages(TextureOwner::Mode mode) { if (IsSurfaceControl(mode) || mode == TextureOwner::Mode::kAImageReaderInsecureMultithreaded) { - DCHECK(!media::MediaCodecUtil::LimitAImageReaderMaxSizeToOne()); + DCHECK(!base::android::AndroidImageReader::LimitAImageReaderMaxSizeToOne()); return 3; } - return media::MediaCodecUtil::LimitAImageReaderMaxSizeToOne() ? 1 : 2; + return base::android::AndroidImageReader::LimitAImageReaderMaxSizeToOne() ? 1 + : 2; } } // namespace diff --git a/chromium/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc b/chromium/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc index 2f03c9f174a..cd675ad2fe7 100644 --- a/chromium/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc +++ b/chromium/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc @@ -8,11 +8,11 @@ #include <memory> #include <utility> +#include "base/android/android_image_reader_compat.h" #include "base/test/task_environment.h" #include "gpu/command_buffer/service/abstract_texture.h" #include "gpu/command_buffer/service/image_reader_gl_owner.h" #include "gpu/command_buffer/service/mock_abstract_texture.h" -#include "media/base/android/media_codec_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context_egl.h" @@ -149,7 +149,9 @@ TEST_F(ImageReaderGLOwnerTest, MaxImageExpectation) { return; EXPECT_EQ(static_cast<ImageReaderGLOwner*>(image_reader_.get()) ->max_images_for_testing(), - media::MediaCodecUtil::LimitAImageReaderMaxSizeToOne() ? 1 : 2); + base::android::AndroidImageReader::LimitAImageReaderMaxSizeToOne() + ? 1 + : 2); } class ImageReaderGLOwnerSecureSurfaceControlTest diff --git a/chromium/gpu/command_buffer/service/raster_decoder.cc b/chromium/gpu/command_buffer/service/raster_decoder.cc index f6e682699d3..04e3061f74d 100644 --- a/chromium/gpu/command_buffer/service/raster_decoder.cc +++ b/chromium/gpu/command_buffer/service/raster_decoder.cc @@ -65,6 +65,7 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurfaceProps.h" #include "third_party/skia/include/core/SkTypeface.h" +#include "third_party/skia/include/core/SkYUVAIndex.h" #include "third_party/skia/include/gpu/GrBackendSemaphore.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" diff --git a/chromium/gpu/command_buffer/service/shared_context_state.cc b/chromium/gpu/command_buffer/service/shared_context_state.cc index bc48671c5c2..eaf0b3a4a0c 100644 --- a/chromium/gpu/command_buffer/service/shared_context_state.cc +++ b/chromium/gpu/command_buffer/service/shared_context_state.cc @@ -734,45 +734,40 @@ QueryManager* SharedContextState::GetQueryManager() { return nullptr; } -bool SharedContextState::CheckResetStatus(bool needs_gl) { +base::Optional<error::ContextLostReason> SharedContextState::GetResetStatus( + bool needs_gl) { DCHECK(!context_lost()); - if (device_needs_reset_) - return true; - if (gr_context_) { // Maybe Skia detected VK_ERROR_DEVICE_LOST. if (gr_context_->abandoned()) { LOG(ERROR) << "SharedContextState context lost via Skia."; - device_needs_reset_ = true; - MarkContextLost(error::kUnknown); - return true; + return error::kUnknown; } if (gr_context_->oomed()) { LOG(ERROR) << "SharedContextState context lost via Skia OOM."; - device_needs_reset_ = true; - MarkContextLost(error::kOutOfMemory); - return true; + return error::kOutOfMemory; } } // Not using GL. if (!GrContextIsGL() && !needs_gl) - return false; + return base::nullopt; // GL is not initialized. if (!context_state_) - return false; + return base::nullopt; - GLenum error = context_state_->api()->glGetErrorFn(); - if (error == GL_OUT_OF_MEMORY) { - LOG(ERROR) << "SharedContextState lost due to GL_OUT_OF_MEMORY"; - MarkContextLost(error::kOutOfMemory); - device_needs_reset_ = true; - return true; + GLenum error; + while ((error = context_state_->api()->glGetErrorFn()) != GL_NO_ERROR) { + if (error == GL_OUT_OF_MEMORY) { + LOG(ERROR) << "SharedContextState lost due to GL_OUT_OF_MEMORY"; + return error::kOutOfMemory; + } + if (error == GL_CONTEXT_LOST_KHR) + break; } - // Checking the reset status is expensive on some OS/drivers // (https://crbug.com/1090232). Rate limit it. constexpr base::TimeDelta kMinCheckDelay = @@ -780,33 +775,42 @@ bool SharedContextState::CheckResetStatus(bool needs_gl) { base::Time now = base::Time::Now(); if (!disable_check_reset_status_throttling_for_test_ && now < last_gl_check_graphics_reset_status_ + kMinCheckDelay) { - return false; + return base::nullopt; } last_gl_check_graphics_reset_status_ = now; GLenum driver_status = context()->CheckStickyGraphicsResetStatus(); if (driver_status == GL_NO_ERROR) - return false; + return base::nullopt; LOG(ERROR) << "SharedContextState context lost via ARB/EXT_robustness. Reset " "status = " << gles2::GLES2Util::GetStringEnum(driver_status); - device_needs_reset_ = true; switch (driver_status) { case GL_GUILTY_CONTEXT_RESET_ARB: - MarkContextLost(error::kGuilty); - break; + return error::kGuilty; case GL_INNOCENT_CONTEXT_RESET_ARB: - MarkContextLost(error::kInnocent); - break; + return error::kInnocent; case GL_UNKNOWN_CONTEXT_RESET_ARB: - MarkContextLost(error::kUnknown); - break; + return error::kUnknown; default: NOTREACHED(); break; } - return true; + return base::nullopt; +} + +bool SharedContextState::CheckResetStatus(bool need_gl) { + DCHECK(!context_lost()); + DCHECK(!device_needs_reset_); + + auto status = GetResetStatus(need_gl); + if (status.has_value()) { + device_needs_reset_ = true; + MarkContextLost(status.value()); + return true; + } + return false; } } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/shared_context_state.h b/chromium/gpu/command_buffer/service/shared_context_state.h index 02416325bdf..bcba574d587 100644 --- a/chromium/gpu/command_buffer/service/shared_context_state.h +++ b/chromium/gpu/command_buffer/service/shared_context_state.h @@ -273,6 +273,8 @@ class GPU_GLES2_EXPORT SharedContextState ~SharedContextState() override; + base::Optional<error::ContextLostReason> GetResetStatus(bool needs_gl); + // gpu::GLContextVirtualDelegate implementation. bool initialized() const override; const gles2::ContextState* GetContextState() override; diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_d3d.cc b/chromium/gpu/command_buffer/service/shared_image_backing_d3d.cc index 194259c931c..05748005ef1 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_d3d.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_d3d.cc @@ -6,6 +6,7 @@ #include "base/trace_event/memory_dump_manager.h" #include "components/viz/common/resources/resource_format_utils.h" +#include "components/viz/common/resources/resource_sizes.h" #include "gpu/command_buffer/common/shared_image_trace_utils.h" #include "gpu/command_buffer/service/shared_image_representation_d3d.h" #include "gpu/command_buffer/service/shared_image_representation_skia_gl.h" @@ -45,7 +46,7 @@ SharedImageBackingD3D::SharedImageBackingD3D( uint32_t usage, Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain, scoped_refptr<gles2::TexturePassthrough> texture, - scoped_refptr<gl::GLImageD3D> image, + scoped_refptr<gl::GLImage> image, size_t buffer_index, Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture, base::win::ScopedHandle shared_handle, @@ -66,7 +67,6 @@ SharedImageBackingD3D::SharedImageBackingD3D( d3d11_texture_(std::move(d3d11_texture)), shared_handle_(std::move(shared_handle)), dxgi_keyed_mutex_(std::move(dxgi_keyed_mutex)) { - DCHECK(d3d11_texture_); DCHECK(texture_); } @@ -171,6 +171,10 @@ HANDLE SharedImageBackingD3D::GetSharedHandle() const { return shared_handle_.Get(); } +gl::GLImage* SharedImageBackingD3D::GetGLImage() const { + return image_.get(); +} + bool SharedImageBackingD3D::PresentSwapChain() { TRACE_EVENT0("gpu", "SharedImageBackingD3D::PresentSwapChain"); if (buffer_index_ != 0) { @@ -195,7 +199,7 @@ bool SharedImageBackingD3D::PresentSwapChain() { api->glBindTextureFn(GL_TEXTURE_2D, texture_->service_id()); if (!image_->BindTexImage(GL_TEXTURE_2D)) { - DLOG(ERROR) << "GLImageD3D::BindTexImage failed"; + DLOG(ERROR) << "GLImage::BindTexImage failed"; return false; } @@ -223,4 +227,12 @@ SharedImageBackingD3D::ProduceSkia( manager, this, tracker); } +std::unique_ptr<SharedImageRepresentationOverlay> +SharedImageBackingD3D::ProduceOverlay(SharedImageManager* manager, + MemoryTypeTracker* tracker) { + TRACE_EVENT0("gpu", "SharedImageBackingD3D::ProduceOverlay"); + return std::make_unique<SharedImageRepresentationOverlayD3D>(manager, this, + tracker); +} + } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_d3d.h b/chromium/gpu/command_buffer/service/shared_image_backing_d3d.h index a808c3c14bd..50e0645458c 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_d3d.h +++ b/chromium/gpu/command_buffer/service/shared_image_backing_d3d.h @@ -32,7 +32,8 @@ struct Mailbox; // Implementation of SharedImageBacking that holds buffer (front buffer/back // buffer of swap chain) texture (as gles2::Texture/gles2::TexturePassthrough) // and a reference to created swap chain. -class SharedImageBackingD3D : public ClearTrackingSharedImageBacking { +class GPU_GLES2_EXPORT SharedImageBackingD3D + : public ClearTrackingSharedImageBacking { public: SharedImageBackingD3D( const Mailbox& mailbox, @@ -44,7 +45,7 @@ class SharedImageBackingD3D : public ClearTrackingSharedImageBacking { uint32_t usage, Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain, scoped_refptr<gles2::TexturePassthrough> texture, - scoped_refptr<gl::GLImageD3D> image, + scoped_refptr<gl::GLImage> image, size_t buffer_index, Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture, base::win::ScopedHandle shared_handle, @@ -73,6 +74,7 @@ class SharedImageBackingD3D : public ClearTrackingSharedImageBacking { void EndAccessD3D11(); HANDLE GetSharedHandle() const; + gl::GLImage* GetGLImage() const; bool PresentSwapChain() override; @@ -81,6 +83,10 @@ class SharedImageBackingD3D : public ClearTrackingSharedImageBacking { ProduceGLTexturePassthrough(SharedImageManager* manager, MemoryTypeTracker* tracker) override; + std::unique_ptr<SharedImageRepresentationOverlay> ProduceOverlay( + SharedImageManager* manager, + MemoryTypeTracker* tracker) override; + std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia( SharedImageManager* manager, MemoryTypeTracker* tracker, @@ -89,8 +95,10 @@ class SharedImageBackingD3D : public ClearTrackingSharedImageBacking { private: Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain_; scoped_refptr<gles2::TexturePassthrough> texture_; - scoped_refptr<gl::GLImageD3D> image_; + scoped_refptr<gl::GLImage> image_; const size_t buffer_index_; + + // Texture could be nullptr if an empty backing is needed for testing. Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture_; // If d3d11_texture_ has a keyed mutex, it will be stored in diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_egl_image.cc b/chromium/gpu/command_buffer/service/shared_image_backing_egl_image.cc index 62dca6c5f2f..c03cad6bf44 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_egl_image.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_egl_image.cc @@ -355,7 +355,7 @@ void SharedImageBackingEglImage::MarkForDestruction() { AutoLock auto_lock(this); DCHECK(!have_context() || created_on_context_ == gl::g_current_gl_context); - if (!have_context()) + if (source_texture_holder_ && !have_context()) source_texture_holder_->MarkContextLost(); source_texture_holder_.reset(); } diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc b/chromium/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc index 44800465005..45558ea3b6c 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc @@ -240,6 +240,7 @@ class SharedImageRepresentationOverlayAHB } gl::GLImage* GetGLImage() override { return gl_image_; } + std::unique_ptr<gfx::GpuFence> GetReadFence() override { return nullptr; } gl::GLImage* gl_image_ = nullptr; }; diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d.cc b/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d.cc index 70585fea8f5..02d5d09af1c 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d.cc @@ -4,7 +4,10 @@ #include "gpu/command_buffer/service/shared_image_backing_factory_d3d.h" +#include <d3d11_1.h> + #include "components/viz/common/resources/resource_format_utils.h" +#include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/service/shared_image_backing_d3d.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gl/direct_composition_surface_win.h" @@ -141,13 +144,9 @@ std::unique_ptr<SharedImageBacking> SharedImageBackingFactoryD3D::MakeBacking( return nullptr; } } else if (shared_handle.IsValid()) { - const HRESULT hr = d3d11_texture.As(&dxgi_keyed_mutex); - if (FAILED(hr)) { - DLOG(ERROR) << "Unable to QueryInterface for IDXGIKeyedMutex on texture " - "with shared handle " - << std::hex; - return nullptr; - } + // Keyed mutexes are required for Dawn interop but are not used + // for XR composition where fences are used instead. + d3d11_texture.As(&dxgi_keyed_mutex); } DCHECK(d3d11_texture); @@ -380,15 +379,58 @@ SharedImageBackingFactoryD3D::CreateSharedImage( GrSurfaceOrigin surface_origin, SkAlphaType alpha_type, uint32_t usage) { - NOTIMPLEMENTED(); - return nullptr; + // TODO: Add support for shared memory GMBs. + DCHECK_EQ(handle.type, gfx::DXGI_SHARED_HANDLE); + if (!handle.dxgi_handle.IsValid()) { + DLOG(ERROR) << "Invalid handle type passed to CreateSharedImage"; + return nullptr; + } + + if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, format)) { + DLOG(ERROR) << "Invalid image size " << size.ToString() << " for " + << gfx::BufferFormatToString(format); + return nullptr; + } + + Microsoft::WRL::ComPtr<ID3D11Device1> d3d11_device1; + HRESULT hr = d3d11_device_.As(&d3d11_device1); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to query for ID3D11Device1. Error: " + << logging::SystemErrorCodeToString(hr); + return nullptr; + } + + Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture; + hr = d3d11_device1->OpenSharedResource1(handle.dxgi_handle.Get(), + IID_PPV_ARGS(&d3d11_texture)); + if (FAILED(hr)) { + DLOG(ERROR) << "Unable to open shared resource from DXGI handle. Error: " + << logging::SystemErrorCodeToString(hr); + return nullptr; + } + + D3D11_TEXTURE2D_DESC desc; + d3d11_texture->GetDesc(&desc); + + // TODO: Add checks for device specific limits. + if (desc.Width != static_cast<UINT>(size.width()) || + desc.Height != static_cast<UINT>(size.height())) { + DLOG(ERROR) + << "Size passed to CreateSharedImage must match texture being opened"; + return nullptr; + } + + return MakeBacking(mailbox, viz::GetResourceFormat(format), size, color_space, + surface_origin, alpha_type, usage, /*swap_chain=*/nullptr, + /*buffer_index=*/0, std::move(d3d11_texture), + std::move(handle.dxgi_handle)); } // Returns true if the specified GpuMemoryBufferType can be imported using // this factory. bool SharedImageBackingFactoryD3D::CanImportGpuMemoryBuffer( gfx::GpuMemoryBufferType memory_buffer_type) { - return false; + return (memory_buffer_type == gfx::DXGI_SHARED_HANDLE); } } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d.h b/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d.h index 7abb0b0e0ac..3a8f9b8608f 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d.h +++ b/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d.h @@ -96,6 +96,10 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryD3D bool CanImportGpuMemoryBuffer( gfx::GpuMemoryBufferType memory_buffer_type) override; + Microsoft::WRL::ComPtr<ID3D11Device> GetDeviceForTesting() const { + return d3d11_device_; + } + private: // Wraps the optional swap chain buffer (front buffer/back buffer) and texture // into GLimage and creates a GL texture and stores it as gles2::Texture or as diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc b/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc index c5ed569920d..82025f30646 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc @@ -11,6 +11,7 @@ #include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/service/service_utils.h" #include "gpu/command_buffer/service/shared_context_state.h" +#include "gpu/command_buffer/service/shared_image_backing_d3d.h" #include "gpu/command_buffer/service/shared_image_factory.h" #include "gpu/command_buffer/service/shared_image_manager.h" #include "gpu/command_buffer/service/shared_image_representation.h" @@ -846,5 +847,72 @@ TEST_F(SharedImageBackingFactoryD3DTest, SkiaAccessFirstFails) { skia_representation->BeginScopedReadAccess(nullptr, nullptr); EXPECT_EQ(scoped_read_access, nullptr); } + +TEST_F(SharedImageBackingFactoryD3DTest, CreateSharedImageFromHandle) { + if (!IsD3DSharedImageSupported()) + return; + + EXPECT_TRUE( + shared_image_factory_->CanImportGpuMemoryBuffer(gfx::DXGI_SHARED_HANDLE)); + + Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = + shared_image_factory_->GetDeviceForTesting(); + + const gfx::Size size(1, 1); + D3D11_TEXTURE2D_DESC desc; + desc.Width = size.width(); + desc.Height = size.height(); + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = + D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED; + Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture; + HRESULT hr = d3d11_device->CreateTexture2D(&desc, nullptr, &d3d11_texture); + ASSERT_EQ(hr, S_OK); + + Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource; + hr = d3d11_texture.As(&dxgi_resource); + ASSERT_EQ(hr, S_OK); + + HANDLE shared_handle; + hr = dxgi_resource->CreateSharedHandle( + nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr, + &shared_handle); + ASSERT_EQ(hr, S_OK); + + gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle; + gpu_memory_buffer_handle.dxgi_handle.Set(shared_handle); + gpu_memory_buffer_handle.type = gfx::DXGI_SHARED_HANDLE; + + auto mailbox = Mailbox::GenerateForSharedImage(); + const auto format = gfx::BufferFormat::RGBA_8888; + const auto color_space = gfx::ColorSpace::CreateSRGB(); + const uint32_t usage = SHARED_IMAGE_USAGE_GLES2 | SHARED_IMAGE_USAGE_DISPLAY; + const gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle; + const GrSurfaceOrigin surface_origin = kTopLeft_GrSurfaceOrigin; + const SkAlphaType alpha_type = kPremul_SkAlphaType; + auto backing = shared_image_factory_->CreateSharedImage( + mailbox, 0, std::move(gpu_memory_buffer_handle), format, surface_handle, + size, color_space, surface_origin, alpha_type, usage); + ASSERT_NE(backing, nullptr); + + EXPECT_EQ(backing->format(), viz::RGBA_8888); + EXPECT_EQ(backing->size(), size); + EXPECT_EQ(backing->color_space(), color_space); + EXPECT_EQ(backing->surface_origin(), surface_origin); + EXPECT_EQ(backing->alpha_type(), alpha_type); + EXPECT_EQ(backing->mailbox(), mailbox); + + SharedImageBackingD3D* backing_d3d = + static_cast<SharedImageBackingD3D*>(backing.get()); + EXPECT_EQ(backing_d3d->GetSharedHandle(), shared_handle); +} + } // anonymous namespace } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.h b/chromium/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.h index 0d1039554b4..c66613bc7c4 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.h +++ b/chromium/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.h @@ -22,6 +22,10 @@ class Size; class ColorSpace; } // namespace gfx +namespace gl { +class ProgressReporter; +} // namespace gl + namespace gpu { class SharedImageBacking; class SharedImageBatchAccessManager; @@ -43,7 +47,8 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryGLTexture const GpuDriverBugWorkarounds& workarounds, const GpuFeatureInfo& gpu_feature_info, ImageFactory* image_factory, - SharedImageBatchAccessManager* batch_access_manager); + SharedImageBatchAccessManager* batch_access_manager, + gl::ProgressReporter* progress_reporter); ~SharedImageBackingFactoryGLTexture() override; // SharedImageBackingFactory implementation. @@ -170,6 +175,10 @@ class GPU_GLES2_EXPORT SharedImageBackingFactoryGLTexture SharedImageBackingGLCommon::UnpackStateAttribs attribs; GpuDriverBugWorkarounds workarounds_; + // Used to notify the watchdog before a buffer allocation in case it takes + // long. + gl::ProgressReporter* const progress_reporter_ = nullptr; + #if defined(OS_ANDROID) SharedImageBatchAccessManager* batch_access_manager_ = nullptr; #endif diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc b/chromium/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc index 0fbb0f60f1f..276317a3f26 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc @@ -29,6 +29,7 @@ #include "gpu/config/gpu_feature_info.h" #include "gpu/config/gpu_preferences.h" #include "gpu/config/gpu_test_config.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkPromiseImageTexture.h" #include "third_party/skia/include/core/SkSurface.h" @@ -44,6 +45,9 @@ #include "ui/gl/gl_image_stub.h" #include "ui/gl/gl_surface.h" #include "ui/gl/init/gl_factory.h" +#include "ui/gl/progress_reporter.h" + +using testing::AtLeast; namespace gpu { namespace { @@ -79,6 +83,15 @@ bool IsAndroid() { #endif } +class MockProgressReporter : public gl::ProgressReporter { + public: + MockProgressReporter() = default; + ~MockProgressReporter() override = default; + + // gl::ProgressReporter implementation. + MOCK_METHOD0(ReportProgress, void()); +}; + class SharedImageBackingFactoryGLTextureTestBase : public testing::TestWithParam<std::tuple<bool, viz::ResourceFormat>> { public: @@ -105,7 +118,7 @@ class SharedImageBackingFactoryGLTextureTestBase preferences.use_passthrough_cmd_decoder = use_passthrough(); backing_factory_ = std::make_unique<SharedImageBackingFactoryGLTexture>( preferences, workarounds, GpuFeatureInfo(), factory, - shared_image_manager_->batch_access_manager()); + shared_image_manager_->batch_access_manager(), &progress_reporter_); memory_type_tracker_ = std::make_unique<MemoryTypeTracker>(nullptr); shared_image_representation_factory_ = @@ -118,11 +131,31 @@ class SharedImageBackingFactoryGLTextureTestBase gles2::PassthroughCommandDecoderSupported(); } + bool can_create_non_scanout_shared_image(viz::ResourceFormat format) const { + if (format == viz::ResourceFormat::BGRA_1010102 || + format == viz::ResourceFormat::RGBA_1010102) { + return supports_ar30_ || supports_ab30_; + } else if (format == viz::ResourceFormat::ETC1) { + return supports_etc1_; + } + return true; + } + + bool can_create_scanout_or_gmb_shared_image( + viz::ResourceFormat format) const { + if (format == viz::ResourceFormat::BGRA_1010102) + return supports_ar30_; + else if (format == viz::ResourceFormat::RGBA_1010102) + return supports_ab30_; + return true; + } + viz::ResourceFormat get_format() { return std::get<1>(GetParam()); } GrDirectContext* gr_context() { return context_state_->gr_context(); } protected: + ::testing::NiceMock<MockProgressReporter> progress_reporter_; scoped_refptr<gl::GLSurface> surface_; scoped_refptr<gl::GLContext> context_; scoped_refptr<SharedContextState> context_state_; @@ -213,6 +246,9 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, Basic) { return; } + const bool should_succeed = can_create_non_scanout_shared_image(get_format()); + if (should_succeed) + EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1)); auto mailbox = Mailbox::GenerateForSharedImage(); auto format = get_format(); gfx::Size size(256, 256); @@ -225,12 +261,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, Basic) { mailbox, format, surface_handle, size, color_space, surface_origin, alpha_type, usage, false /* is_thread_safe */); - // As long as either |chromium_image_ar30| or |chromium_image_ab30| is - // enabled, we can create a non-scanout SharedImage with format - // viz::ResourceFormat::{BGRA,RGBA}_1010102. - if ((format == viz::ResourceFormat::BGRA_1010102 || - format == viz::ResourceFormat::RGBA_1010102) && - !supports_ar30_ && !supports_ab30_) { + if (!should_succeed) { EXPECT_FALSE(backing); return; } @@ -347,6 +378,11 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, Image) { bot_config.Matches("mac passthrough")) { return; } + + const bool should_succeed = + can_create_scanout_or_gmb_shared_image(get_format()); + if (should_succeed) + EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1)); auto mailbox = Mailbox::GenerateForSharedImage(); auto format = get_format(); gfx::Size size(256, 256); @@ -359,15 +395,12 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, Image) { mailbox, format, surface_handle, size, color_space, surface_origin, alpha_type, usage, false /* is_thread_safe */); - // We can only create a scanout SharedImage with format - // viz::ResourceFormat::{BGRA,RGBA}_1010102 if the corresponding - // |chromium_image_ar30| or |chromium_image_ab30| is enabled. - if ((format == viz::ResourceFormat::BGRA_1010102 && !supports_ar30_) || - (format == viz::ResourceFormat::RGBA_1010102 && !supports_ab30_)) { + if (!should_succeed) { EXPECT_FALSE(backing); return; } ASSERT_TRUE(backing); + ::testing::Mock::VerifyAndClearExpectations(&progress_reporter_); // Check clearing. if (!backing->IsCleared()) { @@ -472,6 +505,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, Image) { if (!use_passthrough() && context_state_->feature_info()->feature_flags().ext_texture_rg) { + EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1)); // Create a R-8 image texture, and check that the internal_format is that // of the image (GL_RGBA for TextureImageFactory). This only matters for // the validating decoder. @@ -503,6 +537,9 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, InitialData) { for (auto format : {viz::ResourceFormat::RGBA_8888, viz::ResourceFormat::ETC1, viz::ResourceFormat::BGRA_1010102, viz::ResourceFormat::RGBA_1010102}) { + const bool should_succeed = can_create_non_scanout_shared_image(format); + if (should_succeed) + EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1)); auto mailbox = Mailbox::GenerateForSharedImage(); gfx::Size size(256, 256); auto color_space = gfx::ColorSpace::CreateSRGB(); @@ -514,22 +551,11 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, InitialData) { auto backing = backing_factory_->CreateSharedImage( mailbox, format, size, color_space, surface_origin, alpha_type, usage, initial_data); - - if (format == viz::ResourceFormat::ETC1 && !supports_etc1_) { - EXPECT_FALSE(backing); - continue; - } - - // As long as either |chromium_image_ar30| or |chromium_image_ab30| is - // enabled, we can create a non-scanout SharedImage with format - // viz::ResourceFormat::{BGRA,RGBA}_1010102. - if ((format == viz::ResourceFormat::BGRA_1010102 || - format == viz::ResourceFormat::RGBA_1010102) && - !supports_ar30_ && !supports_ab30_) { + ::testing::Mock::VerifyAndClearExpectations(&progress_reporter_); + if (!should_succeed) { EXPECT_FALSE(backing); continue; } - ASSERT_TRUE(backing); EXPECT_TRUE(backing->IsCleared()); @@ -571,6 +597,10 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, InitialData) { } TEST_P(SharedImageBackingFactoryGLTextureTest, InitialDataImage) { + const bool should_succeed = + can_create_scanout_or_gmb_shared_image(get_format()); + if (should_succeed) + EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1)); auto mailbox = Mailbox::GenerateForSharedImage(); auto format = get_format(); gfx::Size size(256, 256); @@ -582,12 +612,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, InitialDataImage) { auto backing = backing_factory_->CreateSharedImage( mailbox, format, size, color_space, surface_origin, alpha_type, usage, initial_data); - - // We can only create a scanout SharedImage with format - // viz::ResourceFormat::{BGRA,RGBA}_1010102 if the corresponding - // |chromium_image_ar30| or |chromium_image_ab30| is enabled. - if ((format == viz::ResourceFormat::BGRA_1010102 && !supports_ar30_) || - (format == viz::ResourceFormat::RGBA_1010102 && !supports_ab30_)) { + if (!should_succeed) { EXPECT_FALSE(backing); return; } @@ -679,6 +704,9 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, InvalidSize) { } TEST_P(SharedImageBackingFactoryGLTextureTest, EstimatedSize) { + const bool should_succeed = can_create_non_scanout_shared_image(get_format()); + if (should_succeed) + EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1)); auto mailbox = Mailbox::GenerateForSharedImage(); auto format = get_format(); gfx::Size size(256, 256); @@ -691,12 +719,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, EstimatedSize) { mailbox, format, surface_handle, size, color_space, surface_origin, alpha_type, usage, false /* is_thread_safe */); - // As long as either |chromium_image_ar30| or |chromium_image_ab30| is - // enabled, we can create a non-scanout SharedImage with format - // viz::ResourceFormat::{BGRA,RGBA}_1010102. - if ((format == viz::ResourceFormat::BGRA_1010102 || - format == viz::ResourceFormat::RGBA_1010102) && - !supports_ar30_ && !supports_ab30_) { + if (!should_succeed) { EXPECT_FALSE(backing); return; } @@ -891,12 +914,7 @@ TEST_P(SharedImageBackingFactoryGLTextureWithGMBTest, auto backing = backing_factory_->CreateSharedImage( mailbox, kClientId, std::move(handle), format, kNullSurfaceHandle, size, color_space, surface_origin, alpha_type, usage); - - // We can only create a GMB SharedImage with format - // viz::ResourceFormat::{BGRA,RGBA}_1010102 if the corresponding - // |chromium_image_ar30| or |chromium_image_ab30| is enabled. - if ((get_format() == viz::ResourceFormat::BGRA_1010102 && !supports_ar30_) || - (get_format() == viz::ResourceFormat::RGBA_1010102 && !supports_ab30_)) { + if (!can_create_scanout_or_gmb_shared_image(get_format())) { EXPECT_FALSE(backing); return; } @@ -952,12 +970,7 @@ TEST_P(SharedImageBackingFactoryGLTextureWithGMBTest, auto backing = backing_factory_->CreateSharedImage( mailbox, kClientId, std::move(handle), format, kNullSurfaceHandle, size, color_space, surface_origin, alpha_type, usage); - - // We can only create a GMB SharedImage with format - // viz::ResourceFormat::{BGRA,RGBA}_1010102 if the corresponding - // |chromium_image_ar30| or |chromium_image_ab30| is enabled. - if ((get_format() == viz::ResourceFormat::BGRA_1010102 && !supports_ar30_) || - (get_format() == viz::ResourceFormat::RGBA_1010102 && !supports_ab30_)) { + if (!can_create_scanout_or_gmb_shared_image(get_format())) { EXPECT_FALSE(backing); return; } @@ -990,12 +1003,7 @@ TEST_P(SharedImageBackingFactoryGLTextureWithGMBTest, auto backing = backing_factory_->CreateSharedImage( mailbox, kClientId, std::move(handle), format, kNullSurfaceHandle, size, color_space, surface_origin, alpha_type, usage); - - // We can only create a GMB SharedImage with format - // viz::ResourceFormat::{BGRA,RGBA}_1010102 if the corresponding - // |chromium_image_ar30| or |chromium_image_ab30| is enabled. - if ((get_format() == viz::ResourceFormat::BGRA_1010102 && !supports_ar30_) || - (get_format() == viz::ResourceFormat::RGBA_1010102 && !supports_ab30_)) { + if (!can_create_scanout_or_gmb_shared_image(get_format())) { EXPECT_FALSE(backing); return; } diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc b/chromium/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc index 5bf507cdbbe..8fc0c73f8a1 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc @@ -67,7 +67,8 @@ class SharedImageBackingFactoryIOSurfaceTest : public testing::Test { backing_factory_ = std::make_unique<SharedImageBackingFactoryGLTexture>( preferences, workarounds, GpuFeatureInfo(), &image_factory_, - shared_image_manager_.batch_access_manager()); + shared_image_manager_.batch_access_manager(), + /*progress_reporter=*/nullptr); memory_type_tracker_ = std::make_unique<MemoryTypeTracker>(nullptr); shared_image_representation_factory_ = diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_gl_common.h b/chromium/gpu/command_buffer/service/shared_image_backing_gl_common.h index dc2dddcfc2b..6af656cf8b7 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_gl_common.h +++ b/chromium/gpu/command_buffer/service/shared_image_backing_gl_common.h @@ -13,7 +13,7 @@ namespace gpu { // Common helper functions for SharedImageBackingGLTexture and // SharedImageBackingPassthroughGLImage. -class SharedImageBackingGLCommon { +class GPU_GLES2_EXPORT SharedImageBackingGLCommon { public: // These parameters are used to explicitly initialize a GL texture. struct InitializeGLTextureParams { diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_gl_image.cc b/chromium/gpu/command_buffer/service/shared_image_backing_gl_image.cc index c34decc537b..0318fd9d783 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_gl_image.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_gl_image.cc @@ -17,6 +17,8 @@ #include "ui/gl/gl_context.h" #include "ui/gl/gl_fence.h" #include "ui/gl/gl_gl_api_implementation.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/scoped_binders.h" #include "ui/gl/trace_util.h" #if defined(OS_MAC) @@ -71,14 +73,20 @@ gles2::Texture* SharedImageRepresentationGLTextureImpl::GetTexture() { } bool SharedImageRepresentationGLTextureImpl::BeginAccess(GLenum mode) { + DCHECK(mode_ == 0); + mode_ = mode; if (client_ && mode != GL_SHARED_IMAGE_ACCESS_MODE_OVERLAY_CHROMIUM) return client_->SharedImageRepresentationGLTextureBeginAccess(); return true; } void SharedImageRepresentationGLTextureImpl::EndAccess() { + DCHECK(mode_ != 0); + GLenum current_mode = mode_; + mode_ = 0; if (client_) - return client_->SharedImageRepresentationGLTextureEndAccess(); + return client_->SharedImageRepresentationGLTextureEndAccess( + current_mode != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM); } /////////////////////////////////////////////////////////////////////////////// @@ -109,14 +117,20 @@ SharedImageRepresentationGLTexturePassthroughImpl::GetTexturePassthrough() { bool SharedImageRepresentationGLTexturePassthroughImpl::BeginAccess( GLenum mode) { + DCHECK(mode_ == 0); + mode_ = mode; if (client_ && mode != GL_SHARED_IMAGE_ACCESS_MODE_OVERLAY_CHROMIUM) return client_->SharedImageRepresentationGLTextureBeginAccess(); return true; } void SharedImageRepresentationGLTexturePassthroughImpl::EndAccess() { + DCHECK(mode_ != 0); + GLenum current_mode = mode_; + mode_ = 0; if (client_) - return client_->SharedImageRepresentationGLTextureEndAccess(); + return client_->SharedImageRepresentationGLTextureEndAccess( + current_mode != GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM); } /////////////////////////////////////////////////////////////////////////////// @@ -189,7 +203,7 @@ void SharedImageRepresentationSkiaImpl::EndWriteAccess( write_surface_ = nullptr; if (client_) - client_->SharedImageRepresentationGLTextureEndAccess(); + client_->SharedImageRepresentationGLTextureEndAccess(false /* readonly */); } sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkiaImpl::BeginReadAccess( @@ -206,7 +220,7 @@ sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkiaImpl::BeginReadAccess( void SharedImageRepresentationSkiaImpl::EndReadAccess() { if (client_) - client_->SharedImageRepresentationGLTextureEndAccess(); + client_->SharedImageRepresentationGLTextureEndAccess(true /* readonly */); } bool SharedImageRepresentationSkiaImpl::SupportsMultipleConcurrentReadAccess() { @@ -244,6 +258,12 @@ gl::GLImage* SharedImageRepresentationOverlayImpl::GetGLImage() { return gl_image_.get(); } +std::unique_ptr<gfx::GpuFence> +SharedImageRepresentationOverlayImpl::GetReadFence() { + auto* gl_backing = static_cast<SharedImageBackingGLImage*>(backing()); + return gl_backing->GetLastWriteGpuFence(); +} + /////////////////////////////////////////////////////////////////////////////// // SharedImageBackingGLImage @@ -357,6 +377,11 @@ GLuint SharedImageBackingGLImage::GetGLServiceId() const { return 0; } +std::unique_ptr<gfx::GpuFence> +SharedImageBackingGLImage::GetLastWriteGpuFence() { + return last_write_gl_fence_ ? last_write_gl_fence_->GetGpuFence() : nullptr; +} + scoped_refptr<gfx::NativePixmap> SharedImageBackingGLImage::GetNativePixmap() { return image_->GetNativePixmap(); } @@ -561,7 +586,8 @@ bool SharedImageBackingGLImage:: return BindOrCopyImageIfNeeded(); } -void SharedImageBackingGLImage::SharedImageRepresentationGLTextureEndAccess() { +void SharedImageBackingGLImage::SharedImageRepresentationGLTextureEndAccess( + bool readonly) { #if defined(OS_MAC) // If this image could potentially be shared with Metal via WebGPU, then flush // the GL context to ensure Metal will see it. @@ -569,6 +595,30 @@ void SharedImageBackingGLImage::SharedImageRepresentationGLTextureEndAccess() { gl::GLApi* api = gl::g_current_gl_context; api->glFlushFn(); } + + // When SwANGLE is used as the GL implementation, we have to call + // ReleaseTexImage to signal an UnlockIOSurface call to sync the surface + // between the CPU and GPU. The next time this texture is accessed we will + // call BindTexImage to signal a LockIOSurface call before rendering to it via + // the CPU. + if (IsPassthrough() && + gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader && + image_->ShouldBindOrCopy() == gl::GLImage::BIND) { + const GLenum target = GetGLTarget(); + gl::ScopedTextureBinder binder(target, passthrough_texture_->service_id()); + if (!passthrough_texture_->is_bind_pending()) { + image_->ReleaseTexImage(target); + image_bind_or_copy_needed_ = true; + } + } +#else + // If the image will be used for an overlay, we insert a fence that can be + // used by OutputPresenter to synchronize image writes with presentation. + if (!readonly && usage() & SHARED_IMAGE_USAGE_SCANOUT && + gl::GLFence::IsGpuFenceSupported()) { + last_write_gl_fence_ = gl::GLFence::CreateForGpuFence(); + DCHECK(last_write_gl_fence_); + } #endif } diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_gl_image.h b/chromium/gpu/command_buffer/service/shared_image_backing_gl_image.h index 9dcb41bfe59..39a7b45a013 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_gl_image.h +++ b/chromium/gpu/command_buffer/service/shared_image_backing_gl_image.h @@ -7,6 +7,8 @@ #include "gpu/command_buffer/service/shared_image_backing.h" #include "gpu/command_buffer/service/shared_image_backing_gl_common.h" +#include "gpu/gpu_gles2_export.h" +#include "ui/gl/gl_fence.h" namespace gpu { @@ -15,7 +17,7 @@ namespace gpu { class SharedImageRepresentationGLTextureClient { public: virtual bool SharedImageRepresentationGLTextureBeginAccess() = 0; - virtual void SharedImageRepresentationGLTextureEndAccess() = 0; + virtual void SharedImageRepresentationGLTextureEndAccess(bool readonly) = 0; virtual void SharedImageRepresentationGLTextureRelease(bool have_context) = 0; }; @@ -40,6 +42,7 @@ class SharedImageRepresentationGLTextureImpl SharedImageRepresentationGLTextureClient* const client_ = nullptr; gles2::Texture* texture_; + GLenum mode_ = 0; }; // Representation of a SharedImageBackingGLTexture or @@ -68,6 +71,7 @@ class SharedImageRepresentationGLTexturePassthroughImpl SharedImageRepresentationGLTextureClient* const client_ = nullptr; scoped_refptr<gles2::TexturePassthrough> texture_passthrough_; + GLenum mode_ = 0; }; // Skia representation for both SharedImageBackingGLCommon. @@ -130,6 +134,7 @@ class SharedImageRepresentationOverlayImpl bool BeginReadAccess() override; void EndReadAccess() override; gl::GLImage* GetGLImage() override; + std::unique_ptr<gfx::GpuFence> GetReadFence() override; scoped_refptr<gl::GLImage> gl_image_; }; @@ -137,7 +142,7 @@ class SharedImageRepresentationOverlayImpl // Implementation of SharedImageBacking that creates a GL Texture that is backed // by a GLImage and stores it as a gles2::Texture. Can be used with the legacy // mailbox implementation. -class SharedImageBackingGLImage +class GPU_GLES2_EXPORT SharedImageBackingGLImage : public SharedImageBacking, public SharedImageRepresentationGLTextureClient { public: @@ -162,6 +167,7 @@ class SharedImageBackingGLImage GLenum GetGLTarget() const; GLuint GetGLServiceId() const; + std::unique_ptr<gfx::GpuFence> GetLastWriteGpuFence(); private: // SharedImageBacking: @@ -197,7 +203,7 @@ class SharedImageBackingGLImage // SharedImageRepresentationGLTextureClient: bool SharedImageRepresentationGLTextureBeginAccess() override; - void SharedImageRepresentationGLTextureEndAccess() override; + void SharedImageRepresentationGLTextureEndAccess(bool readonly) override; void SharedImageRepresentationGLTextureRelease(bool have_context) override; bool IsPassthrough() const { return is_passthrough_; } @@ -227,6 +233,7 @@ class SharedImageBackingGLImage scoped_refptr<gles2::TexturePassthrough> passthrough_texture_; sk_sp<SkPromiseImageTexture> cached_promise_texture_; + std::unique_ptr<gl::GLFence> last_write_gl_fence_; base::WeakPtrFactory<SharedImageBackingGLImage> weak_factory_; }; diff --git a/chromium/gpu/command_buffer/service/shared_image_backing_gl_texture.cc b/chromium/gpu/command_buffer/service/shared_image_backing_gl_texture.cc index bb72877968e..354d49401d1 100644 --- a/chromium/gpu/command_buffer/service/shared_image_backing_gl_texture.cc +++ b/chromium/gpu/command_buffer/service/shared_image_backing_gl_texture.cc @@ -44,6 +44,7 @@ #include "ui/gl/gl_image_shared_memory.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_version_info.h" +#include "ui/gl/progress_reporter.h" #include "ui/gl/scoped_binders.h" #include "ui/gl/shared_gl_fence_egl.h" #include "ui/gl/trace_util.h" @@ -75,11 +76,13 @@ SharedImageBackingFactoryGLTexture::SharedImageBackingFactoryGLTexture( const GpuDriverBugWorkarounds& workarounds, const GpuFeatureInfo& gpu_feature_info, ImageFactory* image_factory, - SharedImageBatchAccessManager* batch_access_manager) + SharedImageBatchAccessManager* batch_access_manager, + gl::ProgressReporter* progress_reporter) : use_passthrough_(gpu_preferences.use_passthrough_cmd_decoder && gles2::PassthroughCommandDecoderSupported()), image_factory_(image_factory), - workarounds_(workarounds) { + workarounds_(workarounds), + progress_reporter_(progress_reporter) { #if defined(OS_ANDROID) batch_access_manager_ = batch_access_manager; #endif @@ -424,7 +427,9 @@ SharedImageBackingFactoryGLTexture::CreateSharedImageInternal( const bool use_buffer = usage & SHARED_IMAGE_USAGE_SCANOUT; #endif if (use_buffer && !format_info.allow_scanout) { - LOG(ERROR) << "CreateSharedImage: SCANOUT shared images unavailable"; + LOG(ERROR) << "CreateSharedImage: SCANOUT shared images unavailable. " + "Buffer format= " + << gfx::BufferFormatToString(format_info.buffer_format); return nullptr; } @@ -503,13 +508,22 @@ SharedImageBackingFactoryGLTexture::CreateSharedImageInternal( // the internal format in the LevelInfo. https://crbug.com/628064 GLuint level_info_internal_format = format_info.gl_format; bool is_cleared = false; + + // |scoped_progress_reporter| will notify |progress_reporter_| upon + // construction and destruction. We limit the scope so that progress is + // reported immediately after allocation/upload and before other GL + // operations. if (use_buffer) { - image = image_factory_->CreateAnonymousImage( - size, format_info.buffer_format, gfx::BufferUsage::SCANOUT, - surface_handle, &is_cleared); + { + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); + image = image_factory_->CreateAnonymousImage( + size, format_info.buffer_format, gfx::BufferUsage::SCANOUT, + surface_handle, &is_cleared); + } // Scanout images have different constraints than GL images and might fail // to allocate even if GL images can be created. if (!image) { + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); // TODO(dcastagna): Use BufferUsage::GPU_READ_WRITE instead // BufferUsage::GPU_READ once we add it. image = image_factory_->CreateAnonymousImage( @@ -544,6 +558,7 @@ SharedImageBackingFactoryGLTexture::CreateSharedImageInternal( image, mailbox, format, size, color_space, surface_origin, alpha_type, usage, params, attribs, use_passthrough_); if (!pixel_data.empty()) { + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); result->InitializePixels(format_info.adjusted_format, format_info.gl_type, pixel_data.data()); } @@ -559,12 +574,16 @@ SharedImageBackingFactoryGLTexture::CreateSharedImageInternal( api->glBindTextureFn(target, result->GetGLServiceId()); if (format_info.supports_storage) { - api->glTexStorage2DEXTFn(target, 1, format_info.storage_internal_format, - size.width(), size.height()); + { + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); + api->glTexStorage2DEXTFn(target, 1, format_info.storage_internal_format, + size.width(), size.height()); + } if (!pixel_data.empty()) { ScopedResetAndRestoreUnpackState scoped_unpack_state( api, attribs, true /* uploading_data */); + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glTexSubImage2DFn(target, 0, 0, 0, size.width(), size.height(), format_info.adjusted_format, format_info.gl_type, pixel_data.data()); @@ -572,12 +591,14 @@ SharedImageBackingFactoryGLTexture::CreateSharedImageInternal( } else if (format_info.is_compressed) { ScopedResetAndRestoreUnpackState scoped_unpack_state(api, attribs, !pixel_data.empty()); + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glCompressedTexImage2DFn( target, 0, format_info.image_internal_format, size.width(), size.height(), 0, pixel_data.size(), pixel_data.data()); } else { ScopedResetAndRestoreUnpackState scoped_unpack_state(api, attribs, !pixel_data.empty()); + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glTexImage2DFn(target, 0, format_info.image_internal_format, size.width(), size.height(), 0, format_info.adjusted_format, format_info.gl_type, diff --git a/chromium/gpu/command_buffer/service/shared_image_factory.cc b/chromium/gpu/command_buffer/service/shared_image_factory.cc index 6b42ed63b84..c671ee2f0b4 100644 --- a/chromium/gpu/command_buffer/service/shared_image_factory.cc +++ b/chromium/gpu/command_buffer/service/shared_image_factory.cc @@ -100,7 +100,9 @@ SharedImageFactory::SharedImageFactory( if (use_gl) { gl_backing_factory_ = std::make_unique<SharedImageBackingFactoryGLTexture>( gpu_preferences, workarounds, gpu_feature_info, image_factory, - shared_image_manager->batch_access_manager()); + shared_image_manager->batch_access_manager(), + shared_context_state_ ? shared_context_state_->progress_reporter() + : nullptr); } // TODO(ccameron): This block of code should be changed to a switch on @@ -341,7 +343,8 @@ bool SharedImageFactory::RegisterSysmemBufferCollection( gfx::SysmemBufferCollectionId id, zx::channel token, gfx::BufferFormat format, - gfx::BufferUsage usage) { + gfx::BufferUsage usage, + bool register_with_image_pipe) { decltype(buffer_collections_)::iterator it; bool inserted; std::tie(it, inserted) = @@ -362,10 +365,10 @@ bool SharedImageFactory::RegisterSysmemBufferCollection( VkDevice device = vulkan_context_provider_->GetDeviceQueue()->GetVulkanDevice(); DCHECK(device != VK_NULL_HANDLE); - it->second = - vulkan_context_provider_->GetVulkanImplementation() - ->RegisterSysmemBufferCollection(device, id, std::move(token), format, - usage, gfx::Size(), 0); + it->second = vulkan_context_provider_->GetVulkanImplementation() + ->RegisterSysmemBufferCollection( + device, id, std::move(token), format, usage, gfx::Size(), + 0, register_with_image_pipe); return true; } diff --git a/chromium/gpu/command_buffer/service/shared_image_factory.h b/chromium/gpu/command_buffer/service/shared_image_factory.h index 6534c88271a..f4668e110bf 100644 --- a/chromium/gpu/command_buffer/service/shared_image_factory.h +++ b/chromium/gpu/command_buffer/service/shared_image_factory.h @@ -111,7 +111,8 @@ class GPU_GLES2_EXPORT SharedImageFactory { bool RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id, zx::channel token, gfx::BufferFormat format, - gfx::BufferUsage usage); + gfx::BufferUsage usage, + bool register_with_image_pipe); bool ReleaseSysmemBufferCollection(gfx::SysmemBufferCollectionId id); #endif // defined(OS_FUCHSIA) diff --git a/chromium/gpu/command_buffer/service/shared_image_representation.cc b/chromium/gpu/command_buffer/service/shared_image_representation.cc index 55d762979e8..e5ddefc7f4a 100644 --- a/chromium/gpu/command_buffer/service/shared_image_representation.cc +++ b/chromium/gpu/command_buffer/service/shared_image_representation.cc @@ -8,6 +8,7 @@ #include "gpu/command_buffer/service/texture_manager.h" #include "third_party/skia/include/core/SkPromiseImageTexture.h" #include "third_party/skia/include/gpu/GrDirectContext.h" +#include "ui/gl/gl_fence.h" #if defined(OS_ANDROID) #include "base/android/scoped_hardware_buffer_fence_sync.h" @@ -227,8 +228,15 @@ sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkia::BeginReadAccess( SharedImageRepresentationOverlay::ScopedReadAccess::ScopedReadAccess( util::PassKey<SharedImageRepresentationOverlay> pass_key, SharedImageRepresentationOverlay* representation, - gl::GLImage* gl_image) - : ScopedAccessBase(representation), gl_image_(gl_image) {} + gl::GLImage* gl_image, + std::unique_ptr<gfx::GpuFence> fence) + : ScopedAccessBase(representation), + gl_image_(gl_image), + fence_(std::move(fence)) {} + +SharedImageRepresentationOverlay::ScopedReadAccess::~ScopedReadAccess() { + representation()->EndReadAccess(); +} std::unique_ptr<SharedImageRepresentationOverlay::ScopedReadAccess> SharedImageRepresentationOverlay::BeginScopedReadAccess(bool needs_gl_image) { @@ -244,7 +252,7 @@ SharedImageRepresentationOverlay::BeginScopedReadAccess(bool needs_gl_image) { return std::make_unique<ScopedReadAccess>( util::PassKey<SharedImageRepresentationOverlay>(), this, - needs_gl_image ? GetGLImage() : nullptr); + needs_gl_image ? GetGLImage() : nullptr, GetReadFence()); } SharedImageRepresentationDawn::ScopedAccess::ScopedAccess( diff --git a/chromium/gpu/command_buffer/service/shared_image_representation.h b/chromium/gpu/command_buffer/service/shared_image_representation.h index 626f610a4c0..2ca5a057479 100644 --- a/chromium/gpu/command_buffer/service/shared_image_representation.h +++ b/chromium/gpu/command_buffer/service/shared_image_representation.h @@ -392,20 +392,22 @@ class GPU_GLES2_EXPORT SharedImageRepresentationOverlay MemoryTypeTracker* tracker) : SharedImageRepresentation(manager, backing, tracker) {} - class ScopedReadAccess + class GPU_GLES2_EXPORT ScopedReadAccess : public ScopedAccessBase<SharedImageRepresentationOverlay> { public: ScopedReadAccess(util::PassKey<SharedImageRepresentationOverlay> pass_key, SharedImageRepresentationOverlay* representation, - gl::GLImage* gl_image); - ~ScopedReadAccess() { representation()->EndReadAccess(); } + gl::GLImage* gl_image, + std::unique_ptr<gfx::GpuFence> fence); + ~ScopedReadAccess(); - gl::GLImage* gl_image() const { - return gl_image_; - } + gl::GLImage* gl_image() const { return gl_image_; } + + std::unique_ptr<gfx::GpuFence> TakeFence() { return std::move(fence_); } private: gl::GLImage* gl_image_; + std::unique_ptr<gfx::GpuFence> fence_; }; #if defined(OS_ANDROID) @@ -426,6 +428,9 @@ class GPU_GLES2_EXPORT SharedImageRepresentationOverlay // TODO(penghuang): Refactor it to not depend on GL. // Get the backing as GLImage for GLSurface::ScheduleOverlayPlane. virtual gl::GLImage* GetGLImage() = 0; + // Optionally returns a fence to synchronize writes on the SharedImage with + // overlay presentation. + virtual std::unique_ptr<gfx::GpuFence> GetReadFence() = 0; }; // An interface that allows a SharedImageBacking to hold a reference to VA-API diff --git a/chromium/gpu/command_buffer/service/shared_image_representation_d3d.cc b/chromium/gpu/command_buffer/service/shared_image_representation_d3d.cc index 9be3bd1599e..afde8952d16 100644 --- a/chromium/gpu/command_buffer/service/shared_image_representation_d3d.cc +++ b/chromium/gpu/command_buffer/service/shared_image_representation_d3d.cc @@ -132,4 +132,27 @@ void SharedImageRepresentationDawnD3D::EndAccess() { } #endif // BUILDFLAG(USE_DAWN) +SharedImageRepresentationOverlayD3D::SharedImageRepresentationOverlayD3D( + SharedImageManager* manager, + SharedImageBacking* backing, + MemoryTypeTracker* tracker) + : SharedImageRepresentationOverlay(manager, backing, tracker) {} + +bool SharedImageRepresentationOverlayD3D::BeginReadAccess() { + // Note: only the DX11 video decoder uses this overlay and does not need to + // synchronize read access from different devices. + return true; +} + +void SharedImageRepresentationOverlayD3D::EndReadAccess() {} + +gl::GLImage* SharedImageRepresentationOverlayD3D::GetGLImage() { + return static_cast<SharedImageBackingD3D*>(backing())->GetGLImage(); +} + +std::unique_ptr<gfx::GpuFence> +SharedImageRepresentationOverlayD3D::GetReadFence() { + return nullptr; +} + } // namespace gpu diff --git a/chromium/gpu/command_buffer/service/shared_image_representation_d3d.h b/chromium/gpu/command_buffer/service/shared_image_representation_d3d.h index 72e41f183a1..164b974431d 100644 --- a/chromium/gpu/command_buffer/service/shared_image_representation_d3d.h +++ b/chromium/gpu/command_buffer/service/shared_image_representation_d3d.h @@ -20,6 +20,8 @@ namespace gpu { +class SharedImageBackingD3D; + // Representation of a SharedImageBackingD3D as a GL TexturePassthrough. class SharedImageRepresentationGLTexturePassthroughD3D : public SharedImageRepresentationGLTexturePassthrough { @@ -65,5 +67,22 @@ class SharedImageRepresentationDawnD3D : public SharedImageRepresentationDawn { }; #endif // BUILDFLAG(USE_DAWN) +// Representation of a SharedImageBackingD3D as an overlay. +class SharedImageRepresentationOverlayD3D + : public SharedImageRepresentationOverlay { + public: + SharedImageRepresentationOverlayD3D(SharedImageManager* manager, + SharedImageBacking* backing, + MemoryTypeTracker* tracker); + ~SharedImageRepresentationOverlayD3D() override = default; + + private: + bool BeginReadAccess() override; + void EndReadAccess() override; + + gl::GLImage* GetGLImage() override; + std::unique_ptr<gfx::GpuFence> GetReadFence() override; +}; + } // namespace gpu #endif // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_REPRESENTATION_D3D_H_ diff --git a/chromium/gpu/command_buffer/service/shared_image_video.cc b/chromium/gpu/command_buffer/service/shared_image_video.cc index 6b7ebfe39c2..9cb70be0488 100644 --- a/chromium/gpu/command_buffer/service/shared_image_video.cc +++ b/chromium/gpu/command_buffer/service/shared_image_video.cc @@ -433,6 +433,8 @@ class SharedImageRepresentationOverlayVideo return stream_image_.get(); } + std::unique_ptr<gfx::GpuFence> GetReadFence() override { return nullptr; } + void NotifyOverlayPromotion(bool promotion, const gfx::Rect& bounds) override { stream_image_->NotifyOverlayPromotion(promotion, bounds); diff --git a/chromium/gpu/command_buffer/service/test_shared_image_backing.cc b/chromium/gpu/command_buffer/service/test_shared_image_backing.cc index ab09c2f9ec6..d51e7bd7f7b 100644 --- a/chromium/gpu/command_buffer/service/test_shared_image_backing.cc +++ b/chromium/gpu/command_buffer/service/test_shared_image_backing.cc @@ -118,6 +118,7 @@ class TestSharedImageRepresentationOverlay bool BeginReadAccess() override { return true; } void EndReadAccess() override {} gl::GLImage* GetGLImage() override { return nullptr; } + std::unique_ptr<gfx::GpuFence> GetReadFence() override { return nullptr; } #if defined(OS_ANDROID) void NotifyOverlayPromotion(bool promotion, diff --git a/chromium/gpu/command_buffer/service/webgpu_decoder_impl.cc b/chromium/gpu/command_buffer/service/webgpu_decoder_impl.cc index b6eb2d3eea7..bacd6d560e7 100644 --- a/chromium/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/chromium/gpu/command_buffer/service/webgpu_decoder_impl.cc @@ -648,6 +648,13 @@ error::Error WebGPUDecoderImpl::InitDawnDeviceAndSetWireServer( if (request_device_properties.textureCompressionBC) { device_descriptor.requiredExtensions.push_back("texture_compression_bc"); } + if (request_device_properties.shaderFloat16) { + device_descriptor.requiredExtensions.push_back("shader_float16"); + } + + if (request_device_properties.timestampQuery) { + device_descriptor.requiredExtensions.push_back("timestamp_query"); + } WGPUDevice wgpu_device = dawn_adapters_[requested_adapter_index].CreateDevice(&device_descriptor); diff --git a/chromium/gpu/command_buffer/service/wrapped_sk_image.cc b/chromium/gpu/command_buffer/service/wrapped_sk_image.cc index 3db30402eef..0f5d11c289d 100644 --- a/chromium/gpu/command_buffer/service/wrapped_sk_image.cc +++ b/chromium/gpu/command_buffer/service/wrapped_sk_image.cc @@ -56,7 +56,7 @@ class WrappedSkImage : public ClearTrackingSharedImageBacking { context_state_->EraseCachedSkSurface(this); if (backend_texture_.isValid()) - DeleteGrBackendTexture(context_state_, &backend_texture_); + DeleteGrBackendTexture(context_state_.get(), &backend_texture_); DCHECK(context_state_->context_lost() || context_state_->IsCurrent(nullptr)); @@ -155,7 +155,7 @@ class WrappedSkImage : public ClearTrackingSharedImageBacking { SkAlphaType alpha_type, uint32_t usage, size_t estimated_size, - SharedContextState* context_state) + scoped_refptr<SharedContextState> context_state) : ClearTrackingSharedImageBacking(mailbox, format, size, @@ -165,7 +165,7 @@ class WrappedSkImage : public ClearTrackingSharedImageBacking { usage, estimated_size, false /* is_thread_safe */), - context_state_(context_state) { + context_state_(std::move(context_state)) { DCHECK(!!context_state_); } @@ -190,7 +190,9 @@ class WrappedSkImage : public ClearTrackingSharedImageBacking { if (context_state_->context_lost()) return false; - DCHECK(context_state_->IsCurrent(nullptr)); + // MakeCurrent to avoid destroying another client's state because Skia may + // change GL state to create and upload textures (crbug.com/1095679). + context_state_->MakeCurrent(nullptr); context_state_->set_need_context_state_reset(true); #if BUILDFLAG(ENABLE_VULKAN) @@ -283,7 +285,7 @@ class WrappedSkImage : public ClearTrackingSharedImageBacking { return true; } - SharedContextState* const context_state_; + scoped_refptr<SharedContextState> context_state_; GrBackendTexture backend_texture_; sk_sp<SkPromiseImageTexture> promise_texture_; @@ -355,8 +357,9 @@ class WrappedSkImageRepresentation : public SharedImageRepresentationSkia { } // namespace -WrappedSkImageFactory::WrappedSkImageFactory(SharedContextState* context_state) - : context_state_(context_state) {} +WrappedSkImageFactory::WrappedSkImageFactory( + scoped_refptr<SharedContextState> context_state) + : context_state_(std::move(context_state)) {} WrappedSkImageFactory::~WrappedSkImageFactory() = default; diff --git a/chromium/gpu/command_buffer/service/wrapped_sk_image.h b/chromium/gpu/command_buffer/service/wrapped_sk_image.h index b0b8bc9fdc3..659ce4d1d1f 100644 --- a/chromium/gpu/command_buffer/service/wrapped_sk_image.h +++ b/chromium/gpu/command_buffer/service/wrapped_sk_image.h @@ -24,7 +24,8 @@ namespace raster { class GPU_GLES2_EXPORT WrappedSkImageFactory : public gpu::SharedImageBackingFactory { public: - explicit WrappedSkImageFactory(SharedContextState* context_state); + explicit WrappedSkImageFactory( + scoped_refptr<SharedContextState> context_state); ~WrappedSkImageFactory() override; // SharedImageBackingFactory implementation: @@ -62,7 +63,7 @@ class GPU_GLES2_EXPORT WrappedSkImageFactory gfx::GpuMemoryBufferType memory_buffer_type) override; private: - SharedContextState* const context_state_; + scoped_refptr<SharedContextState> context_state_; DISALLOW_COPY_AND_ASSIGN(WrappedSkImageFactory); }; |