| 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 3e0e02ac6a65431059ab47b5bdd147e1a2727f38..e23c05b62168a511f162b28e10e04cb6481bace0 100644
|
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| @@ -126,7 +126,7 @@ static bool IsAngle() {
|
| #endif
|
| }
|
|
|
| -void WrappedTexImage2D(
|
| +static void WrappedTexImage2D(
|
| GLenum target,
|
| GLint level,
|
| GLenum internal_format,
|
| @@ -735,6 +735,15 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
|
| void RestoreCurrentRenderbufferBindings();
|
| void RestoreCurrentTexture2DBindings();
|
|
|
| + // Sets DEPTH_TEST, STENCIL_TEST and color mask for the current framebuffer.
|
| + void ApplyDirtyState();
|
| +
|
| + // These check the state of the currently bound framebuffer or the
|
| + // backbuffer if no framebuffer is bound.
|
| + bool BoundFramebufferHasColorAttachmentWithAlpha();
|
| + bool BoundFramebufferHasDepthAttachment();
|
| + bool BoundFramebufferHasStencilAttachment();
|
| +
|
| private:
|
| friend class ScopedGLErrorSuppressor;
|
| friend class ScopedResolvedFrameBufferBinder;
|
| @@ -824,6 +833,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
|
| // Get the format of the currently bound frame buffer (either FBO or regular
|
| // back buffer)
|
| GLenum GetBoundReadFrameBufferInternalFormat();
|
| + GLenum GetBoundDrawFrameBufferInternalFormat();
|
|
|
| // Wrapper for CompressedTexImage2D commands.
|
| error::Error DoCompressedTexImage2D(
|
| @@ -1259,8 +1269,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
|
| // Wrapper for glValidateProgram.
|
| void DoValidateProgram(GLuint program_client_id);
|
|
|
| - void DoCopyTextureToParentTextureCHROMIUM(GLuint client_texture_id,
|
| - GLuint parent_client_texture_id);
|
| + void DoCopyTextureToParentTextureCHROMIUM(
|
| + GLuint client_texture_id, GLuint parent_client_texture_id);
|
|
|
| void DoResizeCHROMIUM(GLuint width, GLuint height);
|
|
|
| @@ -1462,6 +1472,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
|
| GLclampf clear_depth_;
|
| GLboolean mask_depth_;
|
| bool enable_scissor_test_;
|
| + bool state_dirty_;
|
|
|
| // The program in use by glUseProgram
|
| ProgramManager::ProgramInfo::Ref current_program_;
|
| @@ -1501,6 +1512,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
|
|
|
| // The format of the back buffer_
|
| GLenum back_buffer_color_format_;
|
| + bool back_buffer_has_depth_;
|
| + bool back_buffer_has_stencil_;
|
|
|
| bool teximage2d_faster_than_texsubimage2d_;
|
| bool bufferdata_faster_than_buffersubdata_;
|
| @@ -1844,6 +1857,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
|
| clear_depth_(1.0f),
|
| mask_depth_(true),
|
| enable_scissor_test_(false),
|
| + state_dirty_(true),
|
| offscreen_target_color_format_(0),
|
| offscreen_target_depth_format_(0),
|
| offscreen_target_stencil_format_(0),
|
| @@ -1851,6 +1865,8 @@ GLES2DecoderImpl::GLES2DecoderImpl(SurfaceManager* surface_manager,
|
| copy_texture_to_parent_texture_fb_(0),
|
| offscreen_saved_color_format_(0),
|
| back_buffer_color_format_(0),
|
| + back_buffer_has_depth_(false),
|
| + back_buffer_has_stencil_(false),
|
| teximage2d_faster_than_texsubimage2d_(true),
|
| bufferdata_faster_than_buffersubdata_(true),
|
| current_decoder_error_(error::kNoError),
|
| @@ -1930,10 +1946,6 @@ bool GLES2DecoderImpl::Initialize(
|
|
|
| vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
|
|
|
| - GLint v = 0;
|
| - glGetIntegerv(GL_ALPHA_BITS, &v);
|
| - back_buffer_color_format_ = v ? GL_RGBA : GL_RGB;
|
| -
|
| if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
|
| // We have to enable vertex array 0 on OpenGL or it won't render. Note that
|
| // OpenGL ES 2.0 does not have this issue.
|
| @@ -1961,11 +1973,30 @@ bool GLES2DecoderImpl::Initialize(
|
| glActiveTexture(GL_TEXTURE0);
|
| CHECK_GL_ERROR();
|
|
|
| - if (surface_->IsOffscreen()) {
|
| - ContextCreationAttribParser attrib_parser;
|
| - if (!attrib_parser.Parse(attribs))
|
| - return false;
|
| + ContextCreationAttribParser attrib_parser;
|
| + if (!attrib_parser.Parse(attribs))
|
| + return false;
|
| +
|
| + // These are NOT if the back buffer has these proprorties. They are
|
| + // if we want the command buffer to enforce them regardless of what
|
| + // the real backbuffer is assuming the real back buffer gives us more than
|
| + // we ask for. In other words, if we ask for RGB and we get RGBA then we'll
|
| + // make it appear RGB. If on the other hand we ask for RGBA nd get RGB we
|
| + // can't do anything about that.
|
| +
|
| + GLint v = 0;
|
| + glGetIntegerv(GL_ALPHA_BITS, &v);
|
| + // This checks if the user requested RGBA and we have RGBA then RGBA. If the
|
| + // user requested RGB then RGB. If the user did not specify a preference than
|
| + // use whatever we were given. Same for DEPTH and STENCIL.
|
| + back_buffer_color_format_ =
|
| + (attrib_parser.alpha_size_ != 0 && v > 0) ? GL_RGBA : GL_RGB;
|
| + glGetIntegerv(GL_DEPTH_BITS, &v);
|
| + back_buffer_has_depth_ = attrib_parser.depth_size_ != 0 && v > 0;
|
| + glGetIntegerv(GL_STENCIL_BITS, &v);
|
| + back_buffer_has_stencil_ = attrib_parser.stencil_size_ != 0 && v > 0;
|
|
|
| + if (surface_->IsOffscreen()) {
|
| if (attrib_parser.samples_ > 0 && attrib_parser.sample_buffers_ > 0 &&
|
| (context_->HasExtension("GL_EXT_framebuffer_multisample") ||
|
| context_->HasExtension("GL_ANGLE_framebuffer_multisample"))) {
|
| @@ -2234,6 +2265,10 @@ void GLES2DecoderImpl::DeleteFramebuffersHelper(
|
| FramebufferManager::FramebufferInfo* info =
|
| GetFramebufferInfo(client_ids[ii]);
|
| if (info) {
|
| + if (info == bound_draw_framebuffer_) {
|
| + bound_draw_framebuffer_ = NULL;
|
| + state_dirty_ = true;
|
| + }
|
| GLuint service_id = info->service_id();
|
| glDeleteFramebuffersEXT(1, &service_id);
|
| RemoveFramebufferInfo(client_ids[ii]);
|
| @@ -2247,6 +2282,7 @@ void GLES2DecoderImpl::DeleteRenderbuffersHelper(
|
| RenderbufferManager::RenderbufferInfo* info =
|
| GetRenderbufferInfo(client_ids[ii]);
|
| if (info) {
|
| + state_dirty_ = true;
|
| GLuint service_id = info->service_id();
|
| glDeleteRenderbuffersEXT(1, &service_id);
|
| RemoveRenderbufferInfo(client_ids[ii]);
|
| @@ -2259,6 +2295,9 @@ void GLES2DecoderImpl::DeleteTexturesHelper(
|
| for (GLsizei ii = 0; ii < n; ++ii) {
|
| TextureManager::TextureInfo* info = GetTextureInfo(client_ids[ii]);
|
| if (info) {
|
| + if (info->IsAttachedToFramebuffer()) {
|
| + state_dirty_ = true;
|
| + }
|
| GLuint service_id = info->service_id();
|
| glDeleteTextures(1, &service_id);
|
| RemoveTextureInfo(client_ids[ii]);
|
| @@ -2283,13 +2322,17 @@ static void RebindCurrentFramebuffer(
|
| FramebufferManager::FramebufferInfo* info,
|
| FrameBuffer* offscreen_frame_buffer) {
|
| GLuint framebuffer_id = info ? info->service_id() : 0;
|
| +
|
| if (framebuffer_id == 0 && offscreen_frame_buffer) {
|
| framebuffer_id = offscreen_frame_buffer->id();
|
| }
|
| +
|
| glBindFramebufferEXT(target, framebuffer_id);
|
| }
|
|
|
| void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() {
|
| + state_dirty_ = true;
|
| +
|
| if (!feature_info_->feature_flags().chromium_framebuffer_multisample) {
|
| RebindCurrentFramebuffer(
|
| GL_FRAMEBUFFER,
|
| @@ -2346,12 +2389,17 @@ gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
|
|
|
| GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() {
|
| if (bound_read_framebuffer_ != 0) {
|
| - const FramebufferManager::FramebufferInfo::Attachment* attachment =
|
| - bound_read_framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0);
|
| - if (attachment) {
|
| - return attachment->internal_format();
|
| - }
|
| - return 0;
|
| + return bound_read_framebuffer_->GetColorAttachmentFormat();
|
| + } else if (offscreen_target_frame_buffer_.get()) {
|
| + return offscreen_target_color_format_;
|
| + } else {
|
| + return back_buffer_color_format_;
|
| + }
|
| +}
|
| +
|
| +GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() {
|
| + if (bound_draw_framebuffer_ != 0) {
|
| + return bound_draw_framebuffer_->GetColorAttachmentFormat();
|
| } else if (offscreen_target_frame_buffer_.get()) {
|
| return offscreen_target_color_format_;
|
| } else {
|
| @@ -2443,7 +2491,7 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
|
| // Clear the target frame buffer.
|
| {
|
| ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
|
| - glClearColor(0, 0, 0, 0);
|
| + glClearColor(0, 0, 0, offscreen_target_color_format_ == GL_RGB);
|
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
| glClearStencil(0);
|
| glStencilMaskSeparate(GL_FRONT, GL_TRUE);
|
| @@ -2824,6 +2872,47 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
|
| glBindBuffer(target, service_id);
|
| }
|
|
|
| +bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() {
|
| + return (GLES2Util::GetChannelsForFormat(
|
| + GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0;
|
| +}
|
| +
|
| +bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() {
|
| + if (bound_draw_framebuffer_) {
|
| + return bound_draw_framebuffer_->HasDepthAttachment();
|
| + }
|
| + if (offscreen_target_frame_buffer_.get()) {
|
| + return offscreen_target_depth_format_ != 0;
|
| + }
|
| + return back_buffer_has_depth_;
|
| +}
|
| +
|
| +bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() {
|
| + if (bound_draw_framebuffer_) {
|
| + return bound_draw_framebuffer_->HasStencilAttachment();
|
| + }
|
| + if (offscreen_target_frame_buffer_.get()) {
|
| + return offscreen_target_stencil_format_ != 0;
|
| + }
|
| + return back_buffer_has_stencil_;
|
| +}
|
| +
|
| +void GLES2DecoderImpl::ApplyDirtyState() {
|
| + if (state_dirty_) {
|
| + glColorMask(
|
| + mask_red_, mask_green_, mask_blue_,
|
| + mask_alpha_ && BoundFramebufferHasColorAttachmentWithAlpha());
|
| + glDepthMask(mask_depth_ && BoundFramebufferHasDepthAttachment());
|
| + glStencilMaskSeparate(
|
| + GL_FRONT,
|
| + BoundFramebufferHasStencilAttachment() ? mask_stencil_front_ : 0);
|
| + glStencilMaskSeparate(
|
| + GL_BACK,
|
| + BoundFramebufferHasStencilAttachment() ? mask_stencil_back_ : 0);
|
| + state_dirty_ = false;
|
| + }
|
| +}
|
| +
|
| void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
|
| FramebufferManager::FramebufferInfo* info = NULL;
|
| GLuint service_id = 0;
|
| @@ -2852,10 +2941,13 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) {
|
| bound_read_framebuffer_ = info;
|
| }
|
|
|
| + state_dirty_ = true;
|
| +
|
| // When rendering to an offscreen frame buffer, instead of unbinding from
|
| // the current frame buffer, bind to the offscreen target frame buffer.
|
| - if (info == NULL && offscreen_target_frame_buffer_.get())
|
| + if (info == NULL && offscreen_target_frame_buffer_.get()) {
|
| service_id = offscreen_target_frame_buffer_->id();
|
| + }
|
|
|
| glBindFramebufferEXT(target, service_id);
|
| }
|
| @@ -3009,6 +3101,57 @@ bool GLES2DecoderImpl::GetHelper(
|
| }
|
| }
|
| switch (pname) {
|
| + case GL_COLOR_WRITEMASK:
|
| + *num_written = 4;
|
| + if (params) {
|
| + params[0] = mask_red_;
|
| + params[1] = mask_green_;
|
| + params[2] = mask_blue_;
|
| + params[3] = mask_alpha_;
|
| + }
|
| + return true;
|
| + case GL_DEPTH_WRITEMASK:
|
| + *num_written = 1;
|
| + if (params) {
|
| + params[0] = mask_depth_;
|
| + }
|
| + return true;
|
| + case GL_STENCIL_BACK_WRITEMASK:
|
| + *num_written = 1;
|
| + if (params) {
|
| + params[0] = mask_stencil_back_;
|
| + }
|
| + return true;
|
| + case GL_STENCIL_WRITEMASK:
|
| + *num_written = 1;
|
| + if (params) {
|
| + params[0] = mask_stencil_front_;
|
| + }
|
| + return true;
|
| + case GL_ALPHA_BITS:
|
| + *num_written = 1;
|
| + if (params) {
|
| + GLint v = 0;
|
| + glGetIntegerv(GL_ALPHA_BITS, &v);
|
| + params[0] = BoundFramebufferHasColorAttachmentWithAlpha() ? v : 0;
|
| + }
|
| + return true;
|
| + case GL_DEPTH_BITS:
|
| + *num_written = 1;
|
| + if (params) {
|
| + GLint v = 0;
|
| + glGetIntegerv(GL_DEPTH_BITS, &v);
|
| + params[0] = BoundFramebufferHasDepthAttachment() ? v : 0;
|
| + }
|
| + return true;
|
| + case GL_STENCIL_BITS:
|
| + *num_written = 1;
|
| + if (params) {
|
| + GLint v = 0;
|
| + glGetIntegerv(GL_STENCIL_BITS, &v);
|
| + params[0] = BoundFramebufferHasStencilAttachment() ? v : 0;
|
| + }
|
| + return true;
|
| case GL_COMPRESSED_TEXTURE_FORMATS:
|
| *num_written = 0;
|
| // We don't support compressed textures.
|
| @@ -3400,6 +3543,7 @@ error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM(
|
|
|
| void GLES2DecoderImpl::DoClear(GLbitfield mask) {
|
| if (CheckFramebufferComplete("glClear")) {
|
| + ApplyDirtyState();
|
| glClear(mask);
|
| }
|
| }
|
| @@ -3426,6 +3570,7 @@ void GLES2DecoderImpl::DoDrawArrays(
|
| bool simulated_fixed_attribs = false;
|
| if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
|
| bool textures_set = SetBlackTextureForNonRenderableTextures();
|
| + ApplyDirtyState();
|
| glDrawArrays(mode, first, count);
|
| if (textures_set) {
|
| RestoreStateForNonRenderableTextures();
|
| @@ -3474,6 +3619,9 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
|
| }
|
| }
|
| }
|
| + if (framebuffer_info == bound_draw_framebuffer_) {
|
| + state_dirty_ = true;
|
| + }
|
| }
|
|
|
| void GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
|
| @@ -3521,27 +3669,28 @@ void GLES2DecoderImpl::DoColorMask(
|
| mask_green_ = green;
|
| mask_blue_ = blue;
|
| mask_alpha_ = alpha;
|
| - glColorMask(red, green, blue, alpha);
|
| + state_dirty_ = true;
|
| }
|
|
|
| void GLES2DecoderImpl::DoDepthMask(GLboolean depth) {
|
| mask_depth_ = depth;
|
| - glDepthMask(depth);
|
| + state_dirty_ = true;
|
| }
|
|
|
| void GLES2DecoderImpl::DoStencilMask(GLuint mask) {
|
| mask_stencil_front_ = mask;
|
| mask_stencil_back_ = mask;
|
| - glStencilMask(mask);
|
| + state_dirty_ = true;
|
| }
|
|
|
| void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) {
|
| - if (face == GL_FRONT) {
|
| + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
|
| mask_stencil_front_ = mask;
|
| - } else {
|
| + }
|
| + if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
|
| mask_stencil_back_ = mask;
|
| }
|
| - glStencilMaskSeparate(face, mask);
|
| + state_dirty_ = true;
|
| }
|
|
|
| // NOTE: There's an assumption here that Texture attachments
|
| @@ -3586,13 +3735,10 @@ void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
|
| }
|
|
|
| void GLES2DecoderImpl::RestoreClearState() {
|
| + state_dirty_ = true;
|
| glClearColor(clear_red_, clear_green_, clear_blue_, clear_alpha_);
|
| - glColorMask(mask_red_, mask_green_, mask_blue_, mask_alpha_);
|
| glClearStencil(clear_stencil_);
|
| - glStencilMaskSeparate(GL_FRONT, mask_stencil_front_);
|
| - glStencilMaskSeparate(GL_BACK, mask_stencil_back_);
|
| glClearDepth(clear_depth_);
|
| - glDepthMask(mask_depth_);
|
| if (enable_scissor_test_) {
|
| glEnable(GL_SCISSOR_TEST);
|
| }
|
| @@ -3638,6 +3784,9 @@ void GLES2DecoderImpl::DoFramebufferTexture2D(
|
| ClearUnclearedRenderbuffers(target, framebuffer_info);
|
| }
|
| }
|
| + if (framebuffer_info == bound_draw_framebuffer_) {
|
| + state_dirty_ = true;
|
| + }
|
| }
|
|
|
| void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
|
| @@ -4433,6 +4582,7 @@ error::Error GLES2DecoderImpl::HandleDrawElements(
|
| bool simulated_fixed_attribs = false;
|
| if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
|
| bool textures_set = SetBlackTextureForNonRenderableTextures();
|
| + ApplyDirtyState();
|
| const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
|
| glDrawElements(mode, count, type, indices);
|
| if (textures_set) {
|
| @@ -5648,6 +5798,10 @@ error::Error GLES2DecoderImpl::DoTexImage2D(
|
| pixels = zero.get();
|
| }
|
|
|
| + if (info->IsAttachedToFramebuffer()) {
|
| + state_dirty_ = true;
|
| + }
|
| +
|
| if (!teximage2d_faster_than_texsubimage2d_) {
|
| GLsizei tex_width = 0;
|
| GLsizei tex_height = 0;
|
| @@ -5828,6 +5982,10 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
|
| ScopedResolvedFrameBufferBinder binder(this, false);
|
| gfx::Size size = GetBoundReadFrameBufferSize();
|
|
|
| + if (info->IsAttachedToFramebuffer()) {
|
| + state_dirty_ = true;
|
| + }
|
| +
|
| // Clip to size to source dimensions
|
| GLint copyX = 0;
|
| GLint copyY = 0;
|
|
|