| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| index e8b9c3087c7b19827a6d7766345d63c161ba906d..fd688cf290519a478f28d15c2dc0bf35f6d9152e 100644
|
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| @@ -1284,15 +1284,18 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
|
| bool FormsTextureCopyingFeedbackLoop(TextureRef* texture, GLint level);
|
|
|
| // Check if a framebuffer meets our requirements.
|
| + // Generates |gl_error| if the framebuffer is incomplete.
|
| bool CheckFramebufferValid(
|
| Framebuffer* framebuffer,
|
| GLenum target,
|
| bool clear_uncleared_images,
|
| + GLenum gl_error,
|
| const char* func_name);
|
|
|
| bool CheckBoundDrawFramebufferValid(
|
| bool clear_uncleared_images, const char* func_name);
|
| - bool CheckBoundReadFramebufferValid(const char* func_name);
|
| + // Generates |gl_error| if the bound read fbo is incomplete.
|
| + bool CheckBoundReadFramebufferValid(const char* func_name, GLenum gl_error);
|
|
|
| // Checks if the current program exists and is valid. If not generates the
|
| // appropriate GL error. Returns true if the current program is in a usable
|
| @@ -3753,6 +3756,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid(
|
| Framebuffer* framebuffer,
|
| GLenum target,
|
| bool clear_uncleared_images,
|
| + GLenum gl_error,
|
| const char* func_name) {
|
| if (!framebuffer) {
|
| if (surfaceless_)
|
| @@ -3792,8 +3796,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid(
|
|
|
| GLenum completeness = framebuffer->IsPossiblyComplete(feature_info_.get());
|
| if (completeness != GL_FRAMEBUFFER_COMPLETE) {
|
| - LOCAL_SET_GL_ERROR(
|
| - GL_INVALID_FRAMEBUFFER_OPERATION, func_name, "framebuffer incomplete");
|
| + LOCAL_SET_GL_ERROR(gl_error, func_name, "framebuffer incomplete");
|
| return false;
|
| }
|
|
|
| @@ -3806,8 +3809,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid(
|
| if (framebuffer->GetStatus(texture_manager(), target) !=
|
| GL_FRAMEBUFFER_COMPLETE) {
|
| LOCAL_SET_GL_ERROR(
|
| - GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
|
| - "framebuffer incomplete (clear)");
|
| + gl_error, func_name, "framebuffer incomplete (clear)");
|
| return false;
|
| }
|
| ClearUnclearedAttachments(target, framebuffer);
|
| @@ -3818,8 +3820,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid(
|
| if (framebuffer->GetStatus(texture_manager(), target) !=
|
| GL_FRAMEBUFFER_COMPLETE) {
|
| LOCAL_SET_GL_ERROR(
|
| - GL_INVALID_FRAMEBUFFER_OPERATION, func_name,
|
| - "framebuffer incomplete (check)");
|
| + gl_error, func_name, "framebuffer incomplete (check)");
|
| return false;
|
| }
|
| framebuffer_manager()->MarkAsComplete(framebuffer);
|
| @@ -3833,17 +3834,20 @@ bool GLES2DecoderImpl::CheckBoundDrawFramebufferValid(
|
| GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER;
|
| Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
|
| bool valid = CheckFramebufferValid(
|
| - framebuffer, target, clear_uncleared_images, func_name);
|
| + framebuffer, target, clear_uncleared_images,
|
| + GL_INVALID_FRAMEBUFFER_OPERATION, func_name);
|
| if (valid && !features().chromium_framebuffer_multisample)
|
| OnUseFramebuffer();
|
| return valid;
|
| }
|
|
|
| -bool GLES2DecoderImpl::CheckBoundReadFramebufferValid(const char* func_name) {
|
| +bool GLES2DecoderImpl::CheckBoundReadFramebufferValid(
|
| + const char* func_name, GLenum gl_error) {
|
| GLenum target = features().chromium_framebuffer_multisample ?
|
| GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER;
|
| Framebuffer* framebuffer = GetFramebufferInfoForTarget(target);
|
| - bool valid = CheckFramebufferValid(framebuffer, target, true, func_name);
|
| + bool valid = CheckFramebufferValid(
|
| + framebuffer, target, true, gl_error, func_name);
|
| return valid;
|
| }
|
|
|
| @@ -5369,50 +5373,52 @@ void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
|
| bool GLES2DecoderImpl::GetHelper(
|
| GLenum pname, GLint* params, GLsizei* num_written) {
|
| DCHECK(num_written);
|
| - if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
|
| - switch (pname) {
|
| - case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
|
| - *num_written = 1;
|
| - // Return the GL implementation's preferred format and (see below type)
|
| - // if we have the GL extension that exposes this. This allows the GPU
|
| - // client to use the implementation's preferred format for glReadPixels
|
| - // for optimisation.
|
| - //
|
| - // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
|
| - // case when requested on integer/floating point buffers but which is
|
| - // acceptable on GLES2 and with the GL_OES_read_format extension.
|
| - //
|
| - // Therefore if an error occurs we swallow the error and use the
|
| - // internal implementation.
|
| + switch (pname) {
|
| + case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
|
| + case GL_IMPLEMENTATION_COLOR_READ_TYPE:
|
| + // They are not supported on Desktop GL until 4.1, but could be exposed
|
| + // through GL_OES_read_format extension. However, a conflicting extension
|
| + // GL_ARB_ES2_compatibility specifies an error case when requested on
|
| + // integer/floating point buffers.
|
| + // To simpify the handling, we just query and check for GL errors. If an
|
| + // GL error occur, we fall back to our internal implementation.
|
| + *num_written = 1;
|
| + if (!CheckBoundReadFramebufferValid("glGetIntegerv",
|
| + GL_INVALID_OPERATION)) {
|
| if (params) {
|
| - if (context_->HasExtension("GL_OES_read_format")) {
|
| - ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
|
| - GetErrorState());
|
| - glGetIntegerv(pname, params);
|
| - if (glGetError() == GL_NO_ERROR)
|
| - return true;
|
| - }
|
| - *params = GLES2Util::GetGLReadPixelsImplementationFormat(
|
| - GetBoundReadFrameBufferInternalFormat(),
|
| - GetBoundReadFrameBufferTextureType(),
|
| - feature_info_->feature_flags().ext_read_format_bgra);
|
| + *params = 0;
|
| }
|
| return true;
|
| - case GL_IMPLEMENTATION_COLOR_READ_TYPE:
|
| - *num_written = 1;
|
| - if (params) {
|
| - if (context_->HasExtension("GL_OES_read_format")) {
|
| - ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
|
| - GetErrorState());
|
| - glGetIntegerv(pname, params);
|
| - if (glGetError() == GL_NO_ERROR)
|
| - return true;
|
| + }
|
| + if (params) {
|
| + ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
|
| + GetErrorState());
|
| + glGetIntegerv(pname, params);
|
| + if (glGetError() != GL_NO_ERROR) {
|
| + if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT) {
|
| + *params = GLES2Util::GetGLReadPixelsImplementationFormat(
|
| + GetBoundReadFrameBufferInternalFormat(),
|
| + GetBoundReadFrameBufferTextureType(),
|
| + feature_info_->feature_flags().ext_read_format_bgra);
|
| + } else {
|
| + *params = GLES2Util::GetGLReadPixelsImplementationType(
|
| + GetBoundReadFrameBufferInternalFormat(),
|
| + GetBoundReadFrameBufferTextureType());
|
| }
|
| - *params = GLES2Util::GetGLReadPixelsImplementationType(
|
| - GetBoundReadFrameBufferInternalFormat(),
|
| - GetBoundReadFrameBufferTextureType());
|
| }
|
| - return true;
|
| + if (*params == GL_HALF_FLOAT &&
|
| + (feature_info_->context_type() == CONTEXT_TYPE_WEBGL1 ||
|
| + feature_info_->context_type() == CONTEXT_TYPE_OPENGLES2)) {
|
| + *params = GL_HALF_FLOAT_OES;
|
| + }
|
| + }
|
| + return true;
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
|
| + switch (pname) {
|
| case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
|
| *num_written = 1;
|
| if (params) {
|
| @@ -6788,7 +6794,8 @@ void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM(
|
| DCHECK(!ShouldDeferReads() && !ShouldDeferDraws());
|
|
|
| if (!CheckBoundDrawFramebufferValid(true, "glBlitFramebufferCHROMIUM") ||
|
| - !CheckBoundReadFramebufferValid("glBlitFramebufferCHROMIUM")) {
|
| + !CheckBoundReadFramebufferValid("glBlitFramebufferCHROMIUM",
|
| + GL_INVALID_FRAMEBUFFER_OPERATION)) {
|
| return;
|
| }
|
|
|
| @@ -9578,7 +9585,8 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32_t immediate_data_size,
|
| return error::kNoError;
|
| }
|
|
|
| - if (!CheckBoundReadFramebufferValid("glReadPixels")) {
|
| + if (!CheckBoundReadFramebufferValid("glReadPixels",
|
| + GL_INVALID_FRAMEBUFFER_OPERATION)) {
|
| return error::kNoError;
|
| }
|
| GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat();
|
| @@ -9632,11 +9640,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32_t immediate_data_size,
|
| case GL_HALF_FLOAT_OES:
|
| case GL_FLOAT:
|
| case GL_UNSIGNED_INT_10F_11F_11F_REV:
|
| - if (!feature_info_->IsES3Enabled()) {
|
| - accepted_types.push_back(GL_UNSIGNED_BYTE);
|
| - } else {
|
| - accepted_types.push_back(GL_FLOAT);
|
| - }
|
| + accepted_types.push_back(GL_FLOAT);
|
| break;
|
| default:
|
| accepted_types.push_back(GL_UNSIGNED_BYTE);
|
| @@ -9674,6 +9678,10 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32_t immediate_data_size,
|
| "format and type incompatible with the current read framebuffer");
|
| return error::kNoError;
|
| }
|
| + if (type == GL_HALF_FLOAT_OES &&
|
| + !(feature_info_->gl_version_info().is_es2)) {
|
| + type = GL_HALF_FLOAT;
|
| + }
|
| if (width == 0 || height == 0) {
|
| return error::kNoError;
|
| }
|
| @@ -11794,7 +11802,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
|
| return;
|
| }
|
|
|
| - if (!CheckBoundReadFramebufferValid("glCopyTexImage2D")) {
|
| + if (!CheckBoundReadFramebufferValid("glCopyTexImage2D",
|
| + GL_INVALID_FRAMEBUFFER_OPERATION)) {
|
| return;
|
| }
|
|
|
| @@ -11993,7 +12002,8 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
|
| return;
|
| }
|
|
|
| - if (!CheckBoundReadFramebufferValid("glCopyTexImage2D")) {
|
| + if (!CheckBoundReadFramebufferValid("glCopyTexImage2D",
|
| + GL_INVALID_FRAMEBUFFER_OPERATION)) {
|
| return;
|
| }
|
|
|
|
|