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 3c2f69440091f8020df96bec44979fa8f6892b18..cf674d9c1ee8b3faafe2499ebe14f37aa160ce08 100644 |
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
@@ -65,6 +65,9 @@ |
#include "gpu/command_buffer/service/transform_feedback_manager.h" |
#include "gpu/command_buffer/service/vertex_array_manager.h" |
#include "gpu/command_buffer/service/vertex_attrib_manager.h" |
+#if defined(OS_ANDROID) |
+#include "gpu/ipc/common/gpu_surface_lookup.h" |
+#endif |
#include "third_party/angle/src/image_util/loadimage.h" |
#include "third_party/smhasher/src/City.h" |
#include "ui/gfx/buffer_types.h" |
@@ -82,6 +85,9 @@ |
#include "ui/gl/gl_image.h" |
#include "ui/gl/gl_implementation.h" |
#include "ui/gl/gl_surface.h" |
+#if defined(OS_ANDROID) |
+#include "ui/gl/gl_surface_egl.h" |
+#endif |
#include "ui/gl/gl_version_info.h" |
#include "ui/gl/gpu_timing.h" |
@@ -1039,6 +1045,18 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
void DoFlushMappedBufferRange( |
GLenum target, GLintptr offset, GLsizeiptr size); |
+ void DoSetSurfaceHandleCHROMIUM(GLint surface_handle); |
+ |
+ // Apply creation attibutes such as depth_bits for the offscreen |
+ // framebuffer or active surface as applicable. |
+ GLint ApplySurfaceAttributesAndGetAlphaBits( |
+ bool offscreen, const ContextCreationAttribHelper& attrib_helper); |
+ |
+ // Apply feature flags and surface-specific workarounds to match the |
+ // capabilities of the current surface. Used by Initialize() and |
+ // DoSetSurfaceHandleCHROMIUM. |
+ void ApplySurfaceFeatures(); |
+ |
// Creates a Program for the given program. |
Program* CreateProgram(GLuint client_id, GLuint service_id) { |
return program_manager()->CreateProgram(client_id, service_id); |
@@ -2179,6 +2197,17 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
scoped_refptr<gl::GLSurface> surface_; |
scoped_refptr<gl::GLContext> context_; |
+ ContextCreationAttribHelper attrib_helper_; |
+ |
+ // Direct render mode data for switching and restoring the |
+ // underlying destination surface, cf. DoSetSurfaceHandleCHROMIUM. |
+ struct DirectRenderState{ |
+ scoped_refptr<gl::GLSurface> direct_surface; |
+ scoped_refptr<gl::GLSurface> orig_surface; |
+ std::unique_ptr<BackFramebuffer> orig_offscreen_target_frame_buffer; |
+ }; |
+ std::unique_ptr<DirectRenderState> direct_render_state_; |
+ |
// The ContextGroup for this decoder uses to track resources. |
scoped_refptr<ContextGroup> group_; |
@@ -3050,6 +3079,163 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) |
GLES2DecoderImpl::~GLES2DecoderImpl() { |
} |
+GLint GLES2DecoderImpl::ApplySurfaceAttributesAndGetAlphaBits( |
+ bool offscreen, const ContextCreationAttribHelper& attrib_helper) { |
+ GLint alpha_bits = 0; |
+ |
+ if (offscreen) { |
+ offscreen_buffer_should_have_alpha_ = attrib_helper.alpha_size > 0; |
+ |
+ // Whether the offscreen buffer texture should have an alpha channel. Does |
+ // not include logic from workarounds. |
+ bool offscreen_buffer_texture_needs_alpha = |
+ offscreen_buffer_should_have_alpha_ || |
+ (ChromiumImageNeedsRGBEmulation() && |
+ attrib_helper.should_use_native_gmb_for_backbuffer); |
+ |
+ if (attrib_helper.samples > 0 && attrib_helper.sample_buffers > 0 && |
+ features().chromium_framebuffer_multisample) { |
+ // Per ext_framebuffer_multisample spec, need max bound on sample count. |
+ // max_sample_count must be initialized to a sane value. If |
+ // glGetIntegerv() throws a GL error, it leaves its argument unchanged. |
+ GLint max_sample_count = 1; |
+ glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count); |
+ offscreen_target_samples_ = std::min(attrib_helper.samples, |
+ max_sample_count); |
+ } else { |
+ offscreen_target_samples_ = 1; |
+ } |
+ offscreen_target_buffer_preserved_ = attrib_helper.buffer_preserved; |
+ |
+ if (gl_version_info().is_es) { |
+ const bool rgb8_supported = context_->HasExtension("GL_OES_rgb8_rgba8"); |
+ // The only available default render buffer formats in GLES2 have very |
+ // little precision. Don't enable multisampling unless 8-bit render |
+ // buffer formats are available--instead fall back to 8-bit textures. |
+ if (rgb8_supported && offscreen_target_samples_ > 1) { |
+ offscreen_target_color_format_ = |
+ offscreen_buffer_texture_needs_alpha ? GL_RGBA8 : GL_RGB8; |
+ } else { |
+ offscreen_target_samples_ = 1; |
+ offscreen_target_color_format_ = |
+ offscreen_buffer_texture_needs_alpha || |
+ workarounds().disable_gl_rgb_format |
+ ? GL_RGBA |
+ : GL_RGB; |
+ } |
+ |
+ // ANGLE only supports packed depth/stencil formats, so use it if it is |
+ // available. |
+ const bool depth24_stencil8_supported = |
+ feature_info_->feature_flags().packed_depth24_stencil8; |
+ VLOG(1) << "GL_OES_packed_depth_stencil " |
+ << (depth24_stencil8_supported ? "" : "not ") << "supported."; |
+ if ((attrib_helper.depth_size > 0 || attrib_helper.stencil_size > 0) && |
+ depth24_stencil8_supported) { |
+ offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8; |
+ offscreen_target_stencil_format_ = 0; |
+ } else { |
+ // It may be the case that this depth/stencil combination is not |
+ // supported, but this will be checked later by CheckFramebufferStatus. |
+ offscreen_target_depth_format_ = attrib_helper.depth_size > 0 ? |
+ GL_DEPTH_COMPONENT16 : 0; |
+ offscreen_target_stencil_format_ = attrib_helper.stencil_size > 0 ? |
+ GL_STENCIL_INDEX8 : 0; |
+ } |
+ } else { |
+ offscreen_target_color_format_ = |
+ offscreen_buffer_texture_needs_alpha || |
+ workarounds().disable_gl_rgb_format |
+ ? GL_RGBA |
+ : GL_RGB; |
+ |
+ // If depth is requested at all, use the packed depth stencil format if |
+ // it's available, as some desktop GL drivers don't support any non-packed |
+ // formats for depth attachments. |
+ const bool depth24_stencil8_supported = |
+ feature_info_->feature_flags().packed_depth24_stencil8; |
+ VLOG(1) << "GL_EXT_packed_depth_stencil " |
+ << (depth24_stencil8_supported ? "" : "not ") << "supported."; |
+ |
+ if ((attrib_helper.depth_size > 0 || attrib_helper.stencil_size > 0) && |
+ depth24_stencil8_supported) { |
+ offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8; |
+ offscreen_target_stencil_format_ = 0; |
+ } else { |
+ offscreen_target_depth_format_ = attrib_helper.depth_size > 0 ? |
+ GL_DEPTH_COMPONENT : 0; |
+ offscreen_target_stencil_format_ = attrib_helper.stencil_size > 0 ? |
+ GL_STENCIL_INDEX : 0; |
+ } |
+ } |
+ |
+ offscreen_saved_color_format_ = offscreen_buffer_texture_needs_alpha || |
+ workarounds().disable_gl_rgb_format |
+ ? GL_RGBA |
+ : GL_RGB; |
+ } else { |
+ glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId()); |
+ // 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. |
+ |
+ if (!surfaceless_) { |
+ GLint depth_bits = 0; |
+ GLint stencil_bits = 0; |
+ |
+ bool default_fb = (GetBackbufferServiceId() == 0); |
+ |
+ if (gl_version_info().is_desktop_core_profile) { |
+ glGetFramebufferAttachmentParameterivEXT( |
+ GL_FRAMEBUFFER, |
+ default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0, |
+ GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits); |
+ glGetFramebufferAttachmentParameterivEXT( |
+ GL_FRAMEBUFFER, |
+ default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT, |
+ GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits); |
+ glGetFramebufferAttachmentParameterivEXT( |
+ GL_FRAMEBUFFER, |
+ default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT, |
+ GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits); |
+ } else { |
+ glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); |
+ glGetIntegerv(GL_DEPTH_BITS, &depth_bits); |
+ glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); |
+ } |
+ |
+ // 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_helper.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB; |
+ back_buffer_has_depth_ = attrib_helper.depth_size != 0 && depth_bits > 0; |
+ back_buffer_has_stencil_ = |
+ attrib_helper.stencil_size != 0 && stencil_bits > 0; |
+ } |
+ } |
+ |
+ return alpha_bits; |
+} |
+ |
+void GLES2DecoderImpl::ApplySurfaceFeatures() { |
+ supports_post_sub_buffer_ = surface_->SupportsPostSubBuffer(); |
+ if (workarounds() |
+ .disable_post_sub_buffers_for_onscreen_surfaces && |
+ !surface_->IsOffscreen()) |
+ supports_post_sub_buffer_ = false; |
+ |
+ supports_swap_buffers_with_damage_ = |
+ surface_->SupportsSwapBuffersWithDamage(); |
+ |
+ supports_commit_overlay_planes_ = surface_->SupportsCommitOverlayPlanes(); |
+ |
+ supports_async_swap_ = surface_->SupportsAsyncSwap(); |
+} |
+ |
bool GLES2DecoderImpl::Initialize( |
const scoped_refptr<gl::GLSurface>& surface, |
const scoped_refptr<gl::GLContext>& context, |
@@ -3060,6 +3246,9 @@ bool GLES2DecoderImpl::Initialize( |
DCHECK(context->IsCurrent(surface.get())); |
DCHECK(!context_.get()); |
+ // Save the attrib helper data for future use in ApplySurfaceFeatures. |
+ attrib_helper_ = attrib_helper; |
+ |
surfaceless_ = surface->IsSurfaceless() && !offscreen; |
set_initialized(); |
@@ -3232,100 +3421,12 @@ bool GLES2DecoderImpl::Initialize( |
CHECK_GL_ERROR(); |
// cache ALPHA_BITS result for re-use with clear behaviour |
- GLint alpha_bits = 0; |
+ GLint alpha_bits = ApplySurfaceAttributesAndGetAlphaBits( |
+ offscreen, attrib_helper); |
if (offscreen) { |
- offscreen_buffer_should_have_alpha_ = attrib_helper.alpha_size > 0; |
- |
- // Whether the offscreen buffer texture should have an alpha channel. Does |
- // not include logic from workarounds. |
- bool offscreen_buffer_texture_needs_alpha = |
- offscreen_buffer_should_have_alpha_ || |
- (ChromiumImageNeedsRGBEmulation() && |
- attrib_helper.should_use_native_gmb_for_backbuffer); |
- |
- if (attrib_helper.samples > 0 && attrib_helper.sample_buffers > 0 && |
- features().chromium_framebuffer_multisample) { |
- // Per ext_framebuffer_multisample spec, need max bound on sample count. |
- // max_sample_count must be initialized to a sane value. If |
- // glGetIntegerv() throws a GL error, it leaves its argument unchanged. |
- GLint max_sample_count = 1; |
- glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count); |
- offscreen_target_samples_ = std::min(attrib_helper.samples, |
- max_sample_count); |
- } else { |
- offscreen_target_samples_ = 1; |
- } |
- offscreen_target_buffer_preserved_ = attrib_helper.buffer_preserved; |
- |
- if (gl_version_info().is_es) { |
- const bool rgb8_supported = context_->HasExtension("GL_OES_rgb8_rgba8"); |
- // The only available default render buffer formats in GLES2 have very |
- // little precision. Don't enable multisampling unless 8-bit render |
- // buffer formats are available--instead fall back to 8-bit textures. |
- if (rgb8_supported && offscreen_target_samples_ > 1) { |
- offscreen_target_color_format_ = |
- offscreen_buffer_texture_needs_alpha ? GL_RGBA8 : GL_RGB8; |
- } else { |
- offscreen_target_samples_ = 1; |
- offscreen_target_color_format_ = |
- offscreen_buffer_texture_needs_alpha || |
- workarounds().disable_gl_rgb_format |
- ? GL_RGBA |
- : GL_RGB; |
- } |
- |
- // ANGLE only supports packed depth/stencil formats, so use it if it is |
- // available. |
- const bool depth24_stencil8_supported = |
- feature_info_->feature_flags().packed_depth24_stencil8; |
- VLOG(1) << "GL_OES_packed_depth_stencil " |
- << (depth24_stencil8_supported ? "" : "not ") << "supported."; |
- if ((attrib_helper.depth_size > 0 || attrib_helper.stencil_size > 0) && |
- depth24_stencil8_supported) { |
- offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8; |
- offscreen_target_stencil_format_ = 0; |
- } else { |
- // It may be the case that this depth/stencil combination is not |
- // supported, but this will be checked later by CheckFramebufferStatus. |
- offscreen_target_depth_format_ = attrib_helper.depth_size > 0 ? |
- GL_DEPTH_COMPONENT16 : 0; |
- offscreen_target_stencil_format_ = attrib_helper.stencil_size > 0 ? |
- GL_STENCIL_INDEX8 : 0; |
- } |
- } else { |
- offscreen_target_color_format_ = |
- offscreen_buffer_texture_needs_alpha || |
- workarounds().disable_gl_rgb_format |
- ? GL_RGBA |
- : GL_RGB; |
- |
- // If depth is requested at all, use the packed depth stencil format if |
- // it's available, as some desktop GL drivers don't support any non-packed |
- // formats for depth attachments. |
- const bool depth24_stencil8_supported = |
- feature_info_->feature_flags().packed_depth24_stencil8; |
- VLOG(1) << "GL_EXT_packed_depth_stencil " |
- << (depth24_stencil8_supported ? "" : "not ") << "supported."; |
- |
- if ((attrib_helper.depth_size > 0 || attrib_helper.stencil_size > 0) && |
- depth24_stencil8_supported) { |
- offscreen_target_depth_format_ = GL_DEPTH24_STENCIL8; |
- offscreen_target_stencil_format_ = 0; |
- } else { |
- offscreen_target_depth_format_ = attrib_helper.depth_size > 0 ? |
- GL_DEPTH_COMPONENT : 0; |
- offscreen_target_stencil_format_ = attrib_helper.stencil_size > 0 ? |
- GL_STENCIL_INDEX : 0; |
- } |
- } |
- |
- offscreen_saved_color_format_ = offscreen_buffer_texture_needs_alpha || |
- workarounds().disable_gl_rgb_format |
- ? GL_RGBA |
- : GL_RGB; |
- |
gfx::Size initial_size = attrib_helper.offscreen_framebuffer_size; |
+ |
if (initial_size.IsEmpty()) { |
// If we're an offscreen surface with zero width and/or height, set to a |
// non-zero size so that we have a complete framebuffer for operations |
@@ -3338,49 +3439,6 @@ bool GLES2DecoderImpl::Initialize( |
state_.viewport_width = initial_size.width(); |
state_.viewport_height = initial_size.height(); |
} else { |
- glBindFramebufferEXT(GL_FRAMEBUFFER, GetBackbufferServiceId()); |
- // 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. |
- |
- if (!surfaceless_) { |
- GLint depth_bits = 0; |
- GLint stencil_bits = 0; |
- |
- bool default_fb = (GetBackbufferServiceId() == 0); |
- |
- if (gl_version_info().is_desktop_core_profile) { |
- glGetFramebufferAttachmentParameterivEXT( |
- GL_FRAMEBUFFER, |
- default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0, |
- GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits); |
- glGetFramebufferAttachmentParameterivEXT( |
- GL_FRAMEBUFFER, |
- default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT, |
- GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits); |
- glGetFramebufferAttachmentParameterivEXT( |
- GL_FRAMEBUFFER, |
- default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT, |
- GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits); |
- } else { |
- glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); |
- glGetIntegerv(GL_DEPTH_BITS, &depth_bits); |
- glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); |
- } |
- |
- // 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_helper.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB; |
- back_buffer_has_depth_ = attrib_helper.depth_size != 0 && depth_bits > 0; |
- back_buffer_has_stencil_ = |
- attrib_helper.stencil_size != 0 && stencil_bits > 0; |
- } |
- |
state_.viewport_width = surface->GetSize().width(); |
state_.viewport_height = surface->GetSize().height(); |
} |
@@ -3521,17 +3579,7 @@ bool GLES2DecoderImpl::Initialize( |
} |
} |
- supports_post_sub_buffer_ = surface->SupportsPostSubBuffer(); |
- if (workarounds() |
- .disable_post_sub_buffers_for_onscreen_surfaces && |
- !surface->IsOffscreen()) |
- supports_post_sub_buffer_ = false; |
- |
- supports_swap_buffers_with_damage_ = surface->SupportsSwapBuffersWithDamage(); |
- |
- supports_commit_overlay_planes_ = surface->SupportsCommitOverlayPlanes(); |
- |
- supports_async_swap_ = surface->SupportsAsyncSwap(); |
+ ApplySurfaceFeatures(); |
if (workarounds().reverse_point_sprite_coord_origin) { |
glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); |
@@ -17261,6 +17309,146 @@ void GLES2DecoderImpl::DoApplyScreenSpaceAntialiasingCHROMIUM() { |
} |
} |
+void GLES2DecoderImpl::DoSetSurfaceHandleCHROMIUM(GLint surface_handle) { |
+#if defined(OS_ANDROID) |
+ if (surface_handle) { |
+ // Use the specified surface as a render target, and save decoder |
+ // state so that this can be reverted later. |
+ |
+ // We don't support switching between different surfaces. If you |
+ // need this, you have to make a call with surface_handle=0 in |
+ // between. |
+ if (!surface_->IsOffscreen()) { |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_OPERATION, |
+ "glSetSurfaceHandleCHROMIUM", |
+ "Current surface is not offscreen, cannot redirect drawing"); |
+ return; |
+ } |
+ |
+ // One-time initialization when first activating a direct draw surface. |
+ ANativeWindow* window = |
+ gpu::GpuSurfaceLookup::GetInstance()->AcquireNativeWidget( |
+ surface_handle); |
+ if (!window) { |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_OPERATION, |
+ "glSetSurfaceHandleCHROMIUM", |
+ "Could not acquire a window for this surface handle"); |
+ return; |
+ } |
+ |
+ direct_render_state_.reset(new DirectRenderState()); |
+ direct_render_state_->direct_surface = |
+ new gl::NativeViewGLSurfaceEGL(window); |
+ |
+ // It would be useful if we could get a custom surface format such |
+ // as one with a depth buffer here, but the new surface must use |
+ // the same format as the one originally used for creating the GL |
+ // context. Anything else just results in BAD_MATCH errors. |
+ bool initialize_success = direct_render_state_->direct_surface->Initialize( |
+ surface_->GetFormat()); |
+ if (!initialize_success) { |
+ LOG(ERROR) << "Direct render surface init failed for handle " << |
+ surface_handle; |
+ } |
+ ANativeWindow_release(window); |
+ |
+ direct_render_state_->orig_surface = surface_; |
+ |
+ // Offscreen surfaces don't support SwapBuffers, make sure it's not |
+ // considered offscreen. Various code in this file checks for is_offscreen |
+ // = !!offscreen_target_frame_buffer_.get(). |
+ direct_render_state_->orig_offscreen_target_frame_buffer = |
+ std::move(offscreen_target_frame_buffer_); |
+ offscreen_target_frame_buffer_.reset(nullptr); |
+ |
+ // Activate the surface and make it current. This does *not* |
+ // rebind the active framebuffer, if the client is drawing to |
+ // a bound FBO they will continue to do so. |
+ SetSurface(direct_render_state_->direct_surface); |
+ context_->MakeCurrent(surface_.get()); |
+ |
+ // Resize the surface to match the offscreen buffer, and update |
+ // decoder feature flags to match its properties. Changing |
+ // the scale is not supported, NativeViewGLSurfaceEGL::Resize |
+ // ignores scale_factor and has_alpha. |
+ surface_->Resize(offscreen_size_, |
+ 1.0f, |
+ ClientExposedBackBufferHasAlpha()); |
+ ApplySurfaceAttributesAndGetAlphaBits(false, attrib_helper_); |
+ ApplySurfaceFeatures(); |
+ |
+ if (!framebuffer_state_.bound_draw_framebuffer.get()) { |
+ // DoReadBuffer and DoDrawBuffersEXT may have modified bindings. |
+ // We don't care for modifications to a user-bound framebuffer |
+ // since those will still be valid. Target GL_NONE also remains |
+ // valid, so we just need to undo the GL_BACK -> |
+ // GL_COLOR_ATTACHMENT0 mapping. Caveat: the current buffer |
+ // content is not preserved across this surface switch. |
+ if (back_buffer_read_buffer_ == GL_BACK) { |
+ glReadBuffer(GL_BACK); |
+ } |
+ if (back_buffer_draw_buffer_ == GL_BACK) { |
+ GLenum buf = GL_BACK; |
+ glDrawBuffersARB(1, &buf); |
+ } |
+ } |
+ } else { |
+ // Restore original state for drawing offscreen. |
+ |
+ // Redundant calls or attempts to unset a surface that wasn't set |
+ // by this function are not supported. |
+ if (!direct_render_state_) { |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_OPERATION, |
+ "glSetSurfaceHandleCHROMIUM", |
+ "Surface was not set by glSetSurfaceHandleCHROMIUM, cannot unset"); |
+ } |
+ |
+ offscreen_target_frame_buffer_ = |
+ std::move(direct_render_state_->orig_offscreen_target_frame_buffer); |
+ |
+ // The viewport size may have been changed, resize it based on the |
+ // current surface size. Get the size while the direct surface is |
+ // current, then apply the size after making the offscreen framebuffer |
+ // current. |
+ gfx::Size surface_size = surface_->GetSize(); |
+ SetSurface(direct_render_state_->orig_surface); |
+ context_->MakeCurrent(surface_.get()); |
+ if (!ResizeOffscreenFramebuffer(surface_size)) { |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_OPERATION, |
+ "glSetSurfaceHandleCHROMIUM", |
+ "Failed to resize offscreen framebuffer"); |
+ } |
+ ApplySurfaceAttributesAndGetAlphaBits(true, attrib_helper_); |
+ ApplySurfaceFeatures(); |
+ |
+ if (!framebuffer_state_.bound_draw_framebuffer.get()) { |
+ // If using the default framebuffer, remap GL_BACK to |
+ // GL_COLOR_ATTACHMENT0 for read and draw. |
+ if (back_buffer_read_buffer_ == GL_BACK) { |
+ glReadBuffer(GL_COLOR_ATTACHMENT0); |
+ } |
+ if (back_buffer_draw_buffer_ == GL_BACK) { |
+ GLenum buf = GL_COLOR_ATTACHMENT0; |
+ glDrawBuffersARB(1, &buf); |
+ } |
+ } |
+ |
+ // Trust the state struct's destructors to handle refcounting for |
+ // surfaces and trigger apprpriate cleanup. |
+ direct_render_state_.reset(); |
+ } |
+#else // !OS_ANDROID |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_OPERATION, |
+ "glSetSurfaceHandleCHROMIUM", |
+ "Direct render surface is unsupported on this platform"); |
+#endif |
+} |
+ |
void GLES2DecoderImpl::DoInsertEventMarkerEXT( |
GLsizei length, const GLchar* marker) { |
if (!marker) { |