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 ed6e00053b88fa5de378124a81ebbaebf7760cca..c982c9a18136ff285d44c851fc22ed8b6f46cfb1 100644 |
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
@@ -219,11 +219,13 @@ class ScopedFrameBufferBinder { |
// Temporarily changes a decoder's bound frame buffer to a resolved version of |
// the multisampled offscreen render buffer if that buffer is multisampled, and, |
-// if it is bound or enforce_internal_framebuffer is true. |
+// if it is bound or enforce_internal_framebuffer is true. If internal is |
+// true, the resolved framebuffer is not visible to the parent. |
class ScopedResolvedFrameBufferBinder { |
public: |
ScopedResolvedFrameBufferBinder(GLES2DecoderImpl* decoder, |
- bool enforce_internal_framebuffer); |
+ bool enforce_internal_framebuffer, |
+ bool internal); |
~ScopedResolvedFrameBufferBinder(); |
private: |
@@ -1285,10 +1287,13 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, |
GLuint copy_texture_to_parent_texture_fb_; |
- // The copy that is saved when SwapBuffers is called. It is also |
- // used as the destination for multi-sample resolves. |
+ // The copy that is saved when SwapBuffers is called. |
scoped_ptr<FrameBuffer> offscreen_saved_frame_buffer_; |
scoped_ptr<Texture> offscreen_saved_color_texture_; |
+ |
+ // The copy that is used as the destination for multi-sample resolves. |
+ scoped_ptr<FrameBuffer> offscreen_resolved_frame_buffer_; |
+ scoped_ptr<Texture> offscreen_resolved_color_texture_; |
GLenum offscreen_saved_color_format_; |
scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_; |
@@ -1380,7 +1385,7 @@ ScopedFrameBufferBinder::~ScopedFrameBufferBinder() { |
} |
ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder( |
- GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer) |
+ GLES2DecoderImpl* decoder, bool enforce_internal_framebuffer, bool internal) |
: decoder_(decoder) { |
resolve_and_bind_ = (decoder_->offscreen_target_frame_buffer_.get() && |
decoder_->IsOffscreenBufferMultisampled() && |
@@ -1392,8 +1397,33 @@ ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder( |
ScopedGLErrorSuppressor suppressor(decoder_); |
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, |
decoder_->offscreen_target_frame_buffer_->id()); |
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, |
- decoder_->offscreen_saved_frame_buffer_->id()); |
+ GLuint targetid; |
+ if (internal) { |
+ if (!decoder_->offscreen_resolved_frame_buffer_.get()) { |
+ decoder_->offscreen_resolved_frame_buffer_.reset( |
+ new FrameBuffer(decoder_)); |
+ decoder_->offscreen_resolved_frame_buffer_->Create(); |
+ decoder_->offscreen_resolved_color_texture_.reset(new Texture(decoder_)); |
+ decoder_->offscreen_resolved_color_texture_->Create(); |
+ |
+ DCHECK(decoder_->offscreen_saved_color_format_); |
+ decoder_->offscreen_resolved_color_texture_->AllocateStorage( |
+ decoder_->offscreen_size_, decoder_->offscreen_saved_color_format_); |
+ |
+ decoder_->offscreen_resolved_frame_buffer_->AttachRenderTexture( |
+ decoder_->offscreen_resolved_color_texture_.get()); |
+ if (decoder_->offscreen_resolved_frame_buffer_->CheckStatus() != |
+ GL_FRAMEBUFFER_COMPLETE) { |
+ LOG(ERROR) << "ScopedResolvedFrameBufferBinder failed " |
+ << "because offscreen resolved FBO was incomplete."; |
+ return; |
+ } |
+ } |
+ targetid = decoder_->offscreen_resolved_frame_buffer_->id(); |
+ } else { |
+ targetid = decoder_->offscreen_saved_frame_buffer_->id(); |
+ } |
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid); |
const int width = decoder_->offscreen_size_.width(); |
const int height = decoder_->offscreen_size_.height(); |
glDisable(GL_SCISSOR_TEST); |
@@ -1404,8 +1434,7 @@ ScopedResolvedFrameBufferBinder::ScopedResolvedFrameBufferBinder( |
glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, |
GL_COLOR_BUFFER_BIT, GL_NEAREST); |
} |
- glBindFramebufferEXT(GL_FRAMEBUFFER, |
- decoder_->offscreen_saved_frame_buffer_->id()); |
+ glBindFramebufferEXT(GL_FRAMEBUFFER, targetid); |
} |
ScopedResolvedFrameBufferBinder::~ScopedResolvedFrameBufferBinder() { |
@@ -2315,6 +2344,14 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() { |
return false; |
} |
+ // Destroy the offscreen resolved framebuffers. |
+ if (offscreen_resolved_frame_buffer_.get()) |
+ offscreen_resolved_frame_buffer_->Destroy(); |
+ if (offscreen_resolved_color_texture_.get()) |
+ offscreen_resolved_color_texture_->Destroy(); |
+ offscreen_resolved_color_texture_.reset(); |
+ offscreen_resolved_frame_buffer_.reset(); |
+ |
// Clear the offscreen color texture. |
{ |
ScopedFrameBufferBinder binder(this, offscreen_saved_frame_buffer_->id()); |
@@ -2434,6 +2471,10 @@ void GLES2DecoderImpl::Destroy() { |
offscreen_saved_frame_buffer_->Destroy(); |
if (offscreen_saved_color_texture_.get()) |
offscreen_saved_color_texture_->Destroy(); |
+ if (offscreen_resolved_frame_buffer_.get()) |
+ offscreen_resolved_frame_buffer_->Destroy(); |
+ if (offscreen_resolved_color_texture_.get()) |
+ offscreen_resolved_color_texture_->Destroy(); |
// must release the ContextGroup before destroying the context as its |
// destructor uses GL. |
@@ -2453,6 +2494,10 @@ void GLES2DecoderImpl::Destroy() { |
offscreen_saved_frame_buffer_->Invalidate(); |
if (offscreen_saved_color_texture_.get()) |
offscreen_saved_color_texture_->Invalidate(); |
+ if (offscreen_resolved_frame_buffer_.get()) |
+ offscreen_resolved_frame_buffer_->Invalidate(); |
+ if (offscreen_resolved_color_texture_.get()) |
+ offscreen_resolved_color_texture_->Invalidate(); |
} |
if (context_.get()) { |
@@ -2468,6 +2513,8 @@ void GLES2DecoderImpl::Destroy() { |
offscreen_target_stencil_render_buffer_.reset(); |
offscreen_saved_frame_buffer_.reset(); |
offscreen_saved_color_texture_.reset(); |
+ offscreen_resolved_frame_buffer_.reset(); |
+ offscreen_resolved_color_texture_.reset(); |
} |
bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent, |
@@ -5115,7 +5162,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels( |
CopyRealGLErrorsToWrapper(); |
- ScopedResolvedFrameBufferBinder binder(this, false); |
+ ScopedResolvedFrameBufferBinder binder(this, false, true); |
// Get the size of the current fbo or backbuffer. |
gfx::Size max_size = GetBoundReadFrameBufferSize(); |
@@ -5902,7 +5949,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D( |
} |
CopyRealGLErrorsToWrapper(); |
- ScopedResolvedFrameBufferBinder binder(this, false); |
+ ScopedResolvedFrameBufferBinder binder(this, false, true); |
gfx::Size size = GetBoundReadFrameBufferSize(); |
if (info->IsAttachedToFramebuffer()) { |
@@ -5990,7 +6037,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( |
return; |
} |
- ScopedResolvedFrameBufferBinder binder(this, false); |
+ ScopedResolvedFrameBufferBinder binder(this, false, true); |
gfx::Size size = GetBoundReadFrameBufferSize(); |
GLint copyX = 0; |
GLint copyY = 0; |
@@ -6533,7 +6580,7 @@ error::Error GLES2DecoderImpl::HandleSwapBuffers( |
if (IsOffscreenBufferMultisampled()) { |
// For multisampled buffers, bind the resolved frame buffer so that |
// callbacks can call ReadPixels or CopyTexImage2D. |
- ScopedResolvedFrameBufferBinder binder(this, true); |
+ ScopedResolvedFrameBufferBinder binder(this, true, false); |
if (swap_buffers_callback_.get()) { |
swap_buffers_callback_->Run(); |
} |