Chromium Code Reviews| 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 70837bf1f9d083b092e9a0bd5bdb745561c2304c..d4af260b6083cec3f97fd44a30421320f90890cc 100644 | 
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc | 
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc | 
| @@ -1247,6 +1247,16 @@ class GLES2DecoderImpl : public GLES2Decoder { | 
| GLenum target, GLenum attachment, GLenum textarget, GLuint texture, | 
| GLint level); | 
| + // Wrapper for glFramebufferTexture2DMultisampleEXT. | 
| + void DoFramebufferTexture2DMultisample( | 
| + GLenum target, GLenum attachment, GLenum textarget, | 
| + GLuint texture, GLint level, GLsizei samples); | 
| + | 
| + // Common implementation for both DoFramebufferTexture2D wrappers. | 
| + void DoFramebufferTexture2DCommon(const char* name, | 
| + GLenum target, GLenum attachment, GLenum textarget, | 
| + GLuint texture, GLint level, GLsizei samples); | 
| + | 
| // Wrapper for glGenerateMipmap | 
| void DoGenerateMipmap(GLenum target); | 
| @@ -1254,6 +1264,11 @@ class GLES2DecoderImpl : public GLES2Decoder { | 
| void DoGenSharedIdsCHROMIUM( | 
| GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids); | 
| + // Helper for DoGetBooleanv, Floatv, and Intergerv to adjust pname | 
| + // to account for different pname values defined in different extension | 
| + // variants. | 
| + GLenum AdjustGetPname(GLenum pname); | 
| + | 
| // Wrapper for DoGetBooleanv. | 
| void DoGetBooleanv(GLenum pname, GLboolean* params); | 
| @@ -4347,6 +4362,14 @@ bool GLES2DecoderImpl::GetNumValuesReturnedForGLGet( | 
| return GetHelper(pname, NULL, num_values); | 
| } | 
| +GLenum GLES2DecoderImpl::AdjustGetPname(GLenum pname) { | 
| + if (GL_MAX_SAMPLES == pname && | 
| + features().use_img_for_multisampled_render_to_texture) { | 
| + return GL_MAX_SAMPLES_IMG; | 
| + } | 
| + return pname; | 
| +} | 
| + | 
| void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) { | 
| DCHECK(params); | 
| GLsizei num_written = 0; | 
| @@ -4359,6 +4382,7 @@ void GLES2DecoderImpl::DoGetBooleanv(GLenum pname, GLboolean* params) { | 
| params[ii] = static_cast<GLboolean>(values[ii]); | 
| } | 
| } else { | 
| + pname = AdjustGetPname(pname); | 
| glGetBooleanv(pname, params); | 
| } | 
| } | 
| @@ -4374,6 +4398,7 @@ void GLES2DecoderImpl::DoGetFloatv(GLenum pname, GLfloat* params) { | 
| params[ii] = static_cast<GLfloat>(values[ii]); | 
| } | 
| } else { | 
| + pname = AdjustGetPname(pname); | 
| glGetFloatv(pname, params); | 
| } | 
| } | 
| @@ -4384,6 +4409,7 @@ void GLES2DecoderImpl::DoGetIntegerv(GLenum pname, GLint* params) { | 
| GLsizei num_written; | 
| if (!state_.GetStateAsGLint(pname, params, &num_written) && | 
| !GetHelper(pname, params, &num_written)) { | 
| + pname = AdjustGetPname(pname); | 
| glGetIntegerv(pname, params); | 
| } | 
| } | 
| @@ -4859,11 +4885,39 @@ GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) { | 
| void GLES2DecoderImpl::DoFramebufferTexture2D( | 
| GLenum target, GLenum attachment, GLenum textarget, | 
| GLuint client_texture_id, GLint level) { | 
| + DoFramebufferTexture2DCommon( | 
| + "glFramebufferTexture2D", target, attachment, | 
| + textarget, client_texture_id, level, 0); | 
| +} | 
| + | 
| +void GLES2DecoderImpl::DoFramebufferTexture2DMultisample( | 
| + GLenum target, GLenum attachment, GLenum textarget, | 
| + GLuint client_texture_id, GLint level, GLsizei samples) { | 
| + if (!features().multisampled_render_to_texture) { | 
| + LOCAL_SET_GL_ERROR( | 
| + GL_INVALID_OPERATION, | 
| + "glFramebufferTexture2DMultisample", "function not available"); | 
| + return; | 
| + } | 
| + DoFramebufferTexture2DCommon( | 
| + "glFramebufferTexture2DMultisample", target, attachment, | 
| + textarget, client_texture_id, level, samples); | 
| +} | 
| + | 
| +void GLES2DecoderImpl::DoFramebufferTexture2DCommon( | 
| + const char* name, GLenum target, GLenum attachment, GLenum textarget, | 
| + GLuint client_texture_id, GLint level, GLsizei samples) { | 
| + if (samples > renderbuffer_manager()->max_samples()) { | 
| + LOCAL_SET_GL_ERROR( | 
| + GL_INVALID_VALUE, | 
| + "glFramebufferTexture2DMultisample", "samples too large"); | 
| + return; | 
| + } | 
| Framebuffer* framebuffer = GetFramebufferInfoForTarget(target); | 
| if (!framebuffer) { | 
| LOCAL_SET_GL_ERROR( | 
| GL_INVALID_OPERATION, | 
| - "glFramebufferTexture2D", "no framebuffer bound."); | 
| + name, "no framebuffer bound."); | 
| return; | 
| } | 
| GLuint service_id = 0; | 
| @@ -4873,7 +4927,7 @@ void GLES2DecoderImpl::DoFramebufferTexture2D( | 
| if (!texture_ref) { | 
| LOCAL_SET_GL_ERROR( | 
| GL_INVALID_OPERATION, | 
| - "glFramebufferTexture2D", "unknown texture_ref"); | 
| + name, "unknown texture_ref"); | 
| return; | 
| } | 
| service_id = texture_ref->service_id(); | 
| @@ -4882,15 +4936,26 @@ void GLES2DecoderImpl::DoFramebufferTexture2D( | 
| if (!texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) { | 
| LOCAL_SET_GL_ERROR( | 
| GL_INVALID_VALUE, | 
| - "glFramebufferTexture2D", "level out of range"); | 
| + name, "level out of range"); | 
| return; | 
| } | 
| - LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glFramebufferTexture2D"); | 
| - glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level); | 
| - GLenum error = LOCAL_PEEK_GL_ERROR("glFramebufferTexture2D"); | 
| + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name); | 
| + if (0 == samples) { | 
| + glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level); | 
| + } else { | 
| + if (features().use_img_for_multisampled_render_to_texture) { | 
| 
 
apatrick_chromium
2013/07/08 21:28:03
Does it need something like this? I can't find any
 
 | 
| + glFramebufferTexture2DMultisampleIMG(target, attachment, textarget, | 
| + service_id, level, samples); | 
| + } else { | 
| + glFramebufferTexture2DMultisampleEXT(target, attachment, textarget, | 
| + service_id, level, samples); | 
| + } | 
| + } | 
| + GLenum error = LOCAL_PEEK_GL_ERROR(name); | 
| if (error == GL_NO_ERROR) { | 
| - framebuffer->AttachTexture(attachment, texture_ref, textarget, level); | 
| + framebuffer->AttachTexture(attachment, texture_ref, textarget, level, | 
| + samples); | 
| } | 
| if (framebuffer == state_.bound_draw_framebuffer.get()) { | 
| clear_state_dirty_ = true; | 
| @@ -4912,6 +4977,10 @@ void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv( | 
| framebuffer->GetAttachment(attachment); | 
| *params = attachment_object ? attachment_object->object_name() : 0; | 
| } else { | 
| + if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT && | 
| + features().use_img_for_multisampled_render_to_texture) { | 
| + pname = GL_TEXTURE_SAMPLES_IMG; | 
| + } | 
| glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params); | 
| } | 
| } | 
| @@ -4936,6 +5005,14 @@ void GLES2DecoderImpl::DoGetRenderbufferParameteriv( | 
| case GL_RENDERBUFFER_HEIGHT: | 
| *params = renderbuffer->height(); | 
| break; | 
| + case GL_RENDERBUFFER_SAMPLES_EXT: | 
| + if (features().use_img_for_multisampled_render_to_texture) { | 
| + glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_IMG, | 
| + params); | 
| + } else { | 
| + glGetRenderbufferParameterivEXT(target, GL_RENDERBUFFER_SAMPLES_EXT, | 
| + params); | 
| + } | 
| default: | 
| glGetRenderbufferParameterivEXT(target, pname, params); | 
| break; | 
| @@ -4971,7 +5048,8 @@ void GLES2DecoderImpl::DoBlitFramebufferEXT( | 
| void GLES2DecoderImpl::DoRenderbufferStorageMultisample( | 
| GLenum target, GLsizei samples, GLenum internalformat, | 
| GLsizei width, GLsizei height) { | 
| - if (!features().chromium_framebuffer_multisample) { | 
| + if (!features().chromium_framebuffer_multisample && | 
| + !features().multisampled_render_to_texture) { | 
| LOCAL_SET_GL_ERROR( | 
| GL_INVALID_OPERATION, | 
| "glRenderbufferStorageMultisample", "function not available"); | 
| @@ -5024,6 +5102,9 @@ void GLES2DecoderImpl::DoRenderbufferStorageMultisample( | 
| if (IsAngle()) { | 
| glRenderbufferStorageMultisampleANGLE( | 
| target, samples, impl_format, width, height); | 
| + } else if (features().use_img_for_multisampled_render_to_texture) { | 
| + glRenderbufferStorageMultisampleIMG( | 
| + target, samples, impl_format, width, height); | 
| } else { | 
| glRenderbufferStorageMultisampleEXT( | 
| target, samples, impl_format, width, height); |