| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| ===================================================================
|
| --- gpu/command_buffer/service/gles2_cmd_decoder.cc (revision 56887)
|
| +++ gpu/command_buffer/service/gles2_cmd_decoder.cc (working copy)
|
| @@ -556,11 +556,13 @@
|
|
|
| virtual void SetSwapBuffersCallback(Callback0::Type* callback);
|
|
|
| + // Restores the current state to the user's settings.
|
| + void RestoreCurrentFramebufferBindings();
|
| + void RestoreCurrentRenderbufferBindings();
|
| + void RestoreCurrentTexture2DBindings();
|
| +
|
| private:
|
| friend class ScopedGLErrorSuppressor;
|
| - friend class ScopedTexture2DBinder;
|
| - friend class ScopedFrameBufferBinder;
|
| - friend class ScopedRenderBufferBinder;
|
| friend class ScopedDefaultGLContext;
|
| friend class RenderBuffer;
|
| friend class FrameBuffer;
|
| @@ -635,7 +637,7 @@
|
|
|
| // Get the size (in pixels) of the currently bound frame buffer (either FBO
|
| // or regular back buffer).
|
| - gfx::Size GetBoundFrameBufferSize();
|
| + gfx::Size GetBoundReadFrameBufferSize();
|
|
|
| // Wrapper for CompressedTexImage2D commands.
|
| error::Error DoCompressedTexImage2D(
|
| @@ -848,7 +850,8 @@
|
| GLuint client_id, const char* data, uint32 data_size);
|
|
|
| // Clears any uncleared render buffers attached to the given frame buffer.
|
| - void ClearUnclearedRenderbuffers(FramebufferManager::FramebufferInfo* info);
|
| + void ClearUnclearedRenderbuffers(
|
| + GLenum target, FramebufferManager::FramebufferInfo* info);
|
|
|
| // Remembers the state of some capabilities.
|
| void SetCapabilityState(GLenum cap, bool enabled);
|
| @@ -897,6 +900,12 @@
|
| // Wrapper for glBindTexture since we need to track the current targets.
|
| void DoBindTexture(GLenum target, GLuint texture);
|
|
|
| + // Wrapper for glBlitFramebufferEXT.
|
| + void DoBlitFramebufferEXT(
|
| + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
| + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
| + GLbitfield mask, GLenum filter);
|
| +
|
| // Wrapper for glBufferData.
|
| void DoBufferData(
|
| GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
|
| @@ -1010,6 +1019,11 @@
|
| void DoRenderbufferStorage(
|
| GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
|
|
| + // Wrapper for glRenderbufferStorageMultisampleEXT.
|
| + void DoRenderbufferStorageMultisample(
|
| + GLenum target, GLsizei samples, GLenum internalformat,
|
| + GLsizei width, GLsizei height);
|
| +
|
| // Wrapper for glReleaseShaderCompiler.
|
| void DoReleaseShaderCompiler() { }
|
|
|
| @@ -1115,6 +1129,25 @@
|
| return (info && !info->IsDeleted()) ? info : NULL;
|
| }
|
|
|
| + // Gets the framebuffer info for a particular target.
|
| + FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget(
|
| + GLenum target) {
|
| + FramebufferManager::FramebufferInfo* info = NULL;
|
| + switch (target) {
|
| + case GL_FRAMEBUFFER:
|
| + case GL_DRAW_FRAMEBUFFER:
|
| + info = bound_draw_framebuffer_;
|
| + break;
|
| + case GL_READ_FRAMEBUFFER:
|
| + info = bound_read_framebuffer_;
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| + return (info && !info->IsDeleted()) ? info : NULL;
|
| + }
|
| +
|
| // Validates the program and location for a glGetUniform call and returns
|
| // a SizeResult setup to receive the result. Returns true if glGetUniform
|
| // should be called.
|
| @@ -1219,8 +1252,9 @@
|
| // The program in use by glUseProgram
|
| ProgramManager::ProgramInfo::Ref current_program_;
|
|
|
| - // The currently bound framebuffer
|
| - FramebufferManager::FramebufferInfo::Ref bound_framebuffer_;
|
| + // The currently bound framebuffers
|
| + FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_;
|
| + FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_;
|
|
|
| // The currently bound renderbuffer
|
| RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_;
|
| @@ -1279,15 +1313,7 @@
|
|
|
| ScopedTexture2DBinder::~ScopedTexture2DBinder() {
|
| ScopedGLErrorSuppressor suppressor(decoder_);
|
| - GLES2DecoderImpl::TextureUnit& info = decoder_->texture_units_[0];
|
| - GLuint last_id;
|
| - if (info.bound_texture_2d)
|
| - last_id = info.bound_texture_2d->service_id();
|
| - else
|
| - last_id = 0;
|
| -
|
| - glBindTexture(GL_TEXTURE_2D, last_id);
|
| - glActiveTexture(GL_TEXTURE0 + decoder_->active_texture_unit_);
|
| + decoder_->RestoreCurrentTexture2DBindings();
|
| }
|
|
|
| ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder,
|
| @@ -1299,10 +1325,7 @@
|
|
|
| ScopedRenderBufferBinder::~ScopedRenderBufferBinder() {
|
| ScopedGLErrorSuppressor suppressor(decoder_);
|
| - glBindRenderbufferEXT(
|
| - GL_RENDERBUFFER,
|
| - decoder_->bound_renderbuffer_ ?
|
| - decoder_->bound_renderbuffer_->service_id() : 0);
|
| + decoder_->RestoreCurrentRenderbufferBindings();
|
| }
|
|
|
| ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder,
|
| @@ -1314,16 +1337,7 @@
|
|
|
| ScopedFrameBufferBinder::~ScopedFrameBufferBinder() {
|
| ScopedGLErrorSuppressor suppressor(decoder_);
|
| - FramebufferManager::FramebufferInfo* info =
|
| - decoder_->bound_framebuffer_.get();
|
| - GLuint framebuffer_id = info ? info->service_id() : 0;
|
| - if (framebuffer_id == 0 &&
|
| - decoder_->offscreen_target_frame_buffer_.get()) {
|
| - glBindFramebufferEXT(GL_FRAMEBUFFER,
|
| - decoder_->offscreen_target_frame_buffer_->id());
|
| - } else {
|
| - glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_id);
|
| - }
|
| + decoder_->RestoreCurrentFramebufferBindings();
|
| }
|
|
|
| ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder)
|
| @@ -1828,16 +1842,67 @@
|
| return context_.get() ? context_->MakeCurrent() : false;
|
| }
|
|
|
| -gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() {
|
| - if (bound_framebuffer_ != 0) {
|
| +void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() {
|
| + glBindRenderbufferEXT(
|
| + GL_RENDERBUFFER,
|
| + bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0);
|
| +}
|
| +
|
| +static void RebindCurrentFramebuffer(
|
| + GLenum target,
|
| + 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() {
|
| + if (!group_->extension_flags().ext_framebuffer_multisample) {
|
| + RebindCurrentFramebuffer(
|
| + GL_FRAMEBUFFER,
|
| + bound_draw_framebuffer_.get(),
|
| + offscreen_target_frame_buffer_.get());
|
| + } else {
|
| + RebindCurrentFramebuffer(
|
| + GL_READ_FRAMEBUFFER_EXT,
|
| + bound_read_framebuffer_.get(),
|
| + offscreen_target_frame_buffer_.get());
|
| + RebindCurrentFramebuffer(
|
| + GL_DRAW_FRAMEBUFFER_EXT,
|
| + bound_draw_framebuffer_.get(),
|
| + offscreen_target_frame_buffer_.get());
|
| + }
|
| +}
|
| +
|
| +void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() {
|
| + GLES2DecoderImpl::TextureUnit& info = texture_units_[0];
|
| + GLuint last_id;
|
| + if (info.bound_texture_2d) {
|
| + last_id = info.bound_texture_2d->service_id();
|
| + } else {
|
| + last_id = 0;
|
| + }
|
| +
|
| + glBindTexture(GL_TEXTURE_2D, last_id);
|
| + glActiveTexture(GL_TEXTURE0 + active_texture_unit_);
|
| +}
|
| +
|
| +gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() {
|
| + if (bound_read_framebuffer_ != 0) {
|
| int width = 0;
|
| int height = 0;
|
|
|
| + GLenum target = group_->extension_flags().ext_framebuffer_multisample ?
|
| + GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER;
|
| +
|
| // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
|
| // stencil.
|
| GLint fb_type = 0;
|
| glGetFramebufferAttachmentParameterivEXT(
|
| - GL_FRAMEBUFFER,
|
| + target,
|
| GL_COLOR_ATTACHMENT0,
|
| GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
|
| &fb_type);
|
| @@ -1846,7 +1911,7 @@
|
| {
|
| GLint renderbuffer_id = 0;
|
| glGetFramebufferAttachmentParameterivEXT(
|
| - GL_FRAMEBUFFER,
|
| + target,
|
| GL_COLOR_ATTACHMENT0,
|
| GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
| &renderbuffer_id);
|
| @@ -1866,7 +1931,7 @@
|
| {
|
| GLint texture_id = 0;
|
| glGetFramebufferAttachmentParameterivEXT(
|
| - GL_FRAMEBUFFER,
|
| + target,
|
| GL_COLOR_ATTACHMENT0,
|
| GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
| &texture_id);
|
| @@ -1879,12 +1944,12 @@
|
| GLint level = 0;
|
| GLint face = 0;
|
| glGetFramebufferAttachmentParameterivEXT(
|
| - GL_FRAMEBUFFER,
|
| + target,
|
| GL_COLOR_ATTACHMENT0,
|
| GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
|
| &level);
|
| glGetFramebufferAttachmentParameterivEXT(
|
| - GL_FRAMEBUFFER,
|
| + target,
|
| GL_COLOR_ATTACHMENT0,
|
| GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
|
| &face);
|
| @@ -2262,8 +2327,14 @@
|
| service_id = info->service_id();
|
| }
|
| }
|
| - bound_framebuffer_ = info;
|
|
|
| + if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) {
|
| + bound_draw_framebuffer_ = info;
|
| + }
|
| + if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) {
|
| + bound_read_framebuffer_ = info;
|
| + }
|
| +
|
| // 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())
|
| @@ -2458,18 +2529,32 @@
|
| }
|
| return true;
|
| case GL_FRAMEBUFFER_BINDING:
|
| + // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING)
|
| *num_written = 1;
|
| if (params) {
|
| - if (bound_framebuffer_) {
|
| + if (bound_draw_framebuffer_) {
|
| GLuint client_id = 0;
|
| framebuffer_manager()->GetClientId(
|
| - bound_framebuffer_->service_id(), &client_id);
|
| + bound_draw_framebuffer_->service_id(), &client_id);
|
| *params = client_id;
|
| } else {
|
| *params = 0;
|
| }
|
| }
|
| return true;
|
| + case GL_READ_FRAMEBUFFER_BINDING:
|
| + *num_written = 1;
|
| + if (params) {
|
| + if (bound_read_framebuffer_) {
|
| + GLuint client_id = 0;
|
| + framebuffer_manager()->GetClientId(
|
| + bound_read_framebuffer_->service_id(), &client_id);
|
| + *params = client_id;
|
| + } else {
|
| + *params = 0;
|
| + }
|
| + }
|
| + return true;
|
| case GL_RENDERBUFFER_BINDING:
|
| *num_written = 1;
|
| if (params) {
|
| @@ -2802,7 +2887,9 @@
|
| void GLES2DecoderImpl::DoFramebufferRenderbuffer(
|
| GLenum target, GLenum attachment, GLenum renderbuffertarget,
|
| GLuint client_renderbuffer_id) {
|
| - if (!bound_framebuffer_) {
|
| + FramebufferManager::FramebufferInfo* framebuffer_info =
|
| + GetFramebufferInfoForTarget(target);
|
| + if (!framebuffer_info) {
|
| SetGLError(GL_INVALID_OPERATION,
|
| "glFramebufferRenderbuffer: no framebuffer bound");
|
| return;
|
| @@ -2822,9 +2909,9 @@
|
| target, attachment, renderbuffertarget, service_id);
|
| if (service_id == 0 ||
|
| glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
|
| - bound_framebuffer_->AttachRenderbuffer(attachment, info);
|
| + framebuffer_info->AttachRenderbuffer(attachment, info);
|
| if (info) {
|
| - ClearUnclearedRenderbuffers(bound_framebuffer_);
|
| + ClearUnclearedRenderbuffers(target, framebuffer_info);
|
| }
|
| }
|
| }
|
| @@ -2901,7 +2988,10 @@
|
| // are cleared because they are textures so we only need to clear
|
| // the renderbuffers.
|
| void GLES2DecoderImpl::ClearUnclearedRenderbuffers(
|
| - FramebufferManager::FramebufferInfo* info) {
|
| + GLenum target, FramebufferManager::FramebufferInfo* info) {
|
| + if (target == GL_READ_FRAMEBUFFER_EXT) {
|
| + // TODO(gman): bind this to the DRAW point, clear then bind back to READ
|
| + }
|
| GLbitfield clear_bits = 0;
|
| if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) {
|
| glClearColor(0, 0, 0, 0);
|
| @@ -2939,10 +3029,16 @@
|
| if (enable_scissor_test_) {
|
| glEnable(GL_SCISSOR_TEST);
|
| }
|
| +
|
| + if (target == GL_READ_FRAMEBUFFER_EXT) {
|
| + // TODO(gman): rebind draw.
|
| + }
|
| }
|
|
|
| GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) {
|
| - if (!bound_framebuffer_) {
|
| + FramebufferManager::FramebufferInfo* info =
|
| + GetFramebufferInfoForTarget(target);
|
| + if (!info) {
|
| return GL_FRAMEBUFFER_COMPLETE;
|
| }
|
| return glCheckFramebufferStatusEXT(target);
|
| @@ -2951,7 +3047,9 @@
|
| void GLES2DecoderImpl::DoFramebufferTexture2D(
|
| GLenum target, GLenum attachment, GLenum textarget,
|
| GLuint client_texture_id, GLint level) {
|
| - if (!bound_framebuffer_) {
|
| + FramebufferManager::FramebufferInfo* framebuffer_info =
|
| + GetFramebufferInfoForTarget(target);
|
| + if (!framebuffer_info) {
|
| SetGLError(GL_INVALID_OPERATION,
|
| "glFramebufferTexture2D: no framebuffer bound.");
|
| return;
|
| @@ -2970,13 +3068,15 @@
|
| glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level);
|
| if (service_id != 0 &&
|
| glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) {
|
| - ClearUnclearedRenderbuffers(bound_framebuffer_);
|
| + ClearUnclearedRenderbuffers(target, framebuffer_info);
|
| }
|
| }
|
|
|
| void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
|
| GLenum target, GLenum attachment, GLenum pname, GLint* params) {
|
| - if (!bound_framebuffer_) {
|
| + FramebufferManager::FramebufferInfo* framebuffer_info =
|
| + GetFramebufferInfoForTarget(target);
|
| + if (!framebuffer_info) {
|
| SetGLError(GL_INVALID_OPERATION,
|
| "glFramebufferAttachmentParameteriv: no framebuffer bound");
|
| return;
|
| @@ -3017,6 +3117,48 @@
|
| glGetRenderbufferParameterivEXT(target, pname, params);
|
| }
|
|
|
| +void GLES2DecoderImpl::DoBlitFramebufferEXT(
|
| + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
| + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
| + GLbitfield mask, GLenum filter) {
|
| + if (!group_->extension_flags().ext_framebuffer_multisample) {
|
| + SetGLError(GL_INVALID_OPERATION,
|
| + "glBlitFramebufferEXT: function not available");
|
| + }
|
| + glBlitFramebufferEXT(
|
| + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
| +}
|
| +
|
| +void GLES2DecoderImpl::DoRenderbufferStorageMultisample(
|
| + GLenum target, GLsizei samples, GLenum internalformat,
|
| + GLsizei width, GLsizei height) {
|
| + if (!group_->extension_flags().ext_framebuffer_multisample) {
|
| + SetGLError(GL_INVALID_OPERATION,
|
| + "glRenderbufferStorageMultisampleEXT: function not available");
|
| + return;
|
| + }
|
| + bound_renderbuffer_->set_internal_format(internalformat);
|
| +
|
| + if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
|
| + switch (internalformat) {
|
| + case GL_DEPTH_COMPONENT16:
|
| + internalformat = GL_DEPTH_COMPONENT;
|
| + break;
|
| + case GL_RGBA4:
|
| + case GL_RGB5_A1:
|
| + internalformat = GL_RGBA;
|
| + break;
|
| + case GL_RGB565:
|
| + internalformat = GL_RGB;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + glRenderbufferStorageMultisampleEXT(
|
| + target, samples, internalformat, width, height);
|
| + // TODO(gman) should not set internal format unless this succeeds
|
| +}
|
| +
|
| void GLES2DecoderImpl::DoRenderbufferStorage(
|
| GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
|
| if (!bound_renderbuffer_) {
|
| @@ -3042,6 +3184,7 @@
|
| }
|
|
|
| glRenderbufferStorageEXT(target, internalformat, width, height);
|
| + // TODO(gman) should not set internal format unless this succeeds
|
| }
|
|
|
| void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
|
| @@ -4087,7 +4230,7 @@
|
| CopyRealGLErrorsToWrapper();
|
|
|
| // Get the size of the current fbo or backbuffer.
|
| - gfx::Size max_size = GetBoundFrameBufferSize();
|
| + gfx::Size max_size = GetBoundReadFrameBufferSize();
|
|
|
| GLint max_x;
|
| GLint max_y;
|
|
|